589533b6d006bfd60b9cc6627dee4963260fed14
[sahlberg/ctdb.git] / tools / ctdb.c
1 /* 
2    ctdb control tool
3
4    Copyright (C) Andrew Tridgell  2007
5    Copyright (C) Ronnie Sahlberg  2007
6
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.
11    
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.
16    
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/>.
19 */
20
21 #include "includes.h"
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"
27 #include "popt.h"
28 #include "cmdline.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_private.h"
31 #include "../common/rb_tree.h"
32 #include "db_wrap.h"
33
34
35 #define ERR_TIMEOUT     20      /* timed out trying to reach node */
36 #define ERR_NONODE      21      /* node does not exist */
37 #define ERR_DISNODE     22      /* node is disconnected */
38
39 static void usage(void);
40
41 static struct {
42         int timelimit;
43         uint32_t pnn;
44         int machinereadable;
45         int maxruntime;
46 } options;
47
48 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
49
50 #ifdef CTDB_VERS
51 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
52 {
53 #define STR(x) #x
54 #define XSTR(x) STR(x)
55         printf("CTDB version: %s\n", XSTR(CTDB_VERS));
56         return 0;
57 }
58 #endif
59
60
61 /*
62   verify that a node exists and is reachable
63  */
64 static void verify_node(struct ctdb_context *ctdb)
65 {
66         int ret;
67         struct ctdb_node_map *nodemap=NULL;
68
69         if (options.pnn == CTDB_CURRENT_NODE) {
70                 return;
71         }
72         if (options.pnn == CTDB_BROADCAST_ALL) {
73                 return;
74         }
75
76         /* verify the node exists */
77         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
78                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
79                 exit(10);
80         }
81         if (options.pnn >= nodemap->num) {
82                 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
83                 exit(ERR_NONODE);
84         }
85         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
86                 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
87                 exit(ERR_DISNODE);
88         }
89         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
90                 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
91                 exit(ERR_DISNODE);
92         }
93
94         /* verify we can access the node */
95         ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
96         if (ret == -1) {
97                 DEBUG(DEBUG_ERR,("Can not ban node. Node is not operational.\n"));
98                 exit(10);
99         }
100 }
101
102 /*
103  check if a database exists
104 */
105 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
106 {
107         int i, ret;
108         struct ctdb_dbid_map *dbmap=NULL;
109
110         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
111         if (ret != 0) {
112                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
113                 return -1;
114         }
115
116         for(i=0;i<dbmap->num;i++){
117                 const char *name;
118
119                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
120                 if (!strcmp(name, db_name)) {
121                         return 0;
122                 }
123         }
124
125         return -1;
126 }
127
128 /*
129   see if a process exists
130  */
131 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
132 {
133         uint32_t pnn, pid;
134         int ret;
135         if (argc < 1) {
136                 usage();
137         }
138
139         if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
140                 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
141                 return -1;
142         }
143
144         ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
145         if (ret == 0) {
146                 printf("%u:%u exists\n", pnn, pid);
147         } else {
148                 printf("%u:%u does not exist\n", pnn, pid);
149         }
150         return ret;
151 }
152
153 /*
154   display statistics structure
155  */
156 static void show_statistics(struct ctdb_statistics *s)
157 {
158         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
159         int i;
160         const char *prefix=NULL;
161         int preflen=0;
162         const struct {
163                 const char *name;
164                 uint32_t offset;
165         } fields[] = {
166 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
167                 STATISTICS_FIELD(num_clients),
168                 STATISTICS_FIELD(frozen),
169                 STATISTICS_FIELD(recovering),
170                 STATISTICS_FIELD(client_packets_sent),
171                 STATISTICS_FIELD(client_packets_recv),
172                 STATISTICS_FIELD(node_packets_sent),
173                 STATISTICS_FIELD(node_packets_recv),
174                 STATISTICS_FIELD(keepalive_packets_sent),
175                 STATISTICS_FIELD(keepalive_packets_recv),
176                 STATISTICS_FIELD(node.req_call),
177                 STATISTICS_FIELD(node.reply_call),
178                 STATISTICS_FIELD(node.req_dmaster),
179                 STATISTICS_FIELD(node.reply_dmaster),
180                 STATISTICS_FIELD(node.reply_error),
181                 STATISTICS_FIELD(node.req_message),
182                 STATISTICS_FIELD(node.req_control),
183                 STATISTICS_FIELD(node.reply_control),
184                 STATISTICS_FIELD(client.req_call),
185                 STATISTICS_FIELD(client.req_message),
186                 STATISTICS_FIELD(client.req_control),
187                 STATISTICS_FIELD(timeouts.call),
188                 STATISTICS_FIELD(timeouts.control),
189                 STATISTICS_FIELD(timeouts.traverse),
190                 STATISTICS_FIELD(total_calls),
191                 STATISTICS_FIELD(pending_calls),
192                 STATISTICS_FIELD(lockwait_calls),
193                 STATISTICS_FIELD(pending_lockwait_calls),
194                 STATISTICS_FIELD(childwrite_calls),
195                 STATISTICS_FIELD(pending_childwrite_calls),
196                 STATISTICS_FIELD(memory_used),
197                 STATISTICS_FIELD(max_hop_count),
198         };
199         printf("CTDB version %u\n", CTDB_VERSION);
200         for (i=0;i<ARRAY_SIZE(fields);i++) {
201                 if (strchr(fields[i].name, '.')) {
202                         preflen = strcspn(fields[i].name, ".")+1;
203                         if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
204                                 prefix = fields[i].name;
205                                 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
206                         }
207                 } else {
208                         preflen = 0;
209                 }
210                 printf(" %*s%-22s%*s%10u\n", 
211                        preflen?4:0, "",
212                        fields[i].name+preflen, 
213                        preflen?0:4, "",
214                        *(uint32_t *)(fields[i].offset+(uint8_t *)s));
215         }
216         printf(" %-30s     %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
217         printf(" %-30s     %.6f sec\n", "max_reclock_recd", s->reclock.recd);
218
219         printf(" %-30s     %.6f sec\n", "max_call_latency", s->max_call_latency);
220         printf(" %-30s     %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
221         printf(" %-30s     %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
222         talloc_free(tmp_ctx);
223 }
224
225 /*
226   display remote ctdb statistics combined from all nodes
227  */
228 static int control_statistics_all(struct ctdb_context *ctdb)
229 {
230         int ret, i;
231         struct ctdb_statistics statistics;
232         uint32_t *nodes;
233         uint32_t num_nodes;
234
235         nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
236         CTDB_NO_MEMORY(ctdb, nodes);
237         
238         ZERO_STRUCT(statistics);
239
240         for (i=0;i<num_nodes;i++) {
241                 struct ctdb_statistics s1;
242                 int j;
243                 uint32_t *v1 = (uint32_t *)&s1;
244                 uint32_t *v2 = (uint32_t *)&statistics;
245                 uint32_t num_ints = 
246                         offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
247                 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
248                 if (ret != 0) {
249                         DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
250                         return ret;
251                 }
252                 for (j=0;j<num_ints;j++) {
253                         v2[j] += v1[j];
254                 }
255                 statistics.max_hop_count = 
256                         MAX(statistics.max_hop_count, s1.max_hop_count);
257                 statistics.max_call_latency = 
258                         MAX(statistics.max_call_latency, s1.max_call_latency);
259                 statistics.max_lockwait_latency = 
260                         MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
261         }
262         talloc_free(nodes);
263         printf("Gathered statistics for %u nodes\n", num_nodes);
264         show_statistics(&statistics);
265         return 0;
266 }
267
268 /*
269   display remote ctdb statistics
270  */
271 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
272 {
273         int ret;
274         struct ctdb_statistics statistics;
275
276         if (options.pnn == CTDB_BROADCAST_ALL) {
277                 return control_statistics_all(ctdb);
278         }
279
280         ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
281         if (ret != 0) {
282                 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
283                 return ret;
284         }
285         show_statistics(&statistics);
286         return 0;
287 }
288
289
290 /*
291   reset remote ctdb statistics
292  */
293 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
294 {
295         int ret;
296
297         ret = ctdb_statistics_reset(ctdb, options.pnn);
298         if (ret != 0) {
299                 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
300                 return ret;
301         }
302         return 0;
303 }
304
305
306 /*
307   display uptime of remote node
308  */
309 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
310 {
311         int ret;
312         struct ctdb_uptime *uptime = NULL;
313         int tmp, days, hours, minutes, seconds;
314
315         ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
316         if (ret != 0) {
317                 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
318                 return ret;
319         }
320
321         if (options.machinereadable){
322                 printf(":Current Node Time:Ctdb Start Time:Last Recovery Time:Last Recovery Duration:\n");
323                 printf(":%u:%u:%u:%lf\n",
324                         (unsigned int)uptime->current_time.tv_sec,
325                         (unsigned int)uptime->ctdbd_start_time.tv_sec,
326                         (unsigned int)uptime->last_recovery_finished.tv_sec,
327                         timeval_delta(&uptime->last_recovery_finished,
328                                       &uptime->last_recovery_started)
329                 );
330                 return 0;
331         }
332
333         printf("Current time of node  : %s", ctime(&uptime->current_time.tv_sec));
334
335         tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
336         seconds = tmp%60;
337         tmp    /= 60;
338         minutes = tmp%60;
339         tmp    /= 60;
340         hours   = tmp%24;
341         tmp    /= 24;
342         days    = tmp;
343         printf("Ctdbd start time      : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
344
345         tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
346         seconds = tmp%60;
347         tmp    /= 60;
348         minutes = tmp%60;
349         tmp    /= 60;
350         hours   = tmp%24;
351         tmp    /= 24;
352         days    = tmp;
353         printf("Time of last recovery : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
354         
355         printf("Duration of last recovery : %lf seconds\n",
356                 timeval_delta(&uptime->last_recovery_finished,
357                               &uptime->last_recovery_started));
358
359         return 0;
360 }
361
362 /*
363   show the PNN of the current node
364  */
365 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
366 {
367         int mypnn;
368
369         mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
370         if (mypnn == -1) {
371                 DEBUG(DEBUG_ERR, ("Unable to get pnn from local node."));
372                 return -1;
373         }
374
375         printf("PNN:%d\n", mypnn);
376         return 0;
377 }
378
379
380 struct pnn_node {
381         struct pnn_node *next;
382         const char *addr;
383         int pnn;
384 };
385
386 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
387 {
388         const char *nodes_list;
389         int nlines;
390         char **lines;
391         int i, pnn;
392         struct pnn_node *pnn_nodes = NULL;
393         struct pnn_node *pnn_node;
394         struct pnn_node *tmp_node;
395
396         /* read the nodes file */
397         nodes_list = getenv("CTDB_NODES");
398         if (nodes_list == NULL) {
399                 nodes_list = "/etc/ctdb/nodes";
400         }
401         lines = file_lines_load(nodes_list, &nlines, mem_ctx);
402         if (lines == NULL) {
403                 return NULL;
404         }
405         while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
406                 nlines--;
407         }
408         for (i=0, pnn=0; i<nlines; i++) {
409                 char *node;
410
411                 node = lines[i];
412                 /* strip leading spaces */
413                 while((*node == ' ') || (*node == '\t')) {
414                         node++;
415                 }
416                 if (*node == '#') {
417                         pnn++;
418                         continue;
419                 }
420                 if (strcmp(node, "") == 0) {
421                         continue;
422                 }
423                 pnn_node = talloc(mem_ctx, struct pnn_node);
424                 pnn_node->pnn = pnn++;
425                 pnn_node->addr = talloc_strdup(pnn_node, node);
426                 pnn_node->next = pnn_nodes;
427                 pnn_nodes = pnn_node;
428         }
429
430         /* swap them around so we return them in incrementing order */
431         pnn_node = pnn_nodes;
432         pnn_nodes = NULL;
433         while (pnn_node) {
434                 tmp_node = pnn_node;
435                 pnn_node = pnn_node->next;
436
437                 tmp_node->next = pnn_nodes;
438                 pnn_nodes = tmp_node;
439         }
440
441         return pnn_nodes;
442 }
443
444 /*
445   show the PNN of the current node
446   discover the pnn by loading the nodes file and try to bind to all
447   addresses one at a time until the ip address is found.
448  */
449 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
450 {
451         TALLOC_CTX *mem_ctx = talloc_new(NULL);
452         struct pnn_node *pnn_nodes;
453         struct pnn_node *pnn_node;
454
455         pnn_nodes = read_nodes_file(mem_ctx);
456         if (pnn_nodes == NULL) {
457                 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
458                 talloc_free(mem_ctx);
459                 return -1;
460         }
461
462         for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
463                 ctdb_sock_addr addr;
464
465                 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
466                         DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
467                         talloc_free(mem_ctx);
468                         return -1;
469                 }
470
471                 if (ctdb_sys_have_ip(&addr)) {
472                         printf("PNN:%d\n", pnn_node->pnn);
473                         talloc_free(mem_ctx);
474                         return 0;
475                 }
476         }
477
478         printf("Failed to detect which PNN this node is\n");
479         talloc_free(mem_ctx);
480         return -1;
481 }
482
483 /*
484   display remote ctdb status
485  */
486 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
487 {
488         int i, ret;
489         struct ctdb_vnn_map *vnnmap=NULL;
490         struct ctdb_node_map *nodemap=NULL;
491         uint32_t recmode, recmaster;
492         int mypnn;
493
494         mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
495         if (mypnn == -1) {
496                 return -1;
497         }
498
499         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
500         if (ret != 0) {
501                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
502                 return ret;
503         }
504
505         if(options.machinereadable){
506                 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:\n");
507                 for(i=0;i<nodemap->num;i++){
508                         if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
509                                 continue;
510                         }
511                         printf(":%d:%s:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
512                                 ctdb_addr_to_str(&nodemap->nodes[i].addr),
513                                !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
514                                !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
515                                !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
516                                !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY));
517                 }
518                 return 0;
519         }
520
521         printf("Number of nodes:%d\n", nodemap->num);
522         for(i=0;i<nodemap->num;i++){
523                 static const struct {
524                         uint32_t flag;
525                         const char *name;
526                 } flag_names[] = {
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                 };
533                 char *flags_str = NULL;
534                 int j;
535
536                 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
537                         continue;
538                 }
539                 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
540                         if (nodemap->nodes[i].flags & flag_names[j].flag) {
541                                 if (flags_str == NULL) {
542                                         flags_str = talloc_strdup(ctdb, flag_names[j].name);
543                                 } else {
544                                         flags_str = talloc_asprintf_append(flags_str, "|%s",
545                                                                            flag_names[j].name);
546                                 }
547                                 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
548                         }
549                 }
550                 if (flags_str == NULL) {
551                         flags_str = talloc_strdup(ctdb, "OK");
552                         CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
553                 }
554                 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
555                        ctdb_addr_to_str(&nodemap->nodes[i].addr),
556                        flags_str,
557                        nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
558                 talloc_free(flags_str);
559         }
560
561         ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
562         if (ret != 0) {
563                 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
564                 return ret;
565         }
566         if (vnnmap->generation == INVALID_GENERATION) {
567                 printf("Generation:INVALID\n");
568         } else {
569                 printf("Generation:%d\n",vnnmap->generation);
570         }
571         printf("Size:%d\n",vnnmap->size);
572         for(i=0;i<vnnmap->size;i++){
573                 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
574         }
575
576         ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
577         if (ret != 0) {
578                 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
579                 return ret;
580         }
581         printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
582
583         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
584         if (ret != 0) {
585                 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
586                 return ret;
587         }
588         printf("Recovery master:%d\n",recmaster);
589
590         return 0;
591 }
592
593
594 struct natgw_node {
595         struct natgw_node *next;
596         const char *addr;
597 };
598
599 /*
600   display the list of nodes belonging to this natgw configuration
601  */
602 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
603 {
604         int i, ret;
605         const char *natgw_list;
606         int nlines;
607         char **lines;
608         struct natgw_node *natgw_nodes = NULL;
609         struct natgw_node *natgw_node;
610         struct ctdb_node_map *nodemap=NULL;
611
612
613         /* read the natgw nodes file into a linked list */
614         natgw_list = getenv("NATGW_NODES");
615         if (natgw_list == NULL) {
616                 natgw_list = "/etc/ctdb/natgw_nodes";
617         }
618         lines = file_lines_load(natgw_list, &nlines, ctdb);
619         if (lines == NULL) {
620                 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
621                 return -1;
622         }
623         while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
624                 nlines--;
625         }
626         for (i=0;i<nlines;i++) {
627                 char *node;
628
629                 node = lines[i];
630                 /* strip leading spaces */
631                 while((*node == ' ') || (*node == '\t')) {
632                         node++;
633                 }
634                 if (*node == '#') {
635                         continue;
636                 }
637                 if (strcmp(node, "") == 0) {
638                         continue;
639                 }
640                 natgw_node = talloc(ctdb, struct natgw_node);
641                 natgw_node->addr = talloc_strdup(natgw_node, node);
642                 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
643                 natgw_node->next = natgw_nodes;
644                 natgw_nodes = natgw_node;
645         }
646
647         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
648         if (ret != 0) {
649                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
650                 return ret;
651         }
652
653         i=0;
654         while(i<nodemap->num) {
655                 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
656                         if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
657                                 break;
658                         }
659                 }
660
661                 /* this node was not in the natgw so we just remove it from
662                  * the list
663                  */
664                 if ((natgw_node == NULL) 
665                 ||  (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
666                         int j;
667
668                         for (j=i+1; j<nodemap->num; j++) {
669                                 nodemap->nodes[j-1] = nodemap->nodes[j];
670                         }
671                         nodemap->num--;
672                         continue;
673                 }
674
675                 i++;
676         }               
677
678         /* print the natgw master */
679         for(i=0;i<nodemap->num;i++){
680                 if (!(nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
681                         printf("%d\n", nodemap->nodes[i].pnn);
682                         break;
683                 }
684         }
685
686         /* print the pruned list of nodes belonging to this natgw list */
687         for(i=0;i<nodemap->num;i++){
688                 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
689                         continue;
690                 }
691                 printf(":%d:%s:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
692                         ctdb_addr_to_str(&nodemap->nodes[i].addr),
693                        !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
694                        !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
695                        !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
696                        !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY));
697         }
698
699         return 0;
700 }
701
702
703 /*
704   display the status of the monitoring scripts
705  */
706 static int control_scriptstatus(struct ctdb_context *ctdb, int argc, const char **argv)
707 {
708         int i, ret;
709         struct ctdb_monitoring_wire *script_status;
710
711         ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, &script_status);
712         if (ret != 0) {
713                 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
714                 return ret;
715         }
716
717         printf("%d scripts were executed last monitoring cycle\n", script_status->num_scripts);
718         for (i=0; i<script_status->num_scripts; i++) {
719                 printf("%-20s Status:%s    ",
720                         script_status->scripts[i].name,
721                         script_status->scripts[i].timedout?"TIMEDOUT":script_status->scripts[i].status==0?"OK":"ERROR");
722                 if (script_status->scripts[i].timedout == 0) {
723                         printf("Duration:%.3lf ",
724                         timeval_delta(&script_status->scripts[i].finished,
725                               &script_status->scripts[i].start));
726                 }
727                 printf("%s",
728                         ctime(&script_status->scripts[i].start.tv_sec));
729                 if ((script_status->scripts[i].timedout != 0)
730                 ||  (script_status->scripts[i].status != 0) ) {
731                         printf("   OUTPUT:%s\n",
732                                 script_status->scripts[i].output);
733                 }
734         }
735
736         return 0;
737 }
738         
739
740 /*
741   display the pnn of the recovery master
742  */
743 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
744 {
745         int ret;
746         uint32_t recmaster;
747
748         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
749         if (ret != 0) {
750                 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
751                 return ret;
752         }
753         printf("%d\n",recmaster);
754
755         return 0;
756 }
757
758 /*
759   get a list of all tickles for this pnn
760  */
761 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
762 {
763         struct ctdb_control_tcp_tickle_list *list;
764         ctdb_sock_addr addr;
765         int i, ret;
766
767         if (argc < 1) {
768                 usage();
769         }
770
771         if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
772                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
773                 return -1;
774         }
775
776         ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
777         if (ret == -1) {
778                 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
779                 return -1;
780         }
781
782         printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
783         printf("Num tickles:%u\n", list->tickles.num);
784         for (i=0;i<list->tickles.num;i++) {
785                 printf("SRC: %s:%u   ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
786                 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));
787         }
788
789         talloc_free(list);
790         
791         return 0;
792 }
793
794
795 /*
796   move/failover an ip address to a specific node
797  */
798 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
799 {
800         uint32_t pnn;
801         ctdb_sock_addr addr;
802         struct ctdb_all_public_ips *ips;
803         struct ctdb_public_ip ip;
804         uint32_t *nodes;
805         int i, ret;
806         TDB_DATA data;
807         struct ctdb_node_map *nodemap=NULL;
808         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
809
810         if (argc < 2) {
811                 usage();
812                 talloc_free(tmp_ctx);
813                 return -1;
814         }
815
816         if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
817                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
818                 talloc_free(tmp_ctx);
819                 return -1;
820         }
821
822
823         if (sscanf(argv[1], "%u", &pnn) != 1) {
824                 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
825                 talloc_free(tmp_ctx);
826                 return -1;
827         }
828
829
830         /* read the public ip list from the node */
831         ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
832         if (ret != 0) {
833                 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
834                 talloc_free(tmp_ctx);
835                 return -1;
836         }
837
838         for (i=0;i<ips->num;i++) {
839                 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
840                         break;
841                 }
842         }
843         if (i==ips->num) {
844                 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
845                         pnn, ctdb_addr_to_str(&addr)));
846                 talloc_free(tmp_ctx);
847                 return -1;
848         }
849         if (ips->ips[i].pnn == pnn) {
850                 DEBUG(DEBUG_ERR, ("Host %u is already hosting '%s'\n",
851                         pnn, ctdb_addr_to_str(&ips->ips[i].addr)));
852                 talloc_free(tmp_ctx);
853                 return -1;
854         }
855
856         ip.pnn  = pnn;
857         ip.addr = addr;
858
859         data.dptr  = (uint8_t *)&ip;
860         data.dsize = sizeof(ip);
861
862         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
863         if (ret != 0) {
864                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
865                 talloc_free(tmp_ctx);
866                 return ret;
867         }
868
869         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
870         ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
871                                         nodes, TIMELIMIT(),
872                                         false, data,
873                                         NULL, NULL,
874                                         NULL);
875         if (ret != 0) {
876                 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
877                 talloc_free(tmp_ctx);
878                 return -1;
879         }
880
881         ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), pnn, &ip);
882         if (ret != 0) {
883                 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
884                 talloc_free(tmp_ctx);
885                 return -1;
886         }
887
888         talloc_free(tmp_ctx);
889         return 0;
890 }
891
892 void getips_store_callback(void *param, void *data)
893 {
894         struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
895         struct ctdb_all_public_ips *ips = param;
896         int i;
897
898         i = ips->num++;
899         ips->ips[i].pnn  = node_ip->pnn;
900         ips->ips[i].addr = node_ip->addr;
901 }
902
903 void getips_count_callback(void *param, void *data)
904 {
905         uint32_t *count = param;
906
907         (*count)++;
908 }
909
910 #define IP_KEYLEN       4
911 static uint32_t *ip_key(ctdb_sock_addr *ip)
912 {
913         static uint32_t key[IP_KEYLEN];
914
915         bzero(key, sizeof(key));
916
917         switch (ip->sa.sa_family) {
918         case AF_INET:
919                 key[0]  = ip->ip.sin_addr.s_addr;
920                 break;
921         case AF_INET6:
922                 key[0]  = ip->ip6.sin6_addr.s6_addr32[3];
923                 key[1]  = ip->ip6.sin6_addr.s6_addr32[2];
924                 key[2]  = ip->ip6.sin6_addr.s6_addr32[1];
925                 key[3]  = ip->ip6.sin6_addr.s6_addr32[0];
926                 break;
927         default:
928                 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
929                 return key;
930         }
931
932         return key;
933 }
934
935 static void *add_ip_callback(void *parm, void *data)
936 {
937         return parm;
938 }
939
940 static int
941 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
942 {
943         struct ctdb_all_public_ips *tmp_ips;
944         struct ctdb_node_map *nodemap=NULL;
945         trbt_tree_t *ip_tree;
946         int i, j, len, ret;
947         uint32_t count;
948
949         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
950         if (ret != 0) {
951                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
952                 return ret;
953         }
954
955         ip_tree = trbt_create(tmp_ctx, 0);
956
957         for(i=0;i<nodemap->num;i++){
958                 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
959                         continue;
960                 }
961                 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
962                         continue;
963                 }
964
965                 /* read the public ip list from this node */
966                 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
967                 if (ret != 0) {
968                         DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
969                         return -1;
970                 }
971         
972                 for (j=0; j<tmp_ips->num;j++) {
973                         struct ctdb_public_ip *node_ip;
974
975                         node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
976                         node_ip->pnn  = tmp_ips->ips[j].pnn;
977                         node_ip->addr = tmp_ips->ips[j].addr;
978
979                         trbt_insertarray32_callback(ip_tree,
980                                 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
981                                 add_ip_callback,
982                                 node_ip);
983                 }
984                 talloc_free(tmp_ips);
985         }
986
987         /* traverse */
988         count = 0;
989         trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
990
991         len = offsetof(struct ctdb_all_public_ips, ips) + 
992                 count*sizeof(struct ctdb_public_ip);
993         tmp_ips = talloc_zero_size(tmp_ctx, len);
994         trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
995
996         *ips = tmp_ips;
997
998         return 0;
999 }
1000
1001
1002 /* 
1003  * scans all other nodes and returns a pnn for another node that can host this 
1004  * ip address or -1
1005  */
1006 static int
1007 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1008 {
1009         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1010         struct ctdb_all_public_ips *ips;
1011         struct ctdb_node_map *nodemap=NULL;
1012         int i, j, ret;
1013
1014         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1015         if (ret != 0) {
1016                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1017                 talloc_free(tmp_ctx);
1018                 return ret;
1019         }
1020
1021         for(i=0;i<nodemap->num;i++){
1022                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1023                         continue;
1024                 }
1025                 if (nodemap->nodes[i].pnn == options.pnn) {
1026                         continue;
1027                 }
1028
1029                 /* read the public ip list from this node */
1030                 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1031                 if (ret != 0) {
1032                         DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1033                         return -1;
1034                 }
1035
1036                 for (j=0;j<ips->num;j++) {
1037                         if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1038                                 talloc_free(tmp_ctx);
1039                                 return nodemap->nodes[i].pnn;
1040                         }
1041                 }
1042                 talloc_free(ips);
1043         }
1044
1045         talloc_free(tmp_ctx);
1046         return -1;
1047 }
1048
1049 /*
1050   add a public ip address to a node
1051  */
1052 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1053 {
1054         int i, ret;
1055         int len;
1056         unsigned mask;
1057         ctdb_sock_addr addr;
1058         struct ctdb_control_ip_iface *pub;
1059         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1060         struct ctdb_all_public_ips *ips;
1061
1062         if (argc != 2) {
1063                 talloc_free(tmp_ctx);
1064                 usage();
1065         }
1066
1067         if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1068                 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1069                 talloc_free(tmp_ctx);
1070                 return -1;
1071         }
1072
1073         ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1074         if (ret != 0) {
1075                 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1076                 talloc_free(tmp_ctx);
1077                 return ret;
1078         }
1079
1080
1081         /* check if some other node is already serving this ip, if not,
1082          * we will claim it
1083          */
1084         for (i=0;i<ips->num;i++) {
1085                 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1086                         break;
1087                 }
1088         }
1089
1090         len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1091         pub = talloc_size(tmp_ctx, len); 
1092         CTDB_NO_MEMORY(ctdb, pub);
1093
1094         pub->addr  = addr;
1095         pub->mask  = mask;
1096         pub->len   = strlen(argv[1])+1;
1097         memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1098
1099         ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1100         if (ret != 0) {
1101                 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1102                 talloc_free(tmp_ctx);
1103                 return ret;
1104         }
1105
1106         /* no one has this ip so we claim it */
1107         if (i == ips->num) {
1108                 struct ctdb_public_ip ip;
1109
1110                 ip.pnn  = options.pnn;
1111                 ip.addr = addr;
1112
1113                 ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), options.pnn, &ip);
1114                 if (ret != 0) {
1115                         DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", options.pnn));
1116                         return -1;
1117                 }
1118         }
1119
1120
1121         if (ret != 0) {
1122                 DEBUG(DEBUG_ERR, ("Failed to send 'change ip' to all nodes\n"));
1123                 return -1;
1124         }
1125
1126         talloc_free(tmp_ctx);
1127         return 0;
1128 }
1129
1130 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1131
1132 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1133 {
1134         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1135         struct ctdb_node_map *nodemap=NULL;
1136         struct ctdb_all_public_ips *ips;
1137         int ret, i, j;
1138
1139         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1140         if (ret != 0) {
1141                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1142                 return ret;
1143         }
1144
1145         /* remove it from the nodes that are not hosting the ip currently */
1146         for(i=0;i<nodemap->num;i++){
1147                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1148                         continue;
1149                 }
1150                 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1151                         DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1152                         continue;
1153                 }
1154
1155                 for (j=0;j<ips->num;j++) {
1156                         if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1157                                 break;
1158                         }
1159                 }
1160                 if (j==ips->num) {
1161                         continue;
1162                 }
1163
1164                 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1165                         continue;
1166                 }
1167
1168                 options.pnn = nodemap->nodes[i].pnn;
1169                 control_delip(ctdb, argc, argv);
1170         }
1171
1172
1173         /* remove it from every node (also the one hosting it) */
1174         for(i=0;i<nodemap->num;i++){
1175                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1176                         continue;
1177                 }
1178                 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1179                         DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1180                         continue;
1181                 }
1182
1183                 for (j=0;j<ips->num;j++) {
1184                         if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1185                                 break;
1186                         }
1187                 }
1188                 if (j==ips->num) {
1189                         continue;
1190                 }
1191
1192                 options.pnn = nodemap->nodes[i].pnn;
1193                 control_delip(ctdb, argc, argv);
1194         }
1195
1196         talloc_free(tmp_ctx);
1197         return 0;
1198 }
1199         
1200 /*
1201   delete a public ip address from a node
1202  */
1203 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1204 {
1205         int i, ret;
1206         ctdb_sock_addr addr;
1207         struct ctdb_control_ip_iface pub;
1208         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1209         struct ctdb_all_public_ips *ips;
1210
1211         if (argc != 1) {
1212                 talloc_free(tmp_ctx);
1213                 usage();
1214         }
1215
1216         if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1217                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1218                 return -1;
1219         }
1220
1221         if (options.pnn == CTDB_BROADCAST_ALL) {
1222                 return control_delip_all(ctdb, argc, argv, &addr);
1223         }
1224
1225         pub.addr  = addr;
1226         pub.mask  = 0;
1227         pub.len   = 0;
1228
1229         ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1230         if (ret != 0) {
1231                 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1232                 talloc_free(tmp_ctx);
1233                 return ret;
1234         }
1235         
1236         for (i=0;i<ips->num;i++) {
1237                 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1238                         break;
1239                 }
1240         }
1241
1242         if (i==ips->num) {
1243                 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1244                         ctdb_addr_to_str(&addr)));
1245                 talloc_free(tmp_ctx);
1246                 return -1;
1247         }
1248
1249         if (ips->ips[i].pnn == options.pnn) {
1250                 ret = find_other_host_for_public_ip(ctdb, &addr);
1251                 if (ret != -1) {
1252                         struct ctdb_public_ip ip;
1253
1254                         ip.pnn  = ret;
1255                         ip.addr = addr;
1256
1257                         ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), ret, &ip);
1258                         if (ret != 0) {
1259                                 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", options.pnn));
1260                                 return -1;
1261                         }
1262                 }
1263         }
1264
1265         ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1266         if (ret != 0) {
1267                 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1268                 talloc_free(tmp_ctx);
1269                 return ret;
1270         }
1271
1272         talloc_free(tmp_ctx);
1273         return 0;
1274 }
1275
1276 /*
1277   kill a tcp connection
1278  */
1279 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1280 {
1281         int ret;
1282         struct ctdb_control_killtcp killtcp;
1283
1284         if (argc < 2) {
1285                 usage();
1286         }
1287
1288         if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1289                 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1290                 return -1;
1291         }
1292
1293         if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1294                 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1295                 return -1;
1296         }
1297
1298         ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1299         if (ret != 0) {
1300                 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1301                 return ret;
1302         }
1303
1304         return 0;
1305 }
1306
1307
1308 /*
1309   send a gratious arp
1310  */
1311 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1312 {
1313         int ret;
1314         ctdb_sock_addr addr;
1315
1316         if (argc < 2) {
1317                 usage();
1318         }
1319
1320         if (!parse_ip(argv[0], NULL, 0, &addr)) {
1321                 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1322                 return -1;
1323         }
1324
1325         ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1326         if (ret != 0) {
1327                 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1328                 return ret;
1329         }
1330
1331         return 0;
1332 }
1333
1334 /*
1335   register a server id
1336  */
1337 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1338 {
1339         int ret;
1340         struct ctdb_server_id server_id;
1341
1342         if (argc < 3) {
1343                 usage();
1344         }
1345
1346         server_id.pnn       = strtoul(argv[0], NULL, 0);
1347         server_id.type      = strtoul(argv[1], NULL, 0);
1348         server_id.server_id = strtoul(argv[2], NULL, 0);
1349
1350         ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1351         if (ret != 0) {
1352                 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1353                 return ret;
1354         }
1355         return -1;
1356 }
1357
1358 /*
1359   unregister a server id
1360  */
1361 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1362 {
1363         int ret;
1364         struct ctdb_server_id server_id;
1365
1366         if (argc < 3) {
1367                 usage();
1368         }
1369
1370         server_id.pnn       = strtoul(argv[0], NULL, 0);
1371         server_id.type      = strtoul(argv[1], NULL, 0);
1372         server_id.server_id = strtoul(argv[2], NULL, 0);
1373
1374         ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1375         if (ret != 0) {
1376                 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1377                 return ret;
1378         }
1379         return -1;
1380 }
1381
1382 /*
1383   check if a server id exists
1384  */
1385 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1386 {
1387         uint32_t status;
1388         int ret;
1389         struct ctdb_server_id server_id;
1390
1391         if (argc < 3) {
1392                 usage();
1393         }
1394
1395         server_id.pnn       = strtoul(argv[0], NULL, 0);
1396         server_id.type      = strtoul(argv[1], NULL, 0);
1397         server_id.server_id = strtoul(argv[2], NULL, 0);
1398
1399         ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1400         if (ret != 0) {
1401                 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1402                 return ret;
1403         }
1404
1405         if (status) {
1406                 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1407         } else {
1408                 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1409         }
1410         return 0;
1411 }
1412
1413 /*
1414   get a list of all server ids that are registered on a node
1415  */
1416 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1417 {
1418         int i, ret;
1419         struct ctdb_server_id_list *server_ids;
1420
1421         ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1422         if (ret != 0) {
1423                 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1424                 return ret;
1425         }
1426
1427         for (i=0; i<server_ids->num; i++) {
1428                 printf("Server id %d:%d:%d\n", 
1429                         server_ids->server_ids[i].pnn, 
1430                         server_ids->server_ids[i].type, 
1431                         server_ids->server_ids[i].server_id); 
1432         }
1433
1434         return -1;
1435 }
1436
1437 /*
1438   send a tcp tickle ack
1439  */
1440 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1441 {
1442         int ret;
1443         ctdb_sock_addr  src, dst;
1444
1445         if (argc < 2) {
1446                 usage();
1447         }
1448
1449         if (!parse_ip_port(argv[0], &src)) {
1450                 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1451                 return -1;
1452         }
1453
1454         if (!parse_ip_port(argv[1], &dst)) {
1455                 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1456                 return -1;
1457         }
1458
1459         ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1460         if (ret==0) {
1461                 return 0;
1462         }
1463         DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1464
1465         return -1;
1466 }
1467
1468
1469 /*
1470   display public ip status
1471  */
1472 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1473 {
1474         int i, ret;
1475         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1476         struct ctdb_all_public_ips *ips;
1477
1478         if (options.pnn == CTDB_BROADCAST_ALL) {
1479                 /* read the list of public ips from all nodes */
1480                 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1481         } else {
1482                 /* read the public ip list from this node */
1483                 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1484         }
1485         if (ret != 0) {
1486                 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1487                 talloc_free(tmp_ctx);
1488                 return ret;
1489         }
1490
1491         if (options.machinereadable){
1492                 printf(":Public IP:Node:\n");
1493         } else {
1494                 if (options.pnn == CTDB_BROADCAST_ALL) {
1495                         printf("Public IPs on ALL nodes\n");
1496                 } else {
1497                         printf("Public IPs on node %u\n", options.pnn);
1498                 }
1499         }
1500
1501         for (i=1;i<=ips->num;i++) {
1502                 if (options.machinereadable){
1503                         printf(":%s:%d:\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1504                 } else {
1505                         printf("%s %d\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1506                 }
1507         }
1508
1509         talloc_free(tmp_ctx);
1510         return 0;
1511 }
1512
1513 /*
1514   display pid of a ctdb daemon
1515  */
1516 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1517 {
1518         uint32_t pid;
1519         int ret;
1520
1521         ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1522         if (ret != 0) {
1523                 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1524                 return ret;
1525         }
1526         printf("Pid:%d\n", pid);
1527
1528         return 0;
1529 }
1530
1531 /*
1532   disable a remote node
1533  */
1534 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
1535 {
1536         int ret;
1537
1538         ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
1539         if (ret != 0) {
1540                 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
1541                 return ret;
1542         }
1543
1544         return 0;
1545 }
1546
1547 /*
1548   enable a disabled remote node
1549  */
1550 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
1551 {
1552         int ret;
1553
1554         ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
1555         if (ret != 0) {
1556                 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
1557                 return ret;
1558         }
1559
1560         return 0;
1561 }
1562
1563 static uint32_t get_generation(struct ctdb_context *ctdb)
1564 {
1565         struct ctdb_vnn_map *vnnmap=NULL;
1566         int ret;
1567
1568         /* wait until the recmaster is not in recovery mode */
1569         while (1) {
1570                 uint32_t recmode, recmaster;
1571                 
1572                 if (vnnmap != NULL) {
1573                         talloc_free(vnnmap);
1574                         vnnmap = NULL;
1575                 }
1576
1577                 /* get the recmaster */
1578                 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
1579                 if (ret != 0) {
1580                         DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1581                         exit(10);
1582                 }
1583
1584                 /* get recovery mode */
1585                 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
1586                 if (ret != 0) {
1587                         DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
1588                         exit(10);
1589                 }
1590
1591                 /* get the current generation number */
1592                 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
1593                 if (ret != 0) {
1594                         DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
1595                         exit(10);
1596                 }
1597
1598                 if ((recmode == CTDB_RECOVERY_NORMAL)
1599                 &&  (vnnmap->generation != 1)){
1600                         return vnnmap->generation;
1601                 }
1602                 sleep(1);
1603         }
1604 }
1605
1606 /*
1607   ban a node from the cluster
1608  */
1609 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
1610 {
1611         int ret;
1612         struct ctdb_ban_info b;
1613         TDB_DATA data;
1614         uint32_t ban_time;
1615         struct ctdb_node_map *nodemap=NULL;
1616         uint32_t generation, next_generation;
1617
1618         if (argc < 1) {
1619                 usage();
1620         }
1621         
1622         /* record the current generation number */
1623         generation = get_generation(ctdb);
1624
1625
1626         /* verify the node exists */
1627         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1628         if (ret != 0) {
1629                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1630                 return ret;
1631         }
1632
1633         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
1634                 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
1635                 return -1;
1636         }
1637
1638         ban_time = strtoul(argv[0], NULL, 0);
1639
1640         b.pnn = options.pnn;
1641         b.ban_time = ban_time;
1642
1643         data.dptr = (uint8_t *)&b;
1644         data.dsize = sizeof(b);
1645
1646         ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_BAN_NODE, data);
1647         if (ret != 0) {
1648                 DEBUG(DEBUG_ERR,("Failed to ban node %u\n", options.pnn));
1649                 return -1;
1650         }
1651
1652         /* wait until we are in a new generation */
1653         while (1) {
1654                 next_generation = get_generation(ctdb);
1655                 if (next_generation != generation) {
1656                         return 0;
1657                 }
1658                 sleep(1);
1659         }
1660
1661         return 0;
1662 }
1663
1664
1665 /*
1666   unban a node from the cluster
1667  */
1668 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
1669 {
1670         int ret;
1671         TDB_DATA data;
1672         uint32_t generation, next_generation;
1673         struct ctdb_node_map *nodemap=NULL;
1674
1675         /* record the current generation number */
1676         generation = get_generation(ctdb);
1677
1678         data.dptr = (uint8_t *)&options.pnn;
1679         data.dsize = sizeof(uint32_t);
1680
1681         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1682         if (ret != 0) {
1683                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1684                 return ret;
1685         }
1686
1687         if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
1688                 DEBUG(DEBUG_ERR, ("Node %d is not banned. Can not unban\n", options.pnn));
1689                 return -1;
1690         }
1691
1692         ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_UNBAN_NODE, data);
1693         if (ret != 0) {
1694                 DEBUG(DEBUG_ERR,("Failed to to unban node %u\n", options.pnn));
1695                 return -1;
1696         }
1697         
1698         /* wait until we are in a new generation */
1699         while (1) {
1700                 next_generation = get_generation(ctdb);
1701                 if (next_generation != generation) {
1702                         return 0;
1703                 }
1704                 sleep(1);
1705         }
1706
1707         return 0;
1708 }
1709
1710
1711 /*
1712   shutdown a daemon
1713  */
1714 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
1715 {
1716         int ret;
1717
1718         ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
1719         if (ret != 0) {
1720                 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
1721                 return ret;
1722         }
1723
1724         return 0;
1725 }
1726
1727 /*
1728   trigger a recovery
1729  */
1730 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
1731 {
1732         int ret;
1733         uint32_t generation, next_generation;
1734
1735         /* record the current generation number */
1736         generation = get_generation(ctdb);
1737
1738         ret = ctdb_ctrl_freeze(ctdb, TIMELIMIT(), options.pnn);
1739         if (ret != 0) {
1740                 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
1741                 return ret;
1742         }
1743
1744         ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
1745         if (ret != 0) {
1746                 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
1747                 return ret;
1748         }
1749
1750         /* wait until we are in a new generation */
1751         while (1) {
1752                 next_generation = get_generation(ctdb);
1753                 if (next_generation != generation) {
1754                         return 0;
1755                 }
1756                 sleep(1);
1757         }
1758
1759         return 0;
1760 }
1761
1762
1763 /*
1764   display monitoring mode of a remote node
1765  */
1766 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
1767 {
1768         uint32_t monmode;
1769         int ret;
1770
1771         ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
1772         if (ret != 0) {
1773                 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
1774                 return ret;
1775         }
1776         if (!options.machinereadable){
1777                 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
1778         } else {
1779                 printf(":mode:\n");
1780                 printf(":%d:\n",monmode);
1781         }
1782         return 0;
1783 }
1784
1785
1786 /*
1787   display capabilities of a remote node
1788  */
1789 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
1790 {
1791         uint32_t capabilities;
1792         int ret;
1793
1794         ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
1795         if (ret != 0) {
1796                 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
1797                 return ret;
1798         }
1799         
1800         if (!options.machinereadable){
1801                 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
1802                 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
1803                 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
1804         } else {
1805                 printf(":RECMASTER:LMASTER:LVS:\n");
1806                 printf(":%d:%d:%d:\n",
1807                         !!(capabilities&CTDB_CAP_RECMASTER),
1808                         !!(capabilities&CTDB_CAP_LMASTER),
1809                         !!(capabilities&CTDB_CAP_LVS));
1810         }
1811         return 0;
1812 }
1813
1814 /*
1815   display lvs configuration
1816  */
1817 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
1818 {
1819         uint32_t *capabilities;
1820         struct ctdb_node_map *nodemap=NULL;
1821         int i, ret;
1822         int healthy_count = 0;
1823
1824         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
1825         if (ret != 0) {
1826                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1827                 return ret;
1828         }
1829
1830         capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
1831         CTDB_NO_MEMORY(ctdb, capabilities);
1832         
1833         /* collect capabilities for all connected nodes */
1834         for (i=0; i<nodemap->num; i++) {
1835                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1836                         continue;
1837                 }
1838                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
1839                         continue;
1840                 }
1841         
1842                 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
1843                 if (ret != 0) {
1844                         DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
1845                         return ret;
1846                 }
1847
1848                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
1849                         continue;
1850                 }
1851
1852                 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
1853                         healthy_count++;
1854                 }
1855         }
1856
1857         /* Print all LVS nodes */
1858         for (i=0; i<nodemap->num; i++) {
1859                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1860                         continue;
1861                 }
1862                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
1863                         continue;
1864                 }
1865                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
1866                         continue;
1867                 }
1868
1869                 if (healthy_count != 0) {
1870                         if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
1871                                 continue;
1872                         }
1873                 }
1874
1875                 printf("%d:%s\n", i, 
1876                         ctdb_addr_to_str(&nodemap->nodes[i].addr));
1877         }
1878
1879         return 0;
1880 }
1881
1882 /*
1883   display who is the lvs master
1884  */
1885 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
1886 {
1887         uint32_t *capabilities;
1888         struct ctdb_node_map *nodemap=NULL;
1889         int i, ret;
1890         int healthy_count = 0;
1891
1892         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
1893         if (ret != 0) {
1894                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1895                 return ret;
1896         }
1897
1898         capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
1899         CTDB_NO_MEMORY(ctdb, capabilities);
1900         
1901         /* collect capabilities for all connected nodes */
1902         for (i=0; i<nodemap->num; i++) {
1903                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1904                         continue;
1905                 }
1906                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
1907                         continue;
1908                 }
1909         
1910                 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
1911                 if (ret != 0) {
1912                         DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
1913                         return ret;
1914                 }
1915
1916                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
1917                         continue;
1918                 }
1919
1920                 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
1921                         healthy_count++;
1922                 }
1923         }
1924
1925         /* find and show the lvsmaster */
1926         for (i=0; i<nodemap->num; i++) {
1927                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1928                         continue;
1929                 }
1930                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
1931                         continue;
1932                 }
1933                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
1934                         continue;
1935                 }
1936
1937                 if (healthy_count != 0) {
1938                         if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
1939                                 continue;
1940                         }
1941                 }
1942
1943                 if (options.machinereadable){
1944                         printf("%d\n", i);
1945                 } else {
1946                         printf("Node %d is LVS master\n", i);
1947                 }
1948                 return 0;
1949         }
1950
1951         printf("There is no LVS master\n");
1952         return -1;
1953 }
1954
1955 /*
1956   disable monitoring on a  node
1957  */
1958 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
1959 {
1960         
1961         int ret;
1962
1963         ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
1964         if (ret != 0) {
1965                 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
1966                 return ret;
1967         }
1968         printf("Monitoring mode:%s\n","DISABLED");
1969
1970         return 0;
1971 }
1972
1973 /*
1974   enable monitoring on a  node
1975  */
1976 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
1977 {
1978         
1979         int ret;
1980
1981         ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
1982         if (ret != 0) {
1983                 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
1984                 return ret;
1985         }
1986         printf("Monitoring mode:%s\n","ACTIVE");
1987
1988         return 0;
1989 }
1990
1991 /*
1992   display remote list of keys/data for a db
1993  */
1994 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
1995 {
1996         const char *db_name;
1997         struct ctdb_db_context *ctdb_db;
1998         int ret;
1999
2000         if (argc < 1) {
2001                 usage();
2002         }
2003
2004         db_name = argv[0];
2005
2006
2007         if (db_exists(ctdb, db_name)) {
2008                 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2009                 return -1;
2010         }
2011
2012         ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2013
2014         if (ctdb_db == NULL) {
2015                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2016                 return -1;
2017         }
2018
2019         /* traverse and dump the cluster tdb */
2020         ret = ctdb_dump_db(ctdb_db, stdout);
2021         if (ret == -1) {
2022                 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2023                 return -1;
2024         }
2025         talloc_free(ctdb_db);
2026
2027         printf("Dumped %d records\n", ret);
2028         return 0;
2029 }
2030
2031
2032 /*
2033   display a list of the databases on a remote ctdb
2034  */
2035 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2036 {
2037         int i, ret;
2038         struct ctdb_dbid_map *dbmap=NULL;
2039
2040         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2041         if (ret != 0) {
2042                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2043                 return ret;
2044         }
2045
2046         printf("Number of databases:%d\n", dbmap->num);
2047         for(i=0;i<dbmap->num;i++){
2048                 const char *path;
2049                 const char *name;
2050                 bool persistent;
2051
2052                 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2053                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2054                 persistent = dbmap->dbs[i].persistent;
2055                 printf("dbid:0x%08x name:%s path:%s %s\n", dbmap->dbs[i].dbid, name, 
2056                        path, persistent?"PERSISTENT":"");
2057         }
2058
2059         return 0;
2060 }
2061
2062 /*
2063   check if the local node is recmaster or not
2064   it will return 1 if this node is the recmaster and 0 if it is not
2065   or if the local ctdb daemon could not be contacted
2066  */
2067 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2068 {
2069         uint32_t mypnn, recmaster;
2070         int ret;
2071
2072         mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2073         if (mypnn == -1) {
2074                 printf("Failed to get pnn of node\n");
2075                 return 1;
2076         }
2077
2078         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2079         if (ret != 0) {
2080                 printf("Failed to get the recmaster\n");
2081                 return 1;
2082         }
2083
2084         if (recmaster != mypnn) {
2085                 printf("this node is not the recmaster\n");
2086                 return 1;
2087         }
2088
2089         printf("this node is the recmaster\n");
2090         return 0;
2091 }
2092
2093 /*
2094   ping a node
2095  */
2096 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2097 {
2098         int ret;
2099         struct timeval tv = timeval_current();
2100         ret = ctdb_ctrl_ping(ctdb, options.pnn);
2101         if (ret == -1) {
2102                 printf("Unable to get ping response from node %u\n", options.pnn);
2103                 return -1;
2104         } else {
2105                 printf("response from %u time=%.6f sec  (%d clients)\n", 
2106                        options.pnn, timeval_elapsed(&tv), ret);
2107         }
2108         return 0;
2109 }
2110
2111
2112 /*
2113   get a tunable
2114  */
2115 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2116 {
2117         const char *name;
2118         uint32_t value;
2119         int ret;
2120
2121         if (argc < 1) {
2122                 usage();
2123         }
2124
2125         name = argv[0];
2126         ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2127         if (ret == -1) {
2128                 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2129                 return -1;
2130         }
2131
2132         printf("%-19s = %u\n", name, value);
2133         return 0;
2134 }
2135
2136 /*
2137   set a tunable
2138  */
2139 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
2140 {
2141         const char *name;
2142         uint32_t value;
2143         int ret;
2144
2145         if (argc < 2) {
2146                 usage();
2147         }
2148
2149         name = argv[0];
2150         value = strtoul(argv[1], NULL, 0);
2151
2152         ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
2153         if (ret == -1) {
2154                 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
2155                 return -1;
2156         }
2157         return 0;
2158 }
2159
2160 /*
2161   list all tunables
2162  */
2163 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
2164 {
2165         uint32_t count;
2166         const char **list;
2167         int ret, i;
2168
2169         ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
2170         if (ret == -1) {
2171                 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
2172                 return -1;
2173         }
2174
2175         for (i=0;i<count;i++) {
2176                 control_getvar(ctdb, 1, &list[i]);
2177         }
2178
2179         talloc_free(list);
2180         
2181         return 0;
2182 }
2183
2184 static struct {
2185         int32_t level;
2186         const char *description;
2187 } debug_levels[] = {
2188         {DEBUG_EMERG,   "EMERG"},
2189         {DEBUG_ALERT,   "ALERT"},
2190         {DEBUG_CRIT,    "CRIT"},
2191         {DEBUG_ERR,     "ERR"},
2192         {DEBUG_WARNING, "WARNING"},
2193         {DEBUG_NOTICE,  "NOTICE"},
2194         {DEBUG_INFO,    "INFO"},
2195         {DEBUG_DEBUG,   "DEBUG"}
2196 };
2197
2198 static const char *get_debug_by_level(int32_t level)
2199 {
2200         int i;
2201
2202         for (i=0;i<ARRAY_SIZE(debug_levels);i++) {
2203                 if (debug_levels[i].level == level) {
2204                         return debug_levels[i].description;
2205                 }
2206         }
2207         return "Unknown";
2208 }
2209
2210 static int32_t get_debug_by_desc(const char *desc)
2211 {
2212         int i;
2213
2214         for (i=0;i<ARRAY_SIZE(debug_levels);i++) {
2215                 if (!strcmp(debug_levels[i].description, desc)) {
2216                         return debug_levels[i].level;
2217                 }
2218         }
2219
2220         fprintf(stderr, "Invalid debug level '%s'\nMust be one of\n", desc);
2221         for (i=0;i<ARRAY_SIZE(debug_levels);i++) {
2222                 fprintf(stderr, "    %s\n", debug_levels[i].description);
2223         }
2224
2225         exit(10);
2226 }
2227
2228 /*
2229   display debug level on a node
2230  */
2231 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2232 {
2233         int ret;
2234         int32_t level;
2235
2236         ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
2237         if (ret != 0) {
2238                 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
2239                 return ret;
2240         } else {
2241                 if (options.machinereadable){
2242                         printf(":Name:Level:\n");
2243                         printf(":%s:%d:\n",get_debug_by_level(level),level);
2244                 } else {
2245                         printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
2246                 }
2247         }
2248         return 0;
2249 }
2250
2251
2252 /*
2253   set debug level on a node or all nodes
2254  */
2255 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2256 {
2257         int ret;
2258         int32_t level;
2259
2260         if (argc < 1) {
2261                 usage();
2262         }
2263
2264         if (isalpha(argv[0][0])) { 
2265                 level = get_debug_by_desc(argv[0]);
2266         } else {
2267                 level = strtol(argv[0], NULL, 0);
2268         }
2269
2270         ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
2271         if (ret != 0) {
2272                 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
2273         }
2274         return 0;
2275 }
2276
2277
2278 /*
2279   freeze a node
2280  */
2281 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
2282 {
2283         int ret;
2284
2285         ret = ctdb_ctrl_freeze(ctdb, TIMELIMIT(), options.pnn);
2286         if (ret != 0) {
2287                 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
2288         }               
2289         return 0;
2290 }
2291
2292 /*
2293   thaw a node
2294  */
2295 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
2296 {
2297         int ret;
2298
2299         ret = ctdb_ctrl_thaw(ctdb, TIMELIMIT(), options.pnn);
2300         if (ret != 0) {
2301                 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
2302         }               
2303         return 0;
2304 }
2305
2306
2307 /*
2308   attach to a database
2309  */
2310 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
2311 {
2312         const char *db_name;
2313         struct ctdb_db_context *ctdb_db;
2314
2315         if (argc < 1) {
2316                 usage();
2317         }
2318         db_name = argv[0];
2319
2320         ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2321         if (ctdb_db == NULL) {
2322                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2323                 return -1;
2324         }
2325
2326         return 0;
2327 }
2328
2329 /*
2330   run an eventscript on a node
2331  */
2332 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
2333 {
2334         TDB_DATA data;
2335         int ret;
2336         int32_t res;
2337         char *errmsg;
2338         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2339
2340         if (argc != 1) {
2341                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2342                 return -1;
2343         }
2344
2345         data.dptr = (unsigned char *)discard_const(argv[0]);
2346         data.dsize = strlen((char *)data.dptr) + 1;
2347
2348         DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
2349
2350         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
2351                            0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2352         if (ret != 0 || res != 0) {
2353                 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
2354                 talloc_free(tmp_ctx);
2355                 return -1;
2356         }
2357         talloc_free(tmp_ctx);
2358         return 0;
2359 }
2360
2361 #define DB_VERSION 1
2362 #define MAX_DB_NAME 64
2363 struct db_file_header {
2364         unsigned long version;
2365         time_t timestamp;
2366         unsigned long persistent;
2367         unsigned long size;
2368         const char name[MAX_DB_NAME];
2369 };
2370
2371 struct backup_data {
2372         struct ctdb_marshall_buffer *records;
2373         uint32_t len;
2374         uint32_t total;
2375         bool traverse_error;
2376 };
2377
2378 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
2379 {
2380         struct backup_data *bd = talloc_get_type(private, struct backup_data);
2381         struct ctdb_rec_data *rec;
2382
2383         /* add the record */
2384         rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
2385         if (rec == NULL) {
2386                 bd->traverse_error = true;
2387                 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
2388                 return -1;
2389         }
2390         bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
2391         if (bd->records == NULL) {
2392                 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
2393                 bd->traverse_error = true;
2394                 return -1;
2395         }
2396         bd->records->count++;
2397         memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
2398         bd->len += rec->length;
2399         talloc_free(rec);
2400
2401         bd->total++;
2402         return 0;
2403 }
2404
2405 /*
2406  * backup a database to a file 
2407  */
2408 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
2409 {
2410         int i, ret;
2411         struct ctdb_dbid_map *dbmap=NULL;
2412         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2413         struct db_file_header dbhdr;
2414         struct ctdb_db_context *ctdb_db;
2415         struct backup_data *bd;
2416         int fh = -1;
2417         int status = -1;
2418
2419         if (argc != 2) {
2420                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2421                 return -1;
2422         }
2423
2424         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
2425         if (ret != 0) {
2426                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2427                 return ret;
2428         }
2429
2430         for(i=0;i<dbmap->num;i++){
2431                 const char *name;
2432
2433                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
2434                 if(!strcmp(argv[0], name)){
2435                         talloc_free(discard_const(name));
2436                         break;
2437                 }
2438                 talloc_free(discard_const(name));
2439         }
2440         if (i == dbmap->num) {
2441                 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
2442                 talloc_free(tmp_ctx);
2443                 return -1;
2444         }
2445
2446
2447         ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
2448         if (ctdb_db == NULL) {
2449                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
2450                 talloc_free(tmp_ctx);
2451                 return -1;
2452         }
2453
2454
2455         ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
2456         if (ret == -1) {
2457                 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
2458                 talloc_free(tmp_ctx);
2459                 return -1;
2460         }
2461
2462
2463         bd = talloc_zero(tmp_ctx, struct backup_data);
2464         if (bd == NULL) {
2465                 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
2466                 talloc_free(tmp_ctx);
2467                 return -1;
2468         }
2469
2470         bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
2471         if (bd->records == NULL) {
2472                 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
2473                 talloc_free(tmp_ctx);
2474                 return -1;
2475         }
2476
2477         bd->len = offsetof(struct ctdb_marshall_buffer, data);
2478         bd->records->db_id = ctdb_db->db_id;
2479         /* traverse the database collecting all records */
2480         if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
2481             bd->traverse_error) {
2482                 DEBUG(DEBUG_ERR,("Traverse error\n"));
2483                 talloc_free(tmp_ctx);
2484                 return -1;              
2485         }
2486
2487         tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2488
2489
2490         fh = open(argv[1], O_RDWR|O_CREAT, 0600);
2491         if (fh == -1) {
2492                 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
2493                 talloc_free(tmp_ctx);
2494                 return -1;
2495         }
2496
2497         dbhdr.version = DB_VERSION;
2498         dbhdr.timestamp = time(NULL);
2499         dbhdr.persistent = dbmap->dbs[i].persistent;
2500         dbhdr.size = bd->len;
2501         if (strlen(argv[0]) >= MAX_DB_NAME) {
2502                 DEBUG(DEBUG_ERR,("Too long dbname\n"));
2503                 goto done;
2504         }
2505         strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
2506         ret = write(fh, &dbhdr, sizeof(dbhdr));
2507         if (ret == -1) {
2508                 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
2509                 goto done;
2510         }
2511         ret = write(fh, bd->records, bd->len);
2512         if (ret == -1) {
2513                 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
2514                 goto done;
2515         }
2516
2517         status = 0;
2518 done:
2519         if (fh != -1) {
2520                 ret = close(fh);
2521                 if (ret == -1) {
2522                         DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
2523                 }
2524         }
2525         talloc_free(tmp_ctx);
2526         return status;
2527 }
2528
2529 /*
2530  * restore a database from a file 
2531  */
2532 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
2533 {
2534         int ret;
2535         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2536         TDB_DATA outdata;
2537         TDB_DATA data;
2538         struct db_file_header dbhdr;
2539         struct ctdb_db_context *ctdb_db;
2540         struct ctdb_node_map *nodemap=NULL;
2541         struct ctdb_vnn_map *vnnmap=NULL;
2542         int fh;
2543         struct ctdb_control_wipe_database w;
2544         uint32_t *nodes;
2545         uint32_t generation;
2546         struct tm *tm;
2547         char tbuf[100];
2548
2549         if (argc != 1) {
2550                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2551                 return -1;
2552         }
2553
2554         fh = open(argv[0], O_RDONLY);
2555         if (fh == -1) {
2556                 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
2557                 talloc_free(tmp_ctx);
2558                 return -1;
2559         }
2560
2561         read(fh, &dbhdr, sizeof(dbhdr));
2562         if (dbhdr.version != DB_VERSION) {
2563                 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
2564                 talloc_free(tmp_ctx);
2565                 return -1;
2566         }
2567
2568         outdata.dsize = dbhdr.size;
2569         outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
2570         if (outdata.dptr == NULL) {
2571                 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
2572                 close(fh);
2573                 talloc_free(tmp_ctx);
2574                 return -1;
2575         }               
2576         read(fh, outdata.dptr, outdata.dsize);
2577         close(fh);
2578
2579         tm = localtime(&dbhdr.timestamp);
2580         strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
2581         printf("Restoring database '%s' from backup @ %s\n",
2582                 dbhdr.name, tbuf);
2583
2584
2585         ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
2586         if (ctdb_db == NULL) {
2587                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
2588                 talloc_free(tmp_ctx);
2589                 return -1;
2590         }
2591
2592         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2593         if (ret != 0) {
2594                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2595                 talloc_free(tmp_ctx);
2596                 return ret;
2597         }
2598
2599
2600         ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
2601         if (ret != 0) {
2602                 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
2603                 talloc_free(tmp_ctx);
2604                 return ret;
2605         }
2606
2607         /* freeze all nodes */
2608         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
2609         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
2610                                         nodes, TIMELIMIT(),
2611                                         false, tdb_null,
2612                                         NULL, NULL,
2613                                         NULL) != 0) {
2614                 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
2615                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2616                 talloc_free(tmp_ctx);
2617                 return -1;
2618         }
2619
2620         generation = vnnmap->generation;
2621         data.dptr = (void *)&generation;
2622         data.dsize = sizeof(generation);
2623
2624         /* start a cluster wide transaction */
2625         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
2626         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
2627                                         nodes,
2628                                         TIMELIMIT(), false, data,
2629                                         NULL, NULL,
2630                                         NULL) != 0) {
2631                 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
2632                 return -1;
2633         }
2634
2635
2636         w.db_id = ctdb_db->db_id;
2637         w.transaction_id = generation;
2638
2639         data.dptr = (void *)&w;
2640         data.dsize = sizeof(w);
2641
2642         /* wipe all the remote databases. */
2643         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
2644         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
2645                                         nodes,
2646                                         TIMELIMIT(), false, data,
2647                                         NULL, NULL,
2648                                         NULL) != 0) {
2649                 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
2650                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2651                 talloc_free(tmp_ctx);
2652                 return -1;
2653         }
2654         
2655         /* push the database */
2656         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
2657         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
2658                                         nodes,
2659                                         TIMELIMIT(), false, outdata,
2660                                         NULL, NULL,
2661                                         NULL) != 0) {
2662                 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
2663                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2664                 talloc_free(tmp_ctx);
2665                 return -1;
2666         }
2667
2668         data.dptr = (void *)&generation;
2669         data.dsize = sizeof(generation);
2670
2671         /* commit all the changes */
2672         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
2673                                         nodes,
2674                                         TIMELIMIT(), false, data,
2675                                         NULL, NULL,
2676                                         NULL) != 0) {
2677                 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
2678                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2679                 talloc_free(tmp_ctx);
2680                 return -1;
2681         }
2682
2683
2684         /* thaw all nodes */
2685         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
2686         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
2687                                         nodes, TIMELIMIT(),
2688                                         false, tdb_null,
2689                                         NULL, NULL,
2690                                         NULL) != 0) {
2691                 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
2692                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2693                 talloc_free(tmp_ctx);
2694                 return -1;
2695         }
2696
2697
2698         talloc_free(tmp_ctx);
2699         return 0;
2700 }
2701
2702 /*
2703  * set flags of a node in the nodemap
2704  */
2705 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
2706 {
2707         int ret;
2708         int32_t status;
2709         int node;
2710         int flags;
2711         TDB_DATA data;
2712         struct ctdb_node_flag_change c;
2713
2714         if (argc != 2) {
2715                 usage();
2716                 return -1;
2717         }
2718
2719         if (sscanf(argv[0], "%d", &node) != 1) {
2720                 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
2721                 usage();
2722                 return -1;
2723         }
2724         if (sscanf(argv[1], "0x%x", &flags) != 1) {
2725                 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
2726                 usage();
2727                 return -1;
2728         }
2729
2730         c.pnn       = node;
2731         c.old_flags = 0;
2732         c.new_flags = flags;
2733
2734         data.dsize = sizeof(c);
2735         data.dptr = (unsigned char *)&c;
2736
2737         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0, 
2738                            data, NULL, NULL, &status, NULL, NULL);
2739         if (ret != 0 || status != 0) {
2740                 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
2741                 return -1;
2742         }
2743         return 0;
2744 }
2745
2746 /*
2747   dump memory usage
2748  */
2749 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
2750 {
2751         TDB_DATA data;
2752         int ret;
2753         int32_t res;
2754         char *errmsg;
2755         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2756         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
2757                            0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
2758         if (ret != 0 || res != 0) {
2759                 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
2760                 talloc_free(tmp_ctx);
2761                 return -1;
2762         }
2763         write(1, data.dptr, data.dsize);
2764         talloc_free(tmp_ctx);
2765         return 0;
2766 }
2767
2768 /*
2769   handler for memory dumps
2770 */
2771 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid, 
2772                              TDB_DATA data, void *private_data)
2773 {
2774         write(1, data.dptr, data.dsize);
2775         exit(0);
2776 }
2777
2778 /*
2779   dump memory usage on the recovery daemon
2780  */
2781 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
2782 {
2783         int ret;
2784         TDB_DATA data;
2785         struct rd_memdump_reply rd;
2786
2787         rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2788         if (rd.pnn == -1) {
2789                 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
2790                 return -1;
2791         }
2792         rd.srvid = getpid();
2793
2794         /* register a message port for receiveing the reply so that we
2795            can receive the reply
2796         */
2797         ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
2798
2799
2800         data.dptr = (uint8_t *)&rd;
2801         data.dsize = sizeof(rd);
2802
2803         ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
2804         if (ret != 0) {
2805                 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
2806                 return -1;
2807         }
2808
2809         /* this loop will terminate when we have received the reply */
2810         while (1) {     
2811                 event_loop_once(ctdb->ev);
2812         }
2813
2814         return 0;
2815 }
2816
2817 /*
2818   list all nodes in the cluster
2819   if the daemon is running, we read the data from the daemon.
2820   if the daemon is not running we parse the nodes file directly
2821  */
2822 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
2823 {
2824         int i, ret;
2825         struct ctdb_node_map *nodemap=NULL;
2826
2827         if (ctdb != NULL) {
2828                 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2829                 if (ret != 0) {
2830                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2831                         return ret;
2832                 }
2833
2834                 for(i=0;i<nodemap->num;i++){
2835                         if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
2836                                 continue;
2837                         }
2838                         if (options.machinereadable){
2839                                 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
2840                         } else {
2841                                 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
2842                         }
2843                 }
2844         } else {
2845                 TALLOC_CTX *mem_ctx = talloc_new(NULL);
2846                 struct pnn_node *pnn_nodes;
2847                 struct pnn_node *pnn_node;
2848         
2849                 pnn_nodes = read_nodes_file(mem_ctx);
2850                 if (pnn_nodes == NULL) {
2851                         DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
2852                         talloc_free(mem_ctx);
2853                         return -1;
2854                 }
2855
2856                 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
2857                         ctdb_sock_addr addr;
2858
2859                         if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
2860                                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
2861                                 talloc_free(mem_ctx);
2862                                 return -1;
2863                         }
2864
2865                         if (options.machinereadable){
2866                                 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
2867                         } else {
2868                                 printf("%s\n", pnn_node->addr);
2869                         }
2870                 }
2871                 talloc_free(mem_ctx);
2872         }
2873
2874         return 0;
2875 }
2876
2877 /*
2878   reload the nodes file on the local node
2879  */
2880 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
2881 {
2882         int i, ret;
2883         int mypnn;
2884         struct ctdb_node_map *nodemap=NULL;
2885
2886         mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2887         if (mypnn == -1) {
2888                 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
2889                 return -1;
2890         }
2891
2892         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2893         if (ret != 0) {
2894                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2895                 return ret;
2896         }
2897
2898         /* reload the nodes file on all remote nodes */
2899         for (i=0;i<nodemap->num;i++) {
2900                 if (nodemap->nodes[i].pnn == mypnn) {
2901                         continue;
2902                 }
2903                 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
2904                 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
2905                         nodemap->nodes[i].pnn);
2906                 if (ret != 0) {
2907                         DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
2908                 }
2909         }
2910
2911         /* reload the nodes file on the local node */
2912         DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
2913         ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
2914         if (ret != 0) {
2915                 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
2916         }
2917
2918         /* initiate a recovery */
2919         control_recover(ctdb, argc, argv);
2920
2921         return 0;
2922 }
2923
2924
2925 static const struct {
2926         const char *name;
2927         int (*fn)(struct ctdb_context *, int, const char **);
2928         bool auto_all;
2929         bool without_daemon; /* can be run without daemon running ? */
2930         const char *msg;
2931         const char *args;
2932 } ctdb_commands[] = {
2933 #ifdef CTDB_VERS
2934         { "version",         control_version,           true,   false,  "show version of ctdb" },
2935 #endif
2936         { "status",          control_status,            true,   false,  "show node status" },
2937         { "uptime",          control_uptime,            true,   false,  "show node uptime" },
2938         { "ping",            control_ping,              true,   false,  "ping all nodes" },
2939         { "getvar",          control_getvar,            true,   false,  "get a tunable variable",               "<name>"},
2940         { "setvar",          control_setvar,            true,   false,  "set a tunable variable",               "<name> <value>"},
2941         { "listvars",        control_listvars,          true,   false,  "list tunable variables"},
2942         { "statistics",      control_statistics,        false,  false, "show statistics" },
2943         { "statisticsreset", control_statistics_reset,  true,   false,  "reset statistics"},
2944         { "ip",              control_ip,                false,  false,  "show which public ip's that ctdb manages" },
2945         { "process-exists",  control_process_exists,    true,   false,  "check if a process exists on a node",  "<pid>"},
2946         { "getdbmap",        control_getdbmap,          true,   false,  "show the database map" },
2947         { "catdb",           control_catdb,             true,   false,  "dump a database" ,                     "<dbname>"},
2948         { "getmonmode",      control_getmonmode,        true,   false,  "show monitoring mode" },
2949         { "getcapabilities", control_getcapabilities,   true,   false,  "show node capabilities" },
2950         { "pnn",             control_pnn,               true,   false,  "show the pnn of the currnet node" },
2951         { "lvs",             control_lvs,               true,   false,  "show lvs configuration" },
2952         { "lvsmaster",       control_lvsmaster,         true,   false,  "show which node is the lvs master" },
2953         { "disablemonitor",      control_disable_monmode,true,  false,  "set monitoring mode to DISABLE" },
2954         { "enablemonitor",      control_enable_monmode, true,   false,  "set monitoring mode to ACTIVE" },
2955         { "setdebug",        control_setdebug,          true,   false,  "set debug level",                      "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
2956         { "getdebug",        control_getdebug,          true,   false,  "get debug level" },
2957         { "attach",          control_attach,            true,   false,  "attach to a database",                 "<dbname>" },
2958         { "dumpmemory",      control_dumpmemory,        true,   false,  "dump memory map to stdout" },
2959         { "rddumpmemory",    control_rddumpmemory,      true,   false,  "dump memory map from the recovery daemon to stdout" },
2960         { "getpid",          control_getpid,            true,   false,  "get ctdbd process ID" },
2961         { "disable",         control_disable,           true,   false,  "disable a nodes public IP" },
2962         { "enable",          control_enable,            true,   false,  "enable a nodes public IP" },
2963         { "ban",             control_ban,               true,   false,  "ban a node from the cluster",          "<bantime|0>"},
2964         { "unban",           control_unban,             true,   false,  "unban a node from the cluster" },
2965         { "shutdown",        control_shutdown,          true,   false,  "shutdown ctdbd" },
2966         { "recover",         control_recover,           true,   false,  "force recovery" },
2967         { "freeze",          control_freeze,            true,   false,  "freeze all databases" },
2968         { "thaw",            control_thaw,              true,   false,  "thaw all databases" },
2969         { "isnotrecmaster",  control_isnotrecmaster,    false,  false,  "check if the local node is recmaster or not" },
2970         { "killtcp",         kill_tcp,                  false,  false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
2971         { "gratiousarp",     control_gratious_arp,      false,  false, "send a gratious arp", "<ip> <interface>" },
2972         { "tickle",          tickle_tcp,                false,  false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
2973         { "gettickles",      control_get_tickles,       false,  false, "get the list of tickles registered for this ip", "<ip>" },
2974
2975         { "regsrvid",        regsrvid,                  false,  false, "register a server id", "<pnn> <type> <id>" },
2976         { "unregsrvid",      unregsrvid,                false,  false, "unregister a server id", "<pnn> <type> <id>" },
2977         { "chksrvid",        chksrvid,                  false,  false, "check if a server id exists", "<pnn> <type> <id>" },
2978         { "getsrvids",       getsrvids,                 false,  false, "get a list of all server ids"},
2979         { "vacuum",          ctdb_vacuum,               false,  false, "vacuum the databases of empty records", "[max_records]"},
2980         { "repack",          ctdb_repack,               false,  false, "repack all databases", "[max_freelist]"},
2981         { "listnodes",       control_listnodes,         false,  true, "list all nodes in the cluster"},
2982         { "reloadnodes",     control_reload_nodes_file, false,  false, "reload the nodes file and restart the transport on all nodes"},
2983         { "moveip",          control_moveip,            false,  false, "move/failover an ip address to another node", "<ip> <node>"},
2984         { "addip",           control_addip,             true,   false, "add a ip address to a node", "<ip/mask> <iface>"},
2985         { "delip",           control_delip,             false,  false, "delete an ip address from a node", "<ip>"},
2986         { "eventscript",     control_eventscript,       true,   false, "run the eventscript with the given parameters on a node", "<arguments>"},
2987         { "backupdb",        control_backupdb,          false,  false, "backup the database into a file.", "<database> <file>"},
2988         { "restoredb",        control_restoredb,        false,  false, "restore the database from a file.", "<file>"},
2989         { "recmaster",        control_recmaster,        false,  false, "show the pnn for the recovery master."},
2990         { "setflags",        control_setflags,          false,  false, "set flags for a node in the nodemap.", "<node> <flags>"},
2991         { "scriptstatus",        control_scriptstatus,  false,  false, "show the status of the monitoring scripts"},
2992         { "natgwlist",        control_natgwlist,        false,  false, "show the nodes belonging to this natgw configuration"},
2993         { "xpnn",             control_xpnn,             true,   true,  "find the pnn of the local node without talking to the daemon (unreliable)" },
2994 };
2995
2996 /*
2997   show usage message
2998  */
2999 static void usage(void)
3000 {
3001         int i;
3002         printf(
3003 "Usage: ctdb [options] <control>\n" \
3004 "Options:\n" \
3005 "   -n <node>          choose node number, or 'all' (defaults to local node)\n"
3006 "   -Y                 generate machinereadable output\n"
3007 "   -t <timelimit>     set timelimit for control in seconds (default %u)\n", options.timelimit);
3008         printf("Controls:\n");
3009         for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
3010                 printf("  %-15s %-27s  %s\n", 
3011                        ctdb_commands[i].name, 
3012                        ctdb_commands[i].args?ctdb_commands[i].args:"",
3013                        ctdb_commands[i].msg);
3014         }
3015         exit(1);
3016 }
3017
3018
3019 static void ctdb_alarm(int sig)
3020 {
3021         printf("Maximum runtime exceeded - exiting\n");
3022         _exit(ERR_TIMEOUT);
3023 }
3024
3025 /*
3026   main program
3027 */
3028 int main(int argc, const char *argv[])
3029 {
3030         struct ctdb_context *ctdb;
3031         char *nodestring = NULL;
3032         struct poptOption popt_options[] = {
3033                 POPT_AUTOHELP
3034                 POPT_CTDB_CMDLINE
3035                 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
3036                 { "node",      'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
3037                 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
3038                 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
3039                 POPT_TABLEEND
3040         };
3041         int opt;
3042         const char **extra_argv;
3043         int extra_argc = 0;
3044         int ret=-1, i;
3045         poptContext pc;
3046         struct event_context *ev;
3047         const char *control;
3048
3049         setlinebuf(stdout);
3050         
3051         /* set some defaults */
3052         options.maxruntime = 0;
3053         options.timelimit = 3;
3054         options.pnn = CTDB_CURRENT_NODE;
3055
3056         pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
3057
3058         while ((opt = poptGetNextOpt(pc)) != -1) {
3059                 switch (opt) {
3060                 default:
3061                         DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n", 
3062                                 poptBadOption(pc, 0), poptStrerror(opt)));
3063                         exit(1);
3064                 }
3065         }
3066
3067         /* setup the remaining options for the main program to use */
3068         extra_argv = poptGetArgs(pc);
3069         if (extra_argv) {
3070                 extra_argv++;
3071                 while (extra_argv[extra_argc]) extra_argc++;
3072         }
3073
3074         if (extra_argc < 1) {
3075                 usage();
3076         }
3077
3078         if (options.maxruntime == 0) {
3079                 const char *ctdb_timeout;
3080                 ctdb_timeout = getenv("CTDB_TIMEOUT");
3081                 if (ctdb_timeout != NULL) {
3082                         options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
3083                 }
3084         }
3085         if (options.maxruntime != 0) {
3086                 signal(SIGALRM, ctdb_alarm);
3087                 alarm(options.maxruntime);
3088         }
3089
3090         /* setup the node number to contact */
3091         if (nodestring != NULL) {
3092                 if (strcmp(nodestring, "all") == 0) {
3093                         options.pnn = CTDB_BROADCAST_ALL;
3094                 } else {
3095                         options.pnn = strtoul(nodestring, NULL, 0);
3096                 }
3097         }
3098
3099         control = extra_argv[0];
3100
3101         ev = event_context_init(NULL);
3102
3103         for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
3104                 if (strcmp(control, ctdb_commands[i].name) == 0) {
3105                         int j;
3106
3107                         if (ctdb_commands[i].without_daemon == true) {
3108                                 close(2);
3109                         }
3110
3111                         /* initialise ctdb */
3112                         ctdb = ctdb_cmdline_client(ev);
3113
3114                         if (ctdb_commands[i].without_daemon == false) {
3115                                 if (ctdb == NULL) {
3116                                         DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
3117                                         exit(1);
3118                                 }
3119
3120                                 /* verify the node exists */
3121                                 verify_node(ctdb);
3122
3123                                 if (options.pnn == CTDB_CURRENT_NODE) {
3124                                         int pnn;
3125                                         pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);         
3126                                         if (pnn == -1) {
3127                                                 return -1;
3128                                         }
3129                                         options.pnn = pnn;
3130                                 }
3131                         }
3132
3133                         if (ctdb_commands[i].auto_all && 
3134                             options.pnn == CTDB_BROADCAST_ALL) {
3135                                 uint32_t *nodes;
3136                                 uint32_t num_nodes;
3137                                 ret = 0;
3138
3139                                 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
3140                                 CTDB_NO_MEMORY(ctdb, nodes);
3141         
3142                                 for (j=0;j<num_nodes;j++) {
3143                                         options.pnn = nodes[j];
3144                                         ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
3145                                 }
3146                                 talloc_free(nodes);
3147                         } else {
3148                                 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
3149                         }
3150                         break;
3151                 }
3152         }
3153
3154         if (i == ARRAY_SIZE(ctdb_commands)) {
3155                 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));
3156                 exit(1);
3157         }
3158
3159         return ret;
3160 }