4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "lib/events/events.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "system/locale.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_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);
50 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
51 #define LONGTIMELIMIT() timeval_current_ofs(options.timelimit*10, 0)
54 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
57 #define XSTR(x) STR(x)
58 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
65 verify that a node exists and is reachable
67 static void verify_node(struct ctdb_context *ctdb)
70 struct ctdb_node_map *nodemap=NULL;
72 if (options.pnn == CTDB_CURRENT_NODE) {
75 if (options.pnn == CTDB_BROADCAST_ALL) {
79 /* verify the node exists */
80 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
81 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
84 if (options.pnn >= nodemap->num) {
85 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
88 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
89 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
92 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
93 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
97 /* verify we can access the node */
98 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
100 DEBUG(DEBUG_ERR,("Can not access node. Node is not operational.\n"));
106 check if a database exists
108 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
111 struct ctdb_dbid_map *dbmap=NULL;
113 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
115 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
119 for(i=0;i<dbmap->num;i++){
122 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
123 if (!strcmp(name, db_name)) {
132 see if a process exists
134 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
142 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
143 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
147 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
149 printf("%u:%u exists\n", pnn, pid);
151 printf("%u:%u does not exist\n", pnn, pid);
157 display statistics structure
159 static void show_statistics(struct ctdb_statistics *s)
161 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
163 const char *prefix=NULL;
165 int tmp, days, hours, minutes, seconds;
170 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
171 STATISTICS_FIELD(num_clients),
172 STATISTICS_FIELD(frozen),
173 STATISTICS_FIELD(recovering),
174 STATISTICS_FIELD(num_recoveries),
175 STATISTICS_FIELD(client_packets_sent),
176 STATISTICS_FIELD(client_packets_recv),
177 STATISTICS_FIELD(node_packets_sent),
178 STATISTICS_FIELD(node_packets_recv),
179 STATISTICS_FIELD(keepalive_packets_sent),
180 STATISTICS_FIELD(keepalive_packets_recv),
181 STATISTICS_FIELD(node.req_call),
182 STATISTICS_FIELD(node.reply_call),
183 STATISTICS_FIELD(node.req_dmaster),
184 STATISTICS_FIELD(node.reply_dmaster),
185 STATISTICS_FIELD(node.reply_error),
186 STATISTICS_FIELD(node.req_message),
187 STATISTICS_FIELD(node.req_control),
188 STATISTICS_FIELD(node.reply_control),
189 STATISTICS_FIELD(client.req_call),
190 STATISTICS_FIELD(client.req_message),
191 STATISTICS_FIELD(client.req_control),
192 STATISTICS_FIELD(timeouts.call),
193 STATISTICS_FIELD(timeouts.control),
194 STATISTICS_FIELD(timeouts.traverse),
195 STATISTICS_FIELD(total_calls),
196 STATISTICS_FIELD(pending_calls),
197 STATISTICS_FIELD(lockwait_calls),
198 STATISTICS_FIELD(pending_lockwait_calls),
199 STATISTICS_FIELD(childwrite_calls),
200 STATISTICS_FIELD(pending_childwrite_calls),
201 STATISTICS_FIELD(memory_used),
202 STATISTICS_FIELD(max_hop_count),
204 tmp = s->statistics_current_time.tv_sec - s->statistics_start_time.tv_sec;
213 printf("CTDB version %u\n", CTDB_VERSION);
214 printf("Current time of statistics : %s", ctime(&s->statistics_current_time.tv_sec));
215 printf("Statistics collected since : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&s->statistics_start_time.tv_sec));
217 for (i=0;i<ARRAY_SIZE(fields);i++) {
218 if (strchr(fields[i].name, '.')) {
219 preflen = strcspn(fields[i].name, ".")+1;
220 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
221 prefix = fields[i].name;
222 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
227 printf(" %*s%-22s%*s%10u\n",
229 fields[i].name+preflen,
231 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
233 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
234 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
236 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
237 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
238 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
239 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
241 talloc_free(tmp_ctx);
245 display remote ctdb statistics combined from all nodes
247 static int control_statistics_all(struct ctdb_context *ctdb)
250 struct ctdb_statistics statistics;
254 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
255 CTDB_NO_MEMORY(ctdb, nodes);
257 ZERO_STRUCT(statistics);
259 for (i=0;i<num_nodes;i++) {
260 struct ctdb_statistics s1;
262 uint32_t *v1 = (uint32_t *)&s1;
263 uint32_t *v2 = (uint32_t *)&statistics;
265 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
266 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
268 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
271 for (j=0;j<num_ints;j++) {
274 statistics.max_hop_count =
275 MAX(statistics.max_hop_count, s1.max_hop_count);
276 statistics.max_call_latency =
277 MAX(statistics.max_call_latency, s1.max_call_latency);
278 statistics.max_lockwait_latency =
279 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
282 printf("Gathered statistics for %u nodes\n", num_nodes);
283 show_statistics(&statistics);
288 display remote ctdb statistics
290 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
293 struct ctdb_statistics statistics;
295 if (options.pnn == CTDB_BROADCAST_ALL) {
296 return control_statistics_all(ctdb);
299 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
301 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
304 show_statistics(&statistics);
310 reset remote ctdb statistics
312 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
316 ret = ctdb_statistics_reset(ctdb, options.pnn);
318 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
326 display uptime of remote node
328 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
331 struct ctdb_uptime *uptime = NULL;
332 int tmp, days, hours, minutes, seconds;
334 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
336 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
340 if (options.machinereadable){
341 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
342 printf(":%u:%u:%u:%lf\n",
343 (unsigned int)uptime->current_time.tv_sec,
344 (unsigned int)uptime->ctdbd_start_time.tv_sec,
345 (unsigned int)uptime->last_recovery_finished.tv_sec,
346 timeval_delta(&uptime->last_recovery_finished,
347 &uptime->last_recovery_started)
352 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
354 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
362 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
364 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
372 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
374 printf("Duration of last recovery/failover: %lf seconds\n",
375 timeval_delta(&uptime->last_recovery_finished,
376 &uptime->last_recovery_started));
382 show the PNN of the current node
384 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
389 ret = ctdb_getpnn(ctdb_connection, options.pnn, &mypnn);
391 DEBUG(DEBUG_ERR, ("Unable to get pnn from node."));
395 printf("PNN:%d\n", mypnn);
401 struct pnn_node *next;
406 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
408 const char *nodes_list;
412 struct pnn_node *pnn_nodes = NULL;
413 struct pnn_node *pnn_node;
414 struct pnn_node *tmp_node;
416 /* read the nodes file */
417 nodes_list = getenv("CTDB_NODES");
418 if (nodes_list == NULL) {
419 nodes_list = "/etc/ctdb/nodes";
421 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
425 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
428 for (i=0, pnn=0; i<nlines; i++) {
432 /* strip leading spaces */
433 while((*node == ' ') || (*node == '\t')) {
440 if (strcmp(node, "") == 0) {
443 pnn_node = talloc(mem_ctx, struct pnn_node);
444 pnn_node->pnn = pnn++;
445 pnn_node->addr = talloc_strdup(pnn_node, node);
446 pnn_node->next = pnn_nodes;
447 pnn_nodes = pnn_node;
450 /* swap them around so we return them in incrementing order */
451 pnn_node = pnn_nodes;
455 pnn_node = pnn_node->next;
457 tmp_node->next = pnn_nodes;
458 pnn_nodes = tmp_node;
465 show the PNN of the current node
466 discover the pnn by loading the nodes file and try to bind to all
467 addresses one at a time until the ip address is found.
469 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
471 TALLOC_CTX *mem_ctx = talloc_new(NULL);
472 struct pnn_node *pnn_nodes;
473 struct pnn_node *pnn_node;
475 pnn_nodes = read_nodes_file(mem_ctx);
476 if (pnn_nodes == NULL) {
477 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
478 talloc_free(mem_ctx);
482 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
485 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
486 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
487 talloc_free(mem_ctx);
491 if (ctdb_sys_have_ip(&addr)) {
492 printf("PNN:%d\n", pnn_node->pnn);
493 talloc_free(mem_ctx);
498 printf("Failed to detect which PNN this node is\n");
499 talloc_free(mem_ctx);
504 display remote ctdb status
506 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
509 struct ctdb_vnn_map *vnnmap=NULL;
510 struct ctdb_node_map *nodemap=NULL;
511 uint32_t recmode, recmaster;
514 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
519 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
521 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
525 if(options.machinereadable){
526 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:PartiallyOnline:\n");
527 for(i=0;i<nodemap->num;i++){
528 int partially_online = 0;
531 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
534 if (nodemap->nodes[i].flags == 0) {
535 struct ctdb_control_get_ifaces *ifaces;
537 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
538 nodemap->nodes[i].pnn,
541 for (j=0; j < ifaces->num; j++) {
542 if (ifaces->ifaces[j].link_state != 0) {
545 partially_online = 1;
551 printf(":%d:%s:%d:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
552 ctdb_addr_to_str(&nodemap->nodes[i].addr),
553 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
554 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
555 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
556 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
557 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
558 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE),
564 printf("Number of nodes:%d\n", nodemap->num);
565 for(i=0;i<nodemap->num;i++){
566 static const struct {
570 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
571 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
572 { NODE_FLAGS_BANNED, "BANNED" },
573 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
574 { NODE_FLAGS_DELETED, "DELETED" },
575 { NODE_FLAGS_STOPPED, "STOPPED" },
576 { NODE_FLAGS_INACTIVE, "INACTIVE" },
578 char *flags_str = NULL;
581 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
584 if (nodemap->nodes[i].flags == 0) {
585 struct ctdb_control_get_ifaces *ifaces;
587 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
588 nodemap->nodes[i].pnn,
591 for (j=0; j < ifaces->num; j++) {
592 if (ifaces->ifaces[j].link_state != 0) {
595 flags_str = talloc_strdup(ctdb, "PARTIALLYONLINE");
601 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
602 if (nodemap->nodes[i].flags & flag_names[j].flag) {
603 if (flags_str == NULL) {
604 flags_str = talloc_strdup(ctdb, flag_names[j].name);
606 flags_str = talloc_asprintf_append(flags_str, "|%s",
609 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
612 if (flags_str == NULL) {
613 flags_str = talloc_strdup(ctdb, "OK");
614 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
616 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
617 ctdb_addr_to_str(&nodemap->nodes[i].addr),
619 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
620 talloc_free(flags_str);
623 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
625 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
628 if (vnnmap->generation == INVALID_GENERATION) {
629 printf("Generation:INVALID\n");
631 printf("Generation:%d\n",vnnmap->generation);
633 printf("Size:%d\n",vnnmap->size);
634 for(i=0;i<vnnmap->size;i++){
635 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
638 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
640 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
643 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
645 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
647 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
650 printf("Recovery master:%d\n",recmaster);
657 struct natgw_node *next;
662 display the list of nodes belonging to this natgw configuration
664 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
667 const char *natgw_list;
670 struct natgw_node *natgw_nodes = NULL;
671 struct natgw_node *natgw_node;
672 struct ctdb_node_map *nodemap=NULL;
675 /* read the natgw nodes file into a linked list */
676 natgw_list = getenv("NATGW_NODES");
677 if (natgw_list == NULL) {
678 natgw_list = "/etc/ctdb/natgw_nodes";
680 lines = file_lines_load(natgw_list, &nlines, ctdb);
682 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
685 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
688 for (i=0;i<nlines;i++) {
692 /* strip leading spaces */
693 while((*node == ' ') || (*node == '\t')) {
699 if (strcmp(node, "") == 0) {
702 natgw_node = talloc(ctdb, struct natgw_node);
703 natgw_node->addr = talloc_strdup(natgw_node, node);
704 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
705 natgw_node->next = natgw_nodes;
706 natgw_nodes = natgw_node;
709 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
711 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
716 while(i<nodemap->num) {
717 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
718 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
723 /* this node was not in the natgw so we just remove it from
726 if ((natgw_node == NULL)
727 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
730 for (j=i+1; j<nodemap->num; j++) {
731 nodemap->nodes[j-1] = nodemap->nodes[j];
740 /* pick a node to be natgwmaster
741 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
743 for(i=0;i<nodemap->num;i++){
744 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
745 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
749 /* we couldnt find any healthy node, try unhealthy ones */
750 if (i == nodemap->num) {
751 for(i=0;i<nodemap->num;i++){
752 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
753 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
758 /* unless all nodes are STOPPED, when we pick one anyway */
759 if (i == nodemap->num) {
760 for(i=0;i<nodemap->num;i++){
761 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
762 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
766 /* or if we still can not find any */
767 if (i == nodemap->num) {
768 printf("-1 0.0.0.0\n");
772 /* print the pruned list of nodes belonging to this natgw list */
773 for(i=0;i<nodemap->num;i++){
774 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
777 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
778 ctdb_addr_to_str(&nodemap->nodes[i].addr),
779 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
780 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
781 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
782 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
783 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
790 display the status of the scripts for monitoring (or other events)
792 static int control_one_scriptstatus(struct ctdb_context *ctdb,
793 enum ctdb_eventscript_call type)
795 struct ctdb_scripts_wire *script_status;
798 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
800 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
804 if (script_status == NULL) {
805 if (!options.machinereadable) {
806 printf("%s cycle never run\n",
807 ctdb_eventscript_call_names[type]);
812 if (!options.machinereadable) {
813 printf("%d scripts were executed last %s cycle\n",
814 script_status->num_scripts,
815 ctdb_eventscript_call_names[type]);
817 for (i=0; i<script_status->num_scripts; i++) {
818 const char *status = NULL;
820 switch (script_status->scripts[i].status) {
831 if (script_status->scripts[i].status > 0)
835 if (options.machinereadable) {
836 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
837 ctdb_eventscript_call_names[type],
838 script_status->scripts[i].name,
839 script_status->scripts[i].status,
841 (long)script_status->scripts[i].start.tv_sec,
842 (long)script_status->scripts[i].start.tv_usec,
843 (long)script_status->scripts[i].finished.tv_sec,
844 (long)script_status->scripts[i].finished.tv_usec,
845 script_status->scripts[i].output);
849 printf("%-20s Status:%s ",
850 script_status->scripts[i].name, status);
852 /* Some other error, eg from stat. */
853 printf("%-20s Status:CANNOT RUN (%s)",
854 script_status->scripts[i].name,
855 strerror(-script_status->scripts[i].status));
857 if (script_status->scripts[i].status >= 0) {
858 printf("Duration:%.3lf ",
859 timeval_delta(&script_status->scripts[i].finished,
860 &script_status->scripts[i].start));
862 if (script_status->scripts[i].status != -ENOEXEC) {
864 ctime(&script_status->scripts[i].start.tv_sec));
865 if (script_status->scripts[i].status != 0) {
866 printf(" OUTPUT:%s\n",
867 script_status->scripts[i].output);
877 static int control_scriptstatus(struct ctdb_context *ctdb,
878 int argc, const char **argv)
881 enum ctdb_eventscript_call type, min, max;
885 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
890 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
894 for (type = 0; type < CTDB_EVENT_MAX; type++) {
895 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
901 if (type == CTDB_EVENT_MAX) {
902 if (strcmp(arg, "all") == 0) {
904 max = CTDB_EVENT_MAX;
906 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
911 if (options.machinereadable) {
912 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
915 for (type = min; type < max; type++) {
916 ret = control_one_scriptstatus(ctdb, type);
926 enable an eventscript
928 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
936 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
938 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
946 disable an eventscript
948 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
956 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
958 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
966 display the pnn of the recovery master
968 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
973 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
975 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
978 printf("%d\n",recmaster);
984 get a list of all tickles for this pnn
986 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
988 struct ctdb_control_tcp_tickle_list *list;
996 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
997 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1001 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
1003 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
1007 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
1008 printf("Num tickles:%u\n", list->tickles.num);
1009 for (i=0;i<list->tickles.num;i++) {
1010 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1011 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));
1020 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1022 struct ctdb_all_public_ips *ips;
1023 struct ctdb_public_ip ip;
1026 uint32_t disable_time;
1028 struct ctdb_node_map *nodemap=NULL;
1029 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1032 data.dptr = (uint8_t*)&disable_time;
1033 data.dsize = sizeof(disable_time);
1034 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1036 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1042 /* read the public ip list from the node */
1043 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1045 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1046 talloc_free(tmp_ctx);
1050 for (i=0;i<ips->num;i++) {
1051 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1056 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1057 pnn, ctdb_addr_to_str(addr)));
1058 talloc_free(tmp_ctx);
1065 data.dptr = (uint8_t *)&ip;
1066 data.dsize = sizeof(ip);
1068 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1070 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1071 talloc_free(tmp_ctx);
1075 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1076 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1083 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1084 talloc_free(tmp_ctx);
1088 ret = ctdb_ctrl_takeover_ip(ctdb, LONGTIMELIMIT(), pnn, &ip);
1090 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1091 talloc_free(tmp_ctx);
1095 /* update the recovery daemon so it now knows to expect the new
1096 node assignment for this ip.
1098 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECD_UPDATE_IP, data);
1100 DEBUG(DEBUG_ERR,("Failed to send message to update the ip on the recovery master.\n"));
1104 talloc_free(tmp_ctx);
1109 move/failover an ip address to a specific node
1111 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1114 ctdb_sock_addr addr;
1121 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1122 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1127 if (sscanf(argv[1], "%u", &pnn) != 1) {
1128 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1132 if (move_ip(ctdb, &addr, pnn) != 0) {
1133 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1140 void getips_store_callback(void *param, void *data)
1142 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1143 struct ctdb_all_public_ips *ips = param;
1147 ips->ips[i].pnn = node_ip->pnn;
1148 ips->ips[i].addr = node_ip->addr;
1151 void getips_count_callback(void *param, void *data)
1153 uint32_t *count = param;
1159 static uint32_t *ip_key(ctdb_sock_addr *ip)
1161 static uint32_t key[IP_KEYLEN];
1163 bzero(key, sizeof(key));
1165 switch (ip->sa.sa_family) {
1167 key[0] = ip->ip.sin_addr.s_addr;
1170 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1171 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1172 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1173 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1176 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1183 static void *add_ip_callback(void *parm, void *data)
1189 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1191 struct ctdb_all_public_ips *tmp_ips;
1192 struct ctdb_node_map *nodemap=NULL;
1193 trbt_tree_t *ip_tree;
1197 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1199 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1203 ip_tree = trbt_create(tmp_ctx, 0);
1205 for(i=0;i<nodemap->num;i++){
1206 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1209 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1213 /* read the public ip list from this node */
1214 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1216 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1220 for (j=0; j<tmp_ips->num;j++) {
1221 struct ctdb_public_ip *node_ip;
1223 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1224 node_ip->pnn = tmp_ips->ips[j].pnn;
1225 node_ip->addr = tmp_ips->ips[j].addr;
1227 trbt_insertarray32_callback(ip_tree,
1228 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1232 talloc_free(tmp_ips);
1237 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1239 len = offsetof(struct ctdb_all_public_ips, ips) +
1240 count*sizeof(struct ctdb_public_ip);
1241 tmp_ips = talloc_zero_size(tmp_ctx, len);
1242 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1251 * scans all other nodes and returns a pnn for another node that can host this
1255 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1257 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1258 struct ctdb_all_public_ips *ips;
1259 struct ctdb_node_map *nodemap=NULL;
1262 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1264 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1265 talloc_free(tmp_ctx);
1269 for(i=0;i<nodemap->num;i++){
1270 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1273 if (nodemap->nodes[i].pnn == options.pnn) {
1277 /* read the public ip list from this node */
1278 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1280 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1284 for (j=0;j<ips->num;j++) {
1285 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1286 talloc_free(tmp_ctx);
1287 return nodemap->nodes[i].pnn;
1293 talloc_free(tmp_ctx);
1298 add a public ip address to a node
1300 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1306 ctdb_sock_addr addr;
1307 struct ctdb_control_ip_iface *pub;
1308 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1309 struct ctdb_all_public_ips *ips;
1313 talloc_free(tmp_ctx);
1317 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1318 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1319 talloc_free(tmp_ctx);
1323 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1325 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1326 talloc_free(tmp_ctx);
1331 /* check if some other node is already serving this ip, if not,
1334 for (i=0;i<ips->num;i++) {
1335 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1340 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1341 pub = talloc_size(tmp_ctx, len);
1342 CTDB_NO_MEMORY(ctdb, pub);
1346 pub->len = strlen(argv[1])+1;
1347 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1349 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1351 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1352 talloc_free(tmp_ctx);
1356 if (i == ips->num) {
1357 /* no one has this ip so we claim it */
1360 pnn = ips->ips[i].pnn;
1363 if (move_ip(ctdb, &addr, pnn) != 0) {
1364 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1368 talloc_free(tmp_ctx);
1372 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1374 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1376 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1377 struct ctdb_node_map *nodemap=NULL;
1378 struct ctdb_all_public_ips *ips;
1381 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1383 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1387 /* remove it from the nodes that are not hosting the ip currently */
1388 for(i=0;i<nodemap->num;i++){
1389 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1392 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1393 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1397 for (j=0;j<ips->num;j++) {
1398 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1406 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1410 options.pnn = nodemap->nodes[i].pnn;
1411 control_delip(ctdb, argc, argv);
1415 /* remove it from every node (also the one hosting it) */
1416 for(i=0;i<nodemap->num;i++){
1417 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1420 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1421 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1425 for (j=0;j<ips->num;j++) {
1426 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1434 options.pnn = nodemap->nodes[i].pnn;
1435 control_delip(ctdb, argc, argv);
1438 talloc_free(tmp_ctx);
1443 delete a public ip address from a node
1445 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1448 ctdb_sock_addr addr;
1449 struct ctdb_control_ip_iface pub;
1450 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1451 struct ctdb_all_public_ips *ips;
1454 talloc_free(tmp_ctx);
1458 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1459 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1463 if (options.pnn == CTDB_BROADCAST_ALL) {
1464 return control_delip_all(ctdb, argc, argv, &addr);
1471 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1473 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1474 talloc_free(tmp_ctx);
1478 for (i=0;i<ips->num;i++) {
1479 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1485 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1486 ctdb_addr_to_str(&addr)));
1487 talloc_free(tmp_ctx);
1491 if (ips->ips[i].pnn == options.pnn) {
1492 ret = find_other_host_for_public_ip(ctdb, &addr);
1494 if (move_ip(ctdb, &addr, ret) != 0) {
1495 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1501 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1503 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1504 talloc_free(tmp_ctx);
1508 talloc_free(tmp_ctx);
1513 kill a tcp connection
1515 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1518 struct ctdb_control_killtcp killtcp;
1524 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1525 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1529 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1530 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1534 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1536 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1547 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1550 ctdb_sock_addr addr;
1556 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1557 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1561 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1563 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1571 register a server id
1573 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1576 struct ctdb_server_id server_id;
1582 server_id.pnn = strtoul(argv[0], NULL, 0);
1583 server_id.type = strtoul(argv[1], NULL, 0);
1584 server_id.server_id = strtoul(argv[2], NULL, 0);
1586 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1588 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1591 DEBUG(DEBUG_ERR,("Srvid registered. Sleeping for 999 seconds\n"));
1597 unregister a server id
1599 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1602 struct ctdb_server_id server_id;
1608 server_id.pnn = strtoul(argv[0], NULL, 0);
1609 server_id.type = strtoul(argv[1], NULL, 0);
1610 server_id.server_id = strtoul(argv[2], NULL, 0);
1612 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1614 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1621 check if a server id exists
1623 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1627 struct ctdb_server_id server_id;
1633 server_id.pnn = strtoul(argv[0], NULL, 0);
1634 server_id.type = strtoul(argv[1], NULL, 0);
1635 server_id.server_id = strtoul(argv[2], NULL, 0);
1637 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1639 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1644 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1646 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1652 get a list of all server ids that are registered on a node
1654 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1657 struct ctdb_server_id_list *server_ids;
1659 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1661 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1665 for (i=0; i<server_ids->num; i++) {
1666 printf("Server id %d:%d:%d\n",
1667 server_ids->server_ids[i].pnn,
1668 server_ids->server_ids[i].type,
1669 server_ids->server_ids[i].server_id);
1676 send a tcp tickle ack
1678 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1681 ctdb_sock_addr src, dst;
1687 if (!parse_ip_port(argv[0], &src)) {
1688 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1692 if (!parse_ip_port(argv[1], &dst)) {
1693 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1697 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1701 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1708 display public ip status
1710 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1713 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1714 struct ctdb_all_public_ips *ips;
1716 if (options.pnn == CTDB_BROADCAST_ALL) {
1717 /* read the list of public ips from all nodes */
1718 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1720 /* read the public ip list from this node */
1721 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1724 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1725 talloc_free(tmp_ctx);
1729 if (options.machinereadable){
1730 printf(":Public IP:Node:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1732 if (options.pnn == CTDB_BROADCAST_ALL) {
1733 printf("Public IPs on ALL nodes\n");
1735 printf("Public IPs on node %u\n", options.pnn);
1739 for (i=1;i<=ips->num;i++) {
1740 struct ctdb_control_public_ip_info *info = NULL;
1742 char *aciface = NULL;
1743 char *avifaces = NULL;
1744 char *cifaces = NULL;
1746 if (options.pnn == CTDB_BROADCAST_ALL) {
1747 pnn = ips->ips[ips->num-i].pnn;
1753 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1754 &ips->ips[ips->num-i].addr, &info);
1761 for (j=0; j < info->num; j++) {
1762 if (cifaces == NULL) {
1763 cifaces = talloc_strdup(info,
1764 info->ifaces[j].name);
1766 cifaces = talloc_asprintf_append(cifaces,
1768 info->ifaces[j].name);
1771 if (info->active_idx == j) {
1772 aciface = info->ifaces[j].name;
1775 if (info->ifaces[j].link_state == 0) {
1779 if (avifaces == NULL) {
1780 avifaces = talloc_strdup(info, info->ifaces[j].name);
1782 avifaces = talloc_asprintf_append(avifaces,
1784 info->ifaces[j].name);
1789 if (options.machinereadable){
1790 printf(":%s:%d:%s:%s:%s:\n",
1791 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1792 ips->ips[ips->num-i].pnn,
1794 avifaces?avifaces:"",
1795 cifaces?cifaces:"");
1797 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1798 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1799 ips->ips[ips->num-i].pnn,
1801 avifaces?avifaces:"",
1802 cifaces?cifaces:"");
1807 talloc_free(tmp_ctx);
1814 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1817 ctdb_sock_addr addr;
1818 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1819 struct ctdb_control_public_ip_info *info;
1822 talloc_free(tmp_ctx);
1826 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1827 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1831 /* read the public ip info from this node */
1832 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1833 tmp_ctx, &addr, &info);
1835 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1836 argv[0], options.pnn));
1837 talloc_free(tmp_ctx);
1841 printf("Public IP[%s] info on node %u\n",
1842 ctdb_addr_to_str(&info->ip.addr),
1845 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1846 ctdb_addr_to_str(&info->ip.addr),
1847 info->ip.pnn, info->num);
1849 for (i=0; i<info->num; i++) {
1850 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1852 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1853 i+1, info->ifaces[i].name,
1854 info->ifaces[i].link_state?"up":"down",
1855 (unsigned int)info->ifaces[i].references,
1856 (i==info->active_idx)?" (active)":"");
1859 talloc_free(tmp_ctx);
1864 display interfaces status
1866 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1869 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1870 struct ctdb_control_get_ifaces *ifaces;
1872 /* read the public ip list from this node */
1873 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1876 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1878 talloc_free(tmp_ctx);
1882 if (options.machinereadable){
1883 printf(":Name:LinkStatus:References:\n");
1885 printf("Interfaces on node %u\n", options.pnn);
1888 for (i=0; i<ifaces->num; i++) {
1889 if (options.machinereadable){
1890 printf(":%s:%s:%u\n",
1891 ifaces->ifaces[i].name,
1892 ifaces->ifaces[i].link_state?"1":"0",
1893 (unsigned int)ifaces->ifaces[i].references);
1895 printf("name:%s link:%s references:%u\n",
1896 ifaces->ifaces[i].name,
1897 ifaces->ifaces[i].link_state?"up":"down",
1898 (unsigned int)ifaces->ifaces[i].references);
1902 talloc_free(tmp_ctx);
1908 set link status of an interface
1910 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
1913 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1914 struct ctdb_control_iface_info info;
1922 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
1923 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
1925 talloc_free(tmp_ctx);
1928 strcpy(info.name, argv[0]);
1930 if (strcmp(argv[1], "up") == 0) {
1931 info.link_state = 1;
1932 } else if (strcmp(argv[1], "down") == 0) {
1933 info.link_state = 0;
1935 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
1937 talloc_free(tmp_ctx);
1941 /* read the public ip list from this node */
1942 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
1945 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
1946 argv[0], options.pnn));
1947 talloc_free(tmp_ctx);
1951 talloc_free(tmp_ctx);
1956 display pid of a ctdb daemon
1958 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1963 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1965 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1968 printf("Pid:%d\n", pid);
1973 static uint32_t ipreallocate_finished;
1976 handler for receiving the response to ipreallocate
1978 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1979 TDB_DATA data, void *private_data)
1981 ipreallocate_finished = 1;
1984 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1986 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1988 event_add_timed(ctdb->ev, ctdb,
1989 timeval_current_ofs(1, 0),
1990 ctdb_every_second, ctdb);
1994 ask the recovery daemon on the recovery master to perform a ip reallocation
1996 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
2000 struct takeover_run_reply rd;
2002 struct ctdb_node_map *nodemap=NULL;
2004 struct timeval tv = timeval_current();
2006 /* we need some events to trigger so we can timeout and restart
2009 event_add_timed(ctdb->ev, ctdb,
2010 timeval_current_ofs(1, 0),
2011 ctdb_every_second, ctdb);
2013 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2015 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
2018 rd.srvid = getpid();
2020 /* register a message port for receiveing the reply so that we
2021 can receive the reply
2023 ctdb_client_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
2025 data.dptr = (uint8_t *)&rd;
2026 data.dsize = sizeof(rd);
2029 /* check that there are valid nodes available */
2030 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2031 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2034 for (i=0; i<nodemap->num;i++) {
2035 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2039 if (i==nodemap->num) {
2040 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2045 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2047 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2051 /* verify the node exists */
2052 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2053 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2058 /* check tha there are nodes available that can act as a recmaster */
2059 for (i=0; i<nodemap->num; i++) {
2060 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2065 if (i == nodemap->num) {
2066 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2070 /* verify the recovery master is not STOPPED, nor BANNED */
2071 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2072 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2079 /* verify the recovery master is not STOPPED, nor BANNED */
2080 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2081 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2087 ipreallocate_finished = 0;
2088 ret = ctdb_client_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2090 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2094 tv = timeval_current();
2095 /* this loop will terminate when we have received the reply */
2096 while (timeval_elapsed(&tv) < 3.0) {
2097 event_loop_once(ctdb->ev);
2099 if (ipreallocate_finished == 1) {
2103 DEBUG(DEBUG_ERR,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2113 disable a remote node
2115 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2118 struct ctdb_node_map *nodemap=NULL;
2120 /* check if the node is already disabled */
2121 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2122 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2125 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2126 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2131 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2133 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2139 /* read the nodemap and verify the change took effect */
2140 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2141 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2145 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2146 ret = control_ipreallocate(ctdb, argc, argv);
2148 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2156 enable a disabled remote node
2158 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2162 struct ctdb_node_map *nodemap=NULL;
2165 /* check if the node is already enabled */
2166 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2167 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2170 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2171 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2176 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2178 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2184 /* read the nodemap and verify the change took effect */
2185 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2186 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2190 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2192 ret = control_ipreallocate(ctdb, argc, argv);
2194 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2204 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2207 struct ctdb_node_map *nodemap=NULL;
2210 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2212 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2217 /* read the nodemap and verify the change took effect */
2218 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2219 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2223 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2224 ret = control_ipreallocate(ctdb, argc, argv);
2226 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2234 restart a stopped remote node
2236 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2240 struct ctdb_node_map *nodemap=NULL;
2243 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2245 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2251 /* read the nodemap and verify the change took effect */
2252 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2253 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2257 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2258 ret = control_ipreallocate(ctdb, argc, argv);
2260 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2267 static uint32_t get_generation(struct ctdb_context *ctdb)
2269 struct ctdb_vnn_map *vnnmap=NULL;
2272 /* wait until the recmaster is not in recovery mode */
2274 uint32_t recmode, recmaster;
2276 if (vnnmap != NULL) {
2277 talloc_free(vnnmap);
2281 /* get the recmaster */
2282 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2284 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2288 /* get recovery mode */
2289 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2291 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2295 /* get the current generation number */
2296 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2298 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2302 if ((recmode == CTDB_RECOVERY_NORMAL)
2303 && (vnnmap->generation != 1)){
2304 return vnnmap->generation;
2311 ban a node from the cluster
2313 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2316 struct ctdb_node_map *nodemap=NULL;
2317 struct ctdb_ban_time bantime;
2323 /* verify the node exists */
2324 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2326 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2330 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2331 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2335 bantime.pnn = options.pnn;
2336 bantime.time = strtoul(argv[0], NULL, 0);
2338 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2340 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2344 ret = control_ipreallocate(ctdb, argc, argv);
2346 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2355 unban a node from the cluster
2357 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2360 struct ctdb_node_map *nodemap=NULL;
2361 struct ctdb_ban_time bantime;
2363 /* verify the node exists */
2364 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2366 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2370 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2371 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2375 bantime.pnn = options.pnn;
2378 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2380 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2384 ret = control_ipreallocate(ctdb, argc, argv);
2386 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2395 show ban information for a node
2397 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2400 struct ctdb_node_map *nodemap=NULL;
2401 struct ctdb_ban_time *bantime;
2403 /* verify the node exists */
2404 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2406 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2410 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2412 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2416 if (bantime->time == 0) {
2417 printf("Node %u is not banned\n", bantime->pnn);
2419 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2428 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2432 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2434 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2444 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2447 uint32_t generation, next_generation;
2449 /* record the current generation number */
2450 generation = get_generation(ctdb);
2452 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2454 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2458 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2460 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2464 /* wait until we are in a new generation */
2466 next_generation = get_generation(ctdb);
2467 if (next_generation != generation) {
2478 display monitoring mode of a remote node
2480 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2485 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2487 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2490 if (!options.machinereadable){
2491 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2494 printf(":%d:\n",monmode);
2501 display capabilities of a remote node
2503 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2505 uint32_t capabilities;
2508 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2510 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2514 if (!options.machinereadable){
2515 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2516 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2517 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2518 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2520 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2521 printf(":%d:%d:%d:%d:\n",
2522 !!(capabilities&CTDB_CAP_RECMASTER),
2523 !!(capabilities&CTDB_CAP_LMASTER),
2524 !!(capabilities&CTDB_CAP_LVS),
2525 !!(capabilities&CTDB_CAP_NATGW));
2531 display lvs configuration
2533 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2535 uint32_t *capabilities;
2536 struct ctdb_node_map *nodemap=NULL;
2538 int healthy_count = 0;
2540 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2542 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2546 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2547 CTDB_NO_MEMORY(ctdb, capabilities);
2549 /* collect capabilities for all connected nodes */
2550 for (i=0; i<nodemap->num; i++) {
2551 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2554 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2558 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2560 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2564 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2568 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2573 /* Print all LVS nodes */
2574 for (i=0; i<nodemap->num; i++) {
2575 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2578 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2581 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2585 if (healthy_count != 0) {
2586 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2591 printf("%d:%s\n", i,
2592 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2599 display who is the lvs master
2601 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2603 uint32_t *capabilities;
2604 struct ctdb_node_map *nodemap=NULL;
2606 int healthy_count = 0;
2608 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2610 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2614 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2615 CTDB_NO_MEMORY(ctdb, capabilities);
2617 /* collect capabilities for all connected nodes */
2618 for (i=0; i<nodemap->num; i++) {
2619 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2622 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2626 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2628 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2632 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2636 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2641 /* find and show the lvsmaster */
2642 for (i=0; i<nodemap->num; i++) {
2643 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2646 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2649 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2653 if (healthy_count != 0) {
2654 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2659 if (options.machinereadable){
2662 printf("Node %d is LVS master\n", i);
2667 printf("There is no LVS master\n");
2672 disable monitoring on a node
2674 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2679 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2681 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2684 printf("Monitoring mode:%s\n","DISABLED");
2690 enable monitoring on a node
2692 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2697 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2699 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2702 printf("Monitoring mode:%s\n","ACTIVE");
2708 display remote list of keys/data for a db
2710 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2712 const char *db_name;
2713 struct ctdb_db_context *ctdb_db;
2723 if (db_exists(ctdb, db_name)) {
2724 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2728 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2730 if (ctdb_db == NULL) {
2731 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2735 /* traverse and dump the cluster tdb */
2736 ret = ctdb_dump_db(ctdb_db, stdout);
2738 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2739 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2740 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2744 talloc_free(ctdb_db);
2746 printf("Dumped %d records\n", ret);
2751 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2752 TDB_DATA data, void *private_data)
2754 DEBUG(DEBUG_ERR,("Log data received\n"));
2755 if (data.dsize > 0) {
2756 printf("%s", data.dptr);
2763 display a list of log messages from the in memory ringbuffer
2765 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2769 struct ctdb_get_log_addr log_addr;
2771 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2776 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2777 talloc_free(tmp_ctx);
2781 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2782 log_addr.srvid = getpid();
2783 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2784 log_addr.level = get_debug_by_desc(argv[0]);
2786 log_addr.level = strtol(argv[0], NULL, 0);
2790 data.dptr = (unsigned char *)&log_addr;
2791 data.dsize = sizeof(log_addr);
2793 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2795 ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2798 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2800 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2801 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2802 if (ret != 0 || res != 0) {
2803 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2804 talloc_free(tmp_ctx);
2809 tv = timeval_current();
2810 /* this loop will terminate when we have received the reply */
2811 while (timeval_elapsed(&tv) < 3.0) {
2812 event_loop_once(ctdb->ev);
2815 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2817 talloc_free(tmp_ctx);
2822 clear the in memory log area
2824 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2829 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2831 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2832 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2833 if (ret != 0 || res != 0) {
2834 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2835 talloc_free(tmp_ctx);
2839 talloc_free(tmp_ctx);
2846 display a list of the databases on a remote ctdb
2848 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2851 struct ctdb_dbid_map *dbmap=NULL;
2853 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2855 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2859 if(options.machinereadable){
2860 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2861 for(i=0;i<dbmap->num;i++){
2867 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2868 dbmap->dbs[i].dbid, ctdb, &path);
2869 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2870 dbmap->dbs[i].dbid, ctdb, &name);
2871 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2872 dbmap->dbs[i].dbid, ctdb, &health);
2873 persistent = dbmap->dbs[i].persistent;
2874 printf(":0x%08X:%s:%s:%d:%d:\n",
2875 dbmap->dbs[i].dbid, name, path,
2876 !!(persistent), !!(health));
2881 printf("Number of databases:%d\n", dbmap->num);
2882 for(i=0;i<dbmap->num;i++){
2888 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2889 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2890 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2891 persistent = dbmap->dbs[i].persistent;
2892 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2893 dbmap->dbs[i].dbid, name, path,
2894 persistent?" PERSISTENT":"",
2895 health?" UNHEALTHY":"");
2902 display the status of a database on a remote ctdb
2904 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2907 struct ctdb_dbid_map *dbmap=NULL;
2908 const char *db_name;
2916 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2918 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2922 for(i=0;i<dbmap->num;i++){
2928 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2929 if (strcmp(name, db_name) != 0) {
2933 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2934 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2935 persistent = dbmap->dbs[i].persistent;
2936 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
2937 dbmap->dbs[i].dbid, name, path,
2938 persistent?"yes":"no",
2939 health?health:"OK");
2943 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
2948 check if the local node is recmaster or not
2949 it will return 1 if this node is the recmaster and 0 if it is not
2950 or if the local ctdb daemon could not be contacted
2952 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2954 uint32_t mypnn, recmaster;
2957 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2959 printf("Failed to get pnn of node\n");
2963 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2965 printf("Failed to get the recmaster\n");
2969 if (recmaster != mypnn) {
2970 printf("this node is not the recmaster\n");
2974 printf("this node is the recmaster\n");
2981 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2984 struct timeval tv = timeval_current();
2985 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2987 printf("Unable to get ping response from node %u\n", options.pnn);
2990 printf("response from %u time=%.6f sec (%d clients)\n",
2991 options.pnn, timeval_elapsed(&tv), ret);
3000 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
3011 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
3013 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
3017 printf("%-19s = %u\n", name, value);
3024 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3035 value = strtoul(argv[1], NULL, 0);
3037 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3039 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3048 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3054 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3056 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3060 for (i=0;i<count;i++) {
3061 control_getvar(ctdb, 1, &list[i]);
3070 display debug level on a node
3072 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3077 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3079 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3082 if (options.machinereadable){
3083 printf(":Name:Level:\n");
3084 printf(":%s:%d:\n",get_debug_by_level(level),level);
3086 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3093 display reclock file of a node
3095 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3098 const char *reclock;
3100 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3102 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3105 if (options.machinereadable){
3106 if (reclock != NULL) {
3107 printf("%s", reclock);
3110 if (reclock == NULL) {
3111 printf("No reclock file used.\n");
3113 printf("Reclock file:%s\n", reclock);
3121 set the reclock file of a node
3123 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3126 const char *reclock;
3130 } else if (argc == 1) {
3136 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3138 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3145 set the natgw state on/off
3147 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3150 uint32_t natgwstate;
3156 if (!strcmp(argv[0], "on")) {
3158 } else if (!strcmp(argv[0], "off")) {
3164 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3166 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3174 set the lmaster role on/off
3176 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3179 uint32_t lmasterrole;
3185 if (!strcmp(argv[0], "on")) {
3187 } else if (!strcmp(argv[0], "off")) {
3193 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3195 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3203 set the recmaster role on/off
3205 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3208 uint32_t recmasterrole;
3214 if (!strcmp(argv[0], "on")) {
3216 } else if (!strcmp(argv[0], "off")) {
3222 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3224 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3232 set debug level on a node or all nodes
3234 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3240 printf("You must specify the debug level. Valid levels are:\n");
3241 for (i=0; debug_levels[i].description != NULL; i++) {
3242 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3248 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3249 level = get_debug_by_desc(argv[0]);
3251 level = strtol(argv[0], NULL, 0);
3254 for (i=0; debug_levels[i].description != NULL; i++) {
3255 if (level == debug_levels[i].level) {
3259 if (debug_levels[i].description == NULL) {
3260 printf("Invalid debug level, must be one of\n");
3261 for (i=0; debug_levels[i].description != NULL; i++) {
3262 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3267 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3269 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3278 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3284 priority = strtol(argv[0], NULL, 0);
3288 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3290 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3292 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3299 attach to a database
3301 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3303 const char *db_name;
3304 struct ctdb_db_context *ctdb_db;
3311 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3312 if (ctdb_db == NULL) {
3313 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3323 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3325 struct ctdb_db_priority db_prio;
3332 db_prio.db_id = strtoul(argv[0], NULL, 0);
3333 db_prio.priority = strtoul(argv[1], NULL, 0);
3335 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3337 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3347 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3349 uint32_t db_id, priority;
3356 db_id = strtoul(argv[0], NULL, 0);
3358 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3360 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3364 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3370 run an eventscript on a node
3372 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3378 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3381 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3385 data.dptr = (unsigned char *)discard_const(argv[0]);
3386 data.dsize = strlen((char *)data.dptr) + 1;
3388 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3390 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3391 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3392 if (ret != 0 || res != 0) {
3393 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3394 talloc_free(tmp_ctx);
3397 talloc_free(tmp_ctx);
3401 #define DB_VERSION 1
3402 #define MAX_DB_NAME 64
3403 struct db_file_header {
3404 unsigned long version;
3406 unsigned long persistent;
3408 const char name[MAX_DB_NAME];
3411 struct backup_data {
3412 struct ctdb_marshall_buffer *records;
3415 bool traverse_error;
3418 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3420 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3421 struct ctdb_rec_data *rec;
3423 /* add the record */
3424 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3426 bd->traverse_error = true;
3427 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3430 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3431 if (bd->records == NULL) {
3432 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3433 bd->traverse_error = true;
3436 bd->records->count++;
3437 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3438 bd->len += rec->length;
3446 * backup a database to a file
3448 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3451 struct ctdb_dbid_map *dbmap=NULL;
3452 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3453 struct db_file_header dbhdr;
3454 struct ctdb_db_context *ctdb_db;
3455 struct backup_data *bd;
3458 const char *reason = NULL;
3461 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3465 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3467 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3471 for(i=0;i<dbmap->num;i++){
3474 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3475 if(!strcmp(argv[0], name)){
3476 talloc_free(discard_const(name));
3479 talloc_free(discard_const(name));
3481 if (i == dbmap->num) {
3482 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3483 talloc_free(tmp_ctx);
3487 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3488 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3490 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3492 talloc_free(tmp_ctx);
3496 uint32_t allow_unhealthy = 0;
3498 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3499 "AllowUnhealthyDBRead",
3502 if (allow_unhealthy != 1) {
3503 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3506 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3508 talloc_free(tmp_ctx);
3512 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3514 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3515 "tunnable AllowUnhealthyDBRead = %u\n",
3519 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3520 if (ctdb_db == NULL) {
3521 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3522 talloc_free(tmp_ctx);
3527 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3529 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3530 talloc_free(tmp_ctx);
3535 bd = talloc_zero(tmp_ctx, struct backup_data);
3537 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3538 talloc_free(tmp_ctx);
3542 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3543 if (bd->records == NULL) {
3544 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3545 talloc_free(tmp_ctx);
3549 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3550 bd->records->db_id = ctdb_db->db_id;
3551 /* traverse the database collecting all records */
3552 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3553 bd->traverse_error) {
3554 DEBUG(DEBUG_ERR,("Traverse error\n"));
3555 talloc_free(tmp_ctx);
3559 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3562 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3564 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3565 talloc_free(tmp_ctx);
3569 dbhdr.version = DB_VERSION;
3570 dbhdr.timestamp = time(NULL);
3571 dbhdr.persistent = dbmap->dbs[i].persistent;
3572 dbhdr.size = bd->len;
3573 if (strlen(argv[0]) >= MAX_DB_NAME) {
3574 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3577 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3578 ret = write(fh, &dbhdr, sizeof(dbhdr));
3580 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3583 ret = write(fh, bd->records, bd->len);
3585 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3594 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3597 talloc_free(tmp_ctx);
3602 * restore a database from a file
3604 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3607 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3610 struct db_file_header dbhdr;
3611 struct ctdb_db_context *ctdb_db;
3612 struct ctdb_node_map *nodemap=NULL;
3613 struct ctdb_vnn_map *vnnmap=NULL;
3615 struct ctdb_control_wipe_database w;
3617 uint32_t generation;
3622 if (argc < 1 || argc > 2) {
3623 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3627 fh = open(argv[0], O_RDONLY);
3629 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3630 talloc_free(tmp_ctx);
3634 read(fh, &dbhdr, sizeof(dbhdr));
3635 if (dbhdr.version != DB_VERSION) {
3636 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3637 talloc_free(tmp_ctx);
3641 dbname = dbhdr.name;
3646 outdata.dsize = dbhdr.size;
3647 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3648 if (outdata.dptr == NULL) {
3649 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3651 talloc_free(tmp_ctx);
3654 read(fh, outdata.dptr, outdata.dsize);
3657 tm = localtime(&dbhdr.timestamp);
3658 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3659 printf("Restoring database '%s' from backup @ %s\n",
3663 ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3664 if (ctdb_db == NULL) {
3665 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3666 talloc_free(tmp_ctx);
3670 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3672 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3673 talloc_free(tmp_ctx);
3678 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3680 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3681 talloc_free(tmp_ctx);
3685 /* freeze all nodes */
3686 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3687 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3688 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3694 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3695 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3696 talloc_free(tmp_ctx);
3701 generation = vnnmap->generation;
3702 data.dptr = (void *)&generation;
3703 data.dsize = sizeof(generation);
3705 /* start a cluster wide transaction */
3706 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3707 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3709 TIMELIMIT(), false, data,
3712 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3717 w.db_id = ctdb_db->db_id;
3718 w.transaction_id = generation;
3720 data.dptr = (void *)&w;
3721 data.dsize = sizeof(w);
3723 /* wipe all the remote databases. */
3724 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3725 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3727 TIMELIMIT(), false, data,
3730 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3731 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3732 talloc_free(tmp_ctx);
3736 /* push the database */
3737 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3738 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3740 TIMELIMIT(), false, outdata,
3743 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3744 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3745 talloc_free(tmp_ctx);
3749 data.dptr = (void *)&ctdb_db->db_id;
3750 data.dsize = sizeof(ctdb_db->db_id);
3752 /* mark the database as healthy */
3753 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3754 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3756 TIMELIMIT(), false, data,
3759 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3760 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3761 talloc_free(tmp_ctx);
3765 data.dptr = (void *)&generation;
3766 data.dsize = sizeof(generation);
3768 /* commit all the changes */
3769 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3771 TIMELIMIT(), false, data,
3774 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3775 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3776 talloc_free(tmp_ctx);
3781 /* thaw all nodes */
3782 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3783 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3789 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3790 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3791 talloc_free(tmp_ctx);
3796 talloc_free(tmp_ctx);
3801 * dump a database backup from a file
3803 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3805 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3807 struct db_file_header dbhdr;
3811 struct ctdb_rec_data *rec = NULL;
3812 struct ctdb_marshall_buffer *m;
3815 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3819 fh = open(argv[0], O_RDONLY);
3821 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3822 talloc_free(tmp_ctx);
3826 read(fh, &dbhdr, sizeof(dbhdr));
3827 if (dbhdr.version != DB_VERSION) {
3828 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3829 talloc_free(tmp_ctx);
3833 outdata.dsize = dbhdr.size;
3834 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3835 if (outdata.dptr == NULL) {
3836 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3838 talloc_free(tmp_ctx);
3841 read(fh, outdata.dptr, outdata.dsize);
3843 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3845 tm = localtime(&dbhdr.timestamp);
3846 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3847 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3848 dbhdr.name, m->db_id, tbuf);
3850 for (i=0; i < m->count; i++) {
3854 /* we do not want the header splitted, so we pass NULL*/
3855 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3858 ctdb_dumpdb_record(ctdb, key, data, stdout);
3861 printf("Dumped %d records\n", i);
3862 talloc_free(tmp_ctx);
3867 * wipe a database from a file
3869 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3873 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3875 struct ctdb_db_context *ctdb_db;
3876 struct ctdb_node_map *nodemap = NULL;
3877 struct ctdb_vnn_map *vnnmap = NULL;
3879 struct ctdb_control_wipe_database w;
3881 uint32_t generation;
3882 struct ctdb_dbid_map *dbmap = NULL;
3885 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3889 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3892 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3897 for(i=0;i<dbmap->num;i++){
3900 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3901 dbmap->dbs[i].dbid, tmp_ctx, &name);
3902 if(!strcmp(argv[0], name)){
3903 talloc_free(discard_const(name));
3906 talloc_free(discard_const(name));
3908 if (i == dbmap->num) {
3909 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3911 talloc_free(tmp_ctx);
3915 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3916 if (ctdb_db == NULL) {
3917 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3919 talloc_free(tmp_ctx);
3923 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3926 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3928 talloc_free(tmp_ctx);
3932 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3935 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3937 talloc_free(tmp_ctx);
3941 /* freeze all nodes */
3942 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3943 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3944 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3951 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3952 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3953 CTDB_RECOVERY_ACTIVE);
3954 talloc_free(tmp_ctx);
3959 generation = vnnmap->generation;
3960 data.dptr = (void *)&generation;
3961 data.dsize = sizeof(generation);
3963 /* start a cluster wide transaction */
3964 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3965 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3967 TIMELIMIT(), false, data,
3971 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3972 "transactions.\n"));
3976 w.db_id = ctdb_db->db_id;
3977 w.transaction_id = generation;
3979 data.dptr = (void *)&w;
3980 data.dsize = sizeof(w);
3982 /* wipe all the remote databases. */
3983 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3984 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3986 TIMELIMIT(), false, data,
3989 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3990 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3991 talloc_free(tmp_ctx);
3995 data.dptr = (void *)&ctdb_db->db_id;
3996 data.dsize = sizeof(ctdb_db->db_id);
3998 /* mark the database as healthy */
3999 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4000 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4002 TIMELIMIT(), false, data,
4005 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4006 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4007 talloc_free(tmp_ctx);
4011 data.dptr = (void *)&generation;
4012 data.dsize = sizeof(generation);
4014 /* commit all the changes */
4015 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4017 TIMELIMIT(), false, data,
4020 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4021 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4022 talloc_free(tmp_ctx);
4026 /* thaw all nodes */
4027 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4028 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4034 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4035 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4036 talloc_free(tmp_ctx);
4040 talloc_free(tmp_ctx);
4045 * set flags of a node in the nodemap
4047 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4054 struct ctdb_node_flag_change c;
4061 if (sscanf(argv[0], "%d", &node) != 1) {
4062 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4066 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4067 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4074 c.new_flags = flags;
4076 data.dsize = sizeof(c);
4077 data.dptr = (unsigned char *)&c;
4079 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4080 data, NULL, NULL, &status, NULL, NULL);
4081 if (ret != 0 || status != 0) {
4082 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4091 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4097 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4098 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4099 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4100 if (ret != 0 || res != 0) {
4101 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4102 talloc_free(tmp_ctx);
4105 write(1, data.dptr, data.dsize);
4106 talloc_free(tmp_ctx);
4111 handler for memory dumps
4113 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4114 TDB_DATA data, void *private_data)
4116 write(1, data.dptr, data.dsize);
4121 dump memory usage on the recovery daemon
4123 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4127 struct rd_memdump_reply rd;
4129 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4131 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4134 rd.srvid = getpid();
4136 /* register a message port for receiveing the reply so that we
4137 can receive the reply
4139 ctdb_client_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4142 data.dptr = (uint8_t *)&rd;
4143 data.dsize = sizeof(rd);
4145 ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4147 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4151 /* this loop will terminate when we have received the reply */
4153 event_loop_once(ctdb->ev);
4160 send a message to a srvid
4162 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4164 unsigned long srvid;
4172 srvid = strtoul(argv[0], NULL, 0);
4174 data.dptr = (uint8_t *)discard_const(argv[1]);
4175 data.dsize= strlen(argv[1]);
4177 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4179 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4187 handler for msglisten
4189 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4190 TDB_DATA data, void *private_data)
4194 printf("Message received: ");
4195 for (i=0;i<data.dsize;i++) {
4196 printf("%c", data.dptr[i]);
4202 listen for messages on a messageport
4204 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4210 /* register a message port and listen for messages
4212 ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4213 printf("Listening for messages on srvid:%d\n", (int)srvid);
4216 event_loop_once(ctdb->ev);
4223 list all nodes in the cluster
4224 if the daemon is running, we read the data from the daemon.
4225 if the daemon is not running we parse the nodes file directly
4227 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4230 struct ctdb_node_map *nodemap=NULL;
4233 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4235 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4239 for(i=0;i<nodemap->num;i++){
4240 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4243 if (options.machinereadable){
4244 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4246 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4250 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4251 struct pnn_node *pnn_nodes;
4252 struct pnn_node *pnn_node;
4254 pnn_nodes = read_nodes_file(mem_ctx);
4255 if (pnn_nodes == NULL) {
4256 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4257 talloc_free(mem_ctx);
4261 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4262 ctdb_sock_addr addr;
4264 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4265 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4266 talloc_free(mem_ctx);
4270 if (options.machinereadable){
4271 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4273 printf("%s\n", pnn_node->addr);
4276 talloc_free(mem_ctx);
4283 reload the nodes file on the local node
4285 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4289 struct ctdb_node_map *nodemap=NULL;
4291 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4293 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4297 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4299 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4303 /* reload the nodes file on all remote nodes */
4304 for (i=0;i<nodemap->num;i++) {
4305 if (nodemap->nodes[i].pnn == mypnn) {
4308 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4309 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4310 nodemap->nodes[i].pnn);
4312 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4316 /* reload the nodes file on the local node */
4317 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4318 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4320 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4323 /* initiate a recovery */
4324 control_recover(ctdb, argc, argv);
4330 static const struct {
4332 int (*fn)(struct ctdb_context *, int, const char **);
4334 bool without_daemon; /* can be run without daemon running ? */
4337 } ctdb_commands[] = {
4339 { "version", control_version, true, false, "show version of ctdb" },
4341 { "status", control_status, true, false, "show node status" },
4342 { "uptime", control_uptime, true, false, "show node uptime" },
4343 { "ping", control_ping, true, false, "ping all nodes" },
4344 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4345 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4346 { "listvars", control_listvars, true, false, "list tunable variables"},
4347 { "statistics", control_statistics, false, false, "show statistics" },
4348 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4349 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4350 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4351 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4352 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4353 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4354 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4355 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4356 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4357 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4358 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4359 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4360 { "lvs", control_lvs, true, false, "show lvs configuration" },
4361 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4362 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4363 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4364 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4365 { "getdebug", control_getdebug, true, false, "get debug level" },
4366 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4367 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4368 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4369 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4370 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4371 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4372 { "disable", control_disable, true, false, "disable a nodes public IP" },
4373 { "enable", control_enable, true, false, "enable a nodes public IP" },
4374 { "stop", control_stop, true, false, "stop a node" },
4375 { "continue", control_continue, true, false, "re-start a stopped node" },
4376 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4377 { "unban", control_unban, true, false, "unban a node" },
4378 { "showban", control_showban, true, false, "show ban information"},
4379 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4380 { "recover", control_recover, true, false, "force recovery" },
4381 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4382 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4383 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4384 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4385 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4386 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4387 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4388 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
4390 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4391 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4392 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4393 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4394 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4395 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4396 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4397 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4398 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4399 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4400 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4401 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4402 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4403 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file> [dbname]"},
4404 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4405 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4406 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4407 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4408 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4409 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4410 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4411 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4412 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4413 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4414 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4415 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4416 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4417 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4418 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4419 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4420 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4421 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4422 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4428 static void usage(void)
4432 "Usage: ctdb [options] <control>\n" \
4434 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4435 " -Y generate machinereadable output\n"
4436 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4437 printf("Controls:\n");
4438 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4439 printf(" %-15s %-27s %s\n",
4440 ctdb_commands[i].name,
4441 ctdb_commands[i].args?ctdb_commands[i].args:"",
4442 ctdb_commands[i].msg);
4448 static void ctdb_alarm(int sig)
4450 printf("Maximum runtime exceeded - exiting\n");
4457 int main(int argc, const char *argv[])
4459 struct ctdb_context *ctdb;
4460 char *nodestring = NULL;
4461 struct poptOption popt_options[] = {
4464 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4465 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4466 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4467 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4471 const char **extra_argv;
4475 struct event_context *ev;
4476 const char *control;
4480 /* set some defaults */
4481 options.maxruntime = 0;
4482 options.timelimit = 3;
4483 options.pnn = CTDB_CURRENT_NODE;
4485 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4487 while ((opt = poptGetNextOpt(pc)) != -1) {
4490 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4491 poptBadOption(pc, 0), poptStrerror(opt)));
4496 /* setup the remaining options for the main program to use */
4497 extra_argv = poptGetArgs(pc);
4500 while (extra_argv[extra_argc]) extra_argc++;
4503 if (extra_argc < 1) {
4507 if (options.maxruntime == 0) {
4508 const char *ctdb_timeout;
4509 ctdb_timeout = getenv("CTDB_TIMEOUT");
4510 if (ctdb_timeout != NULL) {
4511 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4513 /* default timeout is 120 seconds */
4514 options.maxruntime = 120;
4518 signal(SIGALRM, ctdb_alarm);
4519 alarm(options.maxruntime);
4521 /* setup the node number to contact */
4522 if (nodestring != NULL) {
4523 if (strcmp(nodestring, "all") == 0) {
4524 options.pnn = CTDB_BROADCAST_ALL;
4526 options.pnn = strtoul(nodestring, NULL, 0);
4530 control = extra_argv[0];
4532 ev = event_context_init(NULL);
4534 DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
4538 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4539 if (strcmp(control, ctdb_commands[i].name) == 0) {
4542 if (ctdb_commands[i].without_daemon == true) {
4546 /* initialise ctdb */
4547 ctdb = ctdb_cmdline_client(ev);
4549 if (ctdb_commands[i].without_daemon == false) {
4550 const char *socket_name;
4553 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4557 /* initialize a libctdb connection as well */
4558 socket_name = ctdb_get_socketname(ctdb);
4559 ctdb_connection = ctdb_connect(socket_name,
4560 ctdb_log_file, stderr);
4561 if (ctdb_connection == NULL) {
4562 fprintf(stderr, "Failed to connect to daemon from libctdb\n");
4566 /* verify the node exists */
4569 if (options.pnn == CTDB_CURRENT_NODE) {
4571 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4579 if (ctdb_commands[i].auto_all &&
4580 options.pnn == CTDB_BROADCAST_ALL) {
4585 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4586 CTDB_NO_MEMORY(ctdb, nodes);
4588 for (j=0;j<num_nodes;j++) {
4589 options.pnn = nodes[j];
4590 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4594 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4600 if (i == ARRAY_SIZE(ctdb_commands)) {
4601 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));