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