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;
1072 port = atoi(argv[1]);
1075 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1076 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1080 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
1082 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
1086 if (options.machinereadable){
1087 printf(":source ip:port:destination ip:port:\n");
1088 for (i=0;i<list->tickles.num;i++) {
1089 if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
1092 printf(":%s:%u", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1093 printf(":%s:%u:\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
1096 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
1097 printf("Num tickles:%u\n", list->tickles.num);
1098 for (i=0;i<list->tickles.num;i++) {
1099 if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
1102 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1103 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));
1113 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1115 struct ctdb_all_public_ips *ips;
1116 struct ctdb_public_ip ip;
1119 uint32_t disable_time;
1121 struct ctdb_node_map *nodemap=NULL;
1122 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1125 data.dptr = (uint8_t*)&disable_time;
1126 data.dsize = sizeof(disable_time);
1127 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1129 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1135 /* read the public ip list from the node */
1136 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1138 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1139 talloc_free(tmp_ctx);
1143 for (i=0;i<ips->num;i++) {
1144 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1149 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1150 pnn, ctdb_addr_to_str(addr)));
1151 talloc_free(tmp_ctx);
1158 data.dptr = (uint8_t *)&ip;
1159 data.dsize = sizeof(ip);
1161 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1163 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1164 talloc_free(tmp_ctx);
1168 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1169 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1176 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1177 talloc_free(tmp_ctx);
1181 ret = ctdb_ctrl_takeover_ip(ctdb, LONGTIMELIMIT(), pnn, &ip);
1183 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1184 talloc_free(tmp_ctx);
1188 /* update the recovery daemon so it now knows to expect the new
1189 node assignment for this ip.
1191 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECD_UPDATE_IP, data);
1193 DEBUG(DEBUG_ERR,("Failed to send message to update the ip on the recovery master.\n"));
1197 talloc_free(tmp_ctx);
1202 move/failover an ip address to a specific node
1204 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1207 ctdb_sock_addr addr;
1214 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1215 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1220 if (sscanf(argv[1], "%u", &pnn) != 1) {
1221 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1225 if (move_ip(ctdb, &addr, pnn) != 0) {
1226 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1233 void getips_store_callback(void *param, void *data)
1235 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1236 struct ctdb_all_public_ips *ips = param;
1240 ips->ips[i].pnn = node_ip->pnn;
1241 ips->ips[i].addr = node_ip->addr;
1244 void getips_count_callback(void *param, void *data)
1246 uint32_t *count = param;
1252 static uint32_t *ip_key(ctdb_sock_addr *ip)
1254 static uint32_t key[IP_KEYLEN];
1256 bzero(key, sizeof(key));
1258 switch (ip->sa.sa_family) {
1260 key[0] = ip->ip.sin_addr.s_addr;
1263 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1264 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1265 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1266 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1269 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1276 static void *add_ip_callback(void *parm, void *data)
1282 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1284 struct ctdb_all_public_ips *tmp_ips;
1285 struct ctdb_node_map *nodemap=NULL;
1286 trbt_tree_t *ip_tree;
1290 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1292 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1296 ip_tree = trbt_create(tmp_ctx, 0);
1298 for(i=0;i<nodemap->num;i++){
1299 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1302 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1306 /* read the public ip list from this node */
1307 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1309 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1313 for (j=0; j<tmp_ips->num;j++) {
1314 struct ctdb_public_ip *node_ip;
1316 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1317 node_ip->pnn = tmp_ips->ips[j].pnn;
1318 node_ip->addr = tmp_ips->ips[j].addr;
1320 trbt_insertarray32_callback(ip_tree,
1321 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1325 talloc_free(tmp_ips);
1330 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1332 len = offsetof(struct ctdb_all_public_ips, ips) +
1333 count*sizeof(struct ctdb_public_ip);
1334 tmp_ips = talloc_zero_size(tmp_ctx, len);
1335 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1344 * scans all other nodes and returns a pnn for another node that can host this
1348 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1350 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1351 struct ctdb_all_public_ips *ips;
1352 struct ctdb_node_map *nodemap=NULL;
1355 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1357 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1358 talloc_free(tmp_ctx);
1362 for(i=0;i<nodemap->num;i++){
1363 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1366 if (nodemap->nodes[i].pnn == options.pnn) {
1370 /* read the public ip list from this node */
1371 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1373 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1377 for (j=0;j<ips->num;j++) {
1378 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1379 talloc_free(tmp_ctx);
1380 return nodemap->nodes[i].pnn;
1386 talloc_free(tmp_ctx);
1391 add a public ip address to a node
1393 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1399 ctdb_sock_addr addr;
1400 struct ctdb_control_ip_iface *pub;
1401 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1402 struct ctdb_all_public_ips *ips;
1406 talloc_free(tmp_ctx);
1410 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1411 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1412 talloc_free(tmp_ctx);
1416 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1418 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1419 talloc_free(tmp_ctx);
1424 /* check if some other node is already serving this ip, if not,
1427 for (i=0;i<ips->num;i++) {
1428 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1433 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1434 pub = talloc_size(tmp_ctx, len);
1435 CTDB_NO_MEMORY(ctdb, pub);
1439 pub->len = strlen(argv[1])+1;
1440 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1442 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1444 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1445 talloc_free(tmp_ctx);
1449 if (i == ips->num) {
1450 /* no one has this ip so we claim it */
1453 pnn = ips->ips[i].pnn;
1456 if (move_ip(ctdb, &addr, pnn) != 0) {
1457 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1461 talloc_free(tmp_ctx);
1465 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1467 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1469 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1470 struct ctdb_node_map *nodemap=NULL;
1471 struct ctdb_all_public_ips *ips;
1474 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1476 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1480 /* remove it from the nodes that are not hosting the ip currently */
1481 for(i=0;i<nodemap->num;i++){
1482 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1485 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1486 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1490 for (j=0;j<ips->num;j++) {
1491 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1499 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1503 options.pnn = nodemap->nodes[i].pnn;
1504 control_delip(ctdb, argc, argv);
1508 /* remove it from every node (also the one hosting it) */
1509 for(i=0;i<nodemap->num;i++){
1510 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1513 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1514 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1518 for (j=0;j<ips->num;j++) {
1519 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1527 options.pnn = nodemap->nodes[i].pnn;
1528 control_delip(ctdb, argc, argv);
1531 talloc_free(tmp_ctx);
1536 delete a public ip address from a node
1538 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1541 ctdb_sock_addr addr;
1542 struct ctdb_control_ip_iface pub;
1543 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1544 struct ctdb_all_public_ips *ips;
1547 talloc_free(tmp_ctx);
1551 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1552 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1556 if (options.pnn == CTDB_BROADCAST_ALL) {
1557 return control_delip_all(ctdb, argc, argv, &addr);
1564 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1566 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1567 talloc_free(tmp_ctx);
1571 for (i=0;i<ips->num;i++) {
1572 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1578 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1579 ctdb_addr_to_str(&addr)));
1580 talloc_free(tmp_ctx);
1584 if (ips->ips[i].pnn == options.pnn) {
1585 ret = find_other_host_for_public_ip(ctdb, &addr);
1587 if (move_ip(ctdb, &addr, ret) != 0) {
1588 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1594 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1596 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1597 talloc_free(tmp_ctx);
1601 talloc_free(tmp_ctx);
1606 kill a tcp connection
1608 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1611 struct ctdb_control_killtcp killtcp;
1617 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1618 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1622 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1623 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1627 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1629 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1640 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1643 ctdb_sock_addr addr;
1649 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1650 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1654 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1656 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1664 register a server id
1666 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1669 struct ctdb_server_id server_id;
1675 server_id.pnn = strtoul(argv[0], NULL, 0);
1676 server_id.type = strtoul(argv[1], NULL, 0);
1677 server_id.server_id = strtoul(argv[2], NULL, 0);
1679 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1681 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1684 DEBUG(DEBUG_ERR,("Srvid registered. Sleeping for 999 seconds\n"));
1690 unregister a server id
1692 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1695 struct ctdb_server_id server_id;
1701 server_id.pnn = strtoul(argv[0], NULL, 0);
1702 server_id.type = strtoul(argv[1], NULL, 0);
1703 server_id.server_id = strtoul(argv[2], NULL, 0);
1705 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1707 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1714 check if a server id exists
1716 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1720 struct ctdb_server_id server_id;
1726 server_id.pnn = strtoul(argv[0], NULL, 0);
1727 server_id.type = strtoul(argv[1], NULL, 0);
1728 server_id.server_id = strtoul(argv[2], NULL, 0);
1730 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1732 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1737 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1739 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1745 get a list of all server ids that are registered on a node
1747 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1750 struct ctdb_server_id_list *server_ids;
1752 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1754 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1758 for (i=0; i<server_ids->num; i++) {
1759 printf("Server id %d:%d:%d\n",
1760 server_ids->server_ids[i].pnn,
1761 server_ids->server_ids[i].type,
1762 server_ids->server_ids[i].server_id);
1769 send a tcp tickle ack
1771 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1774 ctdb_sock_addr src, dst;
1780 if (!parse_ip_port(argv[0], &src)) {
1781 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1785 if (!parse_ip_port(argv[1], &dst)) {
1786 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1790 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1794 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1801 display public ip status
1803 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1806 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1807 struct ctdb_all_public_ips *ips;
1809 if (options.pnn == CTDB_BROADCAST_ALL) {
1810 /* read the list of public ips from all nodes */
1811 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1813 /* read the public ip list from this node */
1814 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1817 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1818 talloc_free(tmp_ctx);
1822 if (options.machinereadable){
1823 printf(":Public IP:Node:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1825 if (options.pnn == CTDB_BROADCAST_ALL) {
1826 printf("Public IPs on ALL nodes\n");
1828 printf("Public IPs on node %u\n", options.pnn);
1832 for (i=1;i<=ips->num;i++) {
1833 struct ctdb_control_public_ip_info *info = NULL;
1835 char *aciface = NULL;
1836 char *avifaces = NULL;
1837 char *cifaces = NULL;
1839 if (options.pnn == CTDB_BROADCAST_ALL) {
1840 pnn = ips->ips[ips->num-i].pnn;
1846 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1847 &ips->ips[ips->num-i].addr, &info);
1854 for (j=0; j < info->num; j++) {
1855 if (cifaces == NULL) {
1856 cifaces = talloc_strdup(info,
1857 info->ifaces[j].name);
1859 cifaces = talloc_asprintf_append(cifaces,
1861 info->ifaces[j].name);
1864 if (info->active_idx == j) {
1865 aciface = info->ifaces[j].name;
1868 if (info->ifaces[j].link_state == 0) {
1872 if (avifaces == NULL) {
1873 avifaces = talloc_strdup(info, info->ifaces[j].name);
1875 avifaces = talloc_asprintf_append(avifaces,
1877 info->ifaces[j].name);
1882 if (options.machinereadable){
1883 printf(":%s:%d:%s:%s:%s:\n",
1884 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1885 ips->ips[ips->num-i].pnn,
1887 avifaces?avifaces:"",
1888 cifaces?cifaces:"");
1890 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1891 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1892 ips->ips[ips->num-i].pnn,
1894 avifaces?avifaces:"",
1895 cifaces?cifaces:"");
1900 talloc_free(tmp_ctx);
1907 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1910 ctdb_sock_addr addr;
1911 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1912 struct ctdb_control_public_ip_info *info;
1915 talloc_free(tmp_ctx);
1919 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1920 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1924 /* read the public ip info from this node */
1925 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1926 tmp_ctx, &addr, &info);
1928 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1929 argv[0], options.pnn));
1930 talloc_free(tmp_ctx);
1934 printf("Public IP[%s] info on node %u\n",
1935 ctdb_addr_to_str(&info->ip.addr),
1938 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1939 ctdb_addr_to_str(&info->ip.addr),
1940 info->ip.pnn, info->num);
1942 for (i=0; i<info->num; i++) {
1943 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1945 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1946 i+1, info->ifaces[i].name,
1947 info->ifaces[i].link_state?"up":"down",
1948 (unsigned int)info->ifaces[i].references,
1949 (i==info->active_idx)?" (active)":"");
1952 talloc_free(tmp_ctx);
1957 display interfaces status
1959 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1962 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1963 struct ctdb_control_get_ifaces *ifaces;
1965 /* read the public ip list from this node */
1966 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1969 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1971 talloc_free(tmp_ctx);
1975 if (options.machinereadable){
1976 printf(":Name:LinkStatus:References:\n");
1978 printf("Interfaces on node %u\n", options.pnn);
1981 for (i=0; i<ifaces->num; i++) {
1982 if (options.machinereadable){
1983 printf(":%s:%s:%u\n",
1984 ifaces->ifaces[i].name,
1985 ifaces->ifaces[i].link_state?"1":"0",
1986 (unsigned int)ifaces->ifaces[i].references);
1988 printf("name:%s link:%s references:%u\n",
1989 ifaces->ifaces[i].name,
1990 ifaces->ifaces[i].link_state?"up":"down",
1991 (unsigned int)ifaces->ifaces[i].references);
1995 talloc_free(tmp_ctx);
2001 set link status of an interface
2003 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
2006 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2007 struct ctdb_control_iface_info info;
2015 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
2016 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
2018 talloc_free(tmp_ctx);
2021 strcpy(info.name, argv[0]);
2023 if (strcmp(argv[1], "up") == 0) {
2024 info.link_state = 1;
2025 } else if (strcmp(argv[1], "down") == 0) {
2026 info.link_state = 0;
2028 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
2030 talloc_free(tmp_ctx);
2034 /* read the public ip list from this node */
2035 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
2038 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
2039 argv[0], options.pnn));
2040 talloc_free(tmp_ctx);
2044 talloc_free(tmp_ctx);
2049 display pid of a ctdb daemon
2051 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
2056 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
2058 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
2061 printf("Pid:%d\n", pid);
2066 static uint32_t ipreallocate_finished;
2069 handler for receiving the response to ipreallocate
2071 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
2072 TDB_DATA data, void *private_data)
2074 ipreallocate_finished = 1;
2077 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
2079 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
2081 event_add_timed(ctdb->ev, ctdb,
2082 timeval_current_ofs(1, 0),
2083 ctdb_every_second, ctdb);
2087 ask the recovery daemon on the recovery master to perform a ip reallocation
2089 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
2093 struct takeover_run_reply rd;
2095 struct ctdb_node_map *nodemap=NULL;
2097 struct timeval tv = timeval_current();
2099 /* we need some events to trigger so we can timeout and restart
2102 event_add_timed(ctdb->ev, ctdb,
2103 timeval_current_ofs(1, 0),
2104 ctdb_every_second, ctdb);
2106 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2108 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
2111 rd.srvid = getpid();
2113 /* register a message port for receiveing the reply so that we
2114 can receive the reply
2116 ctdb_client_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
2118 data.dptr = (uint8_t *)&rd;
2119 data.dsize = sizeof(rd);
2122 /* check that there are valid nodes available */
2123 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2124 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2127 for (i=0; i<nodemap->num;i++) {
2128 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2132 if (i==nodemap->num) {
2133 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2138 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2140 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2144 /* verify the node exists */
2145 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2146 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2151 /* check tha there are nodes available that can act as a recmaster */
2152 for (i=0; i<nodemap->num; i++) {
2153 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2158 if (i == nodemap->num) {
2159 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2163 /* verify the recovery master is not STOPPED, nor BANNED */
2164 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2165 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2172 /* verify the recovery master is not STOPPED, nor BANNED */
2173 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2174 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2180 ipreallocate_finished = 0;
2181 ret = ctdb_client_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2183 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2187 tv = timeval_current();
2188 /* this loop will terminate when we have received the reply */
2189 while (timeval_elapsed(&tv) < 3.0) {
2190 event_loop_once(ctdb->ev);
2192 if (ipreallocate_finished == 1) {
2196 DEBUG(DEBUG_ERR,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2206 disable a remote node
2208 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2211 struct ctdb_node_map *nodemap=NULL;
2213 /* check if the node is already disabled */
2214 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2215 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2218 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2219 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2224 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2226 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2232 /* read the nodemap and verify the change took effect */
2233 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2234 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2238 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2239 ret = control_ipreallocate(ctdb, argc, argv);
2241 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2249 enable a disabled remote node
2251 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2255 struct ctdb_node_map *nodemap=NULL;
2258 /* check if the node is already enabled */
2259 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2260 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2263 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2264 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2269 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2271 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2277 /* read the nodemap and verify the change took effect */
2278 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2279 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2283 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2285 ret = control_ipreallocate(ctdb, argc, argv);
2287 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2297 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2300 struct ctdb_node_map *nodemap=NULL;
2303 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2305 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2310 /* read the nodemap and verify the change took effect */
2311 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2312 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2316 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2317 ret = control_ipreallocate(ctdb, argc, argv);
2319 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2327 restart a stopped remote node
2329 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2333 struct ctdb_node_map *nodemap=NULL;
2336 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2338 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2344 /* read the nodemap and verify the change took effect */
2345 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2346 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2350 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2351 ret = control_ipreallocate(ctdb, argc, argv);
2353 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2360 static uint32_t get_generation(struct ctdb_context *ctdb)
2362 struct ctdb_vnn_map *vnnmap=NULL;
2365 /* wait until the recmaster is not in recovery mode */
2367 uint32_t recmode, recmaster;
2369 if (vnnmap != NULL) {
2370 talloc_free(vnnmap);
2374 /* get the recmaster */
2375 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2377 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2381 /* get recovery mode */
2382 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2384 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2388 /* get the current generation number */
2389 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2391 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2395 if ((recmode == CTDB_RECOVERY_NORMAL)
2396 && (vnnmap->generation != 1)){
2397 return vnnmap->generation;
2404 ban a node from the cluster
2406 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2409 struct ctdb_node_map *nodemap=NULL;
2410 struct ctdb_ban_time bantime;
2416 /* verify the node exists */
2417 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2419 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2423 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2424 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2428 bantime.pnn = options.pnn;
2429 bantime.time = strtoul(argv[0], NULL, 0);
2431 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2433 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2437 ret = control_ipreallocate(ctdb, argc, argv);
2439 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2448 unban a node from the cluster
2450 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2453 struct ctdb_node_map *nodemap=NULL;
2454 struct ctdb_ban_time bantime;
2456 /* verify the node exists */
2457 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2459 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2463 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2464 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2468 bantime.pnn = options.pnn;
2471 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2473 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2477 ret = control_ipreallocate(ctdb, argc, argv);
2479 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2488 show ban information for a node
2490 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2493 struct ctdb_node_map *nodemap=NULL;
2494 struct ctdb_ban_time *bantime;
2496 /* verify the node exists */
2497 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2499 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2503 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2505 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2509 if (bantime->time == 0) {
2510 printf("Node %u is not banned\n", bantime->pnn);
2512 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2521 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2525 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2527 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2537 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2540 uint32_t generation, next_generation;
2542 /* record the current generation number */
2543 generation = get_generation(ctdb);
2545 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2547 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2551 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2553 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2557 /* wait until we are in a new generation */
2559 next_generation = get_generation(ctdb);
2560 if (next_generation != generation) {
2571 display monitoring mode of a remote node
2573 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2578 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2580 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2583 if (!options.machinereadable){
2584 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2587 printf(":%d:\n",monmode);
2594 display capabilities of a remote node
2596 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2598 uint32_t capabilities;
2601 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2603 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2607 if (!options.machinereadable){
2608 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2609 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2610 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2611 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2613 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2614 printf(":%d:%d:%d:%d:\n",
2615 !!(capabilities&CTDB_CAP_RECMASTER),
2616 !!(capabilities&CTDB_CAP_LMASTER),
2617 !!(capabilities&CTDB_CAP_LVS),
2618 !!(capabilities&CTDB_CAP_NATGW));
2624 display lvs configuration
2626 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2628 uint32_t *capabilities;
2629 struct ctdb_node_map *nodemap=NULL;
2631 int healthy_count = 0;
2633 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2635 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2639 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2640 CTDB_NO_MEMORY(ctdb, capabilities);
2642 /* collect capabilities for all connected nodes */
2643 for (i=0; i<nodemap->num; i++) {
2644 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2647 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2651 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2653 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2657 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2661 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2666 /* Print all LVS nodes */
2667 for (i=0; i<nodemap->num; i++) {
2668 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2671 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2674 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2678 if (healthy_count != 0) {
2679 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2684 printf("%d:%s\n", i,
2685 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2692 display who is the lvs master
2694 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2696 uint32_t *capabilities;
2697 struct ctdb_node_map *nodemap=NULL;
2699 int healthy_count = 0;
2701 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2703 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2707 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2708 CTDB_NO_MEMORY(ctdb, capabilities);
2710 /* collect capabilities for all connected nodes */
2711 for (i=0; i<nodemap->num; i++) {
2712 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2715 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2719 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2721 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2725 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2729 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2734 /* find and show the lvsmaster */
2735 for (i=0; i<nodemap->num; i++) {
2736 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2739 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2742 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2746 if (healthy_count != 0) {
2747 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2752 if (options.machinereadable){
2755 printf("Node %d is LVS master\n", i);
2760 printf("There is no LVS master\n");
2765 disable monitoring on a node
2767 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2772 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2774 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2777 printf("Monitoring mode:%s\n","DISABLED");
2783 enable monitoring on a node
2785 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2790 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2792 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2795 printf("Monitoring mode:%s\n","ACTIVE");
2801 display remote list of keys/data for a db
2803 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2805 const char *db_name;
2806 struct ctdb_db_context *ctdb_db;
2816 if (db_exists(ctdb, db_name)) {
2817 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2821 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2823 if (ctdb_db == NULL) {
2824 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2828 /* traverse and dump the cluster tdb */
2829 ret = ctdb_dump_db(ctdb_db, stdout);
2831 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2832 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2833 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2837 talloc_free(ctdb_db);
2839 printf("Dumped %d records\n", ret);
2844 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2845 TDB_DATA data, void *private_data)
2847 DEBUG(DEBUG_ERR,("Log data received\n"));
2848 if (data.dsize > 0) {
2849 printf("%s", data.dptr);
2856 display a list of log messages from the in memory ringbuffer
2858 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2862 struct ctdb_get_log_addr log_addr;
2864 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2869 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2870 talloc_free(tmp_ctx);
2874 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2875 log_addr.srvid = getpid();
2876 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2877 log_addr.level = get_debug_by_desc(argv[0]);
2879 log_addr.level = strtol(argv[0], NULL, 0);
2883 data.dptr = (unsigned char *)&log_addr;
2884 data.dsize = sizeof(log_addr);
2886 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2888 ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2891 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2893 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2894 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2895 if (ret != 0 || res != 0) {
2896 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2897 talloc_free(tmp_ctx);
2902 tv = timeval_current();
2903 /* this loop will terminate when we have received the reply */
2904 while (timeval_elapsed(&tv) < 3.0) {
2905 event_loop_once(ctdb->ev);
2908 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2910 talloc_free(tmp_ctx);
2915 clear the in memory log area
2917 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2922 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2924 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2925 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2926 if (ret != 0 || res != 0) {
2927 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2928 talloc_free(tmp_ctx);
2932 talloc_free(tmp_ctx);
2939 display a list of the databases on a remote ctdb
2941 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2944 struct ctdb_dbid_map *dbmap=NULL;
2946 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2948 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2952 if(options.machinereadable){
2953 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2954 for(i=0;i<dbmap->num;i++){
2960 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2961 dbmap->dbs[i].dbid, ctdb, &path);
2962 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2963 dbmap->dbs[i].dbid, ctdb, &name);
2964 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2965 dbmap->dbs[i].dbid, ctdb, &health);
2966 persistent = dbmap->dbs[i].persistent;
2967 printf(":0x%08X:%s:%s:%d:%d:\n",
2968 dbmap->dbs[i].dbid, name, path,
2969 !!(persistent), !!(health));
2974 printf("Number of databases:%d\n", dbmap->num);
2975 for(i=0;i<dbmap->num;i++){
2981 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2982 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2983 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2984 persistent = dbmap->dbs[i].persistent;
2985 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2986 dbmap->dbs[i].dbid, name, path,
2987 persistent?" PERSISTENT":"",
2988 health?" UNHEALTHY":"");
2995 display the status of a database on a remote ctdb
2997 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
3000 struct ctdb_dbid_map *dbmap=NULL;
3001 const char *db_name;
3009 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3011 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3015 for(i=0;i<dbmap->num;i++){
3021 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3022 if (strcmp(name, db_name) != 0) {
3026 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3027 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3028 persistent = dbmap->dbs[i].persistent;
3029 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
3030 dbmap->dbs[i].dbid, name, path,
3031 persistent?"yes":"no",
3032 health?health:"OK");
3036 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
3041 check if the local node is recmaster or not
3042 it will return 1 if this node is the recmaster and 0 if it is not
3043 or if the local ctdb daemon could not be contacted
3045 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
3047 uint32_t mypnn, recmaster;
3050 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3052 printf("Failed to get pnn of node\n");
3056 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
3058 printf("Failed to get the recmaster\n");
3062 if (recmaster != mypnn) {
3063 printf("this node is not the recmaster\n");
3067 printf("this node is the recmaster\n");
3074 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
3077 struct timeval tv = timeval_current();
3078 ret = ctdb_ctrl_ping(ctdb, options.pnn);
3080 printf("Unable to get ping response from node %u\n", options.pnn);
3083 printf("response from %u time=%.6f sec (%d clients)\n",
3084 options.pnn, timeval_elapsed(&tv), ret);
3093 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
3104 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
3106 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
3110 printf("%-19s = %u\n", name, value);
3117 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3128 value = strtoul(argv[1], NULL, 0);
3130 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3132 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3141 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3147 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3149 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3153 for (i=0;i<count;i++) {
3154 control_getvar(ctdb, 1, &list[i]);
3163 display debug level on a node
3165 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3170 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3172 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3175 if (options.machinereadable){
3176 printf(":Name:Level:\n");
3177 printf(":%s:%d:\n",get_debug_by_level(level),level);
3179 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3186 display reclock file of a node
3188 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3191 const char *reclock;
3193 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3195 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3198 if (options.machinereadable){
3199 if (reclock != NULL) {
3200 printf("%s", reclock);
3203 if (reclock == NULL) {
3204 printf("No reclock file used.\n");
3206 printf("Reclock file:%s\n", reclock);
3214 set the reclock file of a node
3216 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3219 const char *reclock;
3223 } else if (argc == 1) {
3229 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3231 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3238 set the natgw state on/off
3240 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3243 uint32_t natgwstate;
3249 if (!strcmp(argv[0], "on")) {
3251 } else if (!strcmp(argv[0], "off")) {
3257 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3259 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3267 set the lmaster role on/off
3269 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3272 uint32_t lmasterrole;
3278 if (!strcmp(argv[0], "on")) {
3280 } else if (!strcmp(argv[0], "off")) {
3286 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3288 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3296 set the recmaster role on/off
3298 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3301 uint32_t recmasterrole;
3307 if (!strcmp(argv[0], "on")) {
3309 } else if (!strcmp(argv[0], "off")) {
3315 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3317 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3325 set debug level on a node or all nodes
3327 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3333 printf("You must specify the debug level. Valid levels are:\n");
3334 for (i=0; debug_levels[i].description != NULL; i++) {
3335 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3341 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3342 level = get_debug_by_desc(argv[0]);
3344 level = strtol(argv[0], NULL, 0);
3347 for (i=0; debug_levels[i].description != NULL; i++) {
3348 if (level == debug_levels[i].level) {
3352 if (debug_levels[i].description == NULL) {
3353 printf("Invalid debug level, must be one of\n");
3354 for (i=0; debug_levels[i].description != NULL; i++) {
3355 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3360 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3362 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3371 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3377 priority = strtol(argv[0], NULL, 0);
3381 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3383 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3385 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3392 attach to a database
3394 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3396 const char *db_name;
3397 struct ctdb_db_context *ctdb_db;
3404 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3405 if (ctdb_db == NULL) {
3406 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3416 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3418 struct ctdb_db_priority db_prio;
3425 db_prio.db_id = strtoul(argv[0], NULL, 0);
3426 db_prio.priority = strtoul(argv[1], NULL, 0);
3428 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3430 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3440 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3442 uint32_t db_id, priority;
3449 db_id = strtoul(argv[0], NULL, 0);
3451 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3453 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3457 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3463 run an eventscript on a node
3465 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3471 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3474 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3478 data.dptr = (unsigned char *)discard_const(argv[0]);
3479 data.dsize = strlen((char *)data.dptr) + 1;
3481 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3483 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3484 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3485 if (ret != 0 || res != 0) {
3486 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3487 talloc_free(tmp_ctx);
3490 talloc_free(tmp_ctx);
3494 #define DB_VERSION 1
3495 #define MAX_DB_NAME 64
3496 struct db_file_header {
3497 unsigned long version;
3499 unsigned long persistent;
3501 const char name[MAX_DB_NAME];
3504 struct backup_data {
3505 struct ctdb_marshall_buffer *records;
3508 bool traverse_error;
3511 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3513 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3514 struct ctdb_rec_data *rec;
3516 /* add the record */
3517 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3519 bd->traverse_error = true;
3520 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3523 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3524 if (bd->records == NULL) {
3525 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3526 bd->traverse_error = true;
3529 bd->records->count++;
3530 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3531 bd->len += rec->length;
3539 * backup a database to a file
3541 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3544 struct ctdb_dbid_map *dbmap=NULL;
3545 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3546 struct db_file_header dbhdr;
3547 struct ctdb_db_context *ctdb_db;
3548 struct backup_data *bd;
3551 const char *reason = NULL;
3554 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3558 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3560 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3564 for(i=0;i<dbmap->num;i++){
3567 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3568 if(!strcmp(argv[0], name)){
3569 talloc_free(discard_const(name));
3572 talloc_free(discard_const(name));
3574 if (i == dbmap->num) {
3575 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3576 talloc_free(tmp_ctx);
3580 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3581 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3583 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3585 talloc_free(tmp_ctx);
3589 uint32_t allow_unhealthy = 0;
3591 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3592 "AllowUnhealthyDBRead",
3595 if (allow_unhealthy != 1) {
3596 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3599 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3601 talloc_free(tmp_ctx);
3605 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3607 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3608 "tunnable AllowUnhealthyDBRead = %u\n",
3612 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3613 if (ctdb_db == NULL) {
3614 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3615 talloc_free(tmp_ctx);
3620 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3622 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3623 talloc_free(tmp_ctx);
3628 bd = talloc_zero(tmp_ctx, struct backup_data);
3630 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3631 talloc_free(tmp_ctx);
3635 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3636 if (bd->records == NULL) {
3637 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3638 talloc_free(tmp_ctx);
3642 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3643 bd->records->db_id = ctdb_db->db_id;
3644 /* traverse the database collecting all records */
3645 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3646 bd->traverse_error) {
3647 DEBUG(DEBUG_ERR,("Traverse error\n"));
3648 talloc_free(tmp_ctx);
3652 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3655 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3657 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3658 talloc_free(tmp_ctx);
3662 dbhdr.version = DB_VERSION;
3663 dbhdr.timestamp = time(NULL);
3664 dbhdr.persistent = dbmap->dbs[i].persistent;
3665 dbhdr.size = bd->len;
3666 if (strlen(argv[0]) >= MAX_DB_NAME) {
3667 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3670 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3671 ret = write(fh, &dbhdr, sizeof(dbhdr));
3673 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3676 ret = write(fh, bd->records, bd->len);
3678 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3687 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3690 talloc_free(tmp_ctx);
3695 * restore a database from a file
3697 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3700 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3703 struct db_file_header dbhdr;
3704 struct ctdb_db_context *ctdb_db;
3705 struct ctdb_node_map *nodemap=NULL;
3706 struct ctdb_vnn_map *vnnmap=NULL;
3708 struct ctdb_control_wipe_database w;
3710 uint32_t generation;
3715 if (argc < 1 || argc > 2) {
3716 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3720 fh = open(argv[0], O_RDONLY);
3722 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3723 talloc_free(tmp_ctx);
3727 read(fh, &dbhdr, sizeof(dbhdr));
3728 if (dbhdr.version != DB_VERSION) {
3729 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3730 talloc_free(tmp_ctx);
3734 dbname = dbhdr.name;
3739 outdata.dsize = dbhdr.size;
3740 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3741 if (outdata.dptr == NULL) {
3742 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3744 talloc_free(tmp_ctx);
3747 read(fh, outdata.dptr, outdata.dsize);
3750 tm = localtime(&dbhdr.timestamp);
3751 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3752 printf("Restoring database '%s' from backup @ %s\n",
3756 ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3757 if (ctdb_db == NULL) {
3758 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3759 talloc_free(tmp_ctx);
3763 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3765 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3766 talloc_free(tmp_ctx);
3771 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3773 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3774 talloc_free(tmp_ctx);
3778 /* freeze all nodes */
3779 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3780 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3781 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3787 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3788 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3789 talloc_free(tmp_ctx);
3794 generation = vnnmap->generation;
3795 data.dptr = (void *)&generation;
3796 data.dsize = sizeof(generation);
3798 /* start a cluster wide transaction */
3799 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3800 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3802 TIMELIMIT(), false, data,
3805 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3810 w.db_id = ctdb_db->db_id;
3811 w.transaction_id = generation;
3813 data.dptr = (void *)&w;
3814 data.dsize = sizeof(w);
3816 /* wipe all the remote databases. */
3817 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3818 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3820 TIMELIMIT(), false, data,
3823 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3824 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3825 talloc_free(tmp_ctx);
3829 /* push the database */
3830 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3831 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3833 TIMELIMIT(), false, outdata,
3836 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3837 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3838 talloc_free(tmp_ctx);
3842 data.dptr = (void *)&ctdb_db->db_id;
3843 data.dsize = sizeof(ctdb_db->db_id);
3845 /* mark the database as healthy */
3846 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3847 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3849 TIMELIMIT(), false, data,
3852 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3853 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3854 talloc_free(tmp_ctx);
3858 data.dptr = (void *)&generation;
3859 data.dsize = sizeof(generation);
3861 /* commit all the changes */
3862 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3864 TIMELIMIT(), false, data,
3867 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3868 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3869 talloc_free(tmp_ctx);
3874 /* thaw all nodes */
3875 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3876 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3882 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3883 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3884 talloc_free(tmp_ctx);
3889 talloc_free(tmp_ctx);
3894 * dump a database backup from a file
3896 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3898 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3900 struct db_file_header dbhdr;
3904 struct ctdb_rec_data *rec = NULL;
3905 struct ctdb_marshall_buffer *m;
3908 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3912 fh = open(argv[0], O_RDONLY);
3914 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3915 talloc_free(tmp_ctx);
3919 read(fh, &dbhdr, sizeof(dbhdr));
3920 if (dbhdr.version != DB_VERSION) {
3921 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3922 talloc_free(tmp_ctx);
3926 outdata.dsize = dbhdr.size;
3927 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3928 if (outdata.dptr == NULL) {
3929 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3931 talloc_free(tmp_ctx);
3934 read(fh, outdata.dptr, outdata.dsize);
3936 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3938 tm = localtime(&dbhdr.timestamp);
3939 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3940 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3941 dbhdr.name, m->db_id, tbuf);
3943 for (i=0; i < m->count; i++) {
3947 /* we do not want the header splitted, so we pass NULL*/
3948 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3951 ctdb_dumpdb_record(ctdb, key, data, stdout);
3954 printf("Dumped %d records\n", i);
3955 talloc_free(tmp_ctx);
3960 * wipe a database from a file
3962 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3966 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3968 struct ctdb_db_context *ctdb_db;
3969 struct ctdb_node_map *nodemap = NULL;
3970 struct ctdb_vnn_map *vnnmap = NULL;
3972 struct ctdb_control_wipe_database w;
3974 uint32_t generation;
3975 struct ctdb_dbid_map *dbmap = NULL;
3978 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3982 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3985 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3990 for(i=0;i<dbmap->num;i++){
3993 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3994 dbmap->dbs[i].dbid, tmp_ctx, &name);
3995 if(!strcmp(argv[0], name)){
3996 talloc_free(discard_const(name));
3999 talloc_free(discard_const(name));
4001 if (i == dbmap->num) {
4002 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
4004 talloc_free(tmp_ctx);
4008 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
4009 if (ctdb_db == NULL) {
4010 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
4012 talloc_free(tmp_ctx);
4016 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
4019 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
4021 talloc_free(tmp_ctx);
4025 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4028 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
4030 talloc_free(tmp_ctx);
4034 /* freeze all nodes */
4035 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4036 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
4037 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
4044 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
4045 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
4046 CTDB_RECOVERY_ACTIVE);
4047 talloc_free(tmp_ctx);
4052 generation = vnnmap->generation;
4053 data.dptr = (void *)&generation;
4054 data.dsize = sizeof(generation);
4056 /* start a cluster wide transaction */
4057 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4058 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
4060 TIMELIMIT(), false, data,
4064 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
4065 "transactions.\n"));
4069 w.db_id = ctdb_db->db_id;
4070 w.transaction_id = generation;
4072 data.dptr = (void *)&w;
4073 data.dsize = sizeof(w);
4075 /* wipe all the remote databases. */
4076 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4077 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
4079 TIMELIMIT(), false, data,
4082 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
4083 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4084 talloc_free(tmp_ctx);
4088 data.dptr = (void *)&ctdb_db->db_id;
4089 data.dsize = sizeof(ctdb_db->db_id);
4091 /* mark the database as healthy */
4092 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4093 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4095 TIMELIMIT(), false, data,
4098 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4099 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4100 talloc_free(tmp_ctx);
4104 data.dptr = (void *)&generation;
4105 data.dsize = sizeof(generation);
4107 /* commit all the changes */
4108 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4110 TIMELIMIT(), false, data,
4113 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4114 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4115 talloc_free(tmp_ctx);
4119 /* thaw all nodes */
4120 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4121 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4127 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4128 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4129 talloc_free(tmp_ctx);
4133 talloc_free(tmp_ctx);
4138 * set flags of a node in the nodemap
4140 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4147 struct ctdb_node_flag_change c;
4154 if (sscanf(argv[0], "%d", &node) != 1) {
4155 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4159 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4160 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4167 c.new_flags = flags;
4169 data.dsize = sizeof(c);
4170 data.dptr = (unsigned char *)&c;
4172 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4173 data, NULL, NULL, &status, NULL, NULL);
4174 if (ret != 0 || status != 0) {
4175 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4184 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4190 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4191 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4192 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4193 if (ret != 0 || res != 0) {
4194 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4195 talloc_free(tmp_ctx);
4198 write(1, data.dptr, data.dsize);
4199 talloc_free(tmp_ctx);
4204 handler for memory dumps
4206 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4207 TDB_DATA data, void *private_data)
4209 write(1, data.dptr, data.dsize);
4214 dump memory usage on the recovery daemon
4216 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4220 struct rd_memdump_reply rd;
4222 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4224 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4227 rd.srvid = getpid();
4229 /* register a message port for receiveing the reply so that we
4230 can receive the reply
4232 ctdb_client_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4235 data.dptr = (uint8_t *)&rd;
4236 data.dsize = sizeof(rd);
4238 ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4240 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4244 /* this loop will terminate when we have received the reply */
4246 event_loop_once(ctdb->ev);
4253 send a message to a srvid
4255 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4257 unsigned long srvid;
4265 srvid = strtoul(argv[0], NULL, 0);
4267 data.dptr = (uint8_t *)discard_const(argv[1]);
4268 data.dsize= strlen(argv[1]);
4270 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4272 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4280 handler for msglisten
4282 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4283 TDB_DATA data, void *private_data)
4287 printf("Message received: ");
4288 for (i=0;i<data.dsize;i++) {
4289 printf("%c", data.dptr[i]);
4295 listen for messages on a messageport
4297 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4303 /* register a message port and listen for messages
4305 ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4306 printf("Listening for messages on srvid:%d\n", (int)srvid);
4309 event_loop_once(ctdb->ev);
4316 list all nodes in the cluster
4317 if the daemon is running, we read the data from the daemon.
4318 if the daemon is not running we parse the nodes file directly
4320 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4323 struct ctdb_node_map *nodemap=NULL;
4326 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4328 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4332 for(i=0;i<nodemap->num;i++){
4333 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4336 if (options.machinereadable){
4337 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4339 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4343 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4344 struct pnn_node *pnn_nodes;
4345 struct pnn_node *pnn_node;
4347 pnn_nodes = read_nodes_file(mem_ctx);
4348 if (pnn_nodes == NULL) {
4349 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4350 talloc_free(mem_ctx);
4354 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4355 ctdb_sock_addr addr;
4357 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4358 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4359 talloc_free(mem_ctx);
4363 if (options.machinereadable){
4364 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4366 printf("%s\n", pnn_node->addr);
4369 talloc_free(mem_ctx);
4376 reload the nodes file on the local node
4378 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4382 struct ctdb_node_map *nodemap=NULL;
4384 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4386 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4390 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4392 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4396 /* reload the nodes file on all remote nodes */
4397 for (i=0;i<nodemap->num;i++) {
4398 if (nodemap->nodes[i].pnn == mypnn) {
4401 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4402 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4403 nodemap->nodes[i].pnn);
4405 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4409 /* reload the nodes file on the local node */
4410 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4411 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4413 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4416 /* initiate a recovery */
4417 control_recover(ctdb, argc, argv);
4423 static const struct {
4425 int (*fn)(struct ctdb_context *, int, const char **);
4427 bool without_daemon; /* can be run without daemon running ? */
4430 } ctdb_commands[] = {
4432 { "version", control_version, true, false, "show version of ctdb" },
4434 { "status", control_status, true, false, "show node status" },
4435 { "uptime", control_uptime, true, false, "show node uptime" },
4436 { "ping", control_ping, true, false, "ping all nodes" },
4437 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4438 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4439 { "listvars", control_listvars, true, false, "list tunable variables"},
4440 { "statistics", control_statistics, false, false, "show statistics" },
4441 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4442 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4443 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4444 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4445 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4446 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4447 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4448 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4449 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4450 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4451 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4452 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4453 { "lvs", control_lvs, true, false, "show lvs configuration" },
4454 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4455 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4456 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4457 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4458 { "getdebug", control_getdebug, true, false, "get debug level" },
4459 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4460 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4461 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4462 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4463 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4464 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4465 { "disable", control_disable, true, false, "disable a nodes public IP" },
4466 { "enable", control_enable, true, false, "enable a nodes public IP" },
4467 { "stop", control_stop, true, false, "stop a node" },
4468 { "continue", control_continue, true, false, "re-start a stopped node" },
4469 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4470 { "unban", control_unban, true, false, "unban a node" },
4471 { "showban", control_showban, true, false, "show ban information"},
4472 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4473 { "recover", control_recover, true, false, "force recovery" },
4474 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4475 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4476 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4477 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4478 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4479 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4480 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4481 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip> [<port>]" },
4482 { "addtickle", control_add_tickle, false, false, "add a tickle for this ip", "<ip>:<port> <ip>:<port>" },
4484 { "deltickle", control_del_tickle, false, false, "delete a tickle from this ip", "<ip>:<port> <ip>:<port>" },
4486 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4487 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4488 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4489 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4490 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4491 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4492 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4493 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4494 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4495 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4496 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4497 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4498 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4499 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file> [dbname]"},
4500 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4501 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4502 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4503 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4504 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4505 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4506 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4507 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4508 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4509 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4510 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4511 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4512 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4513 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4514 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4515 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4516 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4517 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4518 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4524 static void usage(void)
4528 "Usage: ctdb [options] <control>\n" \
4530 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4531 " -Y generate machinereadable output\n"
4532 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4533 printf("Controls:\n");
4534 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4535 printf(" %-15s %-27s %s\n",
4536 ctdb_commands[i].name,
4537 ctdb_commands[i].args?ctdb_commands[i].args:"",
4538 ctdb_commands[i].msg);
4544 static void ctdb_alarm(int sig)
4546 printf("Maximum runtime exceeded - exiting\n");
4553 int main(int argc, const char *argv[])
4555 struct ctdb_context *ctdb;
4556 char *nodestring = NULL;
4557 struct poptOption popt_options[] = {
4560 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4561 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4562 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4563 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4567 const char **extra_argv;
4571 struct event_context *ev;
4572 const char *control;
4576 /* set some defaults */
4577 options.maxruntime = 0;
4578 options.timelimit = 3;
4579 options.pnn = CTDB_CURRENT_NODE;
4581 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4583 while ((opt = poptGetNextOpt(pc)) != -1) {
4586 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4587 poptBadOption(pc, 0), poptStrerror(opt)));
4592 /* setup the remaining options for the main program to use */
4593 extra_argv = poptGetArgs(pc);
4596 while (extra_argv[extra_argc]) extra_argc++;
4599 if (extra_argc < 1) {
4603 if (options.maxruntime == 0) {
4604 const char *ctdb_timeout;
4605 ctdb_timeout = getenv("CTDB_TIMEOUT");
4606 if (ctdb_timeout != NULL) {
4607 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4609 /* default timeout is 120 seconds */
4610 options.maxruntime = 120;
4614 signal(SIGALRM, ctdb_alarm);
4615 alarm(options.maxruntime);
4617 /* setup the node number to contact */
4618 if (nodestring != NULL) {
4619 if (strcmp(nodestring, "all") == 0) {
4620 options.pnn = CTDB_BROADCAST_ALL;
4622 options.pnn = strtoul(nodestring, NULL, 0);
4626 control = extra_argv[0];
4628 ev = event_context_init(NULL);
4630 DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
4633 tevent_loop_allow_nesting(ev);
4635 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4636 if (strcmp(control, ctdb_commands[i].name) == 0) {
4639 if (ctdb_commands[i].without_daemon == true) {
4643 /* initialise ctdb */
4644 ctdb = ctdb_cmdline_client(ev);
4646 if (ctdb_commands[i].without_daemon == false) {
4647 const char *socket_name;
4650 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4654 /* initialize a libctdb connection as well */
4655 socket_name = ctdb_get_socketname(ctdb);
4656 ctdb_connection = ctdb_connect(socket_name,
4657 ctdb_log_file, stderr);
4658 if (ctdb_connection == NULL) {
4659 fprintf(stderr, "Failed to connect to daemon from libctdb\n");
4663 /* verify the node exists */
4666 if (options.pnn == CTDB_CURRENT_NODE) {
4668 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4676 if (ctdb_commands[i].auto_all &&
4677 options.pnn == CTDB_BROADCAST_ALL) {
4682 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4683 CTDB_NO_MEMORY(ctdb, nodes);
4685 for (j=0;j<num_nodes;j++) {
4686 options.pnn = nodes[j];
4687 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4691 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4697 if (i == ARRAY_SIZE(ctdb_commands)) {
4698 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));