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 access node. Node is not operational.\n"));
106 check if a database exists
108 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
111 struct ctdb_dbid_map *dbmap=NULL;
113 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
115 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
119 for(i=0;i<dbmap->num;i++){
122 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
123 if (!strcmp(name, db_name)) {
132 see if a process exists
134 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
142 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
143 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
147 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
149 printf("%u:%u exists\n", pnn, pid);
151 printf("%u:%u does not exist\n", pnn, pid);
157 display statistics structure
159 static void show_statistics(struct ctdb_statistics *s)
161 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
163 const char *prefix=NULL;
165 int tmp, days, hours, minutes, seconds;
170 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
171 STATISTICS_FIELD(num_clients),
172 STATISTICS_FIELD(frozen),
173 STATISTICS_FIELD(recovering),
174 STATISTICS_FIELD(num_recoveries),
175 STATISTICS_FIELD(client_packets_sent),
176 STATISTICS_FIELD(client_packets_recv),
177 STATISTICS_FIELD(node_packets_sent),
178 STATISTICS_FIELD(node_packets_recv),
179 STATISTICS_FIELD(keepalive_packets_sent),
180 STATISTICS_FIELD(keepalive_packets_recv),
181 STATISTICS_FIELD(node.req_call),
182 STATISTICS_FIELD(node.reply_call),
183 STATISTICS_FIELD(node.req_dmaster),
184 STATISTICS_FIELD(node.reply_dmaster),
185 STATISTICS_FIELD(node.reply_error),
186 STATISTICS_FIELD(node.req_message),
187 STATISTICS_FIELD(node.req_control),
188 STATISTICS_FIELD(node.reply_control),
189 STATISTICS_FIELD(client.req_call),
190 STATISTICS_FIELD(client.req_message),
191 STATISTICS_FIELD(client.req_control),
192 STATISTICS_FIELD(timeouts.call),
193 STATISTICS_FIELD(timeouts.control),
194 STATISTICS_FIELD(timeouts.traverse),
195 STATISTICS_FIELD(total_calls),
196 STATISTICS_FIELD(pending_calls),
197 STATISTICS_FIELD(lockwait_calls),
198 STATISTICS_FIELD(pending_lockwait_calls),
199 STATISTICS_FIELD(childwrite_calls),
200 STATISTICS_FIELD(pending_childwrite_calls),
201 STATISTICS_FIELD(memory_used),
202 STATISTICS_FIELD(max_hop_count),
204 tmp = s->statistics_current_time.tv_sec - s->statistics_start_time.tv_sec;
213 printf("CTDB version %u\n", CTDB_VERSION);
214 printf("Current time of statistics : %s", ctime(&s->statistics_current_time.tv_sec));
215 printf("Statistics collected since : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&s->statistics_start_time.tv_sec));
217 for (i=0;i<ARRAY_SIZE(fields);i++) {
218 if (strchr(fields[i].name, '.')) {
219 preflen = strcspn(fields[i].name, ".")+1;
220 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
221 prefix = fields[i].name;
222 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
227 printf(" %*s%-22s%*s%10u\n",
229 fields[i].name+preflen,
231 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
233 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
234 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
236 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
237 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
238 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
239 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
241 talloc_free(tmp_ctx);
245 display remote ctdb statistics combined from all nodes
247 static int control_statistics_all(struct ctdb_context *ctdb)
250 struct ctdb_statistics statistics;
254 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
255 CTDB_NO_MEMORY(ctdb, nodes);
257 ZERO_STRUCT(statistics);
259 for (i=0;i<num_nodes;i++) {
260 struct ctdb_statistics s1;
262 uint32_t *v1 = (uint32_t *)&s1;
263 uint32_t *v2 = (uint32_t *)&statistics;
265 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
266 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
268 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
271 for (j=0;j<num_ints;j++) {
274 statistics.max_hop_count =
275 MAX(statistics.max_hop_count, s1.max_hop_count);
276 statistics.max_call_latency =
277 MAX(statistics.max_call_latency, s1.max_call_latency);
278 statistics.max_lockwait_latency =
279 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
282 printf("Gathered statistics for %u nodes\n", num_nodes);
283 show_statistics(&statistics);
288 display remote ctdb statistics
290 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
293 struct ctdb_statistics statistics;
295 if (options.pnn == CTDB_BROADCAST_ALL) {
296 return control_statistics_all(ctdb);
299 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
301 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
304 show_statistics(&statistics);
310 reset remote ctdb statistics
312 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
316 ret = ctdb_statistics_reset(ctdb, options.pnn);
318 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
326 display uptime of remote node
328 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
331 struct ctdb_uptime *uptime = NULL;
332 int tmp, days, hours, minutes, seconds;
334 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
336 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
340 if (options.machinereadable){
341 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
342 printf(":%u:%u:%u:%lf\n",
343 (unsigned int)uptime->current_time.tv_sec,
344 (unsigned int)uptime->ctdbd_start_time.tv_sec,
345 (unsigned int)uptime->last_recovery_finished.tv_sec,
346 timeval_delta(&uptime->last_recovery_finished,
347 &uptime->last_recovery_started)
352 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
354 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
362 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
364 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
372 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
374 printf("Duration of last recovery/failover: %lf seconds\n",
375 timeval_delta(&uptime->last_recovery_finished,
376 &uptime->last_recovery_started));
382 show the PNN of the current node
384 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
389 ret = ctdb_getpnn(ctdb_connection, options.pnn, &mypnn);
391 DEBUG(DEBUG_ERR, ("Unable to get pnn from node."));
395 printf("PNN:%d\n", mypnn);
401 struct pnn_node *next;
406 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
408 const char *nodes_list;
412 struct pnn_node *pnn_nodes = NULL;
413 struct pnn_node *pnn_node;
414 struct pnn_node *tmp_node;
416 /* read the nodes file */
417 nodes_list = getenv("CTDB_NODES");
418 if (nodes_list == NULL) {
419 nodes_list = "/etc/ctdb/nodes";
421 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
425 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
428 for (i=0, pnn=0; i<nlines; i++) {
432 /* strip leading spaces */
433 while((*node == ' ') || (*node == '\t')) {
440 if (strcmp(node, "") == 0) {
443 pnn_node = talloc(mem_ctx, struct pnn_node);
444 pnn_node->pnn = pnn++;
445 pnn_node->addr = talloc_strdup(pnn_node, node);
446 pnn_node->next = pnn_nodes;
447 pnn_nodes = pnn_node;
450 /* swap them around so we return them in incrementing order */
451 pnn_node = pnn_nodes;
455 pnn_node = pnn_node->next;
457 tmp_node->next = pnn_nodes;
458 pnn_nodes = tmp_node;
465 show the PNN of the current node
466 discover the pnn by loading the nodes file and try to bind to all
467 addresses one at a time until the ip address is found.
469 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
471 TALLOC_CTX *mem_ctx = talloc_new(NULL);
472 struct pnn_node *pnn_nodes;
473 struct pnn_node *pnn_node;
475 pnn_nodes = read_nodes_file(mem_ctx);
476 if (pnn_nodes == NULL) {
477 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
478 talloc_free(mem_ctx);
482 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
485 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
486 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
487 talloc_free(mem_ctx);
491 if (ctdb_sys_have_ip(&addr)) {
492 printf("PNN:%d\n", pnn_node->pnn);
493 talloc_free(mem_ctx);
498 printf("Failed to detect which PNN this node is\n");
499 talloc_free(mem_ctx);
504 display remote ctdb status
506 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
509 struct ctdb_vnn_map *vnnmap=NULL;
510 struct ctdb_node_map *nodemap=NULL;
511 uint32_t recmode, recmaster;
514 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
519 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
521 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
525 if(options.machinereadable){
526 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:PartiallyOnline:\n");
527 for(i=0;i<nodemap->num;i++){
528 int partially_online = 0;
531 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
534 if (nodemap->nodes[i].flags == 0) {
535 struct ctdb_control_get_ifaces *ifaces;
537 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
538 nodemap->nodes[i].pnn,
541 for (j=0; j < ifaces->num; j++) {
542 if (ifaces->ifaces[j].link_state != 0) {
545 partially_online = 1;
551 printf(":%d:%s:%d:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
552 ctdb_addr_to_str(&nodemap->nodes[i].addr),
553 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
554 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
555 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
556 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
557 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
558 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE),
564 printf("Number of nodes:%d\n", nodemap->num);
565 for(i=0;i<nodemap->num;i++){
566 static const struct {
570 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
571 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
572 { NODE_FLAGS_BANNED, "BANNED" },
573 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
574 { NODE_FLAGS_DELETED, "DELETED" },
575 { NODE_FLAGS_STOPPED, "STOPPED" },
576 { NODE_FLAGS_INACTIVE, "INACTIVE" },
578 char *flags_str = NULL;
581 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
584 if (nodemap->nodes[i].flags == 0) {
585 struct ctdb_control_get_ifaces *ifaces;
587 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
588 nodemap->nodes[i].pnn,
591 for (j=0; j < ifaces->num; j++) {
592 if (ifaces->ifaces[j].link_state != 0) {
595 flags_str = talloc_strdup(ctdb, "PARTIALLYONLINE");
601 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
602 if (nodemap->nodes[i].flags & flag_names[j].flag) {
603 if (flags_str == NULL) {
604 flags_str = talloc_strdup(ctdb, flag_names[j].name);
606 flags_str = talloc_asprintf_append(flags_str, "|%s",
609 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
612 if (flags_str == NULL) {
613 flags_str = talloc_strdup(ctdb, "OK");
614 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
616 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
617 ctdb_addr_to_str(&nodemap->nodes[i].addr),
619 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
620 talloc_free(flags_str);
623 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
625 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
628 if (vnnmap->generation == INVALID_GENERATION) {
629 printf("Generation:INVALID\n");
631 printf("Generation:%d\n",vnnmap->generation);
633 printf("Size:%d\n",vnnmap->size);
634 for(i=0;i<vnnmap->size;i++){
635 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
638 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
640 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
643 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
645 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
647 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
650 printf("Recovery master:%d\n",recmaster);
657 struct natgw_node *next;
662 display the list of nodes belonging to this natgw configuration
664 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
667 const char *natgw_list;
670 struct natgw_node *natgw_nodes = NULL;
671 struct natgw_node *natgw_node;
672 struct ctdb_node_map *nodemap=NULL;
675 /* read the natgw nodes file into a linked list */
676 natgw_list = getenv("NATGW_NODES");
677 if (natgw_list == NULL) {
678 natgw_list = "/etc/ctdb/natgw_nodes";
680 lines = file_lines_load(natgw_list, &nlines, ctdb);
682 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
685 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
688 for (i=0;i<nlines;i++) {
692 /* strip leading spaces */
693 while((*node == ' ') || (*node == '\t')) {
699 if (strcmp(node, "") == 0) {
702 natgw_node = talloc(ctdb, struct natgw_node);
703 natgw_node->addr = talloc_strdup(natgw_node, node);
704 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
705 natgw_node->next = natgw_nodes;
706 natgw_nodes = natgw_node;
709 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
711 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
716 while(i<nodemap->num) {
717 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
718 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
723 /* this node was not in the natgw so we just remove it from
726 if ((natgw_node == NULL)
727 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
730 for (j=i+1; j<nodemap->num; j++) {
731 nodemap->nodes[j-1] = nodemap->nodes[j];
740 /* pick a node to be natgwmaster
741 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
743 for(i=0;i<nodemap->num;i++){
744 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
745 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
749 /* we couldnt find any healthy node, try unhealthy ones */
750 if (i == nodemap->num) {
751 for(i=0;i<nodemap->num;i++){
752 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
753 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
758 /* unless all nodes are STOPPED, when we pick one anyway */
759 if (i == nodemap->num) {
760 for(i=0;i<nodemap->num;i++){
761 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
762 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
766 /* or if we still can not find any */
767 if (i == nodemap->num) {
768 printf("-1 0.0.0.0\n");
772 /* print the pruned list of nodes belonging to this natgw list */
773 for(i=0;i<nodemap->num;i++){
774 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
777 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
778 ctdb_addr_to_str(&nodemap->nodes[i].addr),
779 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
780 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
781 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
782 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
783 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
790 display the status of the scripts for monitoring (or other events)
792 static int control_one_scriptstatus(struct ctdb_context *ctdb,
793 enum ctdb_eventscript_call type)
795 struct ctdb_scripts_wire *script_status;
798 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
800 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
804 if (script_status == NULL) {
805 if (!options.machinereadable) {
806 printf("%s cycle never run\n",
807 ctdb_eventscript_call_names[type]);
812 if (!options.machinereadable) {
813 printf("%d scripts were executed last %s cycle\n",
814 script_status->num_scripts,
815 ctdb_eventscript_call_names[type]);
817 for (i=0; i<script_status->num_scripts; i++) {
818 const char *status = NULL;
820 switch (script_status->scripts[i].status) {
831 if (script_status->scripts[i].status > 0)
835 if (options.machinereadable) {
836 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
837 ctdb_eventscript_call_names[type],
838 script_status->scripts[i].name,
839 script_status->scripts[i].status,
841 (long)script_status->scripts[i].start.tv_sec,
842 (long)script_status->scripts[i].start.tv_usec,
843 (long)script_status->scripts[i].finished.tv_sec,
844 (long)script_status->scripts[i].finished.tv_usec,
845 script_status->scripts[i].output);
849 printf("%-20s Status:%s ",
850 script_status->scripts[i].name, status);
852 /* Some other error, eg from stat. */
853 printf("%-20s Status:CANNOT RUN (%s)",
854 script_status->scripts[i].name,
855 strerror(-script_status->scripts[i].status));
857 if (script_status->scripts[i].status >= 0) {
858 printf("Duration:%.3lf ",
859 timeval_delta(&script_status->scripts[i].finished,
860 &script_status->scripts[i].start));
862 if (script_status->scripts[i].status != -ENOEXEC) {
864 ctime(&script_status->scripts[i].start.tv_sec));
865 if (script_status->scripts[i].status != 0) {
866 printf(" OUTPUT:%s\n",
867 script_status->scripts[i].output);
877 static int control_scriptstatus(struct ctdb_context *ctdb,
878 int argc, const char **argv)
881 enum ctdb_eventscript_call type, min, max;
885 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
890 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
894 for (type = 0; type < CTDB_EVENT_MAX; type++) {
895 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
901 if (type == CTDB_EVENT_MAX) {
902 if (strcmp(arg, "all") == 0) {
904 max = CTDB_EVENT_MAX;
906 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
911 if (options.machinereadable) {
912 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
915 for (type = min; type < max; type++) {
916 ret = control_one_scriptstatus(ctdb, type);
926 enable an eventscript
928 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
936 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
938 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
946 disable an eventscript
948 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
956 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
958 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
966 display the pnn of the recovery master
968 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
973 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
975 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
978 printf("%d\n",recmaster);
984 add a tickle to a public address
986 static int control_add_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
988 struct ctdb_tcp_connection t;
996 if (parse_ip_port(argv[0], &t.src_addr) == 0) {
997 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1000 if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
1001 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
1005 data.dptr = (uint8_t *)&t;
1006 data.dsize = sizeof(t);
1008 /* tell all nodes about this tcp connection */
1009 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE,
1010 0, data, ctdb, NULL, NULL, NULL, NULL);
1012 DEBUG(DEBUG_ERR,("Failed to add tickle\n"));
1021 delete a tickle from a node
1023 static int control_del_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
1025 struct ctdb_tcp_connection t;
1033 if (parse_ip_port(argv[0], &t.src_addr) == 0) {
1034 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1037 if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
1038 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
1042 data.dptr = (uint8_t *)&t;
1043 data.dsize = sizeof(t);
1045 /* tell all nodes about this tcp connection */
1046 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_TCP_REMOVE,
1047 0, data, ctdb, NULL, NULL, NULL, NULL);
1049 DEBUG(DEBUG_ERR,("Failed to remove tickle\n"));
1058 get a list of all tickles for this pnn
1060 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
1062 struct ctdb_control_tcp_tickle_list *list;
1063 ctdb_sock_addr addr;
1070 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1071 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1075 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
1077 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
1081 if (options.machinereadable){
1082 printf(":source ip:port:destination ip:port:\n");
1083 for (i=0;i<list->tickles.num;i++) {
1084 printf(":%s:%u", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1085 printf(":%s:%u:\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
1088 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
1089 printf("Num tickles:%u\n", list->tickles.num);
1090 for (i=0;i<list->tickles.num;i++) {
1091 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1092 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));
1102 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1104 struct ctdb_all_public_ips *ips;
1105 struct ctdb_public_ip ip;
1108 uint32_t disable_time;
1110 struct ctdb_node_map *nodemap=NULL;
1111 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1114 data.dptr = (uint8_t*)&disable_time;
1115 data.dsize = sizeof(disable_time);
1116 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1118 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1124 /* read the public ip list from the node */
1125 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1127 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1128 talloc_free(tmp_ctx);
1132 for (i=0;i<ips->num;i++) {
1133 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1138 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1139 pnn, ctdb_addr_to_str(addr)));
1140 talloc_free(tmp_ctx);
1147 data.dptr = (uint8_t *)&ip;
1148 data.dsize = sizeof(ip);
1150 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1152 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1153 talloc_free(tmp_ctx);
1157 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1158 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1165 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1166 talloc_free(tmp_ctx);
1170 ret = ctdb_ctrl_takeover_ip(ctdb, LONGTIMELIMIT(), pnn, &ip);
1172 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1173 talloc_free(tmp_ctx);
1177 /* update the recovery daemon so it now knows to expect the new
1178 node assignment for this ip.
1180 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECD_UPDATE_IP, data);
1182 DEBUG(DEBUG_ERR,("Failed to send message to update the ip on the recovery master.\n"));
1186 talloc_free(tmp_ctx);
1191 move/failover an ip address to a specific node
1193 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1196 ctdb_sock_addr addr;
1203 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1204 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1209 if (sscanf(argv[1], "%u", &pnn) != 1) {
1210 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1214 if (move_ip(ctdb, &addr, pnn) != 0) {
1215 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1222 void getips_store_callback(void *param, void *data)
1224 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1225 struct ctdb_all_public_ips *ips = param;
1229 ips->ips[i].pnn = node_ip->pnn;
1230 ips->ips[i].addr = node_ip->addr;
1233 void getips_count_callback(void *param, void *data)
1235 uint32_t *count = param;
1241 static uint32_t *ip_key(ctdb_sock_addr *ip)
1243 static uint32_t key[IP_KEYLEN];
1245 bzero(key, sizeof(key));
1247 switch (ip->sa.sa_family) {
1249 key[0] = ip->ip.sin_addr.s_addr;
1252 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1253 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1254 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1255 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1258 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1265 static void *add_ip_callback(void *parm, void *data)
1271 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1273 struct ctdb_all_public_ips *tmp_ips;
1274 struct ctdb_node_map *nodemap=NULL;
1275 trbt_tree_t *ip_tree;
1279 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1281 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1285 ip_tree = trbt_create(tmp_ctx, 0);
1287 for(i=0;i<nodemap->num;i++){
1288 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1291 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1295 /* read the public ip list from this node */
1296 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1298 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1302 for (j=0; j<tmp_ips->num;j++) {
1303 struct ctdb_public_ip *node_ip;
1305 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1306 node_ip->pnn = tmp_ips->ips[j].pnn;
1307 node_ip->addr = tmp_ips->ips[j].addr;
1309 trbt_insertarray32_callback(ip_tree,
1310 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1314 talloc_free(tmp_ips);
1319 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1321 len = offsetof(struct ctdb_all_public_ips, ips) +
1322 count*sizeof(struct ctdb_public_ip);
1323 tmp_ips = talloc_zero_size(tmp_ctx, len);
1324 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1333 * scans all other nodes and returns a pnn for another node that can host this
1337 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1339 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1340 struct ctdb_all_public_ips *ips;
1341 struct ctdb_node_map *nodemap=NULL;
1344 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1346 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1347 talloc_free(tmp_ctx);
1351 for(i=0;i<nodemap->num;i++){
1352 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1355 if (nodemap->nodes[i].pnn == options.pnn) {
1359 /* read the public ip list from this node */
1360 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1362 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1366 for (j=0;j<ips->num;j++) {
1367 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1368 talloc_free(tmp_ctx);
1369 return nodemap->nodes[i].pnn;
1375 talloc_free(tmp_ctx);
1380 add a public ip address to a node
1382 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1388 ctdb_sock_addr addr;
1389 struct ctdb_control_ip_iface *pub;
1390 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1391 struct ctdb_all_public_ips *ips;
1395 talloc_free(tmp_ctx);
1399 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1400 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1401 talloc_free(tmp_ctx);
1405 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1407 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1408 talloc_free(tmp_ctx);
1413 /* check if some other node is already serving this ip, if not,
1416 for (i=0;i<ips->num;i++) {
1417 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1422 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1423 pub = talloc_size(tmp_ctx, len);
1424 CTDB_NO_MEMORY(ctdb, pub);
1428 pub->len = strlen(argv[1])+1;
1429 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1431 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1433 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1434 talloc_free(tmp_ctx);
1438 if (i == ips->num) {
1439 /* no one has this ip so we claim it */
1442 pnn = ips->ips[i].pnn;
1445 if (move_ip(ctdb, &addr, pnn) != 0) {
1446 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1450 talloc_free(tmp_ctx);
1454 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1456 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1458 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1459 struct ctdb_node_map *nodemap=NULL;
1460 struct ctdb_all_public_ips *ips;
1463 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1465 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1469 /* remove it from the nodes that are not hosting the ip currently */
1470 for(i=0;i<nodemap->num;i++){
1471 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1474 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1475 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1479 for (j=0;j<ips->num;j++) {
1480 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1488 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1492 options.pnn = nodemap->nodes[i].pnn;
1493 control_delip(ctdb, argc, argv);
1497 /* remove it from every node (also the one hosting it) */
1498 for(i=0;i<nodemap->num;i++){
1499 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1502 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1503 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1507 for (j=0;j<ips->num;j++) {
1508 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1516 options.pnn = nodemap->nodes[i].pnn;
1517 control_delip(ctdb, argc, argv);
1520 talloc_free(tmp_ctx);
1525 delete a public ip address from a node
1527 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1530 ctdb_sock_addr addr;
1531 struct ctdb_control_ip_iface pub;
1532 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1533 struct ctdb_all_public_ips *ips;
1536 talloc_free(tmp_ctx);
1540 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1541 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1545 if (options.pnn == CTDB_BROADCAST_ALL) {
1546 return control_delip_all(ctdb, argc, argv, &addr);
1553 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1555 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1556 talloc_free(tmp_ctx);
1560 for (i=0;i<ips->num;i++) {
1561 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1567 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1568 ctdb_addr_to_str(&addr)));
1569 talloc_free(tmp_ctx);
1573 if (ips->ips[i].pnn == options.pnn) {
1574 ret = find_other_host_for_public_ip(ctdb, &addr);
1576 if (move_ip(ctdb, &addr, ret) != 0) {
1577 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1583 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1585 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1586 talloc_free(tmp_ctx);
1590 talloc_free(tmp_ctx);
1595 kill a tcp connection
1597 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1600 struct ctdb_control_killtcp killtcp;
1606 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1607 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1611 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1612 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1616 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1618 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1629 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1632 ctdb_sock_addr addr;
1638 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1639 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1643 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1645 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1653 register a server id
1655 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1658 struct ctdb_server_id server_id;
1664 server_id.pnn = strtoul(argv[0], NULL, 0);
1665 server_id.type = strtoul(argv[1], NULL, 0);
1666 server_id.server_id = strtoul(argv[2], NULL, 0);
1668 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1670 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1673 DEBUG(DEBUG_ERR,("Srvid registered. Sleeping for 999 seconds\n"));
1679 unregister a server id
1681 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1684 struct ctdb_server_id server_id;
1690 server_id.pnn = strtoul(argv[0], NULL, 0);
1691 server_id.type = strtoul(argv[1], NULL, 0);
1692 server_id.server_id = strtoul(argv[2], NULL, 0);
1694 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1696 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1703 check if a server id exists
1705 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1709 struct ctdb_server_id server_id;
1715 server_id.pnn = strtoul(argv[0], NULL, 0);
1716 server_id.type = strtoul(argv[1], NULL, 0);
1717 server_id.server_id = strtoul(argv[2], NULL, 0);
1719 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1721 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1726 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1728 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1734 get a list of all server ids that are registered on a node
1736 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1739 struct ctdb_server_id_list *server_ids;
1741 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1743 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1747 for (i=0; i<server_ids->num; i++) {
1748 printf("Server id %d:%d:%d\n",
1749 server_ids->server_ids[i].pnn,
1750 server_ids->server_ids[i].type,
1751 server_ids->server_ids[i].server_id);
1758 send a tcp tickle ack
1760 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1763 ctdb_sock_addr src, dst;
1769 if (!parse_ip_port(argv[0], &src)) {
1770 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1774 if (!parse_ip_port(argv[1], &dst)) {
1775 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1779 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1783 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1790 display public ip status
1792 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1795 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1796 struct ctdb_all_public_ips *ips;
1798 if (options.pnn == CTDB_BROADCAST_ALL) {
1799 /* read the list of public ips from all nodes */
1800 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1802 /* read the public ip list from this node */
1803 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1806 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1807 talloc_free(tmp_ctx);
1811 if (options.machinereadable){
1812 printf(":Public IP:Node:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1814 if (options.pnn == CTDB_BROADCAST_ALL) {
1815 printf("Public IPs on ALL nodes\n");
1817 printf("Public IPs on node %u\n", options.pnn);
1821 for (i=1;i<=ips->num;i++) {
1822 struct ctdb_control_public_ip_info *info = NULL;
1824 char *aciface = NULL;
1825 char *avifaces = NULL;
1826 char *cifaces = NULL;
1828 if (options.pnn == CTDB_BROADCAST_ALL) {
1829 pnn = ips->ips[ips->num-i].pnn;
1835 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1836 &ips->ips[ips->num-i].addr, &info);
1843 for (j=0; j < info->num; j++) {
1844 if (cifaces == NULL) {
1845 cifaces = talloc_strdup(info,
1846 info->ifaces[j].name);
1848 cifaces = talloc_asprintf_append(cifaces,
1850 info->ifaces[j].name);
1853 if (info->active_idx == j) {
1854 aciface = info->ifaces[j].name;
1857 if (info->ifaces[j].link_state == 0) {
1861 if (avifaces == NULL) {
1862 avifaces = talloc_strdup(info, info->ifaces[j].name);
1864 avifaces = talloc_asprintf_append(avifaces,
1866 info->ifaces[j].name);
1871 if (options.machinereadable){
1872 printf(":%s:%d:%s:%s:%s:\n",
1873 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1874 ips->ips[ips->num-i].pnn,
1876 avifaces?avifaces:"",
1877 cifaces?cifaces:"");
1879 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1880 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1881 ips->ips[ips->num-i].pnn,
1883 avifaces?avifaces:"",
1884 cifaces?cifaces:"");
1889 talloc_free(tmp_ctx);
1896 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1899 ctdb_sock_addr addr;
1900 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1901 struct ctdb_control_public_ip_info *info;
1904 talloc_free(tmp_ctx);
1908 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1909 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1913 /* read the public ip info from this node */
1914 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1915 tmp_ctx, &addr, &info);
1917 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1918 argv[0], options.pnn));
1919 talloc_free(tmp_ctx);
1923 printf("Public IP[%s] info on node %u\n",
1924 ctdb_addr_to_str(&info->ip.addr),
1927 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1928 ctdb_addr_to_str(&info->ip.addr),
1929 info->ip.pnn, info->num);
1931 for (i=0; i<info->num; i++) {
1932 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1934 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1935 i+1, info->ifaces[i].name,
1936 info->ifaces[i].link_state?"up":"down",
1937 (unsigned int)info->ifaces[i].references,
1938 (i==info->active_idx)?" (active)":"");
1941 talloc_free(tmp_ctx);
1946 display interfaces status
1948 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1951 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1952 struct ctdb_control_get_ifaces *ifaces;
1954 /* read the public ip list from this node */
1955 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1958 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1960 talloc_free(tmp_ctx);
1964 if (options.machinereadable){
1965 printf(":Name:LinkStatus:References:\n");
1967 printf("Interfaces on node %u\n", options.pnn);
1970 for (i=0; i<ifaces->num; i++) {
1971 if (options.machinereadable){
1972 printf(":%s:%s:%u\n",
1973 ifaces->ifaces[i].name,
1974 ifaces->ifaces[i].link_state?"1":"0",
1975 (unsigned int)ifaces->ifaces[i].references);
1977 printf("name:%s link:%s references:%u\n",
1978 ifaces->ifaces[i].name,
1979 ifaces->ifaces[i].link_state?"up":"down",
1980 (unsigned int)ifaces->ifaces[i].references);
1984 talloc_free(tmp_ctx);
1990 set link status of an interface
1992 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
1995 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1996 struct ctdb_control_iface_info info;
2004 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
2005 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
2007 talloc_free(tmp_ctx);
2010 strcpy(info.name, argv[0]);
2012 if (strcmp(argv[1], "up") == 0) {
2013 info.link_state = 1;
2014 } else if (strcmp(argv[1], "down") == 0) {
2015 info.link_state = 0;
2017 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
2019 talloc_free(tmp_ctx);
2023 /* read the public ip list from this node */
2024 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
2027 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
2028 argv[0], options.pnn));
2029 talloc_free(tmp_ctx);
2033 talloc_free(tmp_ctx);
2038 display pid of a ctdb daemon
2040 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
2045 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
2047 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
2050 printf("Pid:%d\n", pid);
2055 static uint32_t ipreallocate_finished;
2058 handler for receiving the response to ipreallocate
2060 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
2061 TDB_DATA data, void *private_data)
2063 ipreallocate_finished = 1;
2066 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
2068 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
2070 event_add_timed(ctdb->ev, ctdb,
2071 timeval_current_ofs(1, 0),
2072 ctdb_every_second, ctdb);
2076 ask the recovery daemon on the recovery master to perform a ip reallocation
2078 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
2082 struct takeover_run_reply rd;
2084 struct ctdb_node_map *nodemap=NULL;
2086 struct timeval tv = timeval_current();
2088 /* we need some events to trigger so we can timeout and restart
2091 event_add_timed(ctdb->ev, ctdb,
2092 timeval_current_ofs(1, 0),
2093 ctdb_every_second, ctdb);
2095 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2097 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
2100 rd.srvid = getpid();
2102 /* register a message port for receiveing the reply so that we
2103 can receive the reply
2105 ctdb_client_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
2107 data.dptr = (uint8_t *)&rd;
2108 data.dsize = sizeof(rd);
2111 /* check that there are valid nodes available */
2112 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2113 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2116 for (i=0; i<nodemap->num;i++) {
2117 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2121 if (i==nodemap->num) {
2122 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2127 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2129 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2133 /* verify the node exists */
2134 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2135 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2140 /* check tha there are nodes available that can act as a recmaster */
2141 for (i=0; i<nodemap->num; i++) {
2142 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2147 if (i == nodemap->num) {
2148 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2152 /* verify the recovery master is not STOPPED, nor BANNED */
2153 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2154 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2161 /* verify the recovery master is not STOPPED, nor BANNED */
2162 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2163 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2169 ipreallocate_finished = 0;
2170 ret = ctdb_client_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2172 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2176 tv = timeval_current();
2177 /* this loop will terminate when we have received the reply */
2178 while (timeval_elapsed(&tv) < 3.0) {
2179 event_loop_once(ctdb->ev);
2181 if (ipreallocate_finished == 1) {
2185 DEBUG(DEBUG_ERR,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2195 disable a remote node
2197 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2200 struct ctdb_node_map *nodemap=NULL;
2202 /* check if the node is already disabled */
2203 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2204 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2207 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2208 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2213 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2215 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2221 /* read the nodemap and verify the change took effect */
2222 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2223 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2227 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2228 ret = control_ipreallocate(ctdb, argc, argv);
2230 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2238 enable a disabled remote node
2240 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2244 struct ctdb_node_map *nodemap=NULL;
2247 /* check if the node is already enabled */
2248 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2249 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2252 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2253 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2258 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2260 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2266 /* read the nodemap and verify the change took effect */
2267 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2268 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2272 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2274 ret = control_ipreallocate(ctdb, argc, argv);
2276 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2286 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2289 struct ctdb_node_map *nodemap=NULL;
2292 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2294 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2299 /* read the nodemap and verify the change took effect */
2300 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2301 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2305 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2306 ret = control_ipreallocate(ctdb, argc, argv);
2308 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2316 restart a stopped remote node
2318 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2322 struct ctdb_node_map *nodemap=NULL;
2325 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2327 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2333 /* read the nodemap and verify the change took effect */
2334 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2335 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2339 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2340 ret = control_ipreallocate(ctdb, argc, argv);
2342 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2349 static uint32_t get_generation(struct ctdb_context *ctdb)
2351 struct ctdb_vnn_map *vnnmap=NULL;
2354 /* wait until the recmaster is not in recovery mode */
2356 uint32_t recmode, recmaster;
2358 if (vnnmap != NULL) {
2359 talloc_free(vnnmap);
2363 /* get the recmaster */
2364 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2366 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2370 /* get recovery mode */
2371 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2373 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2377 /* get the current generation number */
2378 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2380 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2384 if ((recmode == CTDB_RECOVERY_NORMAL)
2385 && (vnnmap->generation != 1)){
2386 return vnnmap->generation;
2393 ban a node from the cluster
2395 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2398 struct ctdb_node_map *nodemap=NULL;
2399 struct ctdb_ban_time bantime;
2405 /* verify the node exists */
2406 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2408 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2412 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2413 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2417 bantime.pnn = options.pnn;
2418 bantime.time = strtoul(argv[0], NULL, 0);
2420 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2422 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2426 ret = control_ipreallocate(ctdb, argc, argv);
2428 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2437 unban a node from the cluster
2439 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2442 struct ctdb_node_map *nodemap=NULL;
2443 struct ctdb_ban_time bantime;
2445 /* verify the node exists */
2446 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2448 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2452 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2453 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2457 bantime.pnn = options.pnn;
2460 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2462 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2466 ret = control_ipreallocate(ctdb, argc, argv);
2468 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2477 show ban information for a node
2479 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2482 struct ctdb_node_map *nodemap=NULL;
2483 struct ctdb_ban_time *bantime;
2485 /* verify the node exists */
2486 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2488 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2492 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2494 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2498 if (bantime->time == 0) {
2499 printf("Node %u is not banned\n", bantime->pnn);
2501 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2510 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2514 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2516 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2526 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2529 uint32_t generation, next_generation;
2531 /* record the current generation number */
2532 generation = get_generation(ctdb);
2534 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2536 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2540 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2542 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2546 /* wait until we are in a new generation */
2548 next_generation = get_generation(ctdb);
2549 if (next_generation != generation) {
2560 display monitoring mode of a remote node
2562 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2567 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2569 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2572 if (!options.machinereadable){
2573 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2576 printf(":%d:\n",monmode);
2583 display capabilities of a remote node
2585 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2587 uint32_t capabilities;
2590 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2592 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2596 if (!options.machinereadable){
2597 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2598 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2599 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2600 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2602 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2603 printf(":%d:%d:%d:%d:\n",
2604 !!(capabilities&CTDB_CAP_RECMASTER),
2605 !!(capabilities&CTDB_CAP_LMASTER),
2606 !!(capabilities&CTDB_CAP_LVS),
2607 !!(capabilities&CTDB_CAP_NATGW));
2613 display lvs configuration
2615 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2617 uint32_t *capabilities;
2618 struct ctdb_node_map *nodemap=NULL;
2620 int healthy_count = 0;
2622 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2624 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2628 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2629 CTDB_NO_MEMORY(ctdb, capabilities);
2631 /* collect capabilities for all connected nodes */
2632 for (i=0; i<nodemap->num; i++) {
2633 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2636 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2640 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2642 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2646 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2650 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2655 /* Print all LVS nodes */
2656 for (i=0; i<nodemap->num; i++) {
2657 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2660 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2663 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2667 if (healthy_count != 0) {
2668 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2673 printf("%d:%s\n", i,
2674 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2681 display who is the lvs master
2683 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2685 uint32_t *capabilities;
2686 struct ctdb_node_map *nodemap=NULL;
2688 int healthy_count = 0;
2690 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2692 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2696 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2697 CTDB_NO_MEMORY(ctdb, capabilities);
2699 /* collect capabilities for all connected nodes */
2700 for (i=0; i<nodemap->num; i++) {
2701 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2704 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2708 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2710 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2714 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2718 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2723 /* find and show the lvsmaster */
2724 for (i=0; i<nodemap->num; i++) {
2725 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2728 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2731 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2735 if (healthy_count != 0) {
2736 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2741 if (options.machinereadable){
2744 printf("Node %d is LVS master\n", i);
2749 printf("There is no LVS master\n");
2754 disable monitoring on a node
2756 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2761 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2763 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2766 printf("Monitoring mode:%s\n","DISABLED");
2772 enable monitoring on a node
2774 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2779 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2781 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2784 printf("Monitoring mode:%s\n","ACTIVE");
2790 display remote list of keys/data for a db
2792 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2794 const char *db_name;
2795 struct ctdb_db_context *ctdb_db;
2805 if (db_exists(ctdb, db_name)) {
2806 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2810 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2812 if (ctdb_db == NULL) {
2813 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2817 /* traverse and dump the cluster tdb */
2818 ret = ctdb_dump_db(ctdb_db, stdout);
2820 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2821 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2822 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2826 talloc_free(ctdb_db);
2828 printf("Dumped %d records\n", ret);
2833 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2834 TDB_DATA data, void *private_data)
2836 DEBUG(DEBUG_ERR,("Log data received\n"));
2837 if (data.dsize > 0) {
2838 printf("%s", data.dptr);
2845 display a list of log messages from the in memory ringbuffer
2847 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2851 struct ctdb_get_log_addr log_addr;
2853 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2858 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2859 talloc_free(tmp_ctx);
2863 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2864 log_addr.srvid = getpid();
2865 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2866 log_addr.level = get_debug_by_desc(argv[0]);
2868 log_addr.level = strtol(argv[0], NULL, 0);
2872 data.dptr = (unsigned char *)&log_addr;
2873 data.dsize = sizeof(log_addr);
2875 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2877 ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2880 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2882 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2883 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2884 if (ret != 0 || res != 0) {
2885 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2886 talloc_free(tmp_ctx);
2891 tv = timeval_current();
2892 /* this loop will terminate when we have received the reply */
2893 while (timeval_elapsed(&tv) < 3.0) {
2894 event_loop_once(ctdb->ev);
2897 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2899 talloc_free(tmp_ctx);
2904 clear the in memory log area
2906 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2911 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2913 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2914 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2915 if (ret != 0 || res != 0) {
2916 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2917 talloc_free(tmp_ctx);
2921 talloc_free(tmp_ctx);
2928 display a list of the databases on a remote ctdb
2930 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2933 struct ctdb_dbid_map *dbmap=NULL;
2935 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2937 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2941 if(options.machinereadable){
2942 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2943 for(i=0;i<dbmap->num;i++){
2949 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2950 dbmap->dbs[i].dbid, ctdb, &path);
2951 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2952 dbmap->dbs[i].dbid, ctdb, &name);
2953 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2954 dbmap->dbs[i].dbid, ctdb, &health);
2955 persistent = dbmap->dbs[i].persistent;
2956 printf(":0x%08X:%s:%s:%d:%d:\n",
2957 dbmap->dbs[i].dbid, name, path,
2958 !!(persistent), !!(health));
2963 printf("Number of databases:%d\n", dbmap->num);
2964 for(i=0;i<dbmap->num;i++){
2970 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2971 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2972 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2973 persistent = dbmap->dbs[i].persistent;
2974 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2975 dbmap->dbs[i].dbid, name, path,
2976 persistent?" PERSISTENT":"",
2977 health?" UNHEALTHY":"");
2984 display the status of a database on a remote ctdb
2986 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2989 struct ctdb_dbid_map *dbmap=NULL;
2990 const char *db_name;
2998 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3000 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3004 for(i=0;i<dbmap->num;i++){
3010 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3011 if (strcmp(name, db_name) != 0) {
3015 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3016 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3017 persistent = dbmap->dbs[i].persistent;
3018 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
3019 dbmap->dbs[i].dbid, name, path,
3020 persistent?"yes":"no",
3021 health?health:"OK");
3025 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
3030 check if the local node is recmaster or not
3031 it will return 1 if this node is the recmaster and 0 if it is not
3032 or if the local ctdb daemon could not be contacted
3034 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
3036 uint32_t mypnn, recmaster;
3039 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3041 printf("Failed to get pnn of node\n");
3045 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
3047 printf("Failed to get the recmaster\n");
3051 if (recmaster != mypnn) {
3052 printf("this node is not the recmaster\n");
3056 printf("this node is the recmaster\n");
3063 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
3066 struct timeval tv = timeval_current();
3067 ret = ctdb_ctrl_ping(ctdb, options.pnn);
3069 printf("Unable to get ping response from node %u\n", options.pnn);
3072 printf("response from %u time=%.6f sec (%d clients)\n",
3073 options.pnn, timeval_elapsed(&tv), ret);
3082 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
3093 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
3095 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
3099 printf("%-19s = %u\n", name, value);
3106 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3117 value = strtoul(argv[1], NULL, 0);
3119 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3121 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3130 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3136 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3138 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3142 for (i=0;i<count;i++) {
3143 control_getvar(ctdb, 1, &list[i]);
3152 display debug level on a node
3154 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3159 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3161 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3164 if (options.machinereadable){
3165 printf(":Name:Level:\n");
3166 printf(":%s:%d:\n",get_debug_by_level(level),level);
3168 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3175 display reclock file of a node
3177 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3180 const char *reclock;
3182 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3184 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3187 if (options.machinereadable){
3188 if (reclock != NULL) {
3189 printf("%s", reclock);
3192 if (reclock == NULL) {
3193 printf("No reclock file used.\n");
3195 printf("Reclock file:%s\n", reclock);
3203 set the reclock file of a node
3205 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3208 const char *reclock;
3212 } else if (argc == 1) {
3218 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3220 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3227 set the natgw state on/off
3229 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3232 uint32_t natgwstate;
3238 if (!strcmp(argv[0], "on")) {
3240 } else if (!strcmp(argv[0], "off")) {
3246 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3248 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3256 set the lmaster role on/off
3258 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3261 uint32_t lmasterrole;
3267 if (!strcmp(argv[0], "on")) {
3269 } else if (!strcmp(argv[0], "off")) {
3275 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3277 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3285 set the recmaster role on/off
3287 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3290 uint32_t recmasterrole;
3296 if (!strcmp(argv[0], "on")) {
3298 } else if (!strcmp(argv[0], "off")) {
3304 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3306 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3314 set debug level on a node or all nodes
3316 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3322 printf("You must specify the debug level. Valid levels are:\n");
3323 for (i=0; debug_levels[i].description != NULL; i++) {
3324 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3330 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3331 level = get_debug_by_desc(argv[0]);
3333 level = strtol(argv[0], NULL, 0);
3336 for (i=0; debug_levels[i].description != NULL; i++) {
3337 if (level == debug_levels[i].level) {
3341 if (debug_levels[i].description == NULL) {
3342 printf("Invalid debug level, must be one of\n");
3343 for (i=0; debug_levels[i].description != NULL; i++) {
3344 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3349 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3351 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3360 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3366 priority = strtol(argv[0], NULL, 0);
3370 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3372 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3374 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3381 attach to a database
3383 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3385 const char *db_name;
3386 struct ctdb_db_context *ctdb_db;
3393 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3394 if (ctdb_db == NULL) {
3395 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3405 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3407 struct ctdb_db_priority db_prio;
3414 db_prio.db_id = strtoul(argv[0], NULL, 0);
3415 db_prio.priority = strtoul(argv[1], NULL, 0);
3417 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3419 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3429 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3431 uint32_t db_id, priority;
3438 db_id = strtoul(argv[0], NULL, 0);
3440 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3442 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3446 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3452 run an eventscript on a node
3454 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3460 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3463 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3467 data.dptr = (unsigned char *)discard_const(argv[0]);
3468 data.dsize = strlen((char *)data.dptr) + 1;
3470 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3472 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3473 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3474 if (ret != 0 || res != 0) {
3475 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3476 talloc_free(tmp_ctx);
3479 talloc_free(tmp_ctx);
3483 #define DB_VERSION 1
3484 #define MAX_DB_NAME 64
3485 struct db_file_header {
3486 unsigned long version;
3488 unsigned long persistent;
3490 const char name[MAX_DB_NAME];
3493 struct backup_data {
3494 struct ctdb_marshall_buffer *records;
3497 bool traverse_error;
3500 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3502 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3503 struct ctdb_rec_data *rec;
3505 /* add the record */
3506 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3508 bd->traverse_error = true;
3509 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3512 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3513 if (bd->records == NULL) {
3514 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3515 bd->traverse_error = true;
3518 bd->records->count++;
3519 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3520 bd->len += rec->length;
3528 * backup a database to a file
3530 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3533 struct ctdb_dbid_map *dbmap=NULL;
3534 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3535 struct db_file_header dbhdr;
3536 struct ctdb_db_context *ctdb_db;
3537 struct backup_data *bd;
3540 const char *reason = NULL;
3543 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3547 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3549 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3553 for(i=0;i<dbmap->num;i++){
3556 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3557 if(!strcmp(argv[0], name)){
3558 talloc_free(discard_const(name));
3561 talloc_free(discard_const(name));
3563 if (i == dbmap->num) {
3564 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3565 talloc_free(tmp_ctx);
3569 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3570 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3572 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3574 talloc_free(tmp_ctx);
3578 uint32_t allow_unhealthy = 0;
3580 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3581 "AllowUnhealthyDBRead",
3584 if (allow_unhealthy != 1) {
3585 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3588 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3590 talloc_free(tmp_ctx);
3594 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3596 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3597 "tunnable AllowUnhealthyDBRead = %u\n",
3601 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3602 if (ctdb_db == NULL) {
3603 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3604 talloc_free(tmp_ctx);
3609 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3611 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3612 talloc_free(tmp_ctx);
3617 bd = talloc_zero(tmp_ctx, struct backup_data);
3619 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3620 talloc_free(tmp_ctx);
3624 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3625 if (bd->records == NULL) {
3626 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3627 talloc_free(tmp_ctx);
3631 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3632 bd->records->db_id = ctdb_db->db_id;
3633 /* traverse the database collecting all records */
3634 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3635 bd->traverse_error) {
3636 DEBUG(DEBUG_ERR,("Traverse error\n"));
3637 talloc_free(tmp_ctx);
3641 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3644 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3646 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3647 talloc_free(tmp_ctx);
3651 dbhdr.version = DB_VERSION;
3652 dbhdr.timestamp = time(NULL);
3653 dbhdr.persistent = dbmap->dbs[i].persistent;
3654 dbhdr.size = bd->len;
3655 if (strlen(argv[0]) >= MAX_DB_NAME) {
3656 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3659 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3660 ret = write(fh, &dbhdr, sizeof(dbhdr));
3662 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3665 ret = write(fh, bd->records, bd->len);
3667 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3676 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3679 talloc_free(tmp_ctx);
3684 * restore a database from a file
3686 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3689 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3692 struct db_file_header dbhdr;
3693 struct ctdb_db_context *ctdb_db;
3694 struct ctdb_node_map *nodemap=NULL;
3695 struct ctdb_vnn_map *vnnmap=NULL;
3697 struct ctdb_control_wipe_database w;
3699 uint32_t generation;
3704 if (argc < 1 || argc > 2) {
3705 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3709 fh = open(argv[0], O_RDONLY);
3711 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3712 talloc_free(tmp_ctx);
3716 read(fh, &dbhdr, sizeof(dbhdr));
3717 if (dbhdr.version != DB_VERSION) {
3718 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3719 talloc_free(tmp_ctx);
3723 dbname = dbhdr.name;
3728 outdata.dsize = dbhdr.size;
3729 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3730 if (outdata.dptr == NULL) {
3731 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3733 talloc_free(tmp_ctx);
3736 read(fh, outdata.dptr, outdata.dsize);
3739 tm = localtime(&dbhdr.timestamp);
3740 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3741 printf("Restoring database '%s' from backup @ %s\n",
3745 ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3746 if (ctdb_db == NULL) {
3747 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3748 talloc_free(tmp_ctx);
3752 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3754 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3755 talloc_free(tmp_ctx);
3760 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3762 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3763 talloc_free(tmp_ctx);
3767 /* freeze all nodes */
3768 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3769 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3770 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3776 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3777 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3778 talloc_free(tmp_ctx);
3783 generation = vnnmap->generation;
3784 data.dptr = (void *)&generation;
3785 data.dsize = sizeof(generation);
3787 /* start a cluster wide transaction */
3788 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3789 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3791 TIMELIMIT(), false, data,
3794 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3799 w.db_id = ctdb_db->db_id;
3800 w.transaction_id = generation;
3802 data.dptr = (void *)&w;
3803 data.dsize = sizeof(w);
3805 /* wipe all the remote databases. */
3806 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3807 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3809 TIMELIMIT(), false, data,
3812 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3813 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3814 talloc_free(tmp_ctx);
3818 /* push the database */
3819 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3820 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3822 TIMELIMIT(), false, outdata,
3825 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3826 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3827 talloc_free(tmp_ctx);
3831 data.dptr = (void *)&ctdb_db->db_id;
3832 data.dsize = sizeof(ctdb_db->db_id);
3834 /* mark the database as healthy */
3835 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3836 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3838 TIMELIMIT(), false, data,
3841 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3842 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3843 talloc_free(tmp_ctx);
3847 data.dptr = (void *)&generation;
3848 data.dsize = sizeof(generation);
3850 /* commit all the changes */
3851 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3853 TIMELIMIT(), false, data,
3856 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3857 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3858 talloc_free(tmp_ctx);
3863 /* thaw all nodes */
3864 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3865 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3871 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3872 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3873 talloc_free(tmp_ctx);
3878 talloc_free(tmp_ctx);
3883 * dump a database backup from a file
3885 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3887 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3889 struct db_file_header dbhdr;
3893 struct ctdb_rec_data *rec = NULL;
3894 struct ctdb_marshall_buffer *m;
3897 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3901 fh = open(argv[0], O_RDONLY);
3903 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3904 talloc_free(tmp_ctx);
3908 read(fh, &dbhdr, sizeof(dbhdr));
3909 if (dbhdr.version != DB_VERSION) {
3910 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3911 talloc_free(tmp_ctx);
3915 outdata.dsize = dbhdr.size;
3916 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3917 if (outdata.dptr == NULL) {
3918 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3920 talloc_free(tmp_ctx);
3923 read(fh, outdata.dptr, outdata.dsize);
3925 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3927 tm = localtime(&dbhdr.timestamp);
3928 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3929 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3930 dbhdr.name, m->db_id, tbuf);
3932 for (i=0; i < m->count; i++) {
3936 /* we do not want the header splitted, so we pass NULL*/
3937 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3940 ctdb_dumpdb_record(ctdb, key, data, stdout);
3943 printf("Dumped %d records\n", i);
3944 talloc_free(tmp_ctx);
3949 * wipe a database from a file
3951 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3955 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3957 struct ctdb_db_context *ctdb_db;
3958 struct ctdb_node_map *nodemap = NULL;
3959 struct ctdb_vnn_map *vnnmap = NULL;
3961 struct ctdb_control_wipe_database w;
3963 uint32_t generation;
3964 struct ctdb_dbid_map *dbmap = NULL;
3967 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3971 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3974 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3979 for(i=0;i<dbmap->num;i++){
3982 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3983 dbmap->dbs[i].dbid, tmp_ctx, &name);
3984 if(!strcmp(argv[0], name)){
3985 talloc_free(discard_const(name));
3988 talloc_free(discard_const(name));
3990 if (i == dbmap->num) {
3991 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3993 talloc_free(tmp_ctx);
3997 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3998 if (ctdb_db == NULL) {
3999 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
4001 talloc_free(tmp_ctx);
4005 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
4008 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
4010 talloc_free(tmp_ctx);
4014 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4017 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
4019 talloc_free(tmp_ctx);
4023 /* freeze all nodes */
4024 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4025 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
4026 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
4033 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
4034 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
4035 CTDB_RECOVERY_ACTIVE);
4036 talloc_free(tmp_ctx);
4041 generation = vnnmap->generation;
4042 data.dptr = (void *)&generation;
4043 data.dsize = sizeof(generation);
4045 /* start a cluster wide transaction */
4046 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4047 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
4049 TIMELIMIT(), false, data,
4053 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
4054 "transactions.\n"));
4058 w.db_id = ctdb_db->db_id;
4059 w.transaction_id = generation;
4061 data.dptr = (void *)&w;
4062 data.dsize = sizeof(w);
4064 /* wipe all the remote databases. */
4065 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4066 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
4068 TIMELIMIT(), false, data,
4071 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
4072 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4073 talloc_free(tmp_ctx);
4077 data.dptr = (void *)&ctdb_db->db_id;
4078 data.dsize = sizeof(ctdb_db->db_id);
4080 /* mark the database as healthy */
4081 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4082 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4084 TIMELIMIT(), false, data,
4087 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4088 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4089 talloc_free(tmp_ctx);
4093 data.dptr = (void *)&generation;
4094 data.dsize = sizeof(generation);
4096 /* commit all the changes */
4097 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4099 TIMELIMIT(), false, data,
4102 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4103 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4104 talloc_free(tmp_ctx);
4108 /* thaw all nodes */
4109 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4110 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4116 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4117 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4118 talloc_free(tmp_ctx);
4122 talloc_free(tmp_ctx);
4127 * set flags of a node in the nodemap
4129 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4136 struct ctdb_node_flag_change c;
4143 if (sscanf(argv[0], "%d", &node) != 1) {
4144 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4148 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4149 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4156 c.new_flags = flags;
4158 data.dsize = sizeof(c);
4159 data.dptr = (unsigned char *)&c;
4161 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4162 data, NULL, NULL, &status, NULL, NULL);
4163 if (ret != 0 || status != 0) {
4164 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4173 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4179 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4180 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4181 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4182 if (ret != 0 || res != 0) {
4183 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4184 talloc_free(tmp_ctx);
4187 write(1, data.dptr, data.dsize);
4188 talloc_free(tmp_ctx);
4193 handler for memory dumps
4195 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4196 TDB_DATA data, void *private_data)
4198 write(1, data.dptr, data.dsize);
4203 dump memory usage on the recovery daemon
4205 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4209 struct rd_memdump_reply rd;
4211 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4213 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4216 rd.srvid = getpid();
4218 /* register a message port for receiveing the reply so that we
4219 can receive the reply
4221 ctdb_client_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4224 data.dptr = (uint8_t *)&rd;
4225 data.dsize = sizeof(rd);
4227 ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4229 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4233 /* this loop will terminate when we have received the reply */
4235 event_loop_once(ctdb->ev);
4242 send a message to a srvid
4244 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4246 unsigned long srvid;
4254 srvid = strtoul(argv[0], NULL, 0);
4256 data.dptr = (uint8_t *)discard_const(argv[1]);
4257 data.dsize= strlen(argv[1]);
4259 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4261 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4269 handler for msglisten
4271 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4272 TDB_DATA data, void *private_data)
4276 printf("Message received: ");
4277 for (i=0;i<data.dsize;i++) {
4278 printf("%c", data.dptr[i]);
4284 listen for messages on a messageport
4286 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4292 /* register a message port and listen for messages
4294 ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4295 printf("Listening for messages on srvid:%d\n", (int)srvid);
4298 event_loop_once(ctdb->ev);
4305 list all nodes in the cluster
4306 if the daemon is running, we read the data from the daemon.
4307 if the daemon is not running we parse the nodes file directly
4309 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4312 struct ctdb_node_map *nodemap=NULL;
4315 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4317 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4321 for(i=0;i<nodemap->num;i++){
4322 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4325 if (options.machinereadable){
4326 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4328 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4332 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4333 struct pnn_node *pnn_nodes;
4334 struct pnn_node *pnn_node;
4336 pnn_nodes = read_nodes_file(mem_ctx);
4337 if (pnn_nodes == NULL) {
4338 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4339 talloc_free(mem_ctx);
4343 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4344 ctdb_sock_addr addr;
4346 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4347 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4348 talloc_free(mem_ctx);
4352 if (options.machinereadable){
4353 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4355 printf("%s\n", pnn_node->addr);
4358 talloc_free(mem_ctx);
4365 reload the nodes file on the local node
4367 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4371 struct ctdb_node_map *nodemap=NULL;
4373 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4375 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4379 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4381 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4385 /* reload the nodes file on all remote nodes */
4386 for (i=0;i<nodemap->num;i++) {
4387 if (nodemap->nodes[i].pnn == mypnn) {
4390 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4391 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4392 nodemap->nodes[i].pnn);
4394 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4398 /* reload the nodes file on the local node */
4399 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4400 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4402 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4405 /* initiate a recovery */
4406 control_recover(ctdb, argc, argv);
4412 static const struct {
4414 int (*fn)(struct ctdb_context *, int, const char **);
4416 bool without_daemon; /* can be run without daemon running ? */
4419 } ctdb_commands[] = {
4421 { "version", control_version, true, false, "show version of ctdb" },
4423 { "status", control_status, true, false, "show node status" },
4424 { "uptime", control_uptime, true, false, "show node uptime" },
4425 { "ping", control_ping, true, false, "ping all nodes" },
4426 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4427 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4428 { "listvars", control_listvars, true, false, "list tunable variables"},
4429 { "statistics", control_statistics, false, false, "show statistics" },
4430 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4431 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4432 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4433 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4434 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4435 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4436 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4437 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4438 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4439 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4440 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4441 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4442 { "lvs", control_lvs, true, false, "show lvs configuration" },
4443 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4444 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4445 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4446 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4447 { "getdebug", control_getdebug, true, false, "get debug level" },
4448 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4449 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4450 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4451 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4452 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4453 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4454 { "disable", control_disable, true, false, "disable a nodes public IP" },
4455 { "enable", control_enable, true, false, "enable a nodes public IP" },
4456 { "stop", control_stop, true, false, "stop a node" },
4457 { "continue", control_continue, true, false, "re-start a stopped node" },
4458 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4459 { "unban", control_unban, true, false, "unban a node" },
4460 { "showban", control_showban, true, false, "show ban information"},
4461 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4462 { "recover", control_recover, true, false, "force recovery" },
4463 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4464 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4465 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4466 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4467 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4468 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4469 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4470 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
4471 { "addtickle", control_add_tickle, false, false, "add a tickle for this ip", "<ip>:<port> <ip>:<port>" },
4473 { "deltickle", control_del_tickle, false, false, "delete a tickle from this ip", "<ip>:<port> <ip>:<port>" },
4475 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4476 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4477 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4478 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4479 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4480 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4481 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4482 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4483 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4484 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4485 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4486 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4487 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4488 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file> [dbname]"},
4489 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4490 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4491 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4492 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4493 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4494 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4495 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4496 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4497 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4498 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4499 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4500 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4501 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4502 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4503 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4504 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4505 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4506 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4507 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4513 static void usage(void)
4517 "Usage: ctdb [options] <control>\n" \
4519 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4520 " -Y generate machinereadable output\n"
4521 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4522 printf("Controls:\n");
4523 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4524 printf(" %-15s %-27s %s\n",
4525 ctdb_commands[i].name,
4526 ctdb_commands[i].args?ctdb_commands[i].args:"",
4527 ctdb_commands[i].msg);
4533 static void ctdb_alarm(int sig)
4535 printf("Maximum runtime exceeded - exiting\n");
4542 int main(int argc, const char *argv[])
4544 struct ctdb_context *ctdb;
4545 char *nodestring = NULL;
4546 struct poptOption popt_options[] = {
4549 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4550 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4551 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4552 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4556 const char **extra_argv;
4560 struct event_context *ev;
4561 const char *control;
4565 /* set some defaults */
4566 options.maxruntime = 0;
4567 options.timelimit = 3;
4568 options.pnn = CTDB_CURRENT_NODE;
4570 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4572 while ((opt = poptGetNextOpt(pc)) != -1) {
4575 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4576 poptBadOption(pc, 0), poptStrerror(opt)));
4581 /* setup the remaining options for the main program to use */
4582 extra_argv = poptGetArgs(pc);
4585 while (extra_argv[extra_argc]) extra_argc++;
4588 if (extra_argc < 1) {
4592 if (options.maxruntime == 0) {
4593 const char *ctdb_timeout;
4594 ctdb_timeout = getenv("CTDB_TIMEOUT");
4595 if (ctdb_timeout != NULL) {
4596 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4598 /* default timeout is 120 seconds */
4599 options.maxruntime = 120;
4603 signal(SIGALRM, ctdb_alarm);
4604 alarm(options.maxruntime);
4606 /* setup the node number to contact */
4607 if (nodestring != NULL) {
4608 if (strcmp(nodestring, "all") == 0) {
4609 options.pnn = CTDB_BROADCAST_ALL;
4611 options.pnn = strtoul(nodestring, NULL, 0);
4615 control = extra_argv[0];
4617 ev = event_context_init(NULL);
4619 DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
4622 tevent_loop_allow_nesting(ev);
4624 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4625 if (strcmp(control, ctdb_commands[i].name) == 0) {
4628 if (ctdb_commands[i].without_daemon == true) {
4632 /* initialise ctdb */
4633 ctdb = ctdb_cmdline_client(ev);
4635 if (ctdb_commands[i].without_daemon == false) {
4636 const char *socket_name;
4639 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4643 /* initialize a libctdb connection as well */
4644 socket_name = ctdb_get_socketname(ctdb);
4645 ctdb_connection = ctdb_connect(socket_name,
4646 ctdb_log_file, stderr);
4647 if (ctdb_connection == NULL) {
4648 fprintf(stderr, "Failed to connect to daemon from libctdb\n");
4652 /* verify the node exists */
4655 if (options.pnn == CTDB_CURRENT_NODE) {
4657 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4665 if (ctdb_commands[i].auto_all &&
4666 options.pnn == CTDB_BROADCAST_ALL) {
4671 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4672 CTDB_NO_MEMORY(ctdb, nodes);
4674 for (j=0;j<num_nodes;j++) {
4675 options.pnn = nodes[j];
4676 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4680 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4686 if (i == ARRAY_SIZE(ctdb_commands)) {
4687 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));