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_scripts_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 const char *status = NULL;
747 switch (script_status->scripts[i].status) {
758 if (script_status->scripts[i].status > 0)
763 printf("%-20s Status:%s ",
764 script_status->scripts[i].name, status);
766 /* Some other error, eg from stat. */
767 printf("%-20s Status:CANNOT RUN (%s)",
768 script_status->scripts[i].name,
769 strerror(-script_status->scripts[i].status));
771 if (script_status->scripts[i].status >= 0) {
772 printf("Duration:%.3lf ",
773 timeval_delta(&script_status->scripts[i].finished,
774 &script_status->scripts[i].start));
776 if (script_status->scripts[i].status != -ENOEXEC) {
778 ctime(&script_status->scripts[i].start.tv_sec));
780 if (script_status->scripts[i].status != 0) {
781 printf(" OUTPUT:%s\n",
782 script_status->scripts[i].output);
791 enable an eventscript
793 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
801 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
803 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
811 disable an eventscript
813 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
821 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
823 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
831 display the pnn of the recovery master
833 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
838 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
840 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
843 printf("%d\n",recmaster);
849 get a list of all tickles for this pnn
851 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
853 struct ctdb_control_tcp_tickle_list *list;
861 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
862 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
866 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
868 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
872 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
873 printf("Num tickles:%u\n", list->tickles.num);
874 for (i=0;i<list->tickles.num;i++) {
875 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
876 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));
886 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
888 struct ctdb_all_public_ips *ips;
889 struct ctdb_public_ip ip;
892 uint32_t disable_time;
894 struct ctdb_node_map *nodemap=NULL;
895 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
898 data.dptr = (uint8_t*)&disable_time;
899 data.dsize = sizeof(disable_time);
900 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
902 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
908 /* read the public ip list from the node */
909 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
911 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
912 talloc_free(tmp_ctx);
916 for (i=0;i<ips->num;i++) {
917 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
922 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
923 pnn, ctdb_addr_to_str(addr)));
924 talloc_free(tmp_ctx);
931 data.dptr = (uint8_t *)&ip;
932 data.dsize = sizeof(ip);
934 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
936 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
937 talloc_free(tmp_ctx);
941 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
942 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
949 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
950 talloc_free(tmp_ctx);
954 ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), pnn, &ip);
956 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
957 talloc_free(tmp_ctx);
961 talloc_free(tmp_ctx);
966 move/failover an ip address to a specific node
968 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
978 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
979 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
984 if (sscanf(argv[1], "%u", &pnn) != 1) {
985 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
989 if (move_ip(ctdb, &addr, pnn) != 0) {
990 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
997 void getips_store_callback(void *param, void *data)
999 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1000 struct ctdb_all_public_ips *ips = param;
1004 ips->ips[i].pnn = node_ip->pnn;
1005 ips->ips[i].addr = node_ip->addr;
1008 void getips_count_callback(void *param, void *data)
1010 uint32_t *count = param;
1016 static uint32_t *ip_key(ctdb_sock_addr *ip)
1018 static uint32_t key[IP_KEYLEN];
1020 bzero(key, sizeof(key));
1022 switch (ip->sa.sa_family) {
1024 key[0] = ip->ip.sin_addr.s_addr;
1027 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1028 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1029 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1030 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1033 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1040 static void *add_ip_callback(void *parm, void *data)
1046 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1048 struct ctdb_all_public_ips *tmp_ips;
1049 struct ctdb_node_map *nodemap=NULL;
1050 trbt_tree_t *ip_tree;
1054 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1056 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1060 ip_tree = trbt_create(tmp_ctx, 0);
1062 for(i=0;i<nodemap->num;i++){
1063 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1066 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1070 /* read the public ip list from this node */
1071 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1073 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1077 for (j=0; j<tmp_ips->num;j++) {
1078 struct ctdb_public_ip *node_ip;
1080 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1081 node_ip->pnn = tmp_ips->ips[j].pnn;
1082 node_ip->addr = tmp_ips->ips[j].addr;
1084 trbt_insertarray32_callback(ip_tree,
1085 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1089 talloc_free(tmp_ips);
1094 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1096 len = offsetof(struct ctdb_all_public_ips, ips) +
1097 count*sizeof(struct ctdb_public_ip);
1098 tmp_ips = talloc_zero_size(tmp_ctx, len);
1099 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1108 * scans all other nodes and returns a pnn for another node that can host this
1112 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1114 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1115 struct ctdb_all_public_ips *ips;
1116 struct ctdb_node_map *nodemap=NULL;
1119 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1121 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1122 talloc_free(tmp_ctx);
1126 for(i=0;i<nodemap->num;i++){
1127 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1130 if (nodemap->nodes[i].pnn == options.pnn) {
1134 /* read the public ip list from this node */
1135 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1137 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1141 for (j=0;j<ips->num;j++) {
1142 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1143 talloc_free(tmp_ctx);
1144 return nodemap->nodes[i].pnn;
1150 talloc_free(tmp_ctx);
1155 add a public ip address to a node
1157 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1163 ctdb_sock_addr addr;
1164 struct ctdb_control_ip_iface *pub;
1165 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1166 struct ctdb_all_public_ips *ips;
1170 talloc_free(tmp_ctx);
1174 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1175 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1176 talloc_free(tmp_ctx);
1180 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1182 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1183 talloc_free(tmp_ctx);
1188 /* check if some other node is already serving this ip, if not,
1191 for (i=0;i<ips->num;i++) {
1192 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1197 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1198 pub = talloc_size(tmp_ctx, len);
1199 CTDB_NO_MEMORY(ctdb, pub);
1203 pub->len = strlen(argv[1])+1;
1204 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1206 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1208 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1209 talloc_free(tmp_ctx);
1213 if (i == ips->num) {
1214 /* no one has this ip so we claim it */
1217 pnn = ips->ips[i].pnn;
1220 if (move_ip(ctdb, &addr, pnn) != 0) {
1221 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1225 talloc_free(tmp_ctx);
1229 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1231 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1233 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1234 struct ctdb_node_map *nodemap=NULL;
1235 struct ctdb_all_public_ips *ips;
1238 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1240 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1244 /* remove it from the nodes that are not hosting the ip currently */
1245 for(i=0;i<nodemap->num;i++){
1246 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1249 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1250 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1254 for (j=0;j<ips->num;j++) {
1255 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1263 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1267 options.pnn = nodemap->nodes[i].pnn;
1268 control_delip(ctdb, argc, argv);
1272 /* remove it from every node (also the one hosting it) */
1273 for(i=0;i<nodemap->num;i++){
1274 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1277 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1278 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1282 for (j=0;j<ips->num;j++) {
1283 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1291 options.pnn = nodemap->nodes[i].pnn;
1292 control_delip(ctdb, argc, argv);
1295 talloc_free(tmp_ctx);
1300 delete a public ip address from a node
1302 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1305 ctdb_sock_addr addr;
1306 struct ctdb_control_ip_iface pub;
1307 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1308 struct ctdb_all_public_ips *ips;
1311 talloc_free(tmp_ctx);
1315 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1316 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1320 if (options.pnn == CTDB_BROADCAST_ALL) {
1321 return control_delip_all(ctdb, argc, argv, &addr);
1328 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1330 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1331 talloc_free(tmp_ctx);
1335 for (i=0;i<ips->num;i++) {
1336 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1342 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1343 ctdb_addr_to_str(&addr)));
1344 talloc_free(tmp_ctx);
1348 if (ips->ips[i].pnn == options.pnn) {
1349 ret = find_other_host_for_public_ip(ctdb, &addr);
1351 if (move_ip(ctdb, &addr, ret) != 0) {
1352 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1358 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1360 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1361 talloc_free(tmp_ctx);
1365 talloc_free(tmp_ctx);
1370 kill a tcp connection
1372 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1375 struct ctdb_control_killtcp killtcp;
1381 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1382 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1386 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1387 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1391 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1393 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1404 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1407 ctdb_sock_addr addr;
1413 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1414 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1418 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1420 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1428 register a server id
1430 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1433 struct ctdb_server_id server_id;
1439 server_id.pnn = strtoul(argv[0], NULL, 0);
1440 server_id.type = strtoul(argv[1], NULL, 0);
1441 server_id.server_id = strtoul(argv[2], NULL, 0);
1443 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1445 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1452 unregister a server id
1454 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1457 struct ctdb_server_id server_id;
1463 server_id.pnn = strtoul(argv[0], NULL, 0);
1464 server_id.type = strtoul(argv[1], NULL, 0);
1465 server_id.server_id = strtoul(argv[2], NULL, 0);
1467 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1469 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1476 check if a server id exists
1478 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1482 struct ctdb_server_id server_id;
1488 server_id.pnn = strtoul(argv[0], NULL, 0);
1489 server_id.type = strtoul(argv[1], NULL, 0);
1490 server_id.server_id = strtoul(argv[2], NULL, 0);
1492 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1494 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1499 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1501 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1507 get a list of all server ids that are registered on a node
1509 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1512 struct ctdb_server_id_list *server_ids;
1514 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1516 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1520 for (i=0; i<server_ids->num; i++) {
1521 printf("Server id %d:%d:%d\n",
1522 server_ids->server_ids[i].pnn,
1523 server_ids->server_ids[i].type,
1524 server_ids->server_ids[i].server_id);
1531 send a tcp tickle ack
1533 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1536 ctdb_sock_addr src, dst;
1542 if (!parse_ip_port(argv[0], &src)) {
1543 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1547 if (!parse_ip_port(argv[1], &dst)) {
1548 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1552 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1556 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1563 display public ip status
1565 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1568 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1569 struct ctdb_all_public_ips *ips;
1571 if (options.pnn == CTDB_BROADCAST_ALL) {
1572 /* read the list of public ips from all nodes */
1573 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1575 /* read the public ip list from this node */
1576 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1579 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1580 talloc_free(tmp_ctx);
1584 if (options.machinereadable){
1585 printf(":Public IP:Node:\n");
1587 if (options.pnn == CTDB_BROADCAST_ALL) {
1588 printf("Public IPs on ALL nodes\n");
1590 printf("Public IPs on node %u\n", options.pnn);
1594 for (i=1;i<=ips->num;i++) {
1595 if (options.machinereadable){
1596 printf(":%s:%d:\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1598 printf("%s %d\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1602 talloc_free(tmp_ctx);
1607 display pid of a ctdb daemon
1609 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1614 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1616 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1619 printf("Pid:%d\n", pid);
1625 handler for receiving the response to ipreallocate
1627 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1628 TDB_DATA data, void *private_data)
1633 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1635 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1637 event_add_timed(ctdb->ev, ctdb,
1638 timeval_current_ofs(1, 0),
1639 ctdb_every_second, ctdb);
1643 ask the recovery daemon on the recovery master to perform a ip reallocation
1645 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1649 struct takeover_run_reply rd;
1651 struct ctdb_node_map *nodemap=NULL;
1653 struct timeval tv = timeval_current();
1655 /* we need some events to trigger so we can timeout and restart
1658 event_add_timed(ctdb->ev, ctdb,
1659 timeval_current_ofs(1, 0),
1660 ctdb_every_second, ctdb);
1662 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1664 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1667 rd.srvid = getpid();
1669 /* register a message port for receiveing the reply so that we
1670 can receive the reply
1672 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
1674 data.dptr = (uint8_t *)&rd;
1675 data.dsize = sizeof(rd);
1679 DEBUG(DEBUG_ERR,("Failed waiting for cluster convergense\n"));
1683 /* check that there are valid nodes available */
1684 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
1685 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1688 for (i=0; i<nodemap->num;i++) {
1689 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
1693 if (i==nodemap->num) {
1694 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
1699 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
1701 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1705 /* verify the node exists */
1706 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
1707 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1712 /* check tha there are nodes available that can act as a recmaster */
1713 for (i=0; i<nodemap->num; i++) {
1714 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1719 if (i == nodemap->num) {
1720 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
1724 /* verify the recovery master is not STOPPED, nor BANNED */
1725 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1726 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1733 /* verify the recovery master is not STOPPED, nor BANNED */
1734 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1735 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1741 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
1743 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
1747 tv = timeval_current();
1748 /* this loop will terminate when we have received the reply */
1749 while (timeval_elapsed(&tv) < 3.0) {
1750 event_loop_once(ctdb->ev);
1753 DEBUG(DEBUG_INFO,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
1763 disable a remote node
1765 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
1768 struct ctdb_node_map *nodemap=NULL;
1771 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
1773 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
1779 /* read the nodemap and verify the change took effect */
1780 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1781 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1785 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
1786 ret = control_ipreallocate(ctdb, argc, argv);
1788 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1796 enable a disabled remote node
1798 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
1802 struct ctdb_node_map *nodemap=NULL;
1805 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
1807 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
1813 /* read the nodemap and verify the change took effect */
1814 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1815 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1819 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
1820 ret = control_ipreallocate(ctdb, argc, argv);
1822 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1832 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
1835 struct ctdb_node_map *nodemap=NULL;
1838 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
1840 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
1845 /* read the nodemap and verify the change took effect */
1846 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1847 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1851 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
1852 ret = control_ipreallocate(ctdb, argc, argv);
1854 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1862 restart a stopped remote node
1864 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
1868 struct ctdb_node_map *nodemap=NULL;
1871 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
1873 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
1879 /* read the nodemap and verify the change took effect */
1880 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1881 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1885 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
1886 ret = control_ipreallocate(ctdb, argc, argv);
1888 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1895 static uint32_t get_generation(struct ctdb_context *ctdb)
1897 struct ctdb_vnn_map *vnnmap=NULL;
1900 /* wait until the recmaster is not in recovery mode */
1902 uint32_t recmode, recmaster;
1904 if (vnnmap != NULL) {
1905 talloc_free(vnnmap);
1909 /* get the recmaster */
1910 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
1912 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1916 /* get recovery mode */
1917 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
1919 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
1923 /* get the current generation number */
1924 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
1926 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
1930 if ((recmode == CTDB_RECOVERY_NORMAL)
1931 && (vnnmap->generation != 1)){
1932 return vnnmap->generation;
1939 ban a node from the cluster
1941 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
1944 struct ctdb_node_map *nodemap=NULL;
1945 struct ctdb_ban_time bantime;
1951 /* verify the node exists */
1952 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1954 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1958 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
1959 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
1963 bantime.pnn = options.pnn;
1964 bantime.time = strtoul(argv[0], NULL, 0);
1966 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
1968 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
1972 ret = control_ipreallocate(ctdb, argc, argv);
1974 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1983 unban a node from the cluster
1985 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
1988 struct ctdb_node_map *nodemap=NULL;
1989 struct ctdb_ban_time bantime;
1991 /* verify the node exists */
1992 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1994 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1998 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
1999 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2003 bantime.pnn = options.pnn;
2006 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2008 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2012 ret = control_ipreallocate(ctdb, argc, argv);
2014 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2023 show ban information for a node
2025 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2028 struct ctdb_node_map *nodemap=NULL;
2029 struct ctdb_ban_time *bantime;
2031 /* verify the node exists */
2032 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2034 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2038 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2040 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2044 if (bantime->time == 0) {
2045 printf("Node %u is not banned\n", bantime->pnn);
2047 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2056 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2060 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2062 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2072 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2075 uint32_t generation, next_generation;
2077 /* record the current generation number */
2078 generation = get_generation(ctdb);
2080 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2082 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2086 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2088 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2092 /* wait until we are in a new generation */
2094 next_generation = get_generation(ctdb);
2095 if (next_generation != generation) {
2106 display monitoring mode of a remote node
2108 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2113 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2115 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2118 if (!options.machinereadable){
2119 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2122 printf(":%d:\n",monmode);
2129 display capabilities of a remote node
2131 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2133 uint32_t capabilities;
2136 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2138 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2142 if (!options.machinereadable){
2143 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2144 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2145 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2146 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2148 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2149 printf(":%d:%d:%d:%d:\n",
2150 !!(capabilities&CTDB_CAP_RECMASTER),
2151 !!(capabilities&CTDB_CAP_LMASTER),
2152 !!(capabilities&CTDB_CAP_LVS),
2153 !!(capabilities&CTDB_CAP_NATGW));
2159 display lvs configuration
2161 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2163 uint32_t *capabilities;
2164 struct ctdb_node_map *nodemap=NULL;
2166 int healthy_count = 0;
2168 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2170 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2174 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2175 CTDB_NO_MEMORY(ctdb, capabilities);
2177 /* collect capabilities for all connected nodes */
2178 for (i=0; i<nodemap->num; i++) {
2179 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2182 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2186 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2188 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2192 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2196 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2201 /* Print all LVS nodes */
2202 for (i=0; i<nodemap->num; i++) {
2203 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2206 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2209 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2213 if (healthy_count != 0) {
2214 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2219 printf("%d:%s\n", i,
2220 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2227 display who is the lvs master
2229 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2231 uint32_t *capabilities;
2232 struct ctdb_node_map *nodemap=NULL;
2234 int healthy_count = 0;
2236 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2238 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2242 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2243 CTDB_NO_MEMORY(ctdb, capabilities);
2245 /* collect capabilities for all connected nodes */
2246 for (i=0; i<nodemap->num; i++) {
2247 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2250 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2254 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2256 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2260 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2264 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2269 /* find and show the lvsmaster */
2270 for (i=0; i<nodemap->num; i++) {
2271 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2274 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2277 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2281 if (healthy_count != 0) {
2282 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2287 if (options.machinereadable){
2290 printf("Node %d is LVS master\n", i);
2295 printf("There is no LVS master\n");
2300 disable monitoring on a node
2302 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2307 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2309 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2312 printf("Monitoring mode:%s\n","DISABLED");
2318 enable monitoring on a node
2320 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2325 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2327 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2330 printf("Monitoring mode:%s\n","ACTIVE");
2336 display remote list of keys/data for a db
2338 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2340 const char *db_name;
2341 struct ctdb_db_context *ctdb_db;
2351 if (db_exists(ctdb, db_name)) {
2352 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2356 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2358 if (ctdb_db == NULL) {
2359 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2363 /* traverse and dump the cluster tdb */
2364 ret = ctdb_dump_db(ctdb_db, stdout);
2366 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2369 talloc_free(ctdb_db);
2371 printf("Dumped %d records\n", ret);
2376 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2377 TDB_DATA data, void *private_data)
2379 DEBUG(DEBUG_ERR,("Log data received\n"));
2380 if (data.dsize > 0) {
2381 printf("%s", data.dptr);
2388 display a list of log messages from the in memory ringbuffer
2390 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2394 struct ctdb_get_log_addr log_addr;
2396 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2401 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2402 talloc_free(tmp_ctx);
2406 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2407 log_addr.srvid = getpid();
2408 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2409 log_addr.level = get_debug_by_desc(argv[0]);
2411 log_addr.level = strtol(argv[0], NULL, 0);
2415 data.dptr = (unsigned char *)&log_addr;
2416 data.dsize = sizeof(log_addr);
2418 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2420 ctdb_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2423 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2425 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2426 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2427 if (ret != 0 || res != 0) {
2428 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2429 talloc_free(tmp_ctx);
2434 tv = timeval_current();
2435 /* this loop will terminate when we have received the reply */
2436 while (timeval_elapsed(&tv) < 3.0) {
2437 event_loop_once(ctdb->ev);
2440 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2442 talloc_free(tmp_ctx);
2447 clear the in memory log area
2449 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2454 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2456 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2457 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2458 if (ret != 0 || res != 0) {
2459 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2460 talloc_free(tmp_ctx);
2464 talloc_free(tmp_ctx);
2471 display a list of the databases on a remote ctdb
2473 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2476 struct ctdb_dbid_map *dbmap=NULL;
2478 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2480 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2484 printf("Number of databases:%d\n", dbmap->num);
2485 for(i=0;i<dbmap->num;i++){
2490 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2491 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2492 persistent = dbmap->dbs[i].persistent;
2493 printf("dbid:0x%08x name:%s path:%s %s\n", dbmap->dbs[i].dbid, name,
2494 path, persistent?"PERSISTENT":"");
2501 check if the local node is recmaster or not
2502 it will return 1 if this node is the recmaster and 0 if it is not
2503 or if the local ctdb daemon could not be contacted
2505 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2507 uint32_t mypnn, recmaster;
2510 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2512 printf("Failed to get pnn of node\n");
2516 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2518 printf("Failed to get the recmaster\n");
2522 if (recmaster != mypnn) {
2523 printf("this node is not the recmaster\n");
2527 printf("this node is the recmaster\n");
2534 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2537 struct timeval tv = timeval_current();
2538 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2540 printf("Unable to get ping response from node %u\n", options.pnn);
2543 printf("response from %u time=%.6f sec (%d clients)\n",
2544 options.pnn, timeval_elapsed(&tv), ret);
2553 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2564 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2566 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2570 printf("%-19s = %u\n", name, value);
2577 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
2588 value = strtoul(argv[1], NULL, 0);
2590 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
2592 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
2601 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
2607 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
2609 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
2613 for (i=0;i<count;i++) {
2614 control_getvar(ctdb, 1, &list[i]);
2623 display debug level on a node
2625 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2630 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
2632 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
2635 if (options.machinereadable){
2636 printf(":Name:Level:\n");
2637 printf(":%s:%d:\n",get_debug_by_level(level),level);
2639 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
2646 display reclock file of a node
2648 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2651 const char *reclock;
2653 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
2655 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2658 if (options.machinereadable){
2659 if (reclock != NULL) {
2660 printf("%s", reclock);
2663 if (reclock == NULL) {
2664 printf("No reclock file used.\n");
2666 printf("Reclock file:%s\n", reclock);
2674 set the reclock file of a node
2676 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2679 const char *reclock;
2683 } else if (argc == 1) {
2689 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
2691 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2698 set the natgw state on/off
2700 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
2703 uint32_t natgwstate;
2709 if (!strcmp(argv[0], "on")) {
2711 } else if (!strcmp(argv[0], "off")) {
2717 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
2719 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
2727 set the lmaster role on/off
2729 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
2732 uint32_t lmasterrole;
2738 if (!strcmp(argv[0], "on")) {
2740 } else if (!strcmp(argv[0], "off")) {
2746 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
2748 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
2756 set the recmaster role on/off
2758 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
2761 uint32_t recmasterrole;
2767 if (!strcmp(argv[0], "on")) {
2769 } else if (!strcmp(argv[0], "off")) {
2775 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
2777 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
2785 set debug level on a node or all nodes
2787 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2793 printf("You must specify the debug level. Valid levels are:\n");
2794 for (i=0; debug_levels[i].description != NULL; i++) {
2795 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
2801 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2802 level = get_debug_by_desc(argv[0]);
2804 level = strtol(argv[0], NULL, 0);
2807 for (i=0; debug_levels[i].description != NULL; i++) {
2808 if (level == debug_levels[i].level) {
2812 if (debug_levels[i].description == NULL) {
2813 printf("Invalid debug level, must be one of\n");
2814 for (i=0; debug_levels[i].description != NULL; i++) {
2815 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
2820 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
2822 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
2831 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
2837 priority = strtol(argv[0], NULL, 0);
2841 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
2843 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
2845 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
2853 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
2859 priority = strtol(argv[0], NULL, 0);
2863 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
2865 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
2867 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
2874 attach to a database
2876 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
2878 const char *db_name;
2879 struct ctdb_db_context *ctdb_db;
2886 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2887 if (ctdb_db == NULL) {
2888 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2898 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
2900 struct ctdb_db_priority db_prio;
2907 db_prio.db_id = strtoul(argv[0], NULL, 0);
2908 db_prio.priority = strtoul(argv[1], NULL, 0);
2910 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
2912 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
2922 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
2924 uint32_t db_id, priority;
2931 db_id = strtoul(argv[0], NULL, 0);
2933 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
2935 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
2939 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
2945 run an eventscript on a node
2947 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
2953 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2956 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2960 data.dptr = (unsigned char *)discard_const(argv[0]);
2961 data.dsize = strlen((char *)data.dptr) + 1;
2963 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
2965 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
2966 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2967 if (ret != 0 || res != 0) {
2968 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
2969 talloc_free(tmp_ctx);
2972 talloc_free(tmp_ctx);
2976 #define DB_VERSION 1
2977 #define MAX_DB_NAME 64
2978 struct db_file_header {
2979 unsigned long version;
2981 unsigned long persistent;
2983 const char name[MAX_DB_NAME];
2986 struct backup_data {
2987 struct ctdb_marshall_buffer *records;
2990 bool traverse_error;
2993 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
2995 struct backup_data *bd = talloc_get_type(private, struct backup_data);
2996 struct ctdb_rec_data *rec;
2998 /* add the record */
2999 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3001 bd->traverse_error = true;
3002 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3005 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3006 if (bd->records == NULL) {
3007 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3008 bd->traverse_error = true;
3011 bd->records->count++;
3012 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3013 bd->len += rec->length;
3021 * backup a database to a file
3023 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3026 struct ctdb_dbid_map *dbmap=NULL;
3027 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3028 struct db_file_header dbhdr;
3029 struct ctdb_db_context *ctdb_db;
3030 struct backup_data *bd;
3035 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3039 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3041 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3045 for(i=0;i<dbmap->num;i++){
3048 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3049 if(!strcmp(argv[0], name)){
3050 talloc_free(discard_const(name));
3053 talloc_free(discard_const(name));
3055 if (i == dbmap->num) {
3056 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3057 talloc_free(tmp_ctx);
3062 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3063 if (ctdb_db == NULL) {
3064 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3065 talloc_free(tmp_ctx);
3070 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3072 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3073 talloc_free(tmp_ctx);
3078 bd = talloc_zero(tmp_ctx, struct backup_data);
3080 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3081 talloc_free(tmp_ctx);
3085 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3086 if (bd->records == NULL) {
3087 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3088 talloc_free(tmp_ctx);
3092 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3093 bd->records->db_id = ctdb_db->db_id;
3094 /* traverse the database collecting all records */
3095 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3096 bd->traverse_error) {
3097 DEBUG(DEBUG_ERR,("Traverse error\n"));
3098 talloc_free(tmp_ctx);
3102 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3105 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3107 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3108 talloc_free(tmp_ctx);
3112 dbhdr.version = DB_VERSION;
3113 dbhdr.timestamp = time(NULL);
3114 dbhdr.persistent = dbmap->dbs[i].persistent;
3115 dbhdr.size = bd->len;
3116 if (strlen(argv[0]) >= MAX_DB_NAME) {
3117 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3120 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3121 ret = write(fh, &dbhdr, sizeof(dbhdr));
3123 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3126 ret = write(fh, bd->records, bd->len);
3128 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3137 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3140 talloc_free(tmp_ctx);
3145 * restore a database from a file
3147 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3150 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3153 struct db_file_header dbhdr;
3154 struct ctdb_db_context *ctdb_db;
3155 struct ctdb_node_map *nodemap=NULL;
3156 struct ctdb_vnn_map *vnnmap=NULL;
3158 struct ctdb_control_wipe_database w;
3160 uint32_t generation;
3165 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3169 fh = open(argv[0], O_RDONLY);
3171 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3172 talloc_free(tmp_ctx);
3176 read(fh, &dbhdr, sizeof(dbhdr));
3177 if (dbhdr.version != DB_VERSION) {
3178 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3179 talloc_free(tmp_ctx);
3183 outdata.dsize = dbhdr.size;
3184 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3185 if (outdata.dptr == NULL) {
3186 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3188 talloc_free(tmp_ctx);
3191 read(fh, outdata.dptr, outdata.dsize);
3194 tm = localtime(&dbhdr.timestamp);
3195 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3196 printf("Restoring database '%s' from backup @ %s\n",
3200 ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
3201 if (ctdb_db == NULL) {
3202 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
3203 talloc_free(tmp_ctx);
3207 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3209 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3210 talloc_free(tmp_ctx);
3215 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3217 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3218 talloc_free(tmp_ctx);
3222 /* freeze all nodes */
3223 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3224 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3225 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3231 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3232 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3233 talloc_free(tmp_ctx);
3238 generation = vnnmap->generation;
3239 data.dptr = (void *)&generation;
3240 data.dsize = sizeof(generation);
3242 /* start a cluster wide transaction */
3243 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3244 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3246 TIMELIMIT(), false, data,
3249 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3254 w.db_id = ctdb_db->db_id;
3255 w.transaction_id = generation;
3257 data.dptr = (void *)&w;
3258 data.dsize = sizeof(w);
3260 /* wipe all the remote databases. */
3261 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3262 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3264 TIMELIMIT(), false, data,
3267 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3268 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3269 talloc_free(tmp_ctx);
3273 /* push the database */
3274 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3275 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3277 TIMELIMIT(), false, outdata,
3280 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3281 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3282 talloc_free(tmp_ctx);
3286 data.dptr = (void *)&generation;
3287 data.dsize = sizeof(generation);
3289 /* commit all the changes */
3290 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3292 TIMELIMIT(), false, data,
3295 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3296 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3297 talloc_free(tmp_ctx);
3302 /* thaw all nodes */
3303 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3304 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3310 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3311 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3312 talloc_free(tmp_ctx);
3317 talloc_free(tmp_ctx);
3322 * wipe a database from a file
3324 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3328 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3330 struct ctdb_db_context *ctdb_db;
3331 struct ctdb_node_map *nodemap = NULL;
3332 struct ctdb_vnn_map *vnnmap = NULL;
3334 struct ctdb_control_wipe_database w;
3336 uint32_t generation;
3337 struct ctdb_dbid_map *dbmap = NULL;
3340 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3344 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3347 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3352 for(i=0;i<dbmap->num;i++){
3355 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3356 dbmap->dbs[i].dbid, tmp_ctx, &name);
3357 if(!strcmp(argv[0], name)){
3358 talloc_free(discard_const(name));
3361 talloc_free(discard_const(name));
3363 if (i == dbmap->num) {
3364 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3366 talloc_free(tmp_ctx);
3370 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3371 if (ctdb_db == NULL) {
3372 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3374 talloc_free(tmp_ctx);
3378 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3381 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3383 talloc_free(tmp_ctx);
3387 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3390 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3392 talloc_free(tmp_ctx);
3396 /* freeze all nodes */
3397 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3398 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3399 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3406 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3407 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3408 CTDB_RECOVERY_ACTIVE);
3409 talloc_free(tmp_ctx);
3414 generation = vnnmap->generation;
3415 data.dptr = (void *)&generation;
3416 data.dsize = sizeof(generation);
3418 /* start a cluster wide transaction */
3419 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3420 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3422 TIMELIMIT(), false, data,
3426 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3427 "transactions.\n"));
3431 w.db_id = ctdb_db->db_id;
3432 w.transaction_id = generation;
3434 data.dptr = (void *)&w;
3435 data.dsize = sizeof(w);
3437 /* wipe all the remote databases. */
3438 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3439 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3441 TIMELIMIT(), false, data,
3444 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3445 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3446 talloc_free(tmp_ctx);
3450 data.dptr = (void *)&generation;
3451 data.dsize = sizeof(generation);
3453 /* commit all the changes */
3454 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3456 TIMELIMIT(), false, data,
3459 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3460 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3461 talloc_free(tmp_ctx);
3465 /* thaw all nodes */
3466 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3467 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3473 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3474 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3475 talloc_free(tmp_ctx);
3479 talloc_free(tmp_ctx);
3484 * set flags of a node in the nodemap
3486 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
3493 struct ctdb_node_flag_change c;
3500 if (sscanf(argv[0], "%d", &node) != 1) {
3501 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
3505 if (sscanf(argv[1], "0x%x", &flags) != 1) {
3506 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
3513 c.new_flags = flags;
3515 data.dsize = sizeof(c);
3516 data.dptr = (unsigned char *)&c;
3518 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
3519 data, NULL, NULL, &status, NULL, NULL);
3520 if (ret != 0 || status != 0) {
3521 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
3530 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3536 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3537 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
3538 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
3539 if (ret != 0 || res != 0) {
3540 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
3541 talloc_free(tmp_ctx);
3544 write(1, data.dptr, data.dsize);
3545 talloc_free(tmp_ctx);
3550 handler for memory dumps
3552 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
3553 TDB_DATA data, void *private_data)
3555 write(1, data.dptr, data.dsize);
3560 dump memory usage on the recovery daemon
3562 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3566 struct rd_memdump_reply rd;
3568 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3570 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
3573 rd.srvid = getpid();
3575 /* register a message port for receiveing the reply so that we
3576 can receive the reply
3578 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
3581 data.dptr = (uint8_t *)&rd;
3582 data.dsize = sizeof(rd);
3584 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
3586 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
3590 /* this loop will terminate when we have received the reply */
3592 event_loop_once(ctdb->ev);
3599 list all nodes in the cluster
3600 if the daemon is running, we read the data from the daemon.
3601 if the daemon is not running we parse the nodes file directly
3603 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
3606 struct ctdb_node_map *nodemap=NULL;
3609 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3611 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3615 for(i=0;i<nodemap->num;i++){
3616 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
3619 if (options.machinereadable){
3620 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
3622 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
3626 TALLOC_CTX *mem_ctx = talloc_new(NULL);
3627 struct pnn_node *pnn_nodes;
3628 struct pnn_node *pnn_node;
3630 pnn_nodes = read_nodes_file(mem_ctx);
3631 if (pnn_nodes == NULL) {
3632 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
3633 talloc_free(mem_ctx);
3637 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
3638 ctdb_sock_addr addr;
3640 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
3641 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
3642 talloc_free(mem_ctx);
3646 if (options.machinereadable){
3647 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
3649 printf("%s\n", pnn_node->addr);
3652 talloc_free(mem_ctx);
3659 reload the nodes file on the local node
3661 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
3665 struct ctdb_node_map *nodemap=NULL;
3667 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3669 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
3673 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
3675 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
3679 /* reload the nodes file on all remote nodes */
3680 for (i=0;i<nodemap->num;i++) {
3681 if (nodemap->nodes[i].pnn == mypnn) {
3684 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
3685 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
3686 nodemap->nodes[i].pnn);
3688 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
3692 /* reload the nodes file on the local node */
3693 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
3694 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
3696 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
3699 /* initiate a recovery */
3700 control_recover(ctdb, argc, argv);
3706 static const struct {
3708 int (*fn)(struct ctdb_context *, int, const char **);
3710 bool without_daemon; /* can be run without daemon running ? */
3713 } ctdb_commands[] = {
3715 { "version", control_version, true, false, "show version of ctdb" },
3717 { "status", control_status, true, false, "show node status" },
3718 { "uptime", control_uptime, true, false, "show node uptime" },
3719 { "ping", control_ping, true, false, "ping all nodes" },
3720 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
3721 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
3722 { "listvars", control_listvars, true, false, "list tunable variables"},
3723 { "statistics", control_statistics, false, false, "show statistics" },
3724 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
3725 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
3726 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
3727 { "getdbmap", control_getdbmap, true, false, "show the database map" },
3728 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
3729 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
3730 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
3731 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
3732 { "lvs", control_lvs, true, false, "show lvs configuration" },
3733 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
3734 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
3735 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
3736 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
3737 { "getdebug", control_getdebug, true, false, "get debug level" },
3738 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
3739 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
3740 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
3741 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
3742 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
3743 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
3744 { "disable", control_disable, true, false, "disable a nodes public IP" },
3745 { "enable", control_enable, true, false, "enable a nodes public IP" },
3746 { "stop", control_stop, true, false, "stop a node" },
3747 { "continue", control_continue, true, false, "re-start a stopped node" },
3748 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
3749 { "unban", control_unban, true, false, "unban a node" },
3750 { "showban", control_showban, true, false, "show ban information"},
3751 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
3752 { "recover", control_recover, true, false, "force recovery" },
3753 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
3754 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
3755 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
3756 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
3757 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
3758 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
3759 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
3760 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
3762 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
3763 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
3764 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
3765 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
3766 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
3767 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
3768 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
3769 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
3770 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
3771 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
3772 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
3773 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
3774 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
3775 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
3776 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
3777 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
3778 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
3779 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts"},
3780 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
3781 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
3782 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
3783 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
3784 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
3785 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
3786 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
3787 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
3788 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
3789 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
3790 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
3796 static void usage(void)
3800 "Usage: ctdb [options] <control>\n" \
3802 " -n <node> choose node number, or 'all' (defaults to local node)\n"
3803 " -Y generate machinereadable output\n"
3804 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
3805 printf("Controls:\n");
3806 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
3807 printf(" %-15s %-27s %s\n",
3808 ctdb_commands[i].name,
3809 ctdb_commands[i].args?ctdb_commands[i].args:"",
3810 ctdb_commands[i].msg);
3816 static void ctdb_alarm(int sig)
3818 printf("Maximum runtime exceeded - exiting\n");
3825 int main(int argc, const char *argv[])
3827 struct ctdb_context *ctdb;
3828 char *nodestring = NULL;
3829 struct poptOption popt_options[] = {
3832 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
3833 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
3834 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
3835 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
3839 const char **extra_argv;
3843 struct event_context *ev;
3844 const char *control;
3848 /* set some defaults */
3849 options.maxruntime = 0;
3850 options.timelimit = 3;
3851 options.pnn = CTDB_CURRENT_NODE;
3853 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
3855 while ((opt = poptGetNextOpt(pc)) != -1) {
3858 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
3859 poptBadOption(pc, 0), poptStrerror(opt)));
3864 /* setup the remaining options for the main program to use */
3865 extra_argv = poptGetArgs(pc);
3868 while (extra_argv[extra_argc]) extra_argc++;
3871 if (extra_argc < 1) {
3875 if (options.maxruntime == 0) {
3876 const char *ctdb_timeout;
3877 ctdb_timeout = getenv("CTDB_TIMEOUT");
3878 if (ctdb_timeout != NULL) {
3879 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
3881 /* default timeout is 120 seconds */
3882 options.maxruntime = 120;
3886 signal(SIGALRM, ctdb_alarm);
3887 alarm(options.maxruntime);
3889 /* setup the node number to contact */
3890 if (nodestring != NULL) {
3891 if (strcmp(nodestring, "all") == 0) {
3892 options.pnn = CTDB_BROADCAST_ALL;
3894 options.pnn = strtoul(nodestring, NULL, 0);
3898 control = extra_argv[0];
3900 ev = event_context_init(NULL);
3902 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
3903 if (strcmp(control, ctdb_commands[i].name) == 0) {
3906 if (ctdb_commands[i].without_daemon == true) {
3910 /* initialise ctdb */
3911 ctdb = ctdb_cmdline_client(ev);
3913 if (ctdb_commands[i].without_daemon == false) {
3915 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
3919 /* verify the node exists */
3922 if (options.pnn == CTDB_CURRENT_NODE) {
3924 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3932 if (ctdb_commands[i].auto_all &&
3933 options.pnn == CTDB_BROADCAST_ALL) {
3938 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
3939 CTDB_NO_MEMORY(ctdb, nodes);
3941 for (j=0;j<num_nodes;j++) {
3942 options.pnn = nodes[j];
3943 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
3947 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
3953 if (i == ARRAY_SIZE(ctdb_commands)) {
3954 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));