4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "lib/tevent/tevent.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "system/locale.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_client.h"
31 #include "../include/ctdb_private.h"
32 #include "../common/rb_tree.h"
35 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
36 #define ERR_NONODE 21 /* node does not exist */
37 #define ERR_DISNODE 22 /* node is disconnected */
39 struct ctdb_connection *ctdb_connection;
41 static void usage(void);
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 ban 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_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
3284 priority = strtol(argv[0], NULL, 0);
3288 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
3290 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3292 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
3300 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3306 priority = strtol(argv[0], NULL, 0);
3310 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3312 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3314 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3321 attach to a database
3323 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3325 const char *db_name;
3326 struct ctdb_db_context *ctdb_db;
3333 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3334 if (ctdb_db == NULL) {
3335 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3345 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3347 struct ctdb_db_priority db_prio;
3354 db_prio.db_id = strtoul(argv[0], NULL, 0);
3355 db_prio.priority = strtoul(argv[1], NULL, 0);
3357 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3359 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3369 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3371 uint32_t db_id, priority;
3378 db_id = strtoul(argv[0], NULL, 0);
3380 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3382 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3386 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3392 run an eventscript on a node
3394 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3400 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3403 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3407 data.dptr = (unsigned char *)discard_const(argv[0]);
3408 data.dsize = strlen((char *)data.dptr) + 1;
3410 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3412 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3413 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3414 if (ret != 0 || res != 0) {
3415 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3416 talloc_free(tmp_ctx);
3419 talloc_free(tmp_ctx);
3423 #define DB_VERSION 1
3424 #define MAX_DB_NAME 64
3425 struct db_file_header {
3426 unsigned long version;
3428 unsigned long persistent;
3430 const char name[MAX_DB_NAME];
3433 struct backup_data {
3434 struct ctdb_marshall_buffer *records;
3437 bool traverse_error;
3440 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3442 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3443 struct ctdb_rec_data *rec;
3445 /* add the record */
3446 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3448 bd->traverse_error = true;
3449 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3452 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3453 if (bd->records == NULL) {
3454 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3455 bd->traverse_error = true;
3458 bd->records->count++;
3459 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3460 bd->len += rec->length;
3468 * backup a database to a file
3470 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3473 struct ctdb_dbid_map *dbmap=NULL;
3474 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3475 struct db_file_header dbhdr;
3476 struct ctdb_db_context *ctdb_db;
3477 struct backup_data *bd;
3480 const char *reason = NULL;
3483 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3487 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3489 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3493 for(i=0;i<dbmap->num;i++){
3496 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3497 if(!strcmp(argv[0], name)){
3498 talloc_free(discard_const(name));
3501 talloc_free(discard_const(name));
3503 if (i == dbmap->num) {
3504 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3505 talloc_free(tmp_ctx);
3509 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3510 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3512 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3514 talloc_free(tmp_ctx);
3518 uint32_t allow_unhealthy = 0;
3520 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3521 "AllowUnhealthyDBRead",
3524 if (allow_unhealthy != 1) {
3525 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3528 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3530 talloc_free(tmp_ctx);
3534 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3536 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3537 "tunnable AllowUnhealthyDBRead = %u\n",
3541 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3542 if (ctdb_db == NULL) {
3543 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3544 talloc_free(tmp_ctx);
3549 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3551 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3552 talloc_free(tmp_ctx);
3557 bd = talloc_zero(tmp_ctx, struct backup_data);
3559 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3560 talloc_free(tmp_ctx);
3564 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3565 if (bd->records == NULL) {
3566 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3567 talloc_free(tmp_ctx);
3571 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3572 bd->records->db_id = ctdb_db->db_id;
3573 /* traverse the database collecting all records */
3574 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3575 bd->traverse_error) {
3576 DEBUG(DEBUG_ERR,("Traverse error\n"));
3577 talloc_free(tmp_ctx);
3581 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3584 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3586 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3587 talloc_free(tmp_ctx);
3591 dbhdr.version = DB_VERSION;
3592 dbhdr.timestamp = time(NULL);
3593 dbhdr.persistent = dbmap->dbs[i].persistent;
3594 dbhdr.size = bd->len;
3595 if (strlen(argv[0]) >= MAX_DB_NAME) {
3596 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3599 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3600 ret = write(fh, &dbhdr, sizeof(dbhdr));
3602 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3605 ret = write(fh, bd->records, bd->len);
3607 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3616 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3619 talloc_free(tmp_ctx);
3624 * restore a database from a file
3626 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3629 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3632 struct db_file_header dbhdr;
3633 struct ctdb_db_context *ctdb_db;
3634 struct ctdb_node_map *nodemap=NULL;
3635 struct ctdb_vnn_map *vnnmap=NULL;
3637 struct ctdb_control_wipe_database w;
3639 uint32_t generation;
3644 if (argc < 1 || argc > 2) {
3645 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3649 fh = open(argv[0], O_RDONLY);
3651 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3652 talloc_free(tmp_ctx);
3656 read(fh, &dbhdr, sizeof(dbhdr));
3657 if (dbhdr.version != DB_VERSION) {
3658 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3659 talloc_free(tmp_ctx);
3663 dbname = dbhdr.name;
3668 outdata.dsize = dbhdr.size;
3669 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3670 if (outdata.dptr == NULL) {
3671 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3673 talloc_free(tmp_ctx);
3676 read(fh, outdata.dptr, outdata.dsize);
3679 tm = localtime(&dbhdr.timestamp);
3680 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3681 printf("Restoring database '%s' from backup @ %s\n",
3685 ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3686 if (ctdb_db == NULL) {
3687 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3688 talloc_free(tmp_ctx);
3692 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3694 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3695 talloc_free(tmp_ctx);
3700 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3702 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3703 talloc_free(tmp_ctx);
3707 /* freeze all nodes */
3708 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3709 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3710 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3716 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3717 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3718 talloc_free(tmp_ctx);
3723 generation = vnnmap->generation;
3724 data.dptr = (void *)&generation;
3725 data.dsize = sizeof(generation);
3727 /* start a cluster wide transaction */
3728 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3729 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3731 TIMELIMIT(), false, data,
3734 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3739 w.db_id = ctdb_db->db_id;
3740 w.transaction_id = generation;
3742 data.dptr = (void *)&w;
3743 data.dsize = sizeof(w);
3745 /* wipe all the remote databases. */
3746 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3747 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3749 TIMELIMIT(), false, data,
3752 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3753 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3754 talloc_free(tmp_ctx);
3758 /* push the database */
3759 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3760 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3762 TIMELIMIT(), false, outdata,
3765 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3766 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3767 talloc_free(tmp_ctx);
3771 data.dptr = (void *)&ctdb_db->db_id;
3772 data.dsize = sizeof(ctdb_db->db_id);
3774 /* mark the database as healthy */
3775 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3776 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3778 TIMELIMIT(), false, data,
3781 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3782 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3783 talloc_free(tmp_ctx);
3787 data.dptr = (void *)&generation;
3788 data.dsize = sizeof(generation);
3790 /* commit all the changes */
3791 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3793 TIMELIMIT(), false, data,
3796 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3797 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3798 talloc_free(tmp_ctx);
3803 /* thaw all nodes */
3804 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3805 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3811 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3812 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3813 talloc_free(tmp_ctx);
3818 talloc_free(tmp_ctx);
3823 * dump a database backup from a file
3825 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3827 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3829 struct db_file_header dbhdr;
3833 struct ctdb_rec_data *rec = NULL;
3834 struct ctdb_marshall_buffer *m;
3837 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3841 fh = open(argv[0], O_RDONLY);
3843 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3844 talloc_free(tmp_ctx);
3848 read(fh, &dbhdr, sizeof(dbhdr));
3849 if (dbhdr.version != DB_VERSION) {
3850 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3851 talloc_free(tmp_ctx);
3855 outdata.dsize = dbhdr.size;
3856 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3857 if (outdata.dptr == NULL) {
3858 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3860 talloc_free(tmp_ctx);
3863 read(fh, outdata.dptr, outdata.dsize);
3865 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3867 tm = localtime(&dbhdr.timestamp);
3868 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3869 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3870 dbhdr.name, m->db_id, tbuf);
3872 for (i=0; i < m->count; i++) {
3876 /* we do not want the header splitted, so we pass NULL*/
3877 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3880 ctdb_dumpdb_record(ctdb, key, data, stdout);
3883 printf("Dumped %d records\n", i);
3884 talloc_free(tmp_ctx);
3889 * wipe a database from a file
3891 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3895 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3897 struct ctdb_db_context *ctdb_db;
3898 struct ctdb_node_map *nodemap = NULL;
3899 struct ctdb_vnn_map *vnnmap = NULL;
3901 struct ctdb_control_wipe_database w;
3903 uint32_t generation;
3904 struct ctdb_dbid_map *dbmap = NULL;
3907 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3911 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3914 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3919 for(i=0;i<dbmap->num;i++){
3922 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3923 dbmap->dbs[i].dbid, tmp_ctx, &name);
3924 if(!strcmp(argv[0], name)){
3925 talloc_free(discard_const(name));
3928 talloc_free(discard_const(name));
3930 if (i == dbmap->num) {
3931 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3933 talloc_free(tmp_ctx);
3937 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3938 if (ctdb_db == NULL) {
3939 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3941 talloc_free(tmp_ctx);
3945 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3948 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3950 talloc_free(tmp_ctx);
3954 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3957 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3959 talloc_free(tmp_ctx);
3963 /* freeze all nodes */
3964 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3965 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3966 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3973 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3974 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3975 CTDB_RECOVERY_ACTIVE);
3976 talloc_free(tmp_ctx);
3981 generation = vnnmap->generation;
3982 data.dptr = (void *)&generation;
3983 data.dsize = sizeof(generation);
3985 /* start a cluster wide transaction */
3986 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3987 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3989 TIMELIMIT(), false, data,
3993 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3994 "transactions.\n"));
3998 w.db_id = ctdb_db->db_id;
3999 w.transaction_id = generation;
4001 data.dptr = (void *)&w;
4002 data.dsize = sizeof(w);
4004 /* wipe all the remote databases. */
4005 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4006 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
4008 TIMELIMIT(), false, data,
4011 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
4012 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4013 talloc_free(tmp_ctx);
4017 data.dptr = (void *)&ctdb_db->db_id;
4018 data.dsize = sizeof(ctdb_db->db_id);
4020 /* mark the database as healthy */
4021 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4022 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4024 TIMELIMIT(), false, data,
4027 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4028 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4029 talloc_free(tmp_ctx);
4033 data.dptr = (void *)&generation;
4034 data.dsize = sizeof(generation);
4036 /* commit all the changes */
4037 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4039 TIMELIMIT(), false, data,
4042 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4043 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4044 talloc_free(tmp_ctx);
4048 /* thaw all nodes */
4049 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4050 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4056 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4057 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4058 talloc_free(tmp_ctx);
4062 talloc_free(tmp_ctx);
4067 * set flags of a node in the nodemap
4069 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4076 struct ctdb_node_flag_change c;
4083 if (sscanf(argv[0], "%d", &node) != 1) {
4084 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4088 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4089 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4096 c.new_flags = flags;
4098 data.dsize = sizeof(c);
4099 data.dptr = (unsigned char *)&c;
4101 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4102 data, NULL, NULL, &status, NULL, NULL);
4103 if (ret != 0 || status != 0) {
4104 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4113 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4119 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4120 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4121 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4122 if (ret != 0 || res != 0) {
4123 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4124 talloc_free(tmp_ctx);
4127 write(1, data.dptr, data.dsize);
4128 talloc_free(tmp_ctx);
4133 handler for memory dumps
4135 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4136 TDB_DATA data, void *private_data)
4138 write(1, data.dptr, data.dsize);
4143 dump memory usage on the recovery daemon
4145 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4149 struct rd_memdump_reply rd;
4151 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4153 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4156 rd.srvid = getpid();
4158 /* register a message port for receiveing the reply so that we
4159 can receive the reply
4161 ctdb_client_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4164 data.dptr = (uint8_t *)&rd;
4165 data.dsize = sizeof(rd);
4167 ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4169 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4173 /* this loop will terminate when we have received the reply */
4175 event_loop_once(ctdb->ev);
4182 send a message to a srvid
4184 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4186 unsigned long srvid;
4194 srvid = strtoul(argv[0], NULL, 0);
4196 data.dptr = (uint8_t *)discard_const(argv[1]);
4197 data.dsize= strlen(argv[1]);
4199 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4201 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4209 handler for msglisten
4211 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4212 TDB_DATA data, void *private_data)
4216 printf("Message received: ");
4217 for (i=0;i<data.dsize;i++) {
4218 printf("%c", data.dptr[i]);
4224 listen for messages on a messageport
4226 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4232 /* register a message port and listen for messages
4234 ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4235 printf("Listening for messages on srvid:%d\n", (int)srvid);
4238 event_loop_once(ctdb->ev);
4245 list all nodes in the cluster
4246 if the daemon is running, we read the data from the daemon.
4247 if the daemon is not running we parse the nodes file directly
4249 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4252 struct ctdb_node_map *nodemap=NULL;
4255 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4257 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4261 for(i=0;i<nodemap->num;i++){
4262 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4265 if (options.machinereadable){
4266 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4268 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4272 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4273 struct pnn_node *pnn_nodes;
4274 struct pnn_node *pnn_node;
4276 pnn_nodes = read_nodes_file(mem_ctx);
4277 if (pnn_nodes == NULL) {
4278 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4279 talloc_free(mem_ctx);
4283 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4284 ctdb_sock_addr addr;
4286 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4287 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4288 talloc_free(mem_ctx);
4292 if (options.machinereadable){
4293 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4295 printf("%s\n", pnn_node->addr);
4298 talloc_free(mem_ctx);
4305 reload the nodes file on the local node
4307 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4311 struct ctdb_node_map *nodemap=NULL;
4313 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4315 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4319 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4321 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4325 /* reload the nodes file on all remote nodes */
4326 for (i=0;i<nodemap->num;i++) {
4327 if (nodemap->nodes[i].pnn == mypnn) {
4330 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4331 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4332 nodemap->nodes[i].pnn);
4334 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4338 /* reload the nodes file on the local node */
4339 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4340 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4342 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4345 /* initiate a recovery */
4346 control_recover(ctdb, argc, argv);
4352 static const struct {
4354 int (*fn)(struct ctdb_context *, int, const char **);
4356 bool without_daemon; /* can be run without daemon running ? */
4359 } ctdb_commands[] = {
4361 { "version", control_version, true, false, "show version of ctdb" },
4363 { "status", control_status, true, false, "show node status" },
4364 { "uptime", control_uptime, true, false, "show node uptime" },
4365 { "ping", control_ping, true, false, "ping all nodes" },
4366 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4367 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4368 { "listvars", control_listvars, true, false, "list tunable variables"},
4369 { "statistics", control_statistics, false, false, "show statistics" },
4370 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4371 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4372 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4373 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4374 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4375 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4376 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4377 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4378 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4379 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4380 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4381 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4382 { "lvs", control_lvs, true, false, "show lvs configuration" },
4383 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4384 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4385 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4386 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4387 { "getdebug", control_getdebug, true, false, "get debug level" },
4388 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4389 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4390 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4391 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4392 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4393 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4394 { "disable", control_disable, true, false, "disable a nodes public IP" },
4395 { "enable", control_enable, true, false, "enable a nodes public IP" },
4396 { "stop", control_stop, true, false, "stop a node" },
4397 { "continue", control_continue, true, false, "re-start a stopped node" },
4398 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4399 { "unban", control_unban, true, false, "unban a node" },
4400 { "showban", control_showban, true, false, "show ban information"},
4401 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4402 { "recover", control_recover, true, false, "force recovery" },
4403 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4404 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
4405 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4406 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4407 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4408 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4409 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4410 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
4412 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4413 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4414 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4415 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4416 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4417 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4418 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4419 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4420 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4421 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4422 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4423 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4424 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4425 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file> [dbname]"},
4426 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4427 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4428 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4429 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4430 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4431 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4432 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4433 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4434 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4435 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4436 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4437 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4438 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4439 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4440 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4441 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4442 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4443 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4449 static void usage(void)
4453 "Usage: ctdb [options] <control>\n" \
4455 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4456 " -Y generate machinereadable output\n"
4457 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4458 printf("Controls:\n");
4459 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4460 printf(" %-15s %-27s %s\n",
4461 ctdb_commands[i].name,
4462 ctdb_commands[i].args?ctdb_commands[i].args:"",
4463 ctdb_commands[i].msg);
4469 static void ctdb_alarm(int sig)
4471 printf("Maximum runtime exceeded - exiting\n");
4478 int main(int argc, const char *argv[])
4480 struct ctdb_context *ctdb;
4481 char *nodestring = NULL;
4482 struct poptOption popt_options[] = {
4485 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4486 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4487 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4488 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4492 const char **extra_argv;
4496 struct event_context *ev;
4497 const char *control;
4501 /* set some defaults */
4502 options.maxruntime = 0;
4503 options.timelimit = 3;
4504 options.pnn = CTDB_CURRENT_NODE;
4506 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4508 while ((opt = poptGetNextOpt(pc)) != -1) {
4511 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4512 poptBadOption(pc, 0), poptStrerror(opt)));
4517 /* setup the remaining options for the main program to use */
4518 extra_argv = poptGetArgs(pc);
4521 while (extra_argv[extra_argc]) extra_argc++;
4524 if (extra_argc < 1) {
4528 if (options.maxruntime == 0) {
4529 const char *ctdb_timeout;
4530 ctdb_timeout = getenv("CTDB_TIMEOUT");
4531 if (ctdb_timeout != NULL) {
4532 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4534 /* default timeout is 120 seconds */
4535 options.maxruntime = 120;
4539 signal(SIGALRM, ctdb_alarm);
4540 alarm(options.maxruntime);
4542 /* setup the node number to contact */
4543 if (nodestring != NULL) {
4544 if (strcmp(nodestring, "all") == 0) {
4545 options.pnn = CTDB_BROADCAST_ALL;
4547 options.pnn = strtoul(nodestring, NULL, 0);
4551 control = extra_argv[0];
4553 ev = event_context_init(NULL);
4555 DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
4559 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4560 if (strcmp(control, ctdb_commands[i].name) == 0) {
4563 if (ctdb_commands[i].without_daemon == true) {
4567 /* initialise ctdb */
4568 ctdb = ctdb_cmdline_client(ev);
4570 if (ctdb_commands[i].without_daemon == false) {
4571 const char *socket_name;
4574 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4578 /* initialize a libctdb connection as well */
4579 socket_name = ctdb_get_socketname(ctdb);
4580 ctdb_connection = ctdb_connect(socket_name,
4581 ctdb_log_file, stderr);
4582 if (ctdb_connection == NULL) {
4583 fprintf(stderr, "Failed to connect to daemon from libctdb\n");
4587 /* verify the node exists */
4590 if (options.pnn == CTDB_CURRENT_NODE) {
4592 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4600 if (ctdb_commands[i].auto_all &&
4601 options.pnn == CTDB_BROADCAST_ALL) {
4606 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4607 CTDB_NO_MEMORY(ctdb, nodes);
4609 for (j=0;j<num_nodes;j++) {
4610 options.pnn = nodes[j];
4611 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4615 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4621 if (i == ARRAY_SIZE(ctdb_commands)) {
4622 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));