4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "lib/events/events.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "system/locale.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_private.h"
31 #include "../common/rb_tree.h"
34 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
35 #define ERR_NONODE 21 /* node does not exist */
36 #define ERR_DISNODE 22 /* node is disconnected */
38 static void usage(void);
47 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
50 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
53 #define XSTR(x) STR(x)
54 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
61 verify that a node exists and is reachable
63 static void verify_node(struct ctdb_context *ctdb)
66 struct ctdb_node_map *nodemap=NULL;
68 if (options.pnn == CTDB_CURRENT_NODE) {
71 if (options.pnn == CTDB_BROADCAST_ALL) {
75 /* verify the node exists */
76 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
77 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
80 if (options.pnn >= nodemap->num) {
81 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
84 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
85 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
88 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
89 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
93 /* verify we can access the node */
94 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
96 DEBUG(DEBUG_ERR,("Can not ban node. Node is not operational.\n"));
102 check if a database exists
104 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
107 struct ctdb_dbid_map *dbmap=NULL;
109 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
111 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
115 for(i=0;i<dbmap->num;i++){
118 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
119 if (!strcmp(name, db_name)) {
128 see if a process exists
130 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
138 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
139 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
143 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
145 printf("%u:%u exists\n", pnn, pid);
147 printf("%u:%u does not exist\n", pnn, pid);
153 display statistics structure
155 static void show_statistics(struct ctdb_statistics *s)
157 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
159 const char *prefix=NULL;
165 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
166 STATISTICS_FIELD(num_clients),
167 STATISTICS_FIELD(frozen),
168 STATISTICS_FIELD(recovering),
169 STATISTICS_FIELD(client_packets_sent),
170 STATISTICS_FIELD(client_packets_recv),
171 STATISTICS_FIELD(node_packets_sent),
172 STATISTICS_FIELD(node_packets_recv),
173 STATISTICS_FIELD(keepalive_packets_sent),
174 STATISTICS_FIELD(keepalive_packets_recv),
175 STATISTICS_FIELD(node.req_call),
176 STATISTICS_FIELD(node.reply_call),
177 STATISTICS_FIELD(node.req_dmaster),
178 STATISTICS_FIELD(node.reply_dmaster),
179 STATISTICS_FIELD(node.reply_error),
180 STATISTICS_FIELD(node.req_message),
181 STATISTICS_FIELD(node.req_control),
182 STATISTICS_FIELD(node.reply_control),
183 STATISTICS_FIELD(client.req_call),
184 STATISTICS_FIELD(client.req_message),
185 STATISTICS_FIELD(client.req_control),
186 STATISTICS_FIELD(timeouts.call),
187 STATISTICS_FIELD(timeouts.control),
188 STATISTICS_FIELD(timeouts.traverse),
189 STATISTICS_FIELD(total_calls),
190 STATISTICS_FIELD(pending_calls),
191 STATISTICS_FIELD(lockwait_calls),
192 STATISTICS_FIELD(pending_lockwait_calls),
193 STATISTICS_FIELD(childwrite_calls),
194 STATISTICS_FIELD(pending_childwrite_calls),
195 STATISTICS_FIELD(memory_used),
196 STATISTICS_FIELD(max_hop_count),
198 printf("CTDB version %u\n", CTDB_VERSION);
199 for (i=0;i<ARRAY_SIZE(fields);i++) {
200 if (strchr(fields[i].name, '.')) {
201 preflen = strcspn(fields[i].name, ".")+1;
202 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
203 prefix = fields[i].name;
204 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
209 printf(" %*s%-22s%*s%10u\n",
211 fields[i].name+preflen,
213 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
215 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
216 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
218 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
219 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
220 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
221 talloc_free(tmp_ctx);
225 display remote ctdb statistics combined from all nodes
227 static int control_statistics_all(struct ctdb_context *ctdb)
230 struct ctdb_statistics statistics;
234 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
235 CTDB_NO_MEMORY(ctdb, nodes);
237 ZERO_STRUCT(statistics);
239 for (i=0;i<num_nodes;i++) {
240 struct ctdb_statistics s1;
242 uint32_t *v1 = (uint32_t *)&s1;
243 uint32_t *v2 = (uint32_t *)&statistics;
245 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
246 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
248 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
251 for (j=0;j<num_ints;j++) {
254 statistics.max_hop_count =
255 MAX(statistics.max_hop_count, s1.max_hop_count);
256 statistics.max_call_latency =
257 MAX(statistics.max_call_latency, s1.max_call_latency);
258 statistics.max_lockwait_latency =
259 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
262 printf("Gathered statistics for %u nodes\n", num_nodes);
263 show_statistics(&statistics);
268 display remote ctdb statistics
270 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
273 struct ctdb_statistics statistics;
275 if (options.pnn == CTDB_BROADCAST_ALL) {
276 return control_statistics_all(ctdb);
279 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
281 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
284 show_statistics(&statistics);
290 reset remote ctdb statistics
292 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
296 ret = ctdb_statistics_reset(ctdb, options.pnn);
298 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
306 display uptime of remote node
308 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
311 struct ctdb_uptime *uptime = NULL;
312 int tmp, days, hours, minutes, seconds;
314 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
316 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
320 if (options.machinereadable){
321 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
322 printf(":%u:%u:%u:%lf\n",
323 (unsigned int)uptime->current_time.tv_sec,
324 (unsigned int)uptime->ctdbd_start_time.tv_sec,
325 (unsigned int)uptime->last_recovery_finished.tv_sec,
326 timeval_delta(&uptime->last_recovery_finished,
327 &uptime->last_recovery_started)
332 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
334 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
342 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
344 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
352 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
354 printf("Duration of last recovery/failover: %lf seconds\n",
355 timeval_delta(&uptime->last_recovery_finished,
356 &uptime->last_recovery_started));
362 show the PNN of the current node
364 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
368 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
370 DEBUG(DEBUG_ERR, ("Unable to get pnn from local node."));
374 printf("PNN:%d\n", mypnn);
380 struct pnn_node *next;
385 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
387 const char *nodes_list;
391 struct pnn_node *pnn_nodes = NULL;
392 struct pnn_node *pnn_node;
393 struct pnn_node *tmp_node;
395 /* read the nodes file */
396 nodes_list = getenv("CTDB_NODES");
397 if (nodes_list == NULL) {
398 nodes_list = "/etc/ctdb/nodes";
400 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
404 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
407 for (i=0, pnn=0; i<nlines; i++) {
411 /* strip leading spaces */
412 while((*node == ' ') || (*node == '\t')) {
419 if (strcmp(node, "") == 0) {
422 pnn_node = talloc(mem_ctx, struct pnn_node);
423 pnn_node->pnn = pnn++;
424 pnn_node->addr = talloc_strdup(pnn_node, node);
425 pnn_node->next = pnn_nodes;
426 pnn_nodes = pnn_node;
429 /* swap them around so we return them in incrementing order */
430 pnn_node = pnn_nodes;
434 pnn_node = pnn_node->next;
436 tmp_node->next = pnn_nodes;
437 pnn_nodes = tmp_node;
444 show the PNN of the current node
445 discover the pnn by loading the nodes file and try to bind to all
446 addresses one at a time until the ip address is found.
448 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
450 TALLOC_CTX *mem_ctx = talloc_new(NULL);
451 struct pnn_node *pnn_nodes;
452 struct pnn_node *pnn_node;
454 pnn_nodes = read_nodes_file(mem_ctx);
455 if (pnn_nodes == NULL) {
456 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
457 talloc_free(mem_ctx);
461 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
464 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
465 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
466 talloc_free(mem_ctx);
470 if (ctdb_sys_have_ip(&addr)) {
471 printf("PNN:%d\n", pnn_node->pnn);
472 talloc_free(mem_ctx);
477 printf("Failed to detect which PNN this node is\n");
478 talloc_free(mem_ctx);
483 display remote ctdb status
485 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
488 struct ctdb_vnn_map *vnnmap=NULL;
489 struct ctdb_node_map *nodemap=NULL;
490 uint32_t recmode, recmaster;
493 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
498 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
500 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
504 if(options.machinereadable){
505 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:\n");
506 for(i=0;i<nodemap->num;i++){
507 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
510 printf(":%d:%s:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
511 ctdb_addr_to_str(&nodemap->nodes[i].addr),
512 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
513 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
514 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
515 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
516 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
521 printf("Number of nodes:%d\n", nodemap->num);
522 for(i=0;i<nodemap->num;i++){
523 static const struct {
527 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
528 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
529 { NODE_FLAGS_BANNED, "BANNED" },
530 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
531 { NODE_FLAGS_DELETED, "DELETED" },
532 { NODE_FLAGS_STOPPED, "STOPPED" },
534 char *flags_str = NULL;
537 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
540 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
541 if (nodemap->nodes[i].flags & flag_names[j].flag) {
542 if (flags_str == NULL) {
543 flags_str = talloc_strdup(ctdb, flag_names[j].name);
545 flags_str = talloc_asprintf_append(flags_str, "|%s",
548 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
551 if (flags_str == NULL) {
552 flags_str = talloc_strdup(ctdb, "OK");
553 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
555 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
556 ctdb_addr_to_str(&nodemap->nodes[i].addr),
558 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
559 talloc_free(flags_str);
562 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
564 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
567 if (vnnmap->generation == INVALID_GENERATION) {
568 printf("Generation:INVALID\n");
570 printf("Generation:%d\n",vnnmap->generation);
572 printf("Size:%d\n",vnnmap->size);
573 for(i=0;i<vnnmap->size;i++){
574 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
577 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
579 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
582 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
584 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
586 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
589 printf("Recovery master:%d\n",recmaster);
596 struct natgw_node *next;
601 display the list of nodes belonging to this natgw configuration
603 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
606 const char *natgw_list;
609 struct natgw_node *natgw_nodes = NULL;
610 struct natgw_node *natgw_node;
611 struct ctdb_node_map *nodemap=NULL;
614 /* read the natgw nodes file into a linked list */
615 natgw_list = getenv("NATGW_NODES");
616 if (natgw_list == NULL) {
617 natgw_list = "/etc/ctdb/natgw_nodes";
619 lines = file_lines_load(natgw_list, &nlines, ctdb);
621 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
624 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
627 for (i=0;i<nlines;i++) {
631 /* strip leading spaces */
632 while((*node == ' ') || (*node == '\t')) {
638 if (strcmp(node, "") == 0) {
641 natgw_node = talloc(ctdb, struct natgw_node);
642 natgw_node->addr = talloc_strdup(natgw_node, node);
643 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
644 natgw_node->next = natgw_nodes;
645 natgw_nodes = natgw_node;
648 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
650 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
655 while(i<nodemap->num) {
656 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
657 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
662 /* this node was not in the natgw so we just remove it from
665 if ((natgw_node == NULL)
666 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
669 for (j=i+1; j<nodemap->num; j++) {
670 nodemap->nodes[j-1] = nodemap->nodes[j];
679 /* pick a node to be natgwmaster
680 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
682 for(i=0;i<nodemap->num;i++){
683 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
684 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
688 /* we couldnt find any healthy node, try unhealthy ones */
689 if (i == nodemap->num) {
690 for(i=0;i<nodemap->num;i++){
691 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
692 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
697 /* unless all nodes are STOPPED, when we pick one anyway */
698 if (i == nodemap->num) {
699 for(i=0;i<nodemap->num;i++){
700 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
701 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
705 /* or if we still can not find any */
706 if (i == nodemap->num) {
707 printf("-1 0.0.0.0\n");
711 /* print the pruned list of nodes belonging to this natgw list */
712 for(i=0;i<nodemap->num;i++){
713 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
716 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
717 ctdb_addr_to_str(&nodemap->nodes[i].addr),
718 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
719 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
720 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
721 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
722 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
730 display the status of the monitoring scripts
732 static int control_scriptstatus(struct ctdb_context *ctdb, int argc, const char **argv)
735 struct ctdb_monitoring_wire *script_status;
737 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, &script_status);
739 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
743 printf("%d scripts were executed last monitoring cycle\n", script_status->num_scripts);
744 for (i=0; i<script_status->num_scripts; i++) {
745 if (script_status->scripts[i].disabled) {
746 printf("%-20s Status:DISABLED\n",
747 script_status->scripts[i].name);
750 printf("%-20s Status:%s ",
751 script_status->scripts[i].name,
752 script_status->scripts[i].timedout?"TIMEDOUT":script_status->scripts[i].status==0?"OK":"ERROR");
753 if (script_status->scripts[i].timedout == 0) {
754 printf("Duration:%.3lf ",
755 timeval_delta(&script_status->scripts[i].finished,
756 &script_status->scripts[i].start));
759 ctime(&script_status->scripts[i].start.tv_sec));
760 if ((script_status->scripts[i].timedout != 0)
761 || (script_status->scripts[i].status != 0) ) {
762 printf(" OUTPUT:%s\n",
763 script_status->scripts[i].output);
772 enable an eventscript
774 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
782 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
784 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
792 disable an eventscript
794 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
802 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
804 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
812 display the pnn of the recovery master
814 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
819 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
821 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
824 printf("%d\n",recmaster);
830 get a list of all tickles for this pnn
832 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
834 struct ctdb_control_tcp_tickle_list *list;
842 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
843 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
847 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
849 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
853 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
854 printf("Num tickles:%u\n", list->tickles.num);
855 for (i=0;i<list->tickles.num;i++) {
856 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
857 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));
867 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
869 struct ctdb_all_public_ips *ips;
870 struct ctdb_public_ip ip;
873 uint32_t disable_time;
875 struct ctdb_node_map *nodemap=NULL;
876 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
879 data.dptr = (uint8_t*)&disable_time;
880 data.dsize = sizeof(disable_time);
881 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
883 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
889 /* read the public ip list from the node */
890 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
892 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
893 talloc_free(tmp_ctx);
897 for (i=0;i<ips->num;i++) {
898 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
903 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
904 pnn, ctdb_addr_to_str(addr)));
905 talloc_free(tmp_ctx);
912 data.dptr = (uint8_t *)&ip;
913 data.dsize = sizeof(ip);
915 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
917 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
918 talloc_free(tmp_ctx);
922 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
923 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
930 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
931 talloc_free(tmp_ctx);
935 ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), pnn, &ip);
937 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
938 talloc_free(tmp_ctx);
942 talloc_free(tmp_ctx);
947 move/failover an ip address to a specific node
949 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
959 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
960 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
965 if (sscanf(argv[1], "%u", &pnn) != 1) {
966 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
970 if (move_ip(ctdb, &addr, pnn) != 0) {
971 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
978 void getips_store_callback(void *param, void *data)
980 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
981 struct ctdb_all_public_ips *ips = param;
985 ips->ips[i].pnn = node_ip->pnn;
986 ips->ips[i].addr = node_ip->addr;
989 void getips_count_callback(void *param, void *data)
991 uint32_t *count = param;
997 static uint32_t *ip_key(ctdb_sock_addr *ip)
999 static uint32_t key[IP_KEYLEN];
1001 bzero(key, sizeof(key));
1003 switch (ip->sa.sa_family) {
1005 key[0] = ip->ip.sin_addr.s_addr;
1008 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1009 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1010 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1011 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1014 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1021 static void *add_ip_callback(void *parm, void *data)
1027 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1029 struct ctdb_all_public_ips *tmp_ips;
1030 struct ctdb_node_map *nodemap=NULL;
1031 trbt_tree_t *ip_tree;
1035 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1037 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1041 ip_tree = trbt_create(tmp_ctx, 0);
1043 for(i=0;i<nodemap->num;i++){
1044 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1047 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1051 /* read the public ip list from this node */
1052 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1054 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1058 for (j=0; j<tmp_ips->num;j++) {
1059 struct ctdb_public_ip *node_ip;
1061 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1062 node_ip->pnn = tmp_ips->ips[j].pnn;
1063 node_ip->addr = tmp_ips->ips[j].addr;
1065 trbt_insertarray32_callback(ip_tree,
1066 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1070 talloc_free(tmp_ips);
1075 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1077 len = offsetof(struct ctdb_all_public_ips, ips) +
1078 count*sizeof(struct ctdb_public_ip);
1079 tmp_ips = talloc_zero_size(tmp_ctx, len);
1080 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1089 * scans all other nodes and returns a pnn for another node that can host this
1093 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1095 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1096 struct ctdb_all_public_ips *ips;
1097 struct ctdb_node_map *nodemap=NULL;
1100 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1102 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1103 talloc_free(tmp_ctx);
1107 for(i=0;i<nodemap->num;i++){
1108 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1111 if (nodemap->nodes[i].pnn == options.pnn) {
1115 /* read the public ip list from this node */
1116 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1118 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1122 for (j=0;j<ips->num;j++) {
1123 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1124 talloc_free(tmp_ctx);
1125 return nodemap->nodes[i].pnn;
1131 talloc_free(tmp_ctx);
1136 add a public ip address to a node
1138 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1144 ctdb_sock_addr addr;
1145 struct ctdb_control_ip_iface *pub;
1146 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1147 struct ctdb_all_public_ips *ips;
1151 talloc_free(tmp_ctx);
1155 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1156 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1157 talloc_free(tmp_ctx);
1161 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1163 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1164 talloc_free(tmp_ctx);
1169 /* check if some other node is already serving this ip, if not,
1172 for (i=0;i<ips->num;i++) {
1173 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1178 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1179 pub = talloc_size(tmp_ctx, len);
1180 CTDB_NO_MEMORY(ctdb, pub);
1184 pub->len = strlen(argv[1])+1;
1185 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1187 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1189 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1190 talloc_free(tmp_ctx);
1194 if (i == ips->num) {
1195 /* no one has this ip so we claim it */
1198 pnn = ips->ips[i].pnn;
1201 if (move_ip(ctdb, &addr, pnn) != 0) {
1202 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1206 talloc_free(tmp_ctx);
1210 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1212 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1214 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1215 struct ctdb_node_map *nodemap=NULL;
1216 struct ctdb_all_public_ips *ips;
1219 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1221 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1225 /* remove it from the nodes that are not hosting the ip currently */
1226 for(i=0;i<nodemap->num;i++){
1227 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1230 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1231 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1235 for (j=0;j<ips->num;j++) {
1236 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1244 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1248 options.pnn = nodemap->nodes[i].pnn;
1249 control_delip(ctdb, argc, argv);
1253 /* remove it from every node (also the one hosting it) */
1254 for(i=0;i<nodemap->num;i++){
1255 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1258 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1259 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1263 for (j=0;j<ips->num;j++) {
1264 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1272 options.pnn = nodemap->nodes[i].pnn;
1273 control_delip(ctdb, argc, argv);
1276 talloc_free(tmp_ctx);
1281 delete a public ip address from a node
1283 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1286 ctdb_sock_addr addr;
1287 struct ctdb_control_ip_iface pub;
1288 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1289 struct ctdb_all_public_ips *ips;
1292 talloc_free(tmp_ctx);
1296 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1297 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1301 if (options.pnn == CTDB_BROADCAST_ALL) {
1302 return control_delip_all(ctdb, argc, argv, &addr);
1309 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1311 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1312 talloc_free(tmp_ctx);
1316 for (i=0;i<ips->num;i++) {
1317 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1323 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1324 ctdb_addr_to_str(&addr)));
1325 talloc_free(tmp_ctx);
1329 if (ips->ips[i].pnn == options.pnn) {
1330 ret = find_other_host_for_public_ip(ctdb, &addr);
1332 if (move_ip(ctdb, &addr, ret) != 0) {
1333 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1339 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1341 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1342 talloc_free(tmp_ctx);
1346 talloc_free(tmp_ctx);
1351 kill a tcp connection
1353 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1356 struct ctdb_control_killtcp killtcp;
1362 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1363 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1367 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1368 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1372 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1374 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1385 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1388 ctdb_sock_addr addr;
1394 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1395 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1399 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1401 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1409 register a server id
1411 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1414 struct ctdb_server_id server_id;
1420 server_id.pnn = strtoul(argv[0], NULL, 0);
1421 server_id.type = strtoul(argv[1], NULL, 0);
1422 server_id.server_id = strtoul(argv[2], NULL, 0);
1424 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1426 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1433 unregister a server id
1435 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1438 struct ctdb_server_id server_id;
1444 server_id.pnn = strtoul(argv[0], NULL, 0);
1445 server_id.type = strtoul(argv[1], NULL, 0);
1446 server_id.server_id = strtoul(argv[2], NULL, 0);
1448 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1450 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1457 check if a server id exists
1459 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1463 struct ctdb_server_id server_id;
1469 server_id.pnn = strtoul(argv[0], NULL, 0);
1470 server_id.type = strtoul(argv[1], NULL, 0);
1471 server_id.server_id = strtoul(argv[2], NULL, 0);
1473 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1475 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1480 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1482 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1488 get a list of all server ids that are registered on a node
1490 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1493 struct ctdb_server_id_list *server_ids;
1495 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1497 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1501 for (i=0; i<server_ids->num; i++) {
1502 printf("Server id %d:%d:%d\n",
1503 server_ids->server_ids[i].pnn,
1504 server_ids->server_ids[i].type,
1505 server_ids->server_ids[i].server_id);
1512 send a tcp tickle ack
1514 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1517 ctdb_sock_addr src, dst;
1523 if (!parse_ip_port(argv[0], &src)) {
1524 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1528 if (!parse_ip_port(argv[1], &dst)) {
1529 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1533 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1537 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1544 display public ip status
1546 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1549 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1550 struct ctdb_all_public_ips *ips;
1552 if (options.pnn == CTDB_BROADCAST_ALL) {
1553 /* read the list of public ips from all nodes */
1554 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1556 /* read the public ip list from this node */
1557 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1560 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1561 talloc_free(tmp_ctx);
1565 if (options.machinereadable){
1566 printf(":Public IP:Node:\n");
1568 if (options.pnn == CTDB_BROADCAST_ALL) {
1569 printf("Public IPs on ALL nodes\n");
1571 printf("Public IPs on node %u\n", options.pnn);
1575 for (i=1;i<=ips->num;i++) {
1576 if (options.machinereadable){
1577 printf(":%s:%d:\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1579 printf("%s %d\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1583 talloc_free(tmp_ctx);
1588 display pid of a ctdb daemon
1590 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1595 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1597 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1600 printf("Pid:%d\n", pid);
1606 handler for receiving the response to ipreallocate
1608 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1609 TDB_DATA data, void *private_data)
1614 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1616 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1618 event_add_timed(ctdb->ev, ctdb,
1619 timeval_current_ofs(1, 0),
1620 ctdb_every_second, ctdb);
1624 ask the recovery daemon on the recovery master to perform a ip reallocation
1626 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1630 struct takeover_run_reply rd;
1632 struct ctdb_node_map *nodemap=NULL;
1634 struct timeval tv = timeval_current();
1636 /* we need some events to trigger so we can timeout and restart
1639 event_add_timed(ctdb->ev, ctdb,
1640 timeval_current_ofs(1, 0),
1641 ctdb_every_second, ctdb);
1643 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1645 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1648 rd.srvid = getpid();
1650 /* register a message port for receiveing the reply so that we
1651 can receive the reply
1653 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
1655 data.dptr = (uint8_t *)&rd;
1656 data.dsize = sizeof(rd);
1660 DEBUG(DEBUG_ERR,("Failed waiting for cluster convergense\n"));
1664 /* check that there are valid nodes available */
1665 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
1666 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1669 for (i=0; i<nodemap->num;i++) {
1670 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
1674 if (i==nodemap->num) {
1675 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
1680 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
1682 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1686 /* verify the node exists */
1687 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
1688 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1693 /* check tha there are nodes available that can act as a recmaster */
1694 for (i=0; i<nodemap->num; i++) {
1695 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1700 if (i == nodemap->num) {
1701 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
1705 /* verify the recovery master is not STOPPED, nor BANNED */
1706 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1707 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1714 /* verify the recovery master is not STOPPED, nor BANNED */
1715 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1716 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1722 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
1724 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
1728 tv = timeval_current();
1729 /* this loop will terminate when we have received the reply */
1730 while (timeval_elapsed(&tv) < 3.0) {
1731 event_loop_once(ctdb->ev);
1734 DEBUG(DEBUG_INFO,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
1744 disable a remote node
1746 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
1749 struct ctdb_node_map *nodemap=NULL;
1752 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
1754 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
1760 /* read the nodemap and verify the change took effect */
1761 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1762 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1766 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
1767 ret = control_ipreallocate(ctdb, argc, argv);
1769 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1777 enable a disabled remote node
1779 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
1783 struct ctdb_node_map *nodemap=NULL;
1786 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
1788 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
1794 /* read the nodemap and verify the change took effect */
1795 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1796 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1800 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
1801 ret = control_ipreallocate(ctdb, argc, argv);
1803 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1813 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
1816 struct ctdb_node_map *nodemap=NULL;
1819 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
1821 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
1826 /* read the nodemap and verify the change took effect */
1827 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1828 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1832 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
1833 ret = control_ipreallocate(ctdb, argc, argv);
1835 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1843 restart a stopped remote node
1845 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
1849 struct ctdb_node_map *nodemap=NULL;
1852 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
1854 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
1860 /* read the nodemap and verify the change took effect */
1861 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1862 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1866 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
1867 ret = control_ipreallocate(ctdb, argc, argv);
1869 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1876 static uint32_t get_generation(struct ctdb_context *ctdb)
1878 struct ctdb_vnn_map *vnnmap=NULL;
1881 /* wait until the recmaster is not in recovery mode */
1883 uint32_t recmode, recmaster;
1885 if (vnnmap != NULL) {
1886 talloc_free(vnnmap);
1890 /* get the recmaster */
1891 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
1893 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1897 /* get recovery mode */
1898 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
1900 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
1904 /* get the current generation number */
1905 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
1907 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
1911 if ((recmode == CTDB_RECOVERY_NORMAL)
1912 && (vnnmap->generation != 1)){
1913 return vnnmap->generation;
1920 ban a node from the cluster
1922 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
1925 struct ctdb_node_map *nodemap=NULL;
1926 struct ctdb_ban_time bantime;
1932 /* verify the node exists */
1933 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1935 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1939 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
1940 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
1944 bantime.pnn = options.pnn;
1945 bantime.time = strtoul(argv[0], NULL, 0);
1947 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
1949 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
1953 ret = control_ipreallocate(ctdb, argc, argv);
1955 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1964 unban a node from the cluster
1966 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
1969 struct ctdb_node_map *nodemap=NULL;
1970 struct ctdb_ban_time bantime;
1972 /* verify the node exists */
1973 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1975 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1979 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
1980 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
1984 bantime.pnn = options.pnn;
1987 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
1989 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
1993 ret = control_ipreallocate(ctdb, argc, argv);
1995 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2004 show ban information for a node
2006 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2009 struct ctdb_node_map *nodemap=NULL;
2010 struct ctdb_ban_time *bantime;
2012 /* verify the node exists */
2013 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2015 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2019 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2021 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2025 if (bantime->time == 0) {
2026 printf("Node %u is not banned\n", bantime->pnn);
2028 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2037 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2041 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2043 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2053 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2056 uint32_t generation, next_generation;
2058 /* record the current generation number */
2059 generation = get_generation(ctdb);
2061 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2063 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2067 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2069 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2073 /* wait until we are in a new generation */
2075 next_generation = get_generation(ctdb);
2076 if (next_generation != generation) {
2087 display monitoring mode of a remote node
2089 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2094 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2096 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2099 if (!options.machinereadable){
2100 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2103 printf(":%d:\n",monmode);
2110 display capabilities of a remote node
2112 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2114 uint32_t capabilities;
2117 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2119 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2123 if (!options.machinereadable){
2124 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2125 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2126 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2127 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2129 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2130 printf(":%d:%d:%d:%d:\n",
2131 !!(capabilities&CTDB_CAP_RECMASTER),
2132 !!(capabilities&CTDB_CAP_LMASTER),
2133 !!(capabilities&CTDB_CAP_LVS),
2134 !!(capabilities&CTDB_CAP_NATGW));
2140 display lvs configuration
2142 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2144 uint32_t *capabilities;
2145 struct ctdb_node_map *nodemap=NULL;
2147 int healthy_count = 0;
2149 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2151 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2155 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2156 CTDB_NO_MEMORY(ctdb, capabilities);
2158 /* collect capabilities for all connected nodes */
2159 for (i=0; i<nodemap->num; i++) {
2160 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2163 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2167 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2169 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2173 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2177 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2182 /* Print all LVS nodes */
2183 for (i=0; i<nodemap->num; i++) {
2184 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2187 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2190 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2194 if (healthy_count != 0) {
2195 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2200 printf("%d:%s\n", i,
2201 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2208 display who is the lvs master
2210 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2212 uint32_t *capabilities;
2213 struct ctdb_node_map *nodemap=NULL;
2215 int healthy_count = 0;
2217 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2219 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2223 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2224 CTDB_NO_MEMORY(ctdb, capabilities);
2226 /* collect capabilities for all connected nodes */
2227 for (i=0; i<nodemap->num; i++) {
2228 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2231 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2235 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2237 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2241 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2245 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2250 /* find and show the lvsmaster */
2251 for (i=0; i<nodemap->num; i++) {
2252 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2255 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2258 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2262 if (healthy_count != 0) {
2263 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2268 if (options.machinereadable){
2271 printf("Node %d is LVS master\n", i);
2276 printf("There is no LVS master\n");
2281 disable monitoring on a node
2283 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2288 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2290 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2293 printf("Monitoring mode:%s\n","DISABLED");
2299 enable monitoring on a node
2301 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2306 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2308 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2311 printf("Monitoring mode:%s\n","ACTIVE");
2317 display remote list of keys/data for a db
2319 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2321 const char *db_name;
2322 struct ctdb_db_context *ctdb_db;
2332 if (db_exists(ctdb, db_name)) {
2333 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2337 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2339 if (ctdb_db == NULL) {
2340 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2344 /* traverse and dump the cluster tdb */
2345 ret = ctdb_dump_db(ctdb_db, stdout);
2347 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2350 talloc_free(ctdb_db);
2352 printf("Dumped %d records\n", ret);
2357 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2358 TDB_DATA data, void *private_data)
2360 DEBUG(DEBUG_ERR,("Log data received\n"));
2361 if (data.dsize > 0) {
2362 printf("%s", data.dptr);
2369 display a list of log messages from the in memory ringbuffer
2371 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2375 struct ctdb_get_log_addr log_addr;
2377 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2382 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2383 talloc_free(tmp_ctx);
2387 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2388 log_addr.srvid = getpid();
2389 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2390 log_addr.level = get_debug_by_desc(argv[0]);
2392 log_addr.level = strtol(argv[0], NULL, 0);
2396 data.dptr = (unsigned char *)&log_addr;
2397 data.dsize = sizeof(log_addr);
2399 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2401 ctdb_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2404 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2406 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2407 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2408 if (ret != 0 || res != 0) {
2409 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2410 talloc_free(tmp_ctx);
2415 tv = timeval_current();
2416 /* this loop will terminate when we have received the reply */
2417 while (timeval_elapsed(&tv) < 3.0) {
2418 event_loop_once(ctdb->ev);
2421 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2423 talloc_free(tmp_ctx);
2428 clear the in memory log area
2430 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2435 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2437 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2438 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2439 if (ret != 0 || res != 0) {
2440 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2441 talloc_free(tmp_ctx);
2445 talloc_free(tmp_ctx);
2452 display a list of the databases on a remote ctdb
2454 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2457 struct ctdb_dbid_map *dbmap=NULL;
2459 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2461 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2465 printf("Number of databases:%d\n", dbmap->num);
2466 for(i=0;i<dbmap->num;i++){
2471 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2472 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2473 persistent = dbmap->dbs[i].persistent;
2474 printf("dbid:0x%08x name:%s path:%s %s\n", dbmap->dbs[i].dbid, name,
2475 path, persistent?"PERSISTENT":"");
2482 check if the local node is recmaster or not
2483 it will return 1 if this node is the recmaster and 0 if it is not
2484 or if the local ctdb daemon could not be contacted
2486 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2488 uint32_t mypnn, recmaster;
2491 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2493 printf("Failed to get pnn of node\n");
2497 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2499 printf("Failed to get the recmaster\n");
2503 if (recmaster != mypnn) {
2504 printf("this node is not the recmaster\n");
2508 printf("this node is the recmaster\n");
2515 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2518 struct timeval tv = timeval_current();
2519 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2521 printf("Unable to get ping response from node %u\n", options.pnn);
2524 printf("response from %u time=%.6f sec (%d clients)\n",
2525 options.pnn, timeval_elapsed(&tv), ret);
2534 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2545 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2547 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2551 printf("%-19s = %u\n", name, value);
2558 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
2569 value = strtoul(argv[1], NULL, 0);
2571 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
2573 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
2582 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
2588 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
2590 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
2594 for (i=0;i<count;i++) {
2595 control_getvar(ctdb, 1, &list[i]);
2604 display debug level on a node
2606 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2611 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
2613 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
2616 if (options.machinereadable){
2617 printf(":Name:Level:\n");
2618 printf(":%s:%d:\n",get_debug_by_level(level),level);
2620 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
2627 display reclock file of a node
2629 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2632 const char *reclock;
2634 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
2636 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2639 if (options.machinereadable){
2640 if (reclock != NULL) {
2641 printf("%s", reclock);
2644 if (reclock == NULL) {
2645 printf("No reclock file used.\n");
2647 printf("Reclock file:%s\n", reclock);
2655 set the reclock file of a node
2657 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2660 const char *reclock;
2664 } else if (argc == 1) {
2670 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
2672 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2679 set the natgw state on/off
2681 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
2684 uint32_t natgwstate;
2690 if (!strcmp(argv[0], "on")) {
2692 } else if (!strcmp(argv[0], "off")) {
2698 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
2700 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
2708 set the lmaster role on/off
2710 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
2713 uint32_t lmasterrole;
2719 if (!strcmp(argv[0], "on")) {
2721 } else if (!strcmp(argv[0], "off")) {
2727 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
2729 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
2737 set the recmaster role on/off
2739 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
2742 uint32_t recmasterrole;
2748 if (!strcmp(argv[0], "on")) {
2750 } else if (!strcmp(argv[0], "off")) {
2756 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
2758 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
2766 set debug level on a node or all nodes
2768 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2774 printf("You must specify the debug level. Valid levels are:\n");
2775 for (i=0; debug_levels[i].description != NULL; i++) {
2776 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
2782 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2783 level = get_debug_by_desc(argv[0]);
2785 level = strtol(argv[0], NULL, 0);
2788 for (i=0; debug_levels[i].description != NULL; i++) {
2789 if (level == debug_levels[i].level) {
2793 if (debug_levels[i].description == NULL) {
2794 printf("Invalid debug level, must be one of\n");
2795 for (i=0; debug_levels[i].description != NULL; i++) {
2796 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
2801 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
2803 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
2812 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
2818 priority = strtol(argv[0], NULL, 0);
2822 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
2824 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
2826 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
2834 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
2840 priority = strtol(argv[0], NULL, 0);
2844 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
2846 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
2848 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
2855 attach to a database
2857 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
2859 const char *db_name;
2860 struct ctdb_db_context *ctdb_db;
2867 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2868 if (ctdb_db == NULL) {
2869 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2879 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
2881 struct ctdb_db_priority db_prio;
2888 db_prio.db_id = strtoul(argv[0], NULL, 0);
2889 db_prio.priority = strtoul(argv[1], NULL, 0);
2891 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
2893 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
2903 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
2905 uint32_t db_id, priority;
2912 db_id = strtoul(argv[0], NULL, 0);
2914 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
2916 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
2920 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
2926 run an eventscript on a node
2928 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
2934 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2937 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2941 data.dptr = (unsigned char *)discard_const(argv[0]);
2942 data.dsize = strlen((char *)data.dptr) + 1;
2944 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
2946 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
2947 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2948 if (ret != 0 || res != 0) {
2949 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
2950 talloc_free(tmp_ctx);
2953 talloc_free(tmp_ctx);
2957 #define DB_VERSION 1
2958 #define MAX_DB_NAME 64
2959 struct db_file_header {
2960 unsigned long version;
2962 unsigned long persistent;
2964 const char name[MAX_DB_NAME];
2967 struct backup_data {
2968 struct ctdb_marshall_buffer *records;
2971 bool traverse_error;
2974 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
2976 struct backup_data *bd = talloc_get_type(private, struct backup_data);
2977 struct ctdb_rec_data *rec;
2979 /* add the record */
2980 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
2982 bd->traverse_error = true;
2983 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
2986 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
2987 if (bd->records == NULL) {
2988 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
2989 bd->traverse_error = true;
2992 bd->records->count++;
2993 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
2994 bd->len += rec->length;
3002 * backup a database to a file
3004 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3007 struct ctdb_dbid_map *dbmap=NULL;
3008 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3009 struct db_file_header dbhdr;
3010 struct ctdb_db_context *ctdb_db;
3011 struct backup_data *bd;
3016 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3020 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3022 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3026 for(i=0;i<dbmap->num;i++){
3029 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3030 if(!strcmp(argv[0], name)){
3031 talloc_free(discard_const(name));
3034 talloc_free(discard_const(name));
3036 if (i == dbmap->num) {
3037 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3038 talloc_free(tmp_ctx);
3043 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3044 if (ctdb_db == NULL) {
3045 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3046 talloc_free(tmp_ctx);
3051 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3053 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3054 talloc_free(tmp_ctx);
3059 bd = talloc_zero(tmp_ctx, struct backup_data);
3061 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3062 talloc_free(tmp_ctx);
3066 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3067 if (bd->records == NULL) {
3068 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3069 talloc_free(tmp_ctx);
3073 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3074 bd->records->db_id = ctdb_db->db_id;
3075 /* traverse the database collecting all records */
3076 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3077 bd->traverse_error) {
3078 DEBUG(DEBUG_ERR,("Traverse error\n"));
3079 talloc_free(tmp_ctx);
3083 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3086 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3088 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3089 talloc_free(tmp_ctx);
3093 dbhdr.version = DB_VERSION;
3094 dbhdr.timestamp = time(NULL);
3095 dbhdr.persistent = dbmap->dbs[i].persistent;
3096 dbhdr.size = bd->len;
3097 if (strlen(argv[0]) >= MAX_DB_NAME) {
3098 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3101 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3102 ret = write(fh, &dbhdr, sizeof(dbhdr));
3104 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3107 ret = write(fh, bd->records, bd->len);
3109 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3118 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3121 talloc_free(tmp_ctx);
3126 * restore a database from a file
3128 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3131 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3134 struct db_file_header dbhdr;
3135 struct ctdb_db_context *ctdb_db;
3136 struct ctdb_node_map *nodemap=NULL;
3137 struct ctdb_vnn_map *vnnmap=NULL;
3139 struct ctdb_control_wipe_database w;
3141 uint32_t generation;
3146 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3150 fh = open(argv[0], O_RDONLY);
3152 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3153 talloc_free(tmp_ctx);
3157 read(fh, &dbhdr, sizeof(dbhdr));
3158 if (dbhdr.version != DB_VERSION) {
3159 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3160 talloc_free(tmp_ctx);
3164 outdata.dsize = dbhdr.size;
3165 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3166 if (outdata.dptr == NULL) {
3167 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3169 talloc_free(tmp_ctx);
3172 read(fh, outdata.dptr, outdata.dsize);
3175 tm = localtime(&dbhdr.timestamp);
3176 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3177 printf("Restoring database '%s' from backup @ %s\n",
3181 ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
3182 if (ctdb_db == NULL) {
3183 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
3184 talloc_free(tmp_ctx);
3188 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3190 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3191 talloc_free(tmp_ctx);
3196 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3198 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3199 talloc_free(tmp_ctx);
3203 /* freeze all nodes */
3204 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3205 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3206 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3212 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3213 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3214 talloc_free(tmp_ctx);
3219 generation = vnnmap->generation;
3220 data.dptr = (void *)&generation;
3221 data.dsize = sizeof(generation);
3223 /* start a cluster wide transaction */
3224 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3225 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3227 TIMELIMIT(), false, data,
3230 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3235 w.db_id = ctdb_db->db_id;
3236 w.transaction_id = generation;
3238 data.dptr = (void *)&w;
3239 data.dsize = sizeof(w);
3241 /* wipe all the remote databases. */
3242 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3243 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3245 TIMELIMIT(), false, data,
3248 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3249 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3250 talloc_free(tmp_ctx);
3254 /* push the database */
3255 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3256 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3258 TIMELIMIT(), false, outdata,
3261 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3262 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3263 talloc_free(tmp_ctx);
3267 data.dptr = (void *)&generation;
3268 data.dsize = sizeof(generation);
3270 /* commit all the changes */
3271 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3273 TIMELIMIT(), false, data,
3276 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3277 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3278 talloc_free(tmp_ctx);
3283 /* thaw all nodes */
3284 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3285 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3291 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3292 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3293 talloc_free(tmp_ctx);
3298 talloc_free(tmp_ctx);
3303 * set flags of a node in the nodemap
3305 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
3312 struct ctdb_node_flag_change c;
3319 if (sscanf(argv[0], "%d", &node) != 1) {
3320 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
3324 if (sscanf(argv[1], "0x%x", &flags) != 1) {
3325 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
3332 c.new_flags = flags;
3334 data.dsize = sizeof(c);
3335 data.dptr = (unsigned char *)&c;
3337 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
3338 data, NULL, NULL, &status, NULL, NULL);
3339 if (ret != 0 || status != 0) {
3340 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
3349 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3355 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3356 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
3357 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
3358 if (ret != 0 || res != 0) {
3359 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
3360 talloc_free(tmp_ctx);
3363 write(1, data.dptr, data.dsize);
3364 talloc_free(tmp_ctx);
3369 handler for memory dumps
3371 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
3372 TDB_DATA data, void *private_data)
3374 write(1, data.dptr, data.dsize);
3379 dump memory usage on the recovery daemon
3381 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3385 struct rd_memdump_reply rd;
3387 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3389 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
3392 rd.srvid = getpid();
3394 /* register a message port for receiveing the reply so that we
3395 can receive the reply
3397 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
3400 data.dptr = (uint8_t *)&rd;
3401 data.dsize = sizeof(rd);
3403 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
3405 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
3409 /* this loop will terminate when we have received the reply */
3411 event_loop_once(ctdb->ev);
3418 list all nodes in the cluster
3419 if the daemon is running, we read the data from the daemon.
3420 if the daemon is not running we parse the nodes file directly
3422 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
3425 struct ctdb_node_map *nodemap=NULL;
3428 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3430 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3434 for(i=0;i<nodemap->num;i++){
3435 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
3438 if (options.machinereadable){
3439 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
3441 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
3445 TALLOC_CTX *mem_ctx = talloc_new(NULL);
3446 struct pnn_node *pnn_nodes;
3447 struct pnn_node *pnn_node;
3449 pnn_nodes = read_nodes_file(mem_ctx);
3450 if (pnn_nodes == NULL) {
3451 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
3452 talloc_free(mem_ctx);
3456 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
3457 ctdb_sock_addr addr;
3459 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
3460 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
3461 talloc_free(mem_ctx);
3465 if (options.machinereadable){
3466 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
3468 printf("%s\n", pnn_node->addr);
3471 talloc_free(mem_ctx);
3478 reload the nodes file on the local node
3480 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
3484 struct ctdb_node_map *nodemap=NULL;
3486 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3488 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
3492 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
3494 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
3498 /* reload the nodes file on all remote nodes */
3499 for (i=0;i<nodemap->num;i++) {
3500 if (nodemap->nodes[i].pnn == mypnn) {
3503 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
3504 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
3505 nodemap->nodes[i].pnn);
3507 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
3511 /* reload the nodes file on the local node */
3512 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
3513 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
3515 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
3518 /* initiate a recovery */
3519 control_recover(ctdb, argc, argv);
3525 static const struct {
3527 int (*fn)(struct ctdb_context *, int, const char **);
3529 bool without_daemon; /* can be run without daemon running ? */
3532 } ctdb_commands[] = {
3534 { "version", control_version, true, false, "show version of ctdb" },
3536 { "status", control_status, true, false, "show node status" },
3537 { "uptime", control_uptime, true, false, "show node uptime" },
3538 { "ping", control_ping, true, false, "ping all nodes" },
3539 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
3540 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
3541 { "listvars", control_listvars, true, false, "list tunable variables"},
3542 { "statistics", control_statistics, false, false, "show statistics" },
3543 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
3544 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
3545 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
3546 { "getdbmap", control_getdbmap, true, false, "show the database map" },
3547 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
3548 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
3549 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
3550 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
3551 { "lvs", control_lvs, true, false, "show lvs configuration" },
3552 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
3553 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
3554 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
3555 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
3556 { "getdebug", control_getdebug, true, false, "get debug level" },
3557 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
3558 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
3559 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
3560 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
3561 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
3562 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
3563 { "disable", control_disable, true, false, "disable a nodes public IP" },
3564 { "enable", control_enable, true, false, "enable a nodes public IP" },
3565 { "stop", control_stop, true, false, "stop a node" },
3566 { "continue", control_continue, true, false, "re-start a stopped node" },
3567 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
3568 { "unban", control_unban, true, false, "unban a node" },
3569 { "showban", control_showban, true, false, "show ban information"},
3570 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
3571 { "recover", control_recover, true, false, "force recovery" },
3572 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
3573 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
3574 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
3575 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
3576 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
3577 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
3578 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
3579 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
3581 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
3582 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
3583 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
3584 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
3585 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
3586 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
3587 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
3588 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
3589 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
3590 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
3591 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
3592 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
3593 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
3594 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
3595 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
3596 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
3597 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts"},
3598 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
3599 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
3600 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
3601 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
3602 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
3603 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
3604 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
3605 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
3606 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
3607 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
3608 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
3614 static void usage(void)
3618 "Usage: ctdb [options] <control>\n" \
3620 " -n <node> choose node number, or 'all' (defaults to local node)\n"
3621 " -Y generate machinereadable output\n"
3622 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
3623 printf("Controls:\n");
3624 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
3625 printf(" %-15s %-27s %s\n",
3626 ctdb_commands[i].name,
3627 ctdb_commands[i].args?ctdb_commands[i].args:"",
3628 ctdb_commands[i].msg);
3634 static void ctdb_alarm(int sig)
3636 printf("Maximum runtime exceeded - exiting\n");
3643 int main(int argc, const char *argv[])
3645 struct ctdb_context *ctdb;
3646 char *nodestring = NULL;
3647 struct poptOption popt_options[] = {
3650 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
3651 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
3652 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
3653 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
3657 const char **extra_argv;
3661 struct event_context *ev;
3662 const char *control;
3666 /* set some defaults */
3667 options.maxruntime = 0;
3668 options.timelimit = 3;
3669 options.pnn = CTDB_CURRENT_NODE;
3671 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
3673 while ((opt = poptGetNextOpt(pc)) != -1) {
3676 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
3677 poptBadOption(pc, 0), poptStrerror(opt)));
3682 /* setup the remaining options for the main program to use */
3683 extra_argv = poptGetArgs(pc);
3686 while (extra_argv[extra_argc]) extra_argc++;
3689 if (extra_argc < 1) {
3693 if (options.maxruntime == 0) {
3694 const char *ctdb_timeout;
3695 ctdb_timeout = getenv("CTDB_TIMEOUT");
3696 if (ctdb_timeout != NULL) {
3697 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
3699 /* default timeout is 120 seconds */
3700 options.maxruntime = 120;
3704 signal(SIGALRM, ctdb_alarm);
3705 alarm(options.maxruntime);
3707 /* setup the node number to contact */
3708 if (nodestring != NULL) {
3709 if (strcmp(nodestring, "all") == 0) {
3710 options.pnn = CTDB_BROADCAST_ALL;
3712 options.pnn = strtoul(nodestring, NULL, 0);
3716 control = extra_argv[0];
3718 ev = event_context_init(NULL);
3720 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
3721 if (strcmp(control, ctdb_commands[i].name) == 0) {
3724 if (ctdb_commands[i].without_daemon == true) {
3728 /* initialise ctdb */
3729 ctdb = ctdb_cmdline_client(ev);
3731 if (ctdb_commands[i].without_daemon == false) {
3733 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
3737 /* verify the node exists */
3740 if (options.pnn == CTDB_CURRENT_NODE) {
3742 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3750 if (ctdb_commands[i].auto_all &&
3751 options.pnn == CTDB_BROADCAST_ALL) {
3756 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
3757 CTDB_NO_MEMORY(ctdb, nodes);
3759 for (j=0;j<num_nodes;j++) {
3760 options.pnn = nodes[j];
3761 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
3765 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
3771 if (i == ARRAY_SIZE(ctdb_commands)) {
3772 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));