make it possible to "ctdb gettickle" to only list tickles for a certain
[metze/ctdb/wip.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/tevent/tevent.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_client.h"
31 #include "../include/ctdb_private.h"
32 #include "../common/rb_tree.h"
33 #include "db_wrap.h"
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 struct ctdb_connection *ctdb_connection;
40
41 static void usage(void);
42
43 static struct {
44         int timelimit;
45         uint32_t pnn;
46         int machinereadable;
47         int maxruntime;
48 } options;
49
50 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
51 #define LONGTIMELIMIT() timeval_current_ofs(options.timelimit*10, 0)
52
53 #ifdef CTDB_VERS
54 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
55 {
56 #define STR(x) #x
57 #define XSTR(x) STR(x)
58         printf("CTDB version: %s\n", XSTR(CTDB_VERS));
59         return 0;
60 }
61 #endif
62
63
64 /*
65   verify that a node exists and is reachable
66  */
67 static void verify_node(struct ctdb_context *ctdb)
68 {
69         int ret;
70         struct ctdb_node_map *nodemap=NULL;
71
72         if (options.pnn == CTDB_CURRENT_NODE) {
73                 return;
74         }
75         if (options.pnn == CTDB_BROADCAST_ALL) {
76                 return;
77         }
78
79         /* verify the node exists */
80         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
81                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
82                 exit(10);
83         }
84         if (options.pnn >= nodemap->num) {
85                 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
86                 exit(ERR_NONODE);
87         }
88         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
89                 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
90                 exit(ERR_DISNODE);
91         }
92         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
93                 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
94                 exit(ERR_DISNODE);
95         }
96
97         /* verify we can access the node */
98         ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
99         if (ret == -1) {
100                 DEBUG(DEBUG_ERR,("Can not access node. Node is not operational.\n"));
101                 exit(10);
102         }
103 }
104
105 /*
106  check if a database exists
107 */
108 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
109 {
110         int i, ret;
111         struct ctdb_dbid_map *dbmap=NULL;
112
113         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
114         if (ret != 0) {
115                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
116                 return -1;
117         }
118
119         for(i=0;i<dbmap->num;i++){
120                 const char *name;
121
122                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
123                 if (!strcmp(name, db_name)) {
124                         return 0;
125                 }
126         }
127
128         return -1;
129 }
130
131 /*
132   see if a process exists
133  */
134 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
135 {
136         uint32_t pnn, pid;
137         int ret;
138         if (argc < 1) {
139                 usage();
140         }
141
142         if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
143                 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
144                 return -1;
145         }
146
147         ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
148         if (ret == 0) {
149                 printf("%u:%u exists\n", pnn, pid);
150         } else {
151                 printf("%u:%u does not exist\n", pnn, pid);
152         }
153         return ret;
154 }
155
156 /*
157   display statistics structure
158  */
159 static void show_statistics(struct ctdb_statistics *s)
160 {
161         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
162         int i;
163         const char *prefix=NULL;
164         int preflen=0;
165         int tmp, days, hours, minutes, seconds;
166         const struct {
167                 const char *name;
168                 uint32_t offset;
169         } fields[] = {
170 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
171                 STATISTICS_FIELD(num_clients),
172                 STATISTICS_FIELD(frozen),
173                 STATISTICS_FIELD(recovering),
174                 STATISTICS_FIELD(num_recoveries),
175                 STATISTICS_FIELD(client_packets_sent),
176                 STATISTICS_FIELD(client_packets_recv),
177                 STATISTICS_FIELD(node_packets_sent),
178                 STATISTICS_FIELD(node_packets_recv),
179                 STATISTICS_FIELD(keepalive_packets_sent),
180                 STATISTICS_FIELD(keepalive_packets_recv),
181                 STATISTICS_FIELD(node.req_call),
182                 STATISTICS_FIELD(node.reply_call),
183                 STATISTICS_FIELD(node.req_dmaster),
184                 STATISTICS_FIELD(node.reply_dmaster),
185                 STATISTICS_FIELD(node.reply_error),
186                 STATISTICS_FIELD(node.req_message),
187                 STATISTICS_FIELD(node.req_control),
188                 STATISTICS_FIELD(node.reply_control),
189                 STATISTICS_FIELD(client.req_call),
190                 STATISTICS_FIELD(client.req_message),
191                 STATISTICS_FIELD(client.req_control),
192                 STATISTICS_FIELD(timeouts.call),
193                 STATISTICS_FIELD(timeouts.control),
194                 STATISTICS_FIELD(timeouts.traverse),
195                 STATISTICS_FIELD(total_calls),
196                 STATISTICS_FIELD(pending_calls),
197                 STATISTICS_FIELD(lockwait_calls),
198                 STATISTICS_FIELD(pending_lockwait_calls),
199                 STATISTICS_FIELD(childwrite_calls),
200                 STATISTICS_FIELD(pending_childwrite_calls),
201                 STATISTICS_FIELD(memory_used),
202                 STATISTICS_FIELD(max_hop_count),
203         };
204         tmp = s->statistics_current_time.tv_sec - s->statistics_start_time.tv_sec;
205         seconds = tmp%60;
206         tmp    /= 60;
207         minutes = tmp%60;
208         tmp    /= 60;
209         hours   = tmp%24;
210         tmp    /= 24;
211         days    = tmp;
212
213         printf("CTDB version %u\n", CTDB_VERSION);
214         printf("Current time of statistics  :                %s", ctime(&s->statistics_current_time.tv_sec));
215         printf("Statistics collected since  : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&s->statistics_start_time.tv_sec));
216
217         for (i=0;i<ARRAY_SIZE(fields);i++) {
218                 if (strchr(fields[i].name, '.')) {
219                         preflen = strcspn(fields[i].name, ".")+1;
220                         if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
221                                 prefix = fields[i].name;
222                                 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
223                         }
224                 } else {
225                         preflen = 0;
226                 }
227                 printf(" %*s%-22s%*s%10u\n", 
228                        preflen?4:0, "",
229                        fields[i].name+preflen, 
230                        preflen?0:4, "",
231                        *(uint32_t *)(fields[i].offset+(uint8_t *)s));
232         }
233         printf(" %-30s     %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
234         printf(" %-30s     %.6f sec\n", "max_reclock_recd", s->reclock.recd);
235
236         printf(" %-30s     %.6f sec\n", "max_call_latency", s->max_call_latency);
237         printf(" %-30s     %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
238         printf(" %-30s     %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
239         printf(" %-30s     %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
240
241         talloc_free(tmp_ctx);
242 }
243
244 /*
245   display remote ctdb statistics combined from all nodes
246  */
247 static int control_statistics_all(struct ctdb_context *ctdb)
248 {
249         int ret, i;
250         struct ctdb_statistics statistics;
251         uint32_t *nodes;
252         uint32_t num_nodes;
253
254         nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
255         CTDB_NO_MEMORY(ctdb, nodes);
256         
257         ZERO_STRUCT(statistics);
258
259         for (i=0;i<num_nodes;i++) {
260                 struct ctdb_statistics s1;
261                 int j;
262                 uint32_t *v1 = (uint32_t *)&s1;
263                 uint32_t *v2 = (uint32_t *)&statistics;
264                 uint32_t num_ints = 
265                         offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
266                 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
267                 if (ret != 0) {
268                         DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
269                         return ret;
270                 }
271                 for (j=0;j<num_ints;j++) {
272                         v2[j] += v1[j];
273                 }
274                 statistics.max_hop_count = 
275                         MAX(statistics.max_hop_count, s1.max_hop_count);
276                 statistics.max_call_latency = 
277                         MAX(statistics.max_call_latency, s1.max_call_latency);
278                 statistics.max_lockwait_latency = 
279                         MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
280         }
281         talloc_free(nodes);
282         printf("Gathered statistics for %u nodes\n", num_nodes);
283         show_statistics(&statistics);
284         return 0;
285 }
286
287 /*
288   display remote ctdb statistics
289  */
290 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
291 {
292         int ret;
293         struct ctdb_statistics statistics;
294
295         if (options.pnn == CTDB_BROADCAST_ALL) {
296                 return control_statistics_all(ctdb);
297         }
298
299         ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
300         if (ret != 0) {
301                 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
302                 return ret;
303         }
304         show_statistics(&statistics);
305         return 0;
306 }
307
308
309 /*
310   reset remote ctdb statistics
311  */
312 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
313 {
314         int ret;
315
316         ret = ctdb_statistics_reset(ctdb, options.pnn);
317         if (ret != 0) {
318                 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
319                 return ret;
320         }
321         return 0;
322 }
323
324
325 /*
326   display uptime of remote node
327  */
328 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
329 {
330         int ret;
331         struct ctdb_uptime *uptime = NULL;
332         int tmp, days, hours, minutes, seconds;
333
334         ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
335         if (ret != 0) {
336                 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
337                 return ret;
338         }
339
340         if (options.machinereadable){
341                 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
342                 printf(":%u:%u:%u:%lf\n",
343                         (unsigned int)uptime->current_time.tv_sec,
344                         (unsigned int)uptime->ctdbd_start_time.tv_sec,
345                         (unsigned int)uptime->last_recovery_finished.tv_sec,
346                         timeval_delta(&uptime->last_recovery_finished,
347                                       &uptime->last_recovery_started)
348                 );
349                 return 0;
350         }
351
352         printf("Current time of node          :                %s", ctime(&uptime->current_time.tv_sec));
353
354         tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
355         seconds = tmp%60;
356         tmp    /= 60;
357         minutes = tmp%60;
358         tmp    /= 60;
359         hours   = tmp%24;
360         tmp    /= 24;
361         days    = tmp;
362         printf("Ctdbd start time              : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
363
364         tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
365         seconds = tmp%60;
366         tmp    /= 60;
367         minutes = tmp%60;
368         tmp    /= 60;
369         hours   = tmp%24;
370         tmp    /= 24;
371         days    = tmp;
372         printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
373         
374         printf("Duration of last recovery/failover: %lf seconds\n",
375                 timeval_delta(&uptime->last_recovery_finished,
376                               &uptime->last_recovery_started));
377
378         return 0;
379 }
380
381 /*
382   show the PNN of the current node
383  */
384 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
385 {
386         uint32_t mypnn;
387         bool ret;
388
389         ret = ctdb_getpnn(ctdb_connection, options.pnn, &mypnn);
390         if (!ret) {
391                 DEBUG(DEBUG_ERR, ("Unable to get pnn from node."));
392                 return -1;
393         }
394
395         printf("PNN:%d\n", mypnn);
396         return 0;
397 }
398
399
400 struct pnn_node {
401         struct pnn_node *next;
402         const char *addr;
403         int pnn;
404 };
405
406 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
407 {
408         const char *nodes_list;
409         int nlines;
410         char **lines;
411         int i, pnn;
412         struct pnn_node *pnn_nodes = NULL;
413         struct pnn_node *pnn_node;
414         struct pnn_node *tmp_node;
415
416         /* read the nodes file */
417         nodes_list = getenv("CTDB_NODES");
418         if (nodes_list == NULL) {
419                 nodes_list = "/etc/ctdb/nodes";
420         }
421         lines = file_lines_load(nodes_list, &nlines, mem_ctx);
422         if (lines == NULL) {
423                 return NULL;
424         }
425         while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
426                 nlines--;
427         }
428         for (i=0, pnn=0; i<nlines; i++) {
429                 char *node;
430
431                 node = lines[i];
432                 /* strip leading spaces */
433                 while((*node == ' ') || (*node == '\t')) {
434                         node++;
435                 }
436                 if (*node == '#') {
437                         pnn++;
438                         continue;
439                 }
440                 if (strcmp(node, "") == 0) {
441                         continue;
442                 }
443                 pnn_node = talloc(mem_ctx, struct pnn_node);
444                 pnn_node->pnn = pnn++;
445                 pnn_node->addr = talloc_strdup(pnn_node, node);
446                 pnn_node->next = pnn_nodes;
447                 pnn_nodes = pnn_node;
448         }
449
450         /* swap them around so we return them in incrementing order */
451         pnn_node = pnn_nodes;
452         pnn_nodes = NULL;
453         while (pnn_node) {
454                 tmp_node = pnn_node;
455                 pnn_node = pnn_node->next;
456
457                 tmp_node->next = pnn_nodes;
458                 pnn_nodes = tmp_node;
459         }
460
461         return pnn_nodes;
462 }
463
464 /*
465   show the PNN of the current node
466   discover the pnn by loading the nodes file and try to bind to all
467   addresses one at a time until the ip address is found.
468  */
469 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
470 {
471         TALLOC_CTX *mem_ctx = talloc_new(NULL);
472         struct pnn_node *pnn_nodes;
473         struct pnn_node *pnn_node;
474
475         pnn_nodes = read_nodes_file(mem_ctx);
476         if (pnn_nodes == NULL) {
477                 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
478                 talloc_free(mem_ctx);
479                 return -1;
480         }
481
482         for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
483                 ctdb_sock_addr addr;
484
485                 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
486                         DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
487                         talloc_free(mem_ctx);
488                         return -1;
489                 }
490
491                 if (ctdb_sys_have_ip(&addr)) {
492                         printf("PNN:%d\n", pnn_node->pnn);
493                         talloc_free(mem_ctx);
494                         return 0;
495                 }
496         }
497
498         printf("Failed to detect which PNN this node is\n");
499         talloc_free(mem_ctx);
500         return -1;
501 }
502
503 /*
504   display remote ctdb status
505  */
506 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
507 {
508         int i, ret;
509         struct ctdb_vnn_map *vnnmap=NULL;
510         struct ctdb_node_map *nodemap=NULL;
511         uint32_t recmode, recmaster;
512         int mypnn;
513
514         mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
515         if (mypnn == -1) {
516                 return -1;
517         }
518
519         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
520         if (ret != 0) {
521                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
522                 return ret;
523         }
524
525         if(options.machinereadable){
526                 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:PartiallyOnline:\n");
527                 for(i=0;i<nodemap->num;i++){
528                         int partially_online = 0;
529                         int j;
530
531                         if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
532                                 continue;
533                         }
534                         if (nodemap->nodes[i].flags == 0) {
535                                 struct ctdb_control_get_ifaces *ifaces;
536
537                                 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
538                                                            nodemap->nodes[i].pnn,
539                                                            ctdb, &ifaces);
540                                 if (ret == 0) {
541                                         for (j=0; j < ifaces->num; j++) {
542                                                 if (ifaces->ifaces[j].link_state != 0) {
543                                                         continue;
544                                                 }
545                                                 partially_online = 1;
546                                                 break;
547                                         }
548                                         talloc_free(ifaces);
549                                 }
550                         }
551                         printf(":%d:%s:%d:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
552                                 ctdb_addr_to_str(&nodemap->nodes[i].addr),
553                                !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
554                                !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
555                                !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
556                                !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
557                                !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
558                                !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE),
559                                partially_online);
560                 }
561                 return 0;
562         }
563
564         printf("Number of nodes:%d\n", nodemap->num);
565         for(i=0;i<nodemap->num;i++){
566                 static const struct {
567                         uint32_t flag;
568                         const char *name;
569                 } flag_names[] = {
570                         { NODE_FLAGS_DISCONNECTED,          "DISCONNECTED" },
571                         { NODE_FLAGS_PERMANENTLY_DISABLED,  "DISABLED" },
572                         { NODE_FLAGS_BANNED,                "BANNED" },
573                         { NODE_FLAGS_UNHEALTHY,             "UNHEALTHY" },
574                         { NODE_FLAGS_DELETED,               "DELETED" },
575                         { NODE_FLAGS_STOPPED,               "STOPPED" },
576                         { NODE_FLAGS_INACTIVE,              "INACTIVE" },
577                 };
578                 char *flags_str = NULL;
579                 int j;
580
581                 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
582                         continue;
583                 }
584                 if (nodemap->nodes[i].flags == 0) {
585                         struct ctdb_control_get_ifaces *ifaces;
586
587                         ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
588                                                    nodemap->nodes[i].pnn,
589                                                    ctdb, &ifaces);
590                         if (ret == 0) {
591                                 for (j=0; j < ifaces->num; j++) {
592                                         if (ifaces->ifaces[j].link_state != 0) {
593                                                 continue;
594                                         }
595                                         flags_str = talloc_strdup(ctdb, "PARTIALLYONLINE");
596                                         break;
597                                 }
598                                 talloc_free(ifaces);
599                         }
600                 }
601                 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
602                         if (nodemap->nodes[i].flags & flag_names[j].flag) {
603                                 if (flags_str == NULL) {
604                                         flags_str = talloc_strdup(ctdb, flag_names[j].name);
605                                 } else {
606                                         flags_str = talloc_asprintf_append(flags_str, "|%s",
607                                                                            flag_names[j].name);
608                                 }
609                                 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
610                         }
611                 }
612                 if (flags_str == NULL) {
613                         flags_str = talloc_strdup(ctdb, "OK");
614                         CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
615                 }
616                 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
617                        ctdb_addr_to_str(&nodemap->nodes[i].addr),
618                        flags_str,
619                        nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
620                 talloc_free(flags_str);
621         }
622
623         ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
624         if (ret != 0) {
625                 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
626                 return ret;
627         }
628         if (vnnmap->generation == INVALID_GENERATION) {
629                 printf("Generation:INVALID\n");
630         } else {
631                 printf("Generation:%d\n",vnnmap->generation);
632         }
633         printf("Size:%d\n",vnnmap->size);
634         for(i=0;i<vnnmap->size;i++){
635                 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
636         }
637
638         ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
639         if (ret != 0) {
640                 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
641                 return ret;
642         }
643         printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
644
645         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
646         if (ret != 0) {
647                 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
648                 return ret;
649         }
650         printf("Recovery master:%d\n",recmaster);
651
652         return 0;
653 }
654
655
656 struct natgw_node {
657         struct natgw_node *next;
658         const char *addr;
659 };
660
661 /*
662   display the list of nodes belonging to this natgw configuration
663  */
664 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
665 {
666         int i, ret;
667         const char *natgw_list;
668         int nlines;
669         char **lines;
670         struct natgw_node *natgw_nodes = NULL;
671         struct natgw_node *natgw_node;
672         struct ctdb_node_map *nodemap=NULL;
673
674
675         /* read the natgw nodes file into a linked list */
676         natgw_list = getenv("NATGW_NODES");
677         if (natgw_list == NULL) {
678                 natgw_list = "/etc/ctdb/natgw_nodes";
679         }
680         lines = file_lines_load(natgw_list, &nlines, ctdb);
681         if (lines == NULL) {
682                 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
683                 return -1;
684         }
685         while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
686                 nlines--;
687         }
688         for (i=0;i<nlines;i++) {
689                 char *node;
690
691                 node = lines[i];
692                 /* strip leading spaces */
693                 while((*node == ' ') || (*node == '\t')) {
694                         node++;
695                 }
696                 if (*node == '#') {
697                         continue;
698                 }
699                 if (strcmp(node, "") == 0) {
700                         continue;
701                 }
702                 natgw_node = talloc(ctdb, struct natgw_node);
703                 natgw_node->addr = talloc_strdup(natgw_node, node);
704                 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
705                 natgw_node->next = natgw_nodes;
706                 natgw_nodes = natgw_node;
707         }
708
709         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
710         if (ret != 0) {
711                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
712                 return ret;
713         }
714
715         i=0;
716         while(i<nodemap->num) {
717                 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
718                         if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
719                                 break;
720                         }
721                 }
722
723                 /* this node was not in the natgw so we just remove it from
724                  * the list
725                  */
726                 if ((natgw_node == NULL) 
727                 ||  (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
728                         int j;
729
730                         for (j=i+1; j<nodemap->num; j++) {
731                                 nodemap->nodes[j-1] = nodemap->nodes[j];
732                         }
733                         nodemap->num--;
734                         continue;
735                 }
736
737                 i++;
738         }               
739
740         /* pick a node to be natgwmaster
741          * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
742          */
743         for(i=0;i<nodemap->num;i++){
744                 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
745                         printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
746                         break;
747                 }
748         }
749         /* we couldnt find any healthy node, try unhealthy ones */
750         if (i == nodemap->num) {
751                 for(i=0;i<nodemap->num;i++){
752                         if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
753                                 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
754                                 break;
755                         }
756                 }
757         }
758         /* unless all nodes are STOPPED, when we pick one anyway */
759         if (i == nodemap->num) {
760                 for(i=0;i<nodemap->num;i++){
761                         if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
762                                 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
763                                 break;
764                         }
765                 }
766                 /* or if we still can not find any */
767                 if (i == nodemap->num) {
768                         printf("-1 0.0.0.0\n");
769                 }
770         }
771
772         /* print the pruned list of nodes belonging to this natgw list */
773         for(i=0;i<nodemap->num;i++){
774                 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
775                         continue;
776                 }
777                 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
778                         ctdb_addr_to_str(&nodemap->nodes[i].addr),
779                        !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
780                        !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
781                        !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
782                        !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
783                        !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
784         }
785
786         return 0;
787 }
788
789 /*
790   display the status of the scripts for monitoring (or other events)
791  */
792 static int control_one_scriptstatus(struct ctdb_context *ctdb,
793                                     enum ctdb_eventscript_call type)
794 {
795         struct ctdb_scripts_wire *script_status;
796         int ret, i;
797
798         ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
799         if (ret != 0) {
800                 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
801                 return ret;
802         }
803
804         if (script_status == NULL) {
805                 if (!options.machinereadable) {
806                         printf("%s cycle never run\n",
807                                ctdb_eventscript_call_names[type]);
808                 }
809                 return 0;
810         }
811
812         if (!options.machinereadable) {
813                 printf("%d scripts were executed last %s cycle\n",
814                        script_status->num_scripts,
815                        ctdb_eventscript_call_names[type]);
816         }
817         for (i=0; i<script_status->num_scripts; i++) {
818                 const char *status = NULL;
819
820                 switch (script_status->scripts[i].status) {
821                 case -ETIME:
822                         status = "TIMEDOUT";
823                         break;
824                 case -ENOEXEC:
825                         status = "DISABLED";
826                         break;
827                 case 0:
828                         status = "OK";
829                         break;
830                 default:
831                         if (script_status->scripts[i].status > 0)
832                                 status = "ERROR";
833                         break;
834                 }
835                 if (options.machinereadable) {
836                         printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
837                                ctdb_eventscript_call_names[type],
838                                script_status->scripts[i].name,
839                                script_status->scripts[i].status,
840                                status,
841                                (long)script_status->scripts[i].start.tv_sec,
842                                (long)script_status->scripts[i].start.tv_usec,
843                                (long)script_status->scripts[i].finished.tv_sec,
844                                (long)script_status->scripts[i].finished.tv_usec,
845                                script_status->scripts[i].output);
846                         continue;
847                 }
848                 if (status)
849                         printf("%-20s Status:%s    ",
850                                script_status->scripts[i].name, status);
851                 else
852                         /* Some other error, eg from stat. */
853                         printf("%-20s Status:CANNOT RUN (%s)",
854                                script_status->scripts[i].name,
855                                strerror(-script_status->scripts[i].status));
856
857                 if (script_status->scripts[i].status >= 0) {
858                         printf("Duration:%.3lf ",
859                         timeval_delta(&script_status->scripts[i].finished,
860                               &script_status->scripts[i].start));
861                 }
862                 if (script_status->scripts[i].status != -ENOEXEC) {
863                         printf("%s",
864                                ctime(&script_status->scripts[i].start.tv_sec));
865                         if (script_status->scripts[i].status != 0) {
866                                 printf("   OUTPUT:%s\n",
867                                        script_status->scripts[i].output);
868                         }
869                 } else {
870                         printf("\n");
871                 }
872         }
873         return 0;
874 }
875
876
877 static int control_scriptstatus(struct ctdb_context *ctdb,
878                                 int argc, const char **argv)
879 {
880         int ret;
881         enum ctdb_eventscript_call type, min, max;
882         const char *arg;
883
884         if (argc > 1) {
885                 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
886                 return -1;
887         }
888
889         if (argc == 0)
890                 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
891         else
892                 arg = argv[0];
893
894         for (type = 0; type < CTDB_EVENT_MAX; type++) {
895                 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
896                         min = type;
897                         max = type+1;
898                         break;
899                 }
900         }
901         if (type == CTDB_EVENT_MAX) {
902                 if (strcmp(arg, "all") == 0) {
903                         min = 0;
904                         max = CTDB_EVENT_MAX;
905                 } else {
906                         DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
907                         return -1;
908                 }
909         }
910
911         if (options.machinereadable) {
912                 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
913         }
914
915         for (type = min; type < max; type++) {
916                 ret = control_one_scriptstatus(ctdb, type);
917                 if (ret != 0) {
918                         return ret;
919                 }
920         }
921
922         return 0;
923 }
924
925 /*
926   enable an eventscript
927  */
928 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
929 {
930         int ret;
931
932         if (argc < 1) {
933                 usage();
934         }
935
936         ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
937         if (ret != 0) {
938           DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
939                 return ret;
940         }
941
942         return 0;
943 }
944
945 /*
946   disable an eventscript
947  */
948 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
949 {
950         int ret;
951
952         if (argc < 1) {
953                 usage();
954         }
955
956         ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
957         if (ret != 0) {
958           DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
959                 return ret;
960         }
961
962         return 0;
963 }
964
965 /*
966   display the pnn of the recovery master
967  */
968 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
969 {
970         int ret;
971         uint32_t recmaster;
972
973         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
974         if (ret != 0) {
975                 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
976                 return ret;
977         }
978         printf("%d\n",recmaster);
979
980         return 0;
981 }
982
983 /*
984   add a tickle to a public address
985  */
986 static int control_add_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
987 {
988         struct ctdb_tcp_connection t;
989         TDB_DATA data;
990         int ret;
991
992         if (argc < 2) {
993                 usage();
994         }
995
996         if (parse_ip_port(argv[0], &t.src_addr) == 0) {
997                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
998                 return -1;
999         }
1000         if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
1001                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
1002                 return -1;
1003         }
1004
1005         data.dptr = (uint8_t *)&t;
1006         data.dsize = sizeof(t);
1007
1008         /* tell all nodes about this tcp connection */
1009         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE,
1010                            0, data, ctdb, NULL, NULL, NULL, NULL);
1011         if (ret != 0) {
1012                 DEBUG(DEBUG_ERR,("Failed to add tickle\n"));
1013                 return -1;
1014         }
1015         
1016         return 0;
1017 }
1018
1019
1020 /*
1021   delete a tickle from a node
1022  */
1023 static int control_del_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
1024 {
1025         struct ctdb_tcp_connection t;
1026         TDB_DATA data;
1027         int ret;
1028
1029         if (argc < 2) {
1030                 usage();
1031         }
1032
1033         if (parse_ip_port(argv[0], &t.src_addr) == 0) {
1034                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1035                 return -1;
1036         }
1037         if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
1038                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
1039                 return -1;
1040         }
1041
1042         data.dptr = (uint8_t *)&t;
1043         data.dsize = sizeof(t);
1044
1045         /* tell all nodes about this tcp connection */
1046         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_TCP_REMOVE,
1047                            0, data, ctdb, NULL, NULL, NULL, NULL);
1048         if (ret != 0) {
1049                 DEBUG(DEBUG_ERR,("Failed to remove tickle\n"));
1050                 return -1;
1051         }
1052         
1053         return 0;
1054 }
1055
1056
1057 /*
1058   get a list of all tickles for this pnn
1059  */
1060 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
1061 {
1062         struct ctdb_control_tcp_tickle_list *list;
1063         ctdb_sock_addr addr;
1064         int i, ret;
1065         unsigned port = 0;
1066
1067         if (argc < 1) {
1068                 usage();
1069         }
1070
1071         if (argc == 2) {
1072                 port = atoi(argv[1]);
1073         }
1074
1075         if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1076                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1077                 return -1;
1078         }
1079
1080         ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
1081         if (ret == -1) {
1082                 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
1083                 return -1;
1084         }
1085
1086         if (options.machinereadable){
1087                 printf(":source ip:port:destination ip:port:\n");
1088                 for (i=0;i<list->tickles.num;i++) {
1089                         if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
1090                                 continue;
1091                         }
1092                         printf(":%s:%u", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1093                         printf(":%s:%u:\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
1094                 }
1095         } else {
1096                 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
1097                 printf("Num tickles:%u\n", list->tickles.num);
1098                 for (i=0;i<list->tickles.num;i++) {
1099                         if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
1100                                 continue;
1101                         }
1102                         printf("SRC: %s:%u   ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1103                         printf("DST: %s:%u\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
1104                 }
1105         }
1106
1107         talloc_free(list);
1108         
1109         return 0;
1110 }
1111
1112
1113 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1114 {
1115         struct ctdb_all_public_ips *ips;
1116         struct ctdb_public_ip ip;
1117         int i, ret;
1118         uint32_t *nodes;
1119         uint32_t disable_time;
1120         TDB_DATA data;
1121         struct ctdb_node_map *nodemap=NULL;
1122         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1123
1124         disable_time = 30;
1125         data.dptr  = (uint8_t*)&disable_time;
1126         data.dsize = sizeof(disable_time);
1127         ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1128         if (ret != 0) {
1129                 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1130                 return -1;
1131         }
1132
1133
1134
1135         /* read the public ip list from the node */
1136         ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1137         if (ret != 0) {
1138                 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1139                 talloc_free(tmp_ctx);
1140                 return -1;
1141         }
1142
1143         for (i=0;i<ips->num;i++) {
1144                 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1145                         break;
1146                 }
1147         }
1148         if (i==ips->num) {
1149                 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1150                         pnn, ctdb_addr_to_str(addr)));
1151                 talloc_free(tmp_ctx);
1152                 return -1;
1153         }
1154
1155         ip.pnn  = pnn;
1156         ip.addr = *addr;
1157
1158         data.dptr  = (uint8_t *)&ip;
1159         data.dsize = sizeof(ip);
1160
1161         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1162         if (ret != 0) {
1163                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1164                 talloc_free(tmp_ctx);
1165                 return ret;
1166         }
1167
1168         nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1169         ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1170                                         nodes, 0,
1171                                         LONGTIMELIMIT(),
1172                                         false, data,
1173                                         NULL, NULL,
1174                                         NULL);
1175         if (ret != 0) {
1176                 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1177                 talloc_free(tmp_ctx);
1178                 return -1;
1179         }
1180
1181         ret = ctdb_ctrl_takeover_ip(ctdb, LONGTIMELIMIT(), pnn, &ip);
1182         if (ret != 0) {
1183                 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1184                 talloc_free(tmp_ctx);
1185                 return -1;
1186         }
1187
1188         /* update the recovery daemon so it now knows to expect the new
1189            node assignment for this ip.
1190         */
1191         ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECD_UPDATE_IP, data);
1192         if (ret != 0) {
1193                 DEBUG(DEBUG_ERR,("Failed to send message to update the ip on the recovery master.\n"));
1194                 return -1;
1195         }
1196
1197         talloc_free(tmp_ctx);
1198         return 0;
1199 }
1200
1201 /*
1202   move/failover an ip address to a specific node
1203  */
1204 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1205 {
1206         uint32_t pnn;
1207         ctdb_sock_addr addr;
1208
1209         if (argc < 2) {
1210                 usage();
1211                 return -1;
1212         }
1213
1214         if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1215                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1216                 return -1;
1217         }
1218
1219
1220         if (sscanf(argv[1], "%u", &pnn) != 1) {
1221                 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1222                 return -1;
1223         }
1224
1225         if (move_ip(ctdb, &addr, pnn) != 0) {
1226                 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1227                 return -1;
1228         }
1229
1230         return 0;
1231 }
1232
1233 void getips_store_callback(void *param, void *data)
1234 {
1235         struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1236         struct ctdb_all_public_ips *ips = param;
1237         int i;
1238
1239         i = ips->num++;
1240         ips->ips[i].pnn  = node_ip->pnn;
1241         ips->ips[i].addr = node_ip->addr;
1242 }
1243
1244 void getips_count_callback(void *param, void *data)
1245 {
1246         uint32_t *count = param;
1247
1248         (*count)++;
1249 }
1250
1251 #define IP_KEYLEN       4
1252 static uint32_t *ip_key(ctdb_sock_addr *ip)
1253 {
1254         static uint32_t key[IP_KEYLEN];
1255
1256         bzero(key, sizeof(key));
1257
1258         switch (ip->sa.sa_family) {
1259         case AF_INET:
1260                 key[0]  = ip->ip.sin_addr.s_addr;
1261                 break;
1262         case AF_INET6:
1263                 key[0]  = ip->ip6.sin6_addr.s6_addr32[3];
1264                 key[1]  = ip->ip6.sin6_addr.s6_addr32[2];
1265                 key[2]  = ip->ip6.sin6_addr.s6_addr32[1];
1266                 key[3]  = ip->ip6.sin6_addr.s6_addr32[0];
1267                 break;
1268         default:
1269                 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1270                 return key;
1271         }
1272
1273         return key;
1274 }
1275
1276 static void *add_ip_callback(void *parm, void *data)
1277 {
1278         return parm;
1279 }
1280
1281 static int
1282 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1283 {
1284         struct ctdb_all_public_ips *tmp_ips;
1285         struct ctdb_node_map *nodemap=NULL;
1286         trbt_tree_t *ip_tree;
1287         int i, j, len, ret;
1288         uint32_t count;
1289
1290         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1291         if (ret != 0) {
1292                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1293                 return ret;
1294         }
1295
1296         ip_tree = trbt_create(tmp_ctx, 0);
1297
1298         for(i=0;i<nodemap->num;i++){
1299                 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1300                         continue;
1301                 }
1302                 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1303                         continue;
1304                 }
1305
1306                 /* read the public ip list from this node */
1307                 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1308                 if (ret != 0) {
1309                         DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1310                         return -1;
1311                 }
1312         
1313                 for (j=0; j<tmp_ips->num;j++) {
1314                         struct ctdb_public_ip *node_ip;
1315
1316                         node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1317                         node_ip->pnn  = tmp_ips->ips[j].pnn;
1318                         node_ip->addr = tmp_ips->ips[j].addr;
1319
1320                         trbt_insertarray32_callback(ip_tree,
1321                                 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1322                                 add_ip_callback,
1323                                 node_ip);
1324                 }
1325                 talloc_free(tmp_ips);
1326         }
1327
1328         /* traverse */
1329         count = 0;
1330         trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1331
1332         len = offsetof(struct ctdb_all_public_ips, ips) + 
1333                 count*sizeof(struct ctdb_public_ip);
1334         tmp_ips = talloc_zero_size(tmp_ctx, len);
1335         trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1336
1337         *ips = tmp_ips;
1338
1339         return 0;
1340 }
1341
1342
1343 /* 
1344  * scans all other nodes and returns a pnn for another node that can host this 
1345  * ip address or -1
1346  */
1347 static int
1348 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1349 {
1350         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1351         struct ctdb_all_public_ips *ips;
1352         struct ctdb_node_map *nodemap=NULL;
1353         int i, j, ret;
1354
1355         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1356         if (ret != 0) {
1357                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1358                 talloc_free(tmp_ctx);
1359                 return ret;
1360         }
1361
1362         for(i=0;i<nodemap->num;i++){
1363                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1364                         continue;
1365                 }
1366                 if (nodemap->nodes[i].pnn == options.pnn) {
1367                         continue;
1368                 }
1369
1370                 /* read the public ip list from this node */
1371                 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1372                 if (ret != 0) {
1373                         DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1374                         return -1;
1375                 }
1376
1377                 for (j=0;j<ips->num;j++) {
1378                         if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1379                                 talloc_free(tmp_ctx);
1380                                 return nodemap->nodes[i].pnn;
1381                         }
1382                 }
1383                 talloc_free(ips);
1384         }
1385
1386         talloc_free(tmp_ctx);
1387         return -1;
1388 }
1389
1390 /*
1391   add a public ip address to a node
1392  */
1393 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1394 {
1395         int i, ret;
1396         int len;
1397         uint32_t pnn;
1398         unsigned mask;
1399         ctdb_sock_addr addr;
1400         struct ctdb_control_ip_iface *pub;
1401         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1402         struct ctdb_all_public_ips *ips;
1403
1404
1405         if (argc != 2) {
1406                 talloc_free(tmp_ctx);
1407                 usage();
1408         }
1409
1410         if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1411                 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1412                 talloc_free(tmp_ctx);
1413                 return -1;
1414         }
1415
1416         ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1417         if (ret != 0) {
1418                 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1419                 talloc_free(tmp_ctx);
1420                 return ret;
1421         }
1422
1423
1424         /* check if some other node is already serving this ip, if not,
1425          * we will claim it
1426          */
1427         for (i=0;i<ips->num;i++) {
1428                 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1429                         break;
1430                 }
1431         }
1432
1433         len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1434         pub = talloc_size(tmp_ctx, len); 
1435         CTDB_NO_MEMORY(ctdb, pub);
1436
1437         pub->addr  = addr;
1438         pub->mask  = mask;
1439         pub->len   = strlen(argv[1])+1;
1440         memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1441
1442         ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1443         if (ret != 0) {
1444                 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1445                 talloc_free(tmp_ctx);
1446                 return ret;
1447         }
1448
1449         if (i == ips->num) {
1450                 /* no one has this ip so we claim it */
1451                 pnn  = options.pnn;
1452         } else {
1453                 pnn  = ips->ips[i].pnn;
1454         }
1455
1456         if (move_ip(ctdb, &addr, pnn) != 0) {
1457                 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1458                 return -1;
1459         }
1460
1461         talloc_free(tmp_ctx);
1462         return 0;
1463 }
1464
1465 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1466
1467 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1468 {
1469         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1470         struct ctdb_node_map *nodemap=NULL;
1471         struct ctdb_all_public_ips *ips;
1472         int ret, i, j;
1473
1474         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1475         if (ret != 0) {
1476                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1477                 return ret;
1478         }
1479
1480         /* remove it from the nodes that are not hosting the ip currently */
1481         for(i=0;i<nodemap->num;i++){
1482                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1483                         continue;
1484                 }
1485                 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1486                         DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1487                         continue;
1488                 }
1489
1490                 for (j=0;j<ips->num;j++) {
1491                         if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1492                                 break;
1493                         }
1494                 }
1495                 if (j==ips->num) {
1496                         continue;
1497                 }
1498
1499                 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1500                         continue;
1501                 }
1502
1503                 options.pnn = nodemap->nodes[i].pnn;
1504                 control_delip(ctdb, argc, argv);
1505         }
1506
1507
1508         /* remove it from every node (also the one hosting it) */
1509         for(i=0;i<nodemap->num;i++){
1510                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1511                         continue;
1512                 }
1513                 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1514                         DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1515                         continue;
1516                 }
1517
1518                 for (j=0;j<ips->num;j++) {
1519                         if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1520                                 break;
1521                         }
1522                 }
1523                 if (j==ips->num) {
1524                         continue;
1525                 }
1526
1527                 options.pnn = nodemap->nodes[i].pnn;
1528                 control_delip(ctdb, argc, argv);
1529         }
1530
1531         talloc_free(tmp_ctx);
1532         return 0;
1533 }
1534         
1535 /*
1536   delete a public ip address from a node
1537  */
1538 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1539 {
1540         int i, ret;
1541         ctdb_sock_addr addr;
1542         struct ctdb_control_ip_iface pub;
1543         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1544         struct ctdb_all_public_ips *ips;
1545
1546         if (argc != 1) {
1547                 talloc_free(tmp_ctx);
1548                 usage();
1549         }
1550
1551         if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1552                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1553                 return -1;
1554         }
1555
1556         if (options.pnn == CTDB_BROADCAST_ALL) {
1557                 return control_delip_all(ctdb, argc, argv, &addr);
1558         }
1559
1560         pub.addr  = addr;
1561         pub.mask  = 0;
1562         pub.len   = 0;
1563
1564         ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1565         if (ret != 0) {
1566                 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1567                 talloc_free(tmp_ctx);
1568                 return ret;
1569         }
1570         
1571         for (i=0;i<ips->num;i++) {
1572                 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1573                         break;
1574                 }
1575         }
1576
1577         if (i==ips->num) {
1578                 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1579                         ctdb_addr_to_str(&addr)));
1580                 talloc_free(tmp_ctx);
1581                 return -1;
1582         }
1583
1584         if (ips->ips[i].pnn == options.pnn) {
1585                 ret = find_other_host_for_public_ip(ctdb, &addr);
1586                 if (ret != -1) {
1587                         if (move_ip(ctdb, &addr, ret) != 0) {
1588                                 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1589                                 return -1;
1590                         }
1591                 }
1592         }
1593
1594         ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1595         if (ret != 0) {
1596                 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1597                 talloc_free(tmp_ctx);
1598                 return ret;
1599         }
1600
1601         talloc_free(tmp_ctx);
1602         return 0;
1603 }
1604
1605 /*
1606   kill a tcp connection
1607  */
1608 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1609 {
1610         int ret;
1611         struct ctdb_control_killtcp killtcp;
1612
1613         if (argc < 2) {
1614                 usage();
1615         }
1616
1617         if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1618                 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1619                 return -1;
1620         }
1621
1622         if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1623                 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1624                 return -1;
1625         }
1626
1627         ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1628         if (ret != 0) {
1629                 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1630                 return ret;
1631         }
1632
1633         return 0;
1634 }
1635
1636
1637 /*
1638   send a gratious arp
1639  */
1640 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1641 {
1642         int ret;
1643         ctdb_sock_addr addr;
1644
1645         if (argc < 2) {
1646                 usage();
1647         }
1648
1649         if (!parse_ip(argv[0], NULL, 0, &addr)) {
1650                 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1651                 return -1;
1652         }
1653
1654         ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1655         if (ret != 0) {
1656                 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1657                 return ret;
1658         }
1659
1660         return 0;
1661 }
1662
1663 /*
1664   register a server id
1665  */
1666 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1667 {
1668         int ret;
1669         struct ctdb_server_id server_id;
1670
1671         if (argc < 3) {
1672                 usage();
1673         }
1674
1675         server_id.pnn       = strtoul(argv[0], NULL, 0);
1676         server_id.type      = strtoul(argv[1], NULL, 0);
1677         server_id.server_id = strtoul(argv[2], NULL, 0);
1678
1679         ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1680         if (ret != 0) {
1681                 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1682                 return ret;
1683         }
1684         DEBUG(DEBUG_ERR,("Srvid registered. Sleeping for 999 seconds\n"));
1685         sleep(999);
1686         return -1;
1687 }
1688
1689 /*
1690   unregister a server id
1691  */
1692 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1693 {
1694         int ret;
1695         struct ctdb_server_id server_id;
1696
1697         if (argc < 3) {
1698                 usage();
1699         }
1700
1701         server_id.pnn       = strtoul(argv[0], NULL, 0);
1702         server_id.type      = strtoul(argv[1], NULL, 0);
1703         server_id.server_id = strtoul(argv[2], NULL, 0);
1704
1705         ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1706         if (ret != 0) {
1707                 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1708                 return ret;
1709         }
1710         return -1;
1711 }
1712
1713 /*
1714   check if a server id exists
1715  */
1716 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1717 {
1718         uint32_t status;
1719         int ret;
1720         struct ctdb_server_id server_id;
1721
1722         if (argc < 3) {
1723                 usage();
1724         }
1725
1726         server_id.pnn       = strtoul(argv[0], NULL, 0);
1727         server_id.type      = strtoul(argv[1], NULL, 0);
1728         server_id.server_id = strtoul(argv[2], NULL, 0);
1729
1730         ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1731         if (ret != 0) {
1732                 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1733                 return ret;
1734         }
1735
1736         if (status) {
1737                 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1738         } else {
1739                 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1740         }
1741         return 0;
1742 }
1743
1744 /*
1745   get a list of all server ids that are registered on a node
1746  */
1747 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1748 {
1749         int i, ret;
1750         struct ctdb_server_id_list *server_ids;
1751
1752         ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1753         if (ret != 0) {
1754                 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1755                 return ret;
1756         }
1757
1758         for (i=0; i<server_ids->num; i++) {
1759                 printf("Server id %d:%d:%d\n", 
1760                         server_ids->server_ids[i].pnn, 
1761                         server_ids->server_ids[i].type, 
1762                         server_ids->server_ids[i].server_id); 
1763         }
1764
1765         return -1;
1766 }
1767
1768 /*
1769   send a tcp tickle ack
1770  */
1771 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1772 {
1773         int ret;
1774         ctdb_sock_addr  src, dst;
1775
1776         if (argc < 2) {
1777                 usage();
1778         }
1779
1780         if (!parse_ip_port(argv[0], &src)) {
1781                 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1782                 return -1;
1783         }
1784
1785         if (!parse_ip_port(argv[1], &dst)) {
1786                 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1787                 return -1;
1788         }
1789
1790         ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1791         if (ret==0) {
1792                 return 0;
1793         }
1794         DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1795
1796         return -1;
1797 }
1798
1799
1800 /*
1801   display public ip status
1802  */
1803 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1804 {
1805         int i, ret;
1806         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1807         struct ctdb_all_public_ips *ips;
1808
1809         if (options.pnn == CTDB_BROADCAST_ALL) {
1810                 /* read the list of public ips from all nodes */
1811                 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1812         } else {
1813                 /* read the public ip list from this node */
1814                 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1815         }
1816         if (ret != 0) {
1817                 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1818                 talloc_free(tmp_ctx);
1819                 return ret;
1820         }
1821
1822         if (options.machinereadable){
1823                 printf(":Public IP:Node:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1824         } else {
1825                 if (options.pnn == CTDB_BROADCAST_ALL) {
1826                         printf("Public IPs on ALL nodes\n");
1827                 } else {
1828                         printf("Public IPs on node %u\n", options.pnn);
1829                 }
1830         }
1831
1832         for (i=1;i<=ips->num;i++) {
1833                 struct ctdb_control_public_ip_info *info = NULL;
1834                 int32_t pnn;
1835                 char *aciface = NULL;
1836                 char *avifaces = NULL;
1837                 char *cifaces = NULL;
1838
1839                 if (options.pnn == CTDB_BROADCAST_ALL) {
1840                         pnn = ips->ips[ips->num-i].pnn;
1841                 } else {
1842                         pnn = options.pnn;
1843                 }
1844
1845                 if (pnn != -1) {
1846                         ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1847                                                    &ips->ips[ips->num-i].addr, &info);
1848                 } else {
1849                         ret = -1;
1850                 }
1851
1852                 if (ret == 0) {
1853                         int j;
1854                         for (j=0; j < info->num; j++) {
1855                                 if (cifaces == NULL) {
1856                                         cifaces = talloc_strdup(info,
1857                                                                 info->ifaces[j].name);
1858                                 } else {
1859                                         cifaces = talloc_asprintf_append(cifaces,
1860                                                                          ",%s",
1861                                                                          info->ifaces[j].name);
1862                                 }
1863
1864                                 if (info->active_idx == j) {
1865                                         aciface = info->ifaces[j].name;
1866                                 }
1867
1868                                 if (info->ifaces[j].link_state == 0) {
1869                                         continue;
1870                                 }
1871
1872                                 if (avifaces == NULL) {
1873                                         avifaces = talloc_strdup(info, info->ifaces[j].name);
1874                                 } else {
1875                                         avifaces = talloc_asprintf_append(avifaces,
1876                                                                           ",%s",
1877                                                                           info->ifaces[j].name);
1878                                 }
1879                         }
1880                 }
1881
1882                 if (options.machinereadable){
1883                         printf(":%s:%d:%s:%s:%s:\n",
1884                                ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1885                                ips->ips[ips->num-i].pnn,
1886                                aciface?aciface:"",
1887                                avifaces?avifaces:"",
1888                                cifaces?cifaces:"");
1889                 } else {
1890                         printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1891                                ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1892                                ips->ips[ips->num-i].pnn,
1893                                aciface?aciface:"",
1894                                avifaces?avifaces:"",
1895                                cifaces?cifaces:"");
1896                 }
1897                 talloc_free(info);
1898         }
1899
1900         talloc_free(tmp_ctx);
1901         return 0;
1902 }
1903
1904 /*
1905   public ip info
1906  */
1907 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1908 {
1909         int i, ret;
1910         ctdb_sock_addr addr;
1911         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1912         struct ctdb_control_public_ip_info *info;
1913
1914         if (argc != 1) {
1915                 talloc_free(tmp_ctx);
1916                 usage();
1917         }
1918
1919         if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1920                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1921                 return -1;
1922         }
1923
1924         /* read the public ip info from this node */
1925         ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1926                                            tmp_ctx, &addr, &info);
1927         if (ret != 0) {
1928                 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1929                                   argv[0], options.pnn));
1930                 talloc_free(tmp_ctx);
1931                 return ret;
1932         }
1933
1934         printf("Public IP[%s] info on node %u\n",
1935                ctdb_addr_to_str(&info->ip.addr),
1936                options.pnn);
1937
1938         printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1939                ctdb_addr_to_str(&info->ip.addr),
1940                info->ip.pnn, info->num);
1941
1942         for (i=0; i<info->num; i++) {
1943                 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1944
1945                 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1946                        i+1, info->ifaces[i].name,
1947                        info->ifaces[i].link_state?"up":"down",
1948                        (unsigned int)info->ifaces[i].references,
1949                        (i==info->active_idx)?" (active)":"");
1950         }
1951
1952         talloc_free(tmp_ctx);
1953         return 0;
1954 }
1955
1956 /*
1957   display interfaces status
1958  */
1959 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1960 {
1961         int i, ret;
1962         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1963         struct ctdb_control_get_ifaces *ifaces;
1964
1965         /* read the public ip list from this node */
1966         ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1967                                    tmp_ctx, &ifaces);
1968         if (ret != 0) {
1969                 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1970                                   options.pnn));
1971                 talloc_free(tmp_ctx);
1972                 return ret;
1973         }
1974
1975         if (options.machinereadable){
1976                 printf(":Name:LinkStatus:References:\n");
1977         } else {
1978                 printf("Interfaces on node %u\n", options.pnn);
1979         }
1980
1981         for (i=0; i<ifaces->num; i++) {
1982                 if (options.machinereadable){
1983                         printf(":%s:%s:%u\n",
1984                                ifaces->ifaces[i].name,
1985                                ifaces->ifaces[i].link_state?"1":"0",
1986                                (unsigned int)ifaces->ifaces[i].references);
1987                 } else {
1988                         printf("name:%s link:%s references:%u\n",
1989                                ifaces->ifaces[i].name,
1990                                ifaces->ifaces[i].link_state?"up":"down",
1991                                (unsigned int)ifaces->ifaces[i].references);
1992                 }
1993         }
1994
1995         talloc_free(tmp_ctx);
1996         return 0;
1997 }
1998
1999
2000 /*
2001   set link status of an interface
2002  */
2003 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
2004 {
2005         int ret;
2006         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2007         struct ctdb_control_iface_info info;
2008
2009         ZERO_STRUCT(info);
2010
2011         if (argc != 2) {
2012                 usage();
2013         }
2014
2015         if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
2016                 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
2017                                   argv[0]));
2018                 talloc_free(tmp_ctx);
2019                 return -1;
2020         }
2021         strcpy(info.name, argv[0]);
2022
2023         if (strcmp(argv[1], "up") == 0) {
2024                 info.link_state = 1;
2025         } else if (strcmp(argv[1], "down") == 0) {
2026                 info.link_state = 0;
2027         } else {
2028                 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
2029                                   argv[1]));
2030                 talloc_free(tmp_ctx);
2031                 return -1;
2032         }
2033
2034         /* read the public ip list from this node */
2035         ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
2036                                    tmp_ctx, &info);
2037         if (ret != 0) {
2038                 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
2039                                   argv[0], options.pnn));
2040                 talloc_free(tmp_ctx);
2041                 return ret;
2042         }
2043
2044         talloc_free(tmp_ctx);
2045         return 0;
2046 }
2047
2048 /*
2049   display pid of a ctdb daemon
2050  */
2051 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
2052 {
2053         uint32_t pid;
2054         int ret;
2055
2056         ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
2057         if (ret != 0) {
2058                 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
2059                 return ret;
2060         }
2061         printf("Pid:%d\n", pid);
2062
2063         return 0;
2064 }
2065
2066 static uint32_t ipreallocate_finished;
2067
2068 /*
2069   handler for receiving the response to ipreallocate
2070 */
2071 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid, 
2072                              TDB_DATA data, void *private_data)
2073 {
2074         ipreallocate_finished = 1;
2075 }
2076
2077 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
2078 {
2079         struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
2080
2081         event_add_timed(ctdb->ev, ctdb, 
2082                                 timeval_current_ofs(1, 0),
2083                                 ctdb_every_second, ctdb);
2084 }
2085
2086 /*
2087   ask the recovery daemon on the recovery master to perform a ip reallocation
2088  */
2089 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
2090 {
2091         int i, ret;
2092         TDB_DATA data;
2093         struct takeover_run_reply rd;
2094         uint32_t recmaster;
2095         struct ctdb_node_map *nodemap=NULL;
2096         int retries=0;
2097         struct timeval tv = timeval_current();
2098
2099         /* we need some events to trigger so we can timeout and restart
2100            the loop
2101         */
2102         event_add_timed(ctdb->ev, ctdb, 
2103                                 timeval_current_ofs(1, 0),
2104                                 ctdb_every_second, ctdb);
2105
2106         rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2107         if (rd.pnn == -1) {
2108                 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
2109                 return -1;
2110         }
2111         rd.srvid = getpid();
2112
2113         /* register a message port for receiveing the reply so that we
2114            can receive the reply
2115         */
2116         ctdb_client_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
2117
2118         data.dptr = (uint8_t *)&rd;
2119         data.dsize = sizeof(rd);
2120
2121 again:
2122         /* check that there are valid nodes available */
2123         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2124                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2125                 return -1;
2126         }
2127         for (i=0; i<nodemap->num;i++) {
2128                 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2129                         break;
2130                 }
2131         }
2132         if (i==nodemap->num) {
2133                 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2134                 return 0;
2135         }
2136
2137
2138         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2139         if (ret != 0) {
2140                 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2141                 return ret;
2142         }
2143
2144         /* verify the node exists */
2145         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2146                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2147                 return -1;
2148         }
2149
2150
2151         /* check tha there are nodes available that can act as a recmaster */
2152         for (i=0; i<nodemap->num; i++) {
2153                 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2154                         continue;
2155                 }
2156                 break;
2157         }
2158         if (i == nodemap->num) {
2159                 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2160                 return 0;
2161         }
2162
2163         /* verify the recovery master is not STOPPED, nor BANNED */
2164         if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2165                 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2166                 retries++;
2167                 sleep(1);
2168                 goto again;
2169         } 
2170
2171         
2172         /* verify the recovery master is not STOPPED, nor BANNED */
2173         if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2174                 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2175                 retries++;
2176                 sleep(1);
2177                 goto again;
2178         } 
2179
2180         ipreallocate_finished = 0;
2181         ret = ctdb_client_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2182         if (ret != 0) {
2183                 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2184                 return -1;
2185         }
2186
2187         tv = timeval_current();
2188         /* this loop will terminate when we have received the reply */
2189         while (timeval_elapsed(&tv) < 3.0) {
2190                 event_loop_once(ctdb->ev);
2191         }
2192         if (ipreallocate_finished == 1) {
2193                 return 0;
2194         }
2195
2196         DEBUG(DEBUG_ERR,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2197         retries++;
2198         sleep(1);
2199         goto again;
2200
2201         return 0;
2202 }
2203
2204
2205 /*
2206   disable a remote node
2207  */
2208 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2209 {
2210         int ret;
2211         struct ctdb_node_map *nodemap=NULL;
2212
2213         /* check if the node is already disabled */
2214         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2215                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2216                 exit(10);
2217         }
2218         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2219                 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2220                 return 0;
2221         }
2222
2223         do {
2224                 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2225                 if (ret != 0) {
2226                         DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2227                         return ret;
2228                 }
2229
2230                 sleep(1);
2231
2232                 /* read the nodemap and verify the change took effect */
2233                 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2234                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2235                         exit(10);
2236                 }
2237
2238         } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2239         ret = control_ipreallocate(ctdb, argc, argv);
2240         if (ret != 0) {
2241                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2242                 return ret;
2243         }
2244
2245         return 0;
2246 }
2247
2248 /*
2249   enable a disabled remote node
2250  */
2251 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2252 {
2253         int ret;
2254
2255         struct ctdb_node_map *nodemap=NULL;
2256
2257
2258         /* check if the node is already enabled */
2259         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2260                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2261                 exit(10);
2262         }
2263         if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2264                 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2265                 return 0;
2266         }
2267
2268         do {
2269                 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2270                 if (ret != 0) {
2271                         DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2272                         return ret;
2273                 }
2274
2275                 sleep(1);
2276
2277                 /* read the nodemap and verify the change took effect */
2278                 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2279                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2280                         exit(10);
2281                 }
2282
2283         } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2284
2285         ret = control_ipreallocate(ctdb, argc, argv);
2286         if (ret != 0) {
2287                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2288                 return ret;
2289         }
2290
2291         return 0;
2292 }
2293
2294 /*
2295   stop a remote node
2296  */
2297 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2298 {
2299         int ret;
2300         struct ctdb_node_map *nodemap=NULL;
2301
2302         do {
2303                 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2304                 if (ret != 0) {
2305                         DEBUG(DEBUG_ERR, ("Unable to stop node %u   try again\n", options.pnn));
2306                 }
2307         
2308                 sleep(1);
2309
2310                 /* read the nodemap and verify the change took effect */
2311                 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2312                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2313                         exit(10);
2314                 }
2315
2316         } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2317         ret = control_ipreallocate(ctdb, argc, argv);
2318         if (ret != 0) {
2319                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2320                 return ret;
2321         }
2322
2323         return 0;
2324 }
2325
2326 /*
2327   restart a stopped remote node
2328  */
2329 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2330 {
2331         int ret;
2332
2333         struct ctdb_node_map *nodemap=NULL;
2334
2335         do {
2336                 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2337                 if (ret != 0) {
2338                         DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2339                         return ret;
2340                 }
2341         
2342                 sleep(1);
2343
2344                 /* read the nodemap and verify the change took effect */
2345                 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2346                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2347                         exit(10);
2348                 }
2349
2350         } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2351         ret = control_ipreallocate(ctdb, argc, argv);
2352         if (ret != 0) {
2353                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2354                 return ret;
2355         }
2356
2357         return 0;
2358 }
2359
2360 static uint32_t get_generation(struct ctdb_context *ctdb)
2361 {
2362         struct ctdb_vnn_map *vnnmap=NULL;
2363         int ret;
2364
2365         /* wait until the recmaster is not in recovery mode */
2366         while (1) {
2367                 uint32_t recmode, recmaster;
2368                 
2369                 if (vnnmap != NULL) {
2370                         talloc_free(vnnmap);
2371                         vnnmap = NULL;
2372                 }
2373
2374                 /* get the recmaster */
2375                 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2376                 if (ret != 0) {
2377                         DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2378                         exit(10);
2379                 }
2380
2381                 /* get recovery mode */
2382                 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2383                 if (ret != 0) {
2384                         DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2385                         exit(10);
2386                 }
2387
2388                 /* get the current generation number */
2389                 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2390                 if (ret != 0) {
2391                         DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2392                         exit(10);
2393                 }
2394
2395                 if ((recmode == CTDB_RECOVERY_NORMAL)
2396                 &&  (vnnmap->generation != 1)){
2397                         return vnnmap->generation;
2398                 }
2399                 sleep(1);
2400         }
2401 }
2402
2403 /*
2404   ban a node from the cluster
2405  */
2406 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2407 {
2408         int ret;
2409         struct ctdb_node_map *nodemap=NULL;
2410         struct ctdb_ban_time bantime;
2411
2412         if (argc < 1) {
2413                 usage();
2414         }
2415         
2416         /* verify the node exists */
2417         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2418         if (ret != 0) {
2419                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2420                 return ret;
2421         }
2422
2423         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2424                 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2425                 return -1;
2426         }
2427
2428         bantime.pnn  = options.pnn;
2429         bantime.time = strtoul(argv[0], NULL, 0);
2430
2431         ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2432         if (ret != 0) {
2433                 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2434                 return -1;
2435         }       
2436
2437         ret = control_ipreallocate(ctdb, argc, argv);
2438         if (ret != 0) {
2439                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2440                 return ret;
2441         }
2442
2443         return 0;
2444 }
2445
2446
2447 /*
2448   unban a node from the cluster
2449  */
2450 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2451 {
2452         int ret;
2453         struct ctdb_node_map *nodemap=NULL;
2454         struct ctdb_ban_time bantime;
2455
2456         /* verify the node exists */
2457         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2458         if (ret != 0) {
2459                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2460                 return ret;
2461         }
2462
2463         if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2464                 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2465                 return -1;
2466         }
2467
2468         bantime.pnn  = options.pnn;
2469         bantime.time = 0;
2470
2471         ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2472         if (ret != 0) {
2473                 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2474                 return -1;
2475         }       
2476
2477         ret = control_ipreallocate(ctdb, argc, argv);
2478         if (ret != 0) {
2479                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2480                 return ret;
2481         }
2482
2483         return 0;
2484 }
2485
2486
2487 /*
2488   show ban information for a node
2489  */
2490 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2491 {
2492         int ret;
2493         struct ctdb_node_map *nodemap=NULL;
2494         struct ctdb_ban_time *bantime;
2495
2496         /* verify the node exists */
2497         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2498         if (ret != 0) {
2499                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2500                 return ret;
2501         }
2502
2503         ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2504         if (ret != 0) {
2505                 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2506                 return -1;
2507         }       
2508
2509         if (bantime->time == 0) {
2510                 printf("Node %u is not banned\n", bantime->pnn);
2511         } else {
2512                 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2513         }
2514
2515         return 0;
2516 }
2517
2518 /*
2519   shutdown a daemon
2520  */
2521 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2522 {
2523         int ret;
2524
2525         ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2526         if (ret != 0) {
2527                 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2528                 return ret;
2529         }
2530
2531         return 0;
2532 }
2533
2534 /*
2535   trigger a recovery
2536  */
2537 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2538 {
2539         int ret;
2540         uint32_t generation, next_generation;
2541
2542         /* record the current generation number */
2543         generation = get_generation(ctdb);
2544
2545         ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2546         if (ret != 0) {
2547                 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2548                 return ret;
2549         }
2550
2551         ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2552         if (ret != 0) {
2553                 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2554                 return ret;
2555         }
2556
2557         /* wait until we are in a new generation */
2558         while (1) {
2559                 next_generation = get_generation(ctdb);
2560                 if (next_generation != generation) {
2561                         return 0;
2562                 }
2563                 sleep(1);
2564         }
2565
2566         return 0;
2567 }
2568
2569
2570 /*
2571   display monitoring mode of a remote node
2572  */
2573 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2574 {
2575         uint32_t monmode;
2576         int ret;
2577
2578         ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2579         if (ret != 0) {
2580                 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2581                 return ret;
2582         }
2583         if (!options.machinereadable){
2584                 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2585         } else {
2586                 printf(":mode:\n");
2587                 printf(":%d:\n",monmode);
2588         }
2589         return 0;
2590 }
2591
2592
2593 /*
2594   display capabilities of a remote node
2595  */
2596 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2597 {
2598         uint32_t capabilities;
2599         int ret;
2600
2601         ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2602         if (ret != 0) {
2603                 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2604                 return ret;
2605         }
2606         
2607         if (!options.machinereadable){
2608                 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2609                 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2610                 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2611                 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2612         } else {
2613                 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2614                 printf(":%d:%d:%d:%d:\n",
2615                         !!(capabilities&CTDB_CAP_RECMASTER),
2616                         !!(capabilities&CTDB_CAP_LMASTER),
2617                         !!(capabilities&CTDB_CAP_LVS),
2618                         !!(capabilities&CTDB_CAP_NATGW));
2619         }
2620         return 0;
2621 }
2622
2623 /*
2624   display lvs configuration
2625  */
2626 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2627 {
2628         uint32_t *capabilities;
2629         struct ctdb_node_map *nodemap=NULL;
2630         int i, ret;
2631         int healthy_count = 0;
2632
2633         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2634         if (ret != 0) {
2635                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2636                 return ret;
2637         }
2638
2639         capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2640         CTDB_NO_MEMORY(ctdb, capabilities);
2641         
2642         /* collect capabilities for all connected nodes */
2643         for (i=0; i<nodemap->num; i++) {
2644                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2645                         continue;
2646                 }
2647                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2648                         continue;
2649                 }
2650         
2651                 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2652                 if (ret != 0) {
2653                         DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2654                         return ret;
2655                 }
2656
2657                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2658                         continue;
2659                 }
2660
2661                 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2662                         healthy_count++;
2663                 }
2664         }
2665
2666         /* Print all LVS nodes */
2667         for (i=0; i<nodemap->num; i++) {
2668                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2669                         continue;
2670                 }
2671                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2672                         continue;
2673                 }
2674                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2675                         continue;
2676                 }
2677
2678                 if (healthy_count != 0) {
2679                         if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2680                                 continue;
2681                         }
2682                 }
2683
2684                 printf("%d:%s\n", i, 
2685                         ctdb_addr_to_str(&nodemap->nodes[i].addr));
2686         }
2687
2688         return 0;
2689 }
2690
2691 /*
2692   display who is the lvs master
2693  */
2694 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2695 {
2696         uint32_t *capabilities;
2697         struct ctdb_node_map *nodemap=NULL;
2698         int i, ret;
2699         int healthy_count = 0;
2700
2701         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2702         if (ret != 0) {
2703                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2704                 return ret;
2705         }
2706
2707         capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2708         CTDB_NO_MEMORY(ctdb, capabilities);
2709         
2710         /* collect capabilities for all connected nodes */
2711         for (i=0; i<nodemap->num; i++) {
2712                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2713                         continue;
2714                 }
2715                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2716                         continue;
2717                 }
2718         
2719                 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2720                 if (ret != 0) {
2721                         DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2722                         return ret;
2723                 }
2724
2725                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2726                         continue;
2727                 }
2728
2729                 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2730                         healthy_count++;
2731                 }
2732         }
2733
2734         /* find and show the lvsmaster */
2735         for (i=0; i<nodemap->num; i++) {
2736                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2737                         continue;
2738                 }
2739                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2740                         continue;
2741                 }
2742                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2743                         continue;
2744                 }
2745
2746                 if (healthy_count != 0) {
2747                         if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2748                                 continue;
2749                         }
2750                 }
2751
2752                 if (options.machinereadable){
2753                         printf("%d\n", i);
2754                 } else {
2755                         printf("Node %d is LVS master\n", i);
2756                 }
2757                 return 0;
2758         }
2759
2760         printf("There is no LVS master\n");
2761         return -1;
2762 }
2763
2764 /*
2765   disable monitoring on a  node
2766  */
2767 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2768 {
2769         
2770         int ret;
2771
2772         ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2773         if (ret != 0) {
2774                 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2775                 return ret;
2776         }
2777         printf("Monitoring mode:%s\n","DISABLED");
2778
2779         return 0;
2780 }
2781
2782 /*
2783   enable monitoring on a  node
2784  */
2785 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2786 {
2787         
2788         int ret;
2789
2790         ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2791         if (ret != 0) {
2792                 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2793                 return ret;
2794         }
2795         printf("Monitoring mode:%s\n","ACTIVE");
2796
2797         return 0;
2798 }
2799
2800 /*
2801   display remote list of keys/data for a db
2802  */
2803 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2804 {
2805         const char *db_name;
2806         struct ctdb_db_context *ctdb_db;
2807         int ret;
2808
2809         if (argc < 1) {
2810                 usage();
2811         }
2812
2813         db_name = argv[0];
2814
2815
2816         if (db_exists(ctdb, db_name)) {
2817                 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2818                 return -1;
2819         }
2820
2821         ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2822
2823         if (ctdb_db == NULL) {
2824                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2825                 return -1;
2826         }
2827
2828         /* traverse and dump the cluster tdb */
2829         ret = ctdb_dump_db(ctdb_db, stdout);
2830         if (ret == -1) {
2831                 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2832                 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2833                                   " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2834                                   db_name));
2835                 return -1;
2836         }
2837         talloc_free(ctdb_db);
2838
2839         printf("Dumped %d records\n", ret);
2840         return 0;
2841 }
2842
2843
2844 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid, 
2845                              TDB_DATA data, void *private_data)
2846 {
2847         DEBUG(DEBUG_ERR,("Log data received\n"));
2848         if (data.dsize > 0) {
2849                 printf("%s", data.dptr);
2850         }
2851
2852         exit(0);
2853 }
2854
2855 /*
2856   display a list of log messages from the in memory ringbuffer
2857  */
2858 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2859 {
2860         int ret;
2861         int32_t res;
2862         struct ctdb_get_log_addr log_addr;
2863         TDB_DATA data;
2864         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2865         char *errmsg;
2866         struct timeval tv;
2867
2868         if (argc != 1) {
2869                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2870                 talloc_free(tmp_ctx);
2871                 return -1;
2872         }
2873
2874         log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2875         log_addr.srvid = getpid();
2876         if (isalpha(argv[0][0]) || argv[0][0] == '-') { 
2877                 log_addr.level = get_debug_by_desc(argv[0]);
2878         } else {
2879                 log_addr.level = strtol(argv[0], NULL, 0);
2880         }
2881
2882
2883         data.dptr = (unsigned char *)&log_addr;
2884         data.dsize = sizeof(log_addr);
2885
2886         DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2887
2888         ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2889         sleep(1);
2890
2891         DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2892
2893         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2894                            0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2895         if (ret != 0 || res != 0) {
2896                 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2897                 talloc_free(tmp_ctx);
2898                 return -1;
2899         }
2900
2901
2902         tv = timeval_current();
2903         /* this loop will terminate when we have received the reply */
2904         while (timeval_elapsed(&tv) < 3.0) {    
2905                 event_loop_once(ctdb->ev);
2906         }
2907
2908         DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2909
2910         talloc_free(tmp_ctx);
2911         return 0;
2912 }
2913
2914 /*
2915   clear the in memory log area
2916  */
2917 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2918 {
2919         int ret;
2920         int32_t res;
2921         char *errmsg;
2922         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2923
2924         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2925                            0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2926         if (ret != 0 || res != 0) {
2927                 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2928                 talloc_free(tmp_ctx);
2929                 return -1;
2930         }
2931
2932         talloc_free(tmp_ctx);
2933         return 0;
2934 }
2935
2936
2937
2938 /*
2939   display a list of the databases on a remote ctdb
2940  */
2941 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2942 {
2943         int i, ret;
2944         struct ctdb_dbid_map *dbmap=NULL;
2945
2946         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2947         if (ret != 0) {
2948                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2949                 return ret;
2950         }
2951
2952         if(options.machinereadable){
2953                 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2954                 for(i=0;i<dbmap->num;i++){
2955                         const char *path;
2956                         const char *name;
2957                         const char *health;
2958                         bool persistent;
2959
2960                         ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2961                                             dbmap->dbs[i].dbid, ctdb, &path);
2962                         ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2963                                             dbmap->dbs[i].dbid, ctdb, &name);
2964                         ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2965                                               dbmap->dbs[i].dbid, ctdb, &health);
2966                         persistent = dbmap->dbs[i].persistent;
2967                         printf(":0x%08X:%s:%s:%d:%d:\n",
2968                                dbmap->dbs[i].dbid, name, path,
2969                                !!(persistent), !!(health));
2970                 }
2971                 return 0;
2972         }
2973
2974         printf("Number of databases:%d\n", dbmap->num);
2975         for(i=0;i<dbmap->num;i++){
2976                 const char *path;
2977                 const char *name;
2978                 const char *health;
2979                 bool persistent;
2980
2981                 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2982                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2983                 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2984                 persistent = dbmap->dbs[i].persistent;
2985                 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2986                        dbmap->dbs[i].dbid, name, path,
2987                        persistent?" PERSISTENT":"",
2988                        health?" UNHEALTHY":"");
2989         }
2990
2991         return 0;
2992 }
2993
2994 /*
2995   display the status of a database on a remote ctdb
2996  */
2997 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2998 {
2999         int i, ret;
3000         struct ctdb_dbid_map *dbmap=NULL;
3001         const char *db_name;
3002
3003         if (argc < 1) {
3004                 usage();
3005         }
3006
3007         db_name = argv[0];
3008
3009         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3010         if (ret != 0) {
3011                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3012                 return ret;
3013         }
3014
3015         for(i=0;i<dbmap->num;i++){
3016                 const char *path;
3017                 const char *name;
3018                 const char *health;
3019                 bool persistent;
3020
3021                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3022                 if (strcmp(name, db_name) != 0) {
3023                         continue;
3024                 }
3025
3026                 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3027                 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3028                 persistent = dbmap->dbs[i].persistent;
3029                 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
3030                        dbmap->dbs[i].dbid, name, path,
3031                        persistent?"yes":"no",
3032                        health?health:"OK");
3033                 return 0;
3034         }
3035
3036         DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
3037         return 0;
3038 }
3039
3040 /*
3041   check if the local node is recmaster or not
3042   it will return 1 if this node is the recmaster and 0 if it is not
3043   or if the local ctdb daemon could not be contacted
3044  */
3045 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
3046 {
3047         uint32_t mypnn, recmaster;
3048         int ret;
3049
3050         mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3051         if (mypnn == -1) {
3052                 printf("Failed to get pnn of node\n");
3053                 return 1;
3054         }
3055
3056         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
3057         if (ret != 0) {
3058                 printf("Failed to get the recmaster\n");
3059                 return 1;
3060         }
3061
3062         if (recmaster != mypnn) {
3063                 printf("this node is not the recmaster\n");
3064                 return 1;
3065         }
3066
3067         printf("this node is the recmaster\n");
3068         return 0;
3069 }
3070
3071 /*
3072   ping a node
3073  */
3074 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
3075 {
3076         int ret;
3077         struct timeval tv = timeval_current();
3078         ret = ctdb_ctrl_ping(ctdb, options.pnn);
3079         if (ret == -1) {
3080                 printf("Unable to get ping response from node %u\n", options.pnn);
3081                 return -1;
3082         } else {
3083                 printf("response from %u time=%.6f sec  (%d clients)\n", 
3084                        options.pnn, timeval_elapsed(&tv), ret);
3085         }
3086         return 0;
3087 }
3088
3089
3090 /*
3091   get a tunable
3092  */
3093 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
3094 {
3095         const char *name;
3096         uint32_t value;
3097         int ret;
3098
3099         if (argc < 1) {
3100                 usage();
3101         }
3102
3103         name = argv[0];
3104         ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
3105         if (ret == -1) {
3106                 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
3107                 return -1;
3108         }
3109
3110         printf("%-19s = %u\n", name, value);
3111         return 0;
3112 }
3113
3114 /*
3115   set a tunable
3116  */
3117 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3118 {
3119         const char *name;
3120         uint32_t value;
3121         int ret;
3122
3123         if (argc < 2) {
3124                 usage();
3125         }
3126
3127         name = argv[0];
3128         value = strtoul(argv[1], NULL, 0);
3129
3130         ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3131         if (ret == -1) {
3132                 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3133                 return -1;
3134         }
3135         return 0;
3136 }
3137
3138 /*
3139   list all tunables
3140  */
3141 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3142 {
3143         uint32_t count;
3144         const char **list;
3145         int ret, i;
3146
3147         ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3148         if (ret == -1) {
3149                 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3150                 return -1;
3151         }
3152
3153         for (i=0;i<count;i++) {
3154                 control_getvar(ctdb, 1, &list[i]);
3155         }
3156
3157         talloc_free(list);
3158         
3159         return 0;
3160 }
3161
3162 /*
3163   display debug level on a node
3164  */
3165 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3166 {
3167         int ret;
3168         int32_t level;
3169
3170         ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3171         if (ret != 0) {
3172                 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3173                 return ret;
3174         } else {
3175                 if (options.machinereadable){
3176                         printf(":Name:Level:\n");
3177                         printf(":%s:%d:\n",get_debug_by_level(level),level);
3178                 } else {
3179                         printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3180                 }
3181         }
3182         return 0;
3183 }
3184
3185 /*
3186   display reclock file of a node
3187  */
3188 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3189 {
3190         int ret;
3191         const char *reclock;
3192
3193         ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3194         if (ret != 0) {
3195                 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3196                 return ret;
3197         } else {
3198                 if (options.machinereadable){
3199                         if (reclock != NULL) {
3200                                 printf("%s", reclock);
3201                         }
3202                 } else {
3203                         if (reclock == NULL) {
3204                                 printf("No reclock file used.\n");
3205                         } else {
3206                                 printf("Reclock file:%s\n", reclock);
3207                         }
3208                 }
3209         }
3210         return 0;
3211 }
3212
3213 /*
3214   set the reclock file of a node
3215  */
3216 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3217 {
3218         int ret;
3219         const char *reclock;
3220
3221         if (argc == 0) {
3222                 reclock = NULL;
3223         } else if (argc == 1) {
3224                 reclock = argv[0];
3225         } else {
3226                 usage();
3227         }
3228
3229         ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3230         if (ret != 0) {
3231                 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3232                 return ret;
3233         }
3234         return 0;
3235 }
3236
3237 /*
3238   set the natgw state on/off
3239  */
3240 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3241 {
3242         int ret;
3243         uint32_t natgwstate;
3244
3245         if (argc == 0) {
3246                 usage();
3247         }
3248
3249         if (!strcmp(argv[0], "on")) {
3250                 natgwstate = 1;
3251         } else if (!strcmp(argv[0], "off")) {
3252                 natgwstate = 0;
3253         } else {
3254                 usage();
3255         }
3256
3257         ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3258         if (ret != 0) {
3259                 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3260                 return ret;
3261         }
3262
3263         return 0;
3264 }
3265
3266 /*
3267   set the lmaster role on/off
3268  */
3269 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3270 {
3271         int ret;
3272         uint32_t lmasterrole;
3273
3274         if (argc == 0) {
3275                 usage();
3276         }
3277
3278         if (!strcmp(argv[0], "on")) {
3279                 lmasterrole = 1;
3280         } else if (!strcmp(argv[0], "off")) {
3281                 lmasterrole = 0;
3282         } else {
3283                 usage();
3284         }
3285
3286         ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3287         if (ret != 0) {
3288                 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3289                 return ret;
3290         }
3291
3292         return 0;
3293 }
3294
3295 /*
3296   set the recmaster role on/off
3297  */
3298 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3299 {
3300         int ret;
3301         uint32_t recmasterrole;
3302
3303         if (argc == 0) {
3304                 usage();
3305         }
3306
3307         if (!strcmp(argv[0], "on")) {
3308                 recmasterrole = 1;
3309         } else if (!strcmp(argv[0], "off")) {
3310                 recmasterrole = 0;
3311         } else {
3312                 usage();
3313         }
3314
3315         ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3316         if (ret != 0) {
3317                 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3318                 return ret;
3319         }
3320
3321         return 0;
3322 }
3323
3324 /*
3325   set debug level on a node or all nodes
3326  */
3327 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3328 {
3329         int i, ret;
3330         int32_t level;
3331
3332         if (argc == 0) {
3333                 printf("You must specify the debug level. Valid levels are:\n");
3334                 for (i=0; debug_levels[i].description != NULL; i++) {
3335                         printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3336                 }
3337
3338                 return 0;
3339         }
3340
3341         if (isalpha(argv[0][0]) || argv[0][0] == '-') { 
3342                 level = get_debug_by_desc(argv[0]);
3343         } else {
3344                 level = strtol(argv[0], NULL, 0);
3345         }
3346
3347         for (i=0; debug_levels[i].description != NULL; i++) {
3348                 if (level == debug_levels[i].level) {
3349                         break;
3350                 }
3351         }
3352         if (debug_levels[i].description == NULL) {
3353                 printf("Invalid debug level, must be one of\n");
3354                 for (i=0; debug_levels[i].description != NULL; i++) {
3355                         printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3356                 }
3357                 return -1;
3358         }
3359
3360         ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3361         if (ret != 0) {
3362                 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3363         }
3364         return 0;
3365 }
3366
3367
3368 /*
3369   thaw a node
3370  */
3371 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3372 {
3373         int ret;
3374         uint32_t priority;
3375         
3376         if (argc == 1) {
3377                 priority = strtol(argv[0], NULL, 0);
3378         } else {
3379                 priority = 0;
3380         }
3381         DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3382
3383         ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3384         if (ret != 0) {
3385                 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3386         }               
3387         return 0;
3388 }
3389
3390
3391 /*
3392   attach to a database
3393  */
3394 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3395 {
3396         const char *db_name;
3397         struct ctdb_db_context *ctdb_db;
3398
3399         if (argc < 1) {
3400                 usage();
3401         }
3402         db_name = argv[0];
3403
3404         ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3405         if (ctdb_db == NULL) {
3406                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3407                 return -1;
3408         }
3409
3410         return 0;
3411 }
3412
3413 /*
3414   set db priority
3415  */
3416 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3417 {
3418         struct ctdb_db_priority db_prio;
3419         int ret;
3420
3421         if (argc < 2) {
3422                 usage();
3423         }
3424
3425         db_prio.db_id    = strtoul(argv[0], NULL, 0);
3426         db_prio.priority = strtoul(argv[1], NULL, 0);
3427
3428         ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3429         if (ret != 0) {
3430                 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3431                 return -1;
3432         }
3433
3434         return 0;
3435 }
3436
3437 /*
3438   get db priority
3439  */
3440 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3441 {
3442         uint32_t db_id, priority;
3443         int ret;
3444
3445         if (argc < 1) {
3446                 usage();
3447         }
3448
3449         db_id = strtoul(argv[0], NULL, 0);
3450
3451         ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3452         if (ret != 0) {
3453                 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3454                 return -1;
3455         }
3456
3457         DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3458
3459         return 0;
3460 }
3461
3462 /*
3463   run an eventscript on a node
3464  */
3465 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3466 {
3467         TDB_DATA data;
3468         int ret;
3469         int32_t res;
3470         char *errmsg;
3471         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3472
3473         if (argc != 1) {
3474                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3475                 return -1;
3476         }
3477
3478         data.dptr = (unsigned char *)discard_const(argv[0]);
3479         data.dsize = strlen((char *)data.dptr) + 1;
3480
3481         DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3482
3483         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3484                            0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3485         if (ret != 0 || res != 0) {
3486                 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3487                 talloc_free(tmp_ctx);
3488                 return -1;
3489         }
3490         talloc_free(tmp_ctx);
3491         return 0;
3492 }
3493
3494 #define DB_VERSION 1
3495 #define MAX_DB_NAME 64
3496 struct db_file_header {
3497         unsigned long version;
3498         time_t timestamp;
3499         unsigned long persistent;
3500         unsigned long size;
3501         const char name[MAX_DB_NAME];
3502 };
3503
3504 struct backup_data {
3505         struct ctdb_marshall_buffer *records;
3506         uint32_t len;
3507         uint32_t total;
3508         bool traverse_error;
3509 };
3510
3511 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3512 {
3513         struct backup_data *bd = talloc_get_type(private, struct backup_data);
3514         struct ctdb_rec_data *rec;
3515
3516         /* add the record */
3517         rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3518         if (rec == NULL) {
3519                 bd->traverse_error = true;
3520                 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3521                 return -1;
3522         }
3523         bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3524         if (bd->records == NULL) {
3525                 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3526                 bd->traverse_error = true;
3527                 return -1;
3528         }
3529         bd->records->count++;
3530         memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3531         bd->len += rec->length;
3532         talloc_free(rec);
3533
3534         bd->total++;
3535         return 0;
3536 }
3537
3538 /*
3539  * backup a database to a file 
3540  */
3541 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3542 {
3543         int i, ret;
3544         struct ctdb_dbid_map *dbmap=NULL;
3545         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3546         struct db_file_header dbhdr;
3547         struct ctdb_db_context *ctdb_db;
3548         struct backup_data *bd;
3549         int fh = -1;
3550         int status = -1;
3551         const char *reason = NULL;
3552
3553         if (argc != 2) {
3554                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3555                 return -1;
3556         }
3557
3558         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3559         if (ret != 0) {
3560                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3561                 return ret;
3562         }
3563
3564         for(i=0;i<dbmap->num;i++){
3565                 const char *name;
3566
3567                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3568                 if(!strcmp(argv[0], name)){
3569                         talloc_free(discard_const(name));
3570                         break;
3571                 }
3572                 talloc_free(discard_const(name));
3573         }
3574         if (i == dbmap->num) {
3575                 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3576                 talloc_free(tmp_ctx);
3577                 return -1;
3578         }
3579
3580         ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3581                                     dbmap->dbs[i].dbid, tmp_ctx, &reason);
3582         if (ret != 0) {
3583                 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3584                                  argv[0]));
3585                 talloc_free(tmp_ctx);
3586                 return -1;
3587         }
3588         if (reason) {
3589                 uint32_t allow_unhealthy = 0;
3590
3591                 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3592                                       "AllowUnhealthyDBRead",
3593                                       &allow_unhealthy);
3594
3595                 if (allow_unhealthy != 1) {
3596                         DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3597                                          argv[0], reason));
3598
3599                         DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3600                                          allow_unhealthy));
3601                         talloc_free(tmp_ctx);
3602                         return -1;
3603                 }
3604
3605                 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3606                                      argv[0], argv[0]));
3607                 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3608                                      "tunnable AllowUnhealthyDBRead = %u\n",
3609                                      allow_unhealthy));
3610         }
3611
3612         ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3613         if (ctdb_db == NULL) {
3614                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3615                 talloc_free(tmp_ctx);
3616                 return -1;
3617         }
3618
3619
3620         ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3621         if (ret == -1) {
3622                 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3623                 talloc_free(tmp_ctx);
3624                 return -1;
3625         }
3626
3627
3628         bd = talloc_zero(tmp_ctx, struct backup_data);
3629         if (bd == NULL) {
3630                 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3631                 talloc_free(tmp_ctx);
3632                 return -1;
3633         }
3634
3635         bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3636         if (bd->records == NULL) {
3637                 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3638                 talloc_free(tmp_ctx);
3639                 return -1;
3640         }
3641
3642         bd->len = offsetof(struct ctdb_marshall_buffer, data);
3643         bd->records->db_id = ctdb_db->db_id;
3644         /* traverse the database collecting all records */
3645         if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3646             bd->traverse_error) {
3647                 DEBUG(DEBUG_ERR,("Traverse error\n"));
3648                 talloc_free(tmp_ctx);
3649                 return -1;              
3650         }
3651
3652         tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3653
3654
3655         fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3656         if (fh == -1) {
3657                 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3658                 talloc_free(tmp_ctx);
3659                 return -1;
3660         }
3661
3662         dbhdr.version = DB_VERSION;
3663         dbhdr.timestamp = time(NULL);
3664         dbhdr.persistent = dbmap->dbs[i].persistent;
3665         dbhdr.size = bd->len;
3666         if (strlen(argv[0]) >= MAX_DB_NAME) {
3667                 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3668                 goto done;
3669         }
3670         strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3671         ret = write(fh, &dbhdr, sizeof(dbhdr));
3672         if (ret == -1) {
3673                 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3674                 goto done;
3675         }
3676         ret = write(fh, bd->records, bd->len);
3677         if (ret == -1) {
3678                 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3679                 goto done;
3680         }
3681
3682         status = 0;
3683 done:
3684         if (fh != -1) {
3685                 ret = close(fh);
3686                 if (ret == -1) {
3687                         DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3688                 }
3689         }
3690         talloc_free(tmp_ctx);
3691         return status;
3692 }
3693
3694 /*
3695  * restore a database from a file 
3696  */
3697 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3698 {
3699         int ret;
3700         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3701         TDB_DATA outdata;
3702         TDB_DATA data;
3703         struct db_file_header dbhdr;
3704         struct ctdb_db_context *ctdb_db;
3705         struct ctdb_node_map *nodemap=NULL;
3706         struct ctdb_vnn_map *vnnmap=NULL;
3707         int i, fh;
3708         struct ctdb_control_wipe_database w;
3709         uint32_t *nodes;
3710         uint32_t generation;
3711         struct tm *tm;
3712         char tbuf[100];
3713         char *dbname;
3714
3715         if (argc < 1 || argc > 2) {
3716                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3717                 return -1;
3718         }
3719
3720         fh = open(argv[0], O_RDONLY);
3721         if (fh == -1) {
3722                 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3723                 talloc_free(tmp_ctx);
3724                 return -1;
3725         }
3726
3727         read(fh, &dbhdr, sizeof(dbhdr));
3728         if (dbhdr.version != DB_VERSION) {
3729                 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3730                 talloc_free(tmp_ctx);
3731                 return -1;
3732         }
3733
3734         dbname = dbhdr.name;
3735         if (argc == 2) {
3736                 dbname = argv[1];
3737         }
3738
3739         outdata.dsize = dbhdr.size;
3740         outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3741         if (outdata.dptr == NULL) {
3742                 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3743                 close(fh);
3744                 talloc_free(tmp_ctx);
3745                 return -1;
3746         }               
3747         read(fh, outdata.dptr, outdata.dsize);
3748         close(fh);
3749
3750         tm = localtime(&dbhdr.timestamp);
3751         strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3752         printf("Restoring database '%s' from backup @ %s\n",
3753                 dbname, tbuf);
3754
3755
3756         ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3757         if (ctdb_db == NULL) {
3758                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3759                 talloc_free(tmp_ctx);
3760                 return -1;
3761         }
3762
3763         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3764         if (ret != 0) {
3765                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3766                 talloc_free(tmp_ctx);
3767                 return ret;
3768         }
3769
3770
3771         ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3772         if (ret != 0) {
3773                 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3774                 talloc_free(tmp_ctx);
3775                 return ret;
3776         }
3777
3778         /* freeze all nodes */
3779         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3780         for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3781                 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3782                                         nodes, i,
3783                                         TIMELIMIT(),
3784                                         false, tdb_null,
3785                                         NULL, NULL,
3786                                         NULL) != 0) {
3787                         DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3788                         ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3789                         talloc_free(tmp_ctx);
3790                         return -1;
3791                 }
3792         }
3793
3794         generation = vnnmap->generation;
3795         data.dptr = (void *)&generation;
3796         data.dsize = sizeof(generation);
3797
3798         /* start a cluster wide transaction */
3799         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3800         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3801                                         nodes, 0,
3802                                         TIMELIMIT(), false, data,
3803                                         NULL, NULL,
3804                                         NULL) != 0) {
3805                 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3806                 return -1;
3807         }
3808
3809
3810         w.db_id = ctdb_db->db_id;
3811         w.transaction_id = generation;
3812
3813         data.dptr = (void *)&w;
3814         data.dsize = sizeof(w);
3815
3816         /* wipe all the remote databases. */
3817         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3818         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3819                                         nodes, 0,
3820                                         TIMELIMIT(), false, data,
3821                                         NULL, NULL,
3822                                         NULL) != 0) {
3823                 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3824                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3825                 talloc_free(tmp_ctx);
3826                 return -1;
3827         }
3828         
3829         /* push the database */
3830         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3831         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3832                                         nodes, 0,
3833                                         TIMELIMIT(), false, outdata,
3834                                         NULL, NULL,
3835                                         NULL) != 0) {
3836                 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3837                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3838                 talloc_free(tmp_ctx);
3839                 return -1;
3840         }
3841
3842         data.dptr = (void *)&ctdb_db->db_id;
3843         data.dsize = sizeof(ctdb_db->db_id);
3844
3845         /* mark the database as healthy */
3846         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3847         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3848                                         nodes, 0,
3849                                         TIMELIMIT(), false, data,
3850                                         NULL, NULL,
3851                                         NULL) != 0) {
3852                 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3853                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3854                 talloc_free(tmp_ctx);
3855                 return -1;
3856         }
3857
3858         data.dptr = (void *)&generation;
3859         data.dsize = sizeof(generation);
3860
3861         /* commit all the changes */
3862         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3863                                         nodes, 0,
3864                                         TIMELIMIT(), false, data,
3865                                         NULL, NULL,
3866                                         NULL) != 0) {
3867                 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3868                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3869                 talloc_free(tmp_ctx);
3870                 return -1;
3871         }
3872
3873
3874         /* thaw all nodes */
3875         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3876         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3877                                         nodes, 0,
3878                                         TIMELIMIT(),
3879                                         false, tdb_null,
3880                                         NULL, NULL,
3881                                         NULL) != 0) {
3882                 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3883                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3884                 talloc_free(tmp_ctx);
3885                 return -1;
3886         }
3887
3888
3889         talloc_free(tmp_ctx);
3890         return 0;
3891 }
3892
3893 /*
3894  * dump a database backup from a file
3895  */
3896 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3897 {
3898         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3899         TDB_DATA outdata;
3900         struct db_file_header dbhdr;
3901         int i, fh;
3902         struct tm *tm;
3903         char tbuf[100];
3904         struct ctdb_rec_data *rec = NULL;
3905         struct ctdb_marshall_buffer *m;
3906
3907         if (argc != 1) {
3908                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3909                 return -1;
3910         }
3911
3912         fh = open(argv[0], O_RDONLY);
3913         if (fh == -1) {
3914                 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3915                 talloc_free(tmp_ctx);
3916                 return -1;
3917         }
3918
3919         read(fh, &dbhdr, sizeof(dbhdr));
3920         if (dbhdr.version != DB_VERSION) {
3921                 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3922                 talloc_free(tmp_ctx);
3923                 return -1;
3924         }
3925
3926         outdata.dsize = dbhdr.size;
3927         outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3928         if (outdata.dptr == NULL) {
3929                 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3930                 close(fh);
3931                 talloc_free(tmp_ctx);
3932                 return -1;
3933         }
3934         read(fh, outdata.dptr, outdata.dsize);
3935         close(fh);
3936         m = (struct ctdb_marshall_buffer *)outdata.dptr;
3937
3938         tm = localtime(&dbhdr.timestamp);
3939         strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3940         printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3941                 dbhdr.name, m->db_id, tbuf);
3942
3943         for (i=0; i < m->count; i++) {
3944                 uint32_t reqid = 0;
3945                 TDB_DATA key, data;
3946
3947                 /* we do not want the header splitted, so we pass NULL*/
3948                 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3949                                               NULL, &key, &data);
3950
3951                 ctdb_dumpdb_record(ctdb, key, data, stdout);
3952         }
3953
3954         printf("Dumped %d records\n", i);
3955         talloc_free(tmp_ctx);
3956         return 0;
3957 }
3958
3959 /*
3960  * wipe a database from a file
3961  */
3962 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3963                           const char **argv)
3964 {
3965         int ret;
3966         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3967         TDB_DATA data;
3968         struct ctdb_db_context *ctdb_db;
3969         struct ctdb_node_map *nodemap = NULL;
3970         struct ctdb_vnn_map *vnnmap = NULL;
3971         int i;
3972         struct ctdb_control_wipe_database w;
3973         uint32_t *nodes;
3974         uint32_t generation;
3975         struct ctdb_dbid_map *dbmap = NULL;
3976
3977         if (argc != 1) {
3978                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3979                 return -1;
3980         }
3981
3982         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3983                                  &dbmap);
3984         if (ret != 0) {
3985                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3986                                   options.pnn));
3987                 return ret;
3988         }
3989
3990         for(i=0;i<dbmap->num;i++){
3991                 const char *name;
3992
3993                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3994                                     dbmap->dbs[i].dbid, tmp_ctx, &name);
3995                 if(!strcmp(argv[0], name)){
3996                         talloc_free(discard_const(name));
3997                         break;
3998                 }
3999                 talloc_free(discard_const(name));
4000         }
4001         if (i == dbmap->num) {
4002                 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
4003                                   argv[0]));
4004                 talloc_free(tmp_ctx);
4005                 return -1;
4006         }
4007
4008         ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
4009         if (ctdb_db == NULL) {
4010                 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
4011                                   argv[0]));
4012                 talloc_free(tmp_ctx);
4013                 return -1;
4014         }
4015
4016         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
4017                                    &nodemap);
4018         if (ret != 0) {
4019                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
4020                                   options.pnn));
4021                 talloc_free(tmp_ctx);
4022                 return ret;
4023         }
4024
4025         ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4026                                   &vnnmap);
4027         if (ret != 0) {
4028                 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
4029                                   options.pnn));
4030                 talloc_free(tmp_ctx);
4031                 return ret;
4032         }
4033
4034         /* freeze all nodes */
4035         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4036         for (i=1; i<=NUM_DB_PRIORITIES; i++) {
4037                 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
4038                                                 nodes, i,
4039                                                 TIMELIMIT(),
4040                                                 false, tdb_null,
4041                                                 NULL, NULL,
4042                                                 NULL);
4043                 if (ret != 0) {
4044                         DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
4045                         ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
4046                                              CTDB_RECOVERY_ACTIVE);
4047                         talloc_free(tmp_ctx);
4048                         return -1;
4049                 }
4050         }
4051
4052         generation = vnnmap->generation;
4053         data.dptr = (void *)&generation;
4054         data.dsize = sizeof(generation);
4055
4056         /* start a cluster wide transaction */
4057         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4058         ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
4059                                         nodes, 0,
4060                                         TIMELIMIT(), false, data,
4061                                         NULL, NULL,
4062                                         NULL);
4063         if (ret!= 0) {
4064                 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
4065                                   "transactions.\n"));
4066                 return -1;
4067         }
4068
4069         w.db_id = ctdb_db->db_id;
4070         w.transaction_id = generation;
4071
4072         data.dptr = (void *)&w;
4073         data.dsize = sizeof(w);
4074
4075         /* wipe all the remote databases. */
4076         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4077         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
4078                                         nodes, 0,
4079                                         TIMELIMIT(), false, data,
4080                                         NULL, NULL,
4081                                         NULL) != 0) {
4082                 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
4083                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4084                 talloc_free(tmp_ctx);
4085                 return -1;
4086         }
4087
4088         data.dptr = (void *)&ctdb_db->db_id;
4089         data.dsize = sizeof(ctdb_db->db_id);
4090
4091         /* mark the database as healthy */
4092         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4093         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4094                                         nodes, 0,
4095                                         TIMELIMIT(), false, data,
4096                                         NULL, NULL,
4097                                         NULL) != 0) {
4098                 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4099                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4100                 talloc_free(tmp_ctx);
4101                 return -1;
4102         }
4103
4104         data.dptr = (void *)&generation;
4105         data.dsize = sizeof(generation);
4106
4107         /* commit all the changes */
4108         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4109                                         nodes, 0,
4110                                         TIMELIMIT(), false, data,
4111                                         NULL, NULL,
4112                                         NULL) != 0) {
4113                 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4114                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4115                 talloc_free(tmp_ctx);
4116                 return -1;
4117         }
4118
4119         /* thaw all nodes */
4120         nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4121         if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4122                                         nodes, 0,
4123                                         TIMELIMIT(),
4124                                         false, tdb_null,
4125                                         NULL, NULL,
4126                                         NULL) != 0) {
4127                 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4128                 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4129                 talloc_free(tmp_ctx);
4130                 return -1;
4131         }
4132
4133         talloc_free(tmp_ctx);
4134         return 0;
4135 }
4136
4137 /*
4138  * set flags of a node in the nodemap
4139  */
4140 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4141 {
4142         int ret;
4143         int32_t status;
4144         int node;
4145         int flags;
4146         TDB_DATA data;
4147         struct ctdb_node_flag_change c;
4148
4149         if (argc != 2) {
4150                 usage();
4151                 return -1;
4152         }
4153
4154         if (sscanf(argv[0], "%d", &node) != 1) {
4155                 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4156                 usage();
4157                 return -1;
4158         }
4159         if (sscanf(argv[1], "0x%x", &flags) != 1) {
4160                 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4161                 usage();
4162                 return -1;
4163         }
4164
4165         c.pnn       = node;
4166         c.old_flags = 0;
4167         c.new_flags = flags;
4168
4169         data.dsize = sizeof(c);
4170         data.dptr = (unsigned char *)&c;
4171
4172         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0, 
4173                            data, NULL, NULL, &status, NULL, NULL);
4174         if (ret != 0 || status != 0) {
4175                 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4176                 return -1;
4177         }
4178         return 0;
4179 }
4180
4181 /*
4182   dump memory usage
4183  */
4184 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4185 {
4186         TDB_DATA data;
4187         int ret;
4188         int32_t res;
4189         char *errmsg;
4190         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4191         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4192                            0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4193         if (ret != 0 || res != 0) {
4194                 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4195                 talloc_free(tmp_ctx);
4196                 return -1;
4197         }
4198         write(1, data.dptr, data.dsize);
4199         talloc_free(tmp_ctx);
4200         return 0;
4201 }
4202
4203 /*
4204   handler for memory dumps
4205 */
4206 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid, 
4207                              TDB_DATA data, void *private_data)
4208 {
4209         write(1, data.dptr, data.dsize);
4210         exit(0);
4211 }
4212
4213 /*
4214   dump memory usage on the recovery daemon
4215  */
4216 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4217 {
4218         int ret;
4219         TDB_DATA data;
4220         struct rd_memdump_reply rd;
4221
4222         rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4223         if (rd.pnn == -1) {
4224                 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4225                 return -1;
4226         }
4227         rd.srvid = getpid();
4228
4229         /* register a message port for receiveing the reply so that we
4230            can receive the reply
4231         */
4232         ctdb_client_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4233
4234
4235         data.dptr = (uint8_t *)&rd;
4236         data.dsize = sizeof(rd);
4237
4238         ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4239         if (ret != 0) {
4240                 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4241                 return -1;
4242         }
4243
4244         /* this loop will terminate when we have received the reply */
4245         while (1) {     
4246                 event_loop_once(ctdb->ev);
4247         }
4248
4249         return 0;
4250 }
4251
4252 /*
4253   send a message to a srvid
4254  */
4255 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4256 {
4257         unsigned long srvid;
4258         int ret;
4259         TDB_DATA data;
4260
4261         if (argc < 2) {
4262                 usage();
4263         }
4264
4265         srvid      = strtoul(argv[0], NULL, 0);
4266
4267         data.dptr = (uint8_t *)discard_const(argv[1]);
4268         data.dsize= strlen(argv[1]);
4269
4270         ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4271         if (ret != 0) {
4272                 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4273                 return -1;
4274         }
4275
4276         return 0;
4277 }
4278
4279 /*
4280   handler for msglisten
4281 */
4282 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid, 
4283                              TDB_DATA data, void *private_data)
4284 {
4285         int i;
4286
4287         printf("Message received: ");
4288         for (i=0;i<data.dsize;i++) {
4289                 printf("%c", data.dptr[i]);
4290         }
4291         printf("\n");
4292 }
4293
4294 /*
4295   listen for messages on a messageport
4296  */
4297 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4298 {
4299         uint64_t srvid;
4300
4301         srvid = getpid();
4302
4303         /* register a message port and listen for messages
4304         */
4305         ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4306         printf("Listening for messages on srvid:%d\n", (int)srvid);
4307
4308         while (1) {     
4309                 event_loop_once(ctdb->ev);
4310         }
4311
4312         return 0;
4313 }
4314
4315 /*
4316   list all nodes in the cluster
4317   if the daemon is running, we read the data from the daemon.
4318   if the daemon is not running we parse the nodes file directly
4319  */
4320 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4321 {
4322         int i, ret;
4323         struct ctdb_node_map *nodemap=NULL;
4324
4325         if (ctdb != NULL) {
4326                 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4327                 if (ret != 0) {
4328                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4329                         return ret;
4330                 }
4331
4332                 for(i=0;i<nodemap->num;i++){
4333                         if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4334                                 continue;
4335                         }
4336                         if (options.machinereadable){
4337                                 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4338                         } else {
4339                                 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4340                         }
4341                 }
4342         } else {
4343                 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4344                 struct pnn_node *pnn_nodes;
4345                 struct pnn_node *pnn_node;
4346         
4347                 pnn_nodes = read_nodes_file(mem_ctx);
4348                 if (pnn_nodes == NULL) {
4349                         DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4350                         talloc_free(mem_ctx);
4351                         return -1;
4352                 }
4353
4354                 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4355                         ctdb_sock_addr addr;
4356
4357                         if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4358                                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4359                                 talloc_free(mem_ctx);
4360                                 return -1;
4361                         }
4362
4363                         if (options.machinereadable){
4364                                 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4365                         } else {
4366                                 printf("%s\n", pnn_node->addr);
4367                         }
4368                 }
4369                 talloc_free(mem_ctx);
4370         }
4371
4372         return 0;
4373 }
4374
4375 /*
4376   reload the nodes file on the local node
4377  */
4378 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4379 {
4380         int i, ret;
4381         int mypnn;
4382         struct ctdb_node_map *nodemap=NULL;
4383
4384         mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4385         if (mypnn == -1) {
4386                 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4387                 return -1;
4388         }
4389
4390         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4391         if (ret != 0) {
4392                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4393                 return ret;
4394         }
4395
4396         /* reload the nodes file on all remote nodes */
4397         for (i=0;i<nodemap->num;i++) {
4398                 if (nodemap->nodes[i].pnn == mypnn) {
4399                         continue;
4400                 }
4401                 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4402                 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4403                         nodemap->nodes[i].pnn);
4404                 if (ret != 0) {
4405                         DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4406                 }
4407         }
4408
4409         /* reload the nodes file on the local node */
4410         DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4411         ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4412         if (ret != 0) {
4413                 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4414         }
4415
4416         /* initiate a recovery */
4417         control_recover(ctdb, argc, argv);
4418
4419         return 0;
4420 }
4421
4422
4423 static const struct {
4424         const char *name;
4425         int (*fn)(struct ctdb_context *, int, const char **);
4426         bool auto_all;
4427         bool without_daemon; /* can be run without daemon running ? */
4428         const char *msg;
4429         const char *args;
4430 } ctdb_commands[] = {
4431 #ifdef CTDB_VERS
4432         { "version",         control_version,           true,   false,  "show version of ctdb" },
4433 #endif
4434         { "status",          control_status,            true,   false,  "show node status" },
4435         { "uptime",          control_uptime,            true,   false,  "show node uptime" },
4436         { "ping",            control_ping,              true,   false,  "ping all nodes" },
4437         { "getvar",          control_getvar,            true,   false,  "get a tunable variable",               "<name>"},
4438         { "setvar",          control_setvar,            true,   false,  "set a tunable variable",               "<name> <value>"},
4439         { "listvars",        control_listvars,          true,   false,  "list tunable variables"},
4440         { "statistics",      control_statistics,        false,  false, "show statistics" },
4441         { "statisticsreset", control_statistics_reset,  true,   false,  "reset statistics"},
4442         { "ip",              control_ip,                false,  false,  "show which public ip's that ctdb manages" },
4443         { "ipinfo",          control_ipinfo,            true,   false,  "show details about a public ip that ctdb manages", "<ip>" },
4444         { "ifaces",          control_ifaces,            true,   false,  "show which interfaces that ctdb manages" },
4445         { "setifacelink",    control_setifacelink,      true,   false,  "set interface link status", "<iface> <status>" },
4446         { "process-exists",  control_process_exists,    true,   false,  "check if a process exists on a node",  "<pid>"},
4447         { "getdbmap",        control_getdbmap,          true,   false,  "show the database map" },
4448         { "getdbstatus",     control_getdbstatus,       true,   false,  "show the status of a database", "<dbname>" },
4449         { "catdb",           control_catdb,             true,   false,  "dump a database" ,                     "<dbname>"},
4450         { "getmonmode",      control_getmonmode,        true,   false,  "show monitoring mode" },
4451         { "getcapabilities", control_getcapabilities,   true,   false,  "show node capabilities" },
4452         { "pnn",             control_pnn,               true,   false,  "show the pnn of the currnet node" },
4453         { "lvs",             control_lvs,               true,   false,  "show lvs configuration" },
4454         { "lvsmaster",       control_lvsmaster,         true,   false,  "show which node is the lvs master" },
4455         { "disablemonitor",      control_disable_monmode,true,  false,  "set monitoring mode to DISABLE" },
4456         { "enablemonitor",      control_enable_monmode, true,   false,  "set monitoring mode to ACTIVE" },
4457         { "setdebug",        control_setdebug,          true,   false,  "set debug level",                      "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4458         { "getdebug",        control_getdebug,          true,   false,  "get debug level" },
4459         { "getlog",          control_getlog,            true,   false,  "get the log data from the in memory ringbuffer", "<level>" },
4460         { "clearlog",          control_clearlog,        true,   false,  "clear the log data from the in memory ringbuffer" },
4461         { "attach",          control_attach,            true,   false,  "attach to a database",                 "<dbname>" },
4462         { "dumpmemory",      control_dumpmemory,        true,   false,  "dump memory map to stdout" },
4463         { "rddumpmemory",    control_rddumpmemory,      true,   false,  "dump memory map from the recovery daemon to stdout" },
4464         { "getpid",          control_getpid,            true,   false,  "get ctdbd process ID" },
4465         { "disable",         control_disable,           true,   false,  "disable a nodes public IP" },
4466         { "enable",          control_enable,            true,   false,  "enable a nodes public IP" },
4467         { "stop",            control_stop,              true,   false,  "stop a node" },
4468         { "continue",        control_continue,          true,   false,  "re-start a stopped node" },
4469         { "ban",             control_ban,               true,   false,  "ban a node from the cluster",          "<bantime|0>"},
4470         { "unban",           control_unban,             true,   false,  "unban a node" },
4471         { "showban",         control_showban,           true,   false,  "show ban information"},
4472         { "shutdown",        control_shutdown,          true,   false,  "shutdown ctdbd" },
4473         { "recover",         control_recover,           true,   false,  "force recovery" },
4474         { "sync",            control_ipreallocate,      true,   false,  "wait until ctdbd has synced all state changes" },
4475         { "ipreallocate",    control_ipreallocate,      true,   false,  "force the recovery daemon to perform a ip reallocation procedure" },
4476         { "thaw",            control_thaw,              true,   false,  "thaw databases", "[priority:1-3]" },
4477         { "isnotrecmaster",  control_isnotrecmaster,    false,  false,  "check if the local node is recmaster or not" },
4478         { "killtcp",         kill_tcp,                  false,  false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4479         { "gratiousarp",     control_gratious_arp,      false,  false, "send a gratious arp", "<ip> <interface>" },
4480         { "tickle",          tickle_tcp,                false,  false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4481         { "gettickles",      control_get_tickles,       false,  false, "get the list of tickles registered for this ip", "<ip> [<port>]" },
4482         { "addtickle",       control_add_tickle,        false,  false, "add a tickle for this ip", "<ip>:<port> <ip>:<port>" },
4483
4484         { "deltickle",       control_del_tickle,        false,  false, "delete a tickle from this ip", "<ip>:<port> <ip>:<port>" },
4485
4486         { "regsrvid",        regsrvid,                  false,  false, "register a server id", "<pnn> <type> <id>" },
4487         { "unregsrvid",      unregsrvid,                false,  false, "unregister a server id", "<pnn> <type> <id>" },
4488         { "chksrvid",        chksrvid,                  false,  false, "check if a server id exists", "<pnn> <type> <id>" },
4489         { "getsrvids",       getsrvids,                 false,  false, "get a list of all server ids"},
4490         { "vacuum",          ctdb_vacuum,               false,  false, "vacuum the databases of empty records", "[max_records]"},
4491         { "repack",          ctdb_repack,               false,  false, "repack all databases", "[max_freelist]"},
4492         { "listnodes",       control_listnodes,         false,  true, "list all nodes in the cluster"},
4493         { "reloadnodes",     control_reload_nodes_file, false,  false, "reload the nodes file and restart the transport on all nodes"},
4494         { "moveip",          control_moveip,            false,  false, "move/failover an ip address to another node", "<ip> <node>"},
4495         { "addip",           control_addip,             true,   false, "add a ip address to a node", "<ip/mask> <iface>"},
4496         { "delip",           control_delip,             false,  false, "delete an ip address from a node", "<ip>"},
4497         { "eventscript",     control_eventscript,       true,   false, "run the eventscript with the given parameters on a node", "<arguments>"},
4498         { "backupdb",        control_backupdb,          false,  false, "backup the database into a file.", "<database> <file>"},
4499         { "restoredb",        control_restoredb,        false,  false, "restore the database from a file.", "<file> [dbname]"},
4500         { "dumpdbbackup",    control_dumpdbbackup,      false,  true,  "dump database backup from a file.", "<file>"},
4501         { "wipedb",           control_wipedb,        false,     false, "wipe the contents of a database.", "<dbname>"},
4502         { "recmaster",        control_recmaster,        false,  false, "show the pnn for the recovery master."},
4503         { "setflags",        control_setflags,          false,  false, "set flags for a node in the nodemap.", "<node> <flags>"},
4504         { "scriptstatus",    control_scriptstatus,  false,      false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4505         { "enablescript",     control_enablescript,  false,     false, "enable an eventscript", "<script>"},
4506         { "disablescript",    control_disablescript,  false,    false, "disable an eventscript", "<script>"},
4507         { "natgwlist",        control_natgwlist,        false,  false, "show the nodes belonging to this natgw configuration"},
4508         { "xpnn",             control_xpnn,             true,   true,  "find the pnn of the local node without talking to the daemon (unreliable)" },
4509         { "getreclock",       control_getreclock,       false,  false, "Show the reclock file of a node"},
4510         { "setreclock",       control_setreclock,       false,  false, "Set/clear the reclock file of a node", "[filename]"},
4511         { "setnatgwstate",    control_setnatgwstate,    false,  false, "Set NATGW state to on/off", "{on|off}"},
4512         { "setlmasterrole",   control_setlmasterrole,   false,  false, "Set LMASTER role to on/off", "{on|off}"},
4513         { "setrecmasterrole", control_setrecmasterrole, false,  false, "Set RECMASTER role to on/off", "{on|off}"},
4514         { "setdbprio",        control_setdbprio,        false,  false, "Set DB priority", "<dbid> <prio:1-3>"},
4515         { "getdbprio",        control_getdbprio,        false,  false, "Get DB priority", "<dbid>"},
4516         { "msglisten",        control_msglisten,        false,  false, "Listen on a srvid port for messages", "<msg srvid>"},
4517         { "msgsend",          control_msgsend,  false,  false, "Send a message to srvid", "<srvid> <message>"},
4518         { "sync",            control_ipreallocate,      true,   false,  "wait until ctdbd has synced all state changes" },
4519 };
4520
4521 /*
4522   show usage message
4523  */
4524 static void usage(void)
4525 {
4526         int i;
4527         printf(
4528 "Usage: ctdb [options] <control>\n" \
4529 "Options:\n" \
4530 "   -n <node>          choose node number, or 'all' (defaults to local node)\n"
4531 "   -Y                 generate machinereadable output\n"
4532 "   -t <timelimit>     set timelimit for control in seconds (default %u)\n", options.timelimit);
4533         printf("Controls:\n");
4534         for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4535                 printf("  %-15s %-27s  %s\n", 
4536                        ctdb_commands[i].name, 
4537                        ctdb_commands[i].args?ctdb_commands[i].args:"",
4538                        ctdb_commands[i].msg);
4539         }
4540         exit(1);
4541 }
4542
4543
4544 static void ctdb_alarm(int sig)
4545 {
4546         printf("Maximum runtime exceeded - exiting\n");
4547         _exit(ERR_TIMEOUT);
4548 }
4549
4550 /*
4551   main program
4552 */
4553 int main(int argc, const char *argv[])
4554 {
4555         struct ctdb_context *ctdb;
4556         char *nodestring = NULL;
4557         struct poptOption popt_options[] = {
4558                 POPT_AUTOHELP
4559                 POPT_CTDB_CMDLINE
4560                 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4561                 { "node",      'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4562                 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4563                 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4564                 POPT_TABLEEND
4565         };
4566         int opt;
4567         const char **extra_argv;
4568         int extra_argc = 0;
4569         int ret=-1, i;
4570         poptContext pc;
4571         struct event_context *ev;
4572         const char *control;
4573
4574         setlinebuf(stdout);
4575         
4576         /* set some defaults */
4577         options.maxruntime = 0;
4578         options.timelimit = 3;
4579         options.pnn = CTDB_CURRENT_NODE;
4580
4581         pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4582
4583         while ((opt = poptGetNextOpt(pc)) != -1) {
4584                 switch (opt) {
4585                 default:
4586                         DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n", 
4587                                 poptBadOption(pc, 0), poptStrerror(opt)));
4588                         exit(1);
4589                 }
4590         }
4591
4592         /* setup the remaining options for the main program to use */
4593         extra_argv = poptGetArgs(pc);
4594         if (extra_argv) {
4595                 extra_argv++;
4596                 while (extra_argv[extra_argc]) extra_argc++;
4597         }
4598
4599         if (extra_argc < 1) {
4600                 usage();
4601         }
4602
4603         if (options.maxruntime == 0) {
4604                 const char *ctdb_timeout;
4605                 ctdb_timeout = getenv("CTDB_TIMEOUT");
4606                 if (ctdb_timeout != NULL) {
4607                         options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4608                 } else {
4609                         /* default timeout is 120 seconds */
4610                         options.maxruntime = 120;
4611                 }
4612         }
4613
4614         signal(SIGALRM, ctdb_alarm);
4615         alarm(options.maxruntime);
4616
4617         /* setup the node number to contact */
4618         if (nodestring != NULL) {
4619                 if (strcmp(nodestring, "all") == 0) {
4620                         options.pnn = CTDB_BROADCAST_ALL;
4621                 } else {
4622                         options.pnn = strtoul(nodestring, NULL, 0);
4623                 }
4624         }
4625
4626         control = extra_argv[0];
4627
4628         ev = event_context_init(NULL);
4629         if (!ev) {
4630                 DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
4631                 exit(1);
4632         }
4633         tevent_loop_allow_nesting(ev);
4634
4635         for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4636                 if (strcmp(control, ctdb_commands[i].name) == 0) {
4637                         int j;
4638
4639                         if (ctdb_commands[i].without_daemon == true) {
4640                                 close(2);
4641                         }
4642
4643                         /* initialise ctdb */
4644                         ctdb = ctdb_cmdline_client(ev);
4645
4646                         if (ctdb_commands[i].without_daemon == false) {
4647                                 const char *socket_name;
4648
4649                                 if (ctdb == NULL) {
4650                                         DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4651                                         exit(1);
4652                                 }
4653
4654                                 /* initialize a libctdb connection as well */
4655                                 socket_name = ctdb_get_socketname(ctdb);
4656                                 ctdb_connection = ctdb_connect(socket_name,
4657                                                        ctdb_log_file, stderr);
4658                                 if (ctdb_connection == NULL) {
4659                                         fprintf(stderr, "Failed to connect to daemon from libctdb\n");
4660                                         exit(1);
4661                                 }                               
4662                         
4663                                 /* verify the node exists */
4664                                 verify_node(ctdb);
4665
4666                                 if (options.pnn == CTDB_CURRENT_NODE) {
4667                                         int pnn;
4668                                         pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);         
4669                                         if (pnn == -1) {
4670                                                 return -1;
4671                                         }
4672                                         options.pnn = pnn;
4673                                 }
4674                         }
4675
4676                         if (ctdb_commands[i].auto_all && 
4677                             options.pnn == CTDB_BROADCAST_ALL) {
4678                                 uint32_t *nodes;
4679                                 uint32_t num_nodes;
4680                                 ret = 0;
4681
4682                                 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4683                                 CTDB_NO_MEMORY(ctdb, nodes);
4684         
4685                                 for (j=0;j<num_nodes;j++) {
4686                                         options.pnn = nodes[j];
4687                                         ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4688                                 }
4689                                 talloc_free(nodes);
4690                         } else {
4691                                 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4692                         }
4693                         break;
4694                 }
4695         }
4696
4697         if (i == ARRAY_SIZE(ctdb_commands)) {
4698                 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));
4699                 exit(1);
4700         }
4701
4702         return ret;
4703 }