add a new commandline flag -v to enable verbose output
[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:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1825         } else {
1826                 if (options.pnn == CTDB_BROADCAST_ALL) {
1827                         printf("Public IPs on ALL nodes\n");
1828                 } else {
1829                         printf("Public IPs on node %u\n", options.pnn);
1830                 }
1831         }
1832
1833         for (i=1;i<=ips->num;i++) {
1834                 struct ctdb_control_public_ip_info *info = NULL;
1835                 int32_t pnn;
1836                 char *aciface = NULL;
1837                 char *avifaces = NULL;
1838                 char *cifaces = NULL;
1839
1840                 if (options.pnn == CTDB_BROADCAST_ALL) {
1841                         pnn = ips->ips[ips->num-i].pnn;
1842                 } else {
1843                         pnn = options.pnn;
1844                 }
1845
1846                 if (pnn != -1) {
1847                         ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1848                                                    &ips->ips[ips->num-i].addr, &info);
1849                 } else {
1850                         ret = -1;
1851                 }
1852
1853                 if (ret == 0) {
1854                         int j;
1855                         for (j=0; j < info->num; j++) {
1856                                 if (cifaces == NULL) {
1857                                         cifaces = talloc_strdup(info,
1858                                                                 info->ifaces[j].name);
1859                                 } else {
1860                                         cifaces = talloc_asprintf_append(cifaces,
1861                                                                          ",%s",
1862                                                                          info->ifaces[j].name);
1863                                 }
1864
1865                                 if (info->active_idx == j) {
1866                                         aciface = info->ifaces[j].name;
1867                                 }
1868
1869                                 if (info->ifaces[j].link_state == 0) {
1870                                         continue;
1871                                 }
1872
1873                                 if (avifaces == NULL) {
1874                                         avifaces = talloc_strdup(info, info->ifaces[j].name);
1875                                 } else {
1876                                         avifaces = talloc_asprintf_append(avifaces,
1877                                                                           ",%s",
1878                                                                           info->ifaces[j].name);
1879                                 }
1880                         }
1881                 }
1882
1883                 if (options.machinereadable){
1884                         printf(":%s:%d:%s:%s:%s:\n",
1885                                ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1886                                ips->ips[ips->num-i].pnn,
1887                                aciface?aciface:"",
1888                                avifaces?avifaces:"",
1889                                cifaces?cifaces:"");
1890                 } else {
1891                         printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1892                                ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1893                                ips->ips[ips->num-i].pnn,
1894                                aciface?aciface:"",
1895                                avifaces?avifaces:"",
1896                                cifaces?cifaces:"");
1897                 }
1898                 talloc_free(info);
1899         }
1900
1901         talloc_free(tmp_ctx);
1902         return 0;
1903 }
1904
1905 /*
1906   public ip info
1907  */
1908 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1909 {
1910         int i, ret;
1911         ctdb_sock_addr addr;
1912         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1913         struct ctdb_control_public_ip_info *info;
1914
1915         if (argc != 1) {
1916                 talloc_free(tmp_ctx);
1917                 usage();
1918         }
1919
1920         if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1921                 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1922                 return -1;
1923         }
1924
1925         /* read the public ip info from this node */
1926         ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1927                                            tmp_ctx, &addr, &info);
1928         if (ret != 0) {
1929                 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1930                                   argv[0], options.pnn));
1931                 talloc_free(tmp_ctx);
1932                 return ret;
1933         }
1934
1935         printf("Public IP[%s] info on node %u\n",
1936                ctdb_addr_to_str(&info->ip.addr),
1937                options.pnn);
1938
1939         printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1940                ctdb_addr_to_str(&info->ip.addr),
1941                info->ip.pnn, info->num);
1942
1943         for (i=0; i<info->num; i++) {
1944                 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1945
1946                 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1947                        i+1, info->ifaces[i].name,
1948                        info->ifaces[i].link_state?"up":"down",
1949                        (unsigned int)info->ifaces[i].references,
1950                        (i==info->active_idx)?" (active)":"");
1951         }
1952
1953         talloc_free(tmp_ctx);
1954         return 0;
1955 }
1956
1957 /*
1958   display interfaces status
1959  */
1960 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1961 {
1962         int i, ret;
1963         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1964         struct ctdb_control_get_ifaces *ifaces;
1965
1966         /* read the public ip list from this node */
1967         ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1968                                    tmp_ctx, &ifaces);
1969         if (ret != 0) {
1970                 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1971                                   options.pnn));
1972                 talloc_free(tmp_ctx);
1973                 return ret;
1974         }
1975
1976         if (options.machinereadable){
1977                 printf(":Name:LinkStatus:References:\n");
1978         } else {
1979                 printf("Interfaces on node %u\n", options.pnn);
1980         }
1981
1982         for (i=0; i<ifaces->num; i++) {
1983                 if (options.machinereadable){
1984                         printf(":%s:%s:%u\n",
1985                                ifaces->ifaces[i].name,
1986                                ifaces->ifaces[i].link_state?"1":"0",
1987                                (unsigned int)ifaces->ifaces[i].references);
1988                 } else {
1989                         printf("name:%s link:%s references:%u\n",
1990                                ifaces->ifaces[i].name,
1991                                ifaces->ifaces[i].link_state?"up":"down",
1992                                (unsigned int)ifaces->ifaces[i].references);
1993                 }
1994         }
1995
1996         talloc_free(tmp_ctx);
1997         return 0;
1998 }
1999
2000
2001 /*
2002   set link status of an interface
2003  */
2004 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
2005 {
2006         int ret;
2007         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2008         struct ctdb_control_iface_info info;
2009
2010         ZERO_STRUCT(info);
2011
2012         if (argc != 2) {
2013                 usage();
2014         }
2015
2016         if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
2017                 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
2018                                   argv[0]));
2019                 talloc_free(tmp_ctx);
2020                 return -1;
2021         }
2022         strcpy(info.name, argv[0]);
2023
2024         if (strcmp(argv[1], "up") == 0) {
2025                 info.link_state = 1;
2026         } else if (strcmp(argv[1], "down") == 0) {
2027                 info.link_state = 0;
2028         } else {
2029                 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
2030                                   argv[1]));
2031                 talloc_free(tmp_ctx);
2032                 return -1;
2033         }
2034
2035         /* read the public ip list from this node */
2036         ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
2037                                    tmp_ctx, &info);
2038         if (ret != 0) {
2039                 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
2040                                   argv[0], options.pnn));
2041                 talloc_free(tmp_ctx);
2042                 return ret;
2043         }
2044
2045         talloc_free(tmp_ctx);
2046         return 0;
2047 }
2048
2049 /*
2050   display pid of a ctdb daemon
2051  */
2052 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
2053 {
2054         uint32_t pid;
2055         int ret;
2056
2057         ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
2058         if (ret != 0) {
2059                 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
2060                 return ret;
2061         }
2062         printf("Pid:%d\n", pid);
2063
2064         return 0;
2065 }
2066
2067 static uint32_t ipreallocate_finished;
2068
2069 /*
2070   handler for receiving the response to ipreallocate
2071 */
2072 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid, 
2073                              TDB_DATA data, void *private_data)
2074 {
2075         ipreallocate_finished = 1;
2076 }
2077
2078 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
2079 {
2080         struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
2081
2082         event_add_timed(ctdb->ev, ctdb, 
2083                                 timeval_current_ofs(1, 0),
2084                                 ctdb_every_second, ctdb);
2085 }
2086
2087 /*
2088   ask the recovery daemon on the recovery master to perform a ip reallocation
2089  */
2090 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
2091 {
2092         int i, ret;
2093         TDB_DATA data;
2094         struct takeover_run_reply rd;
2095         uint32_t recmaster;
2096         struct ctdb_node_map *nodemap=NULL;
2097         int retries=0;
2098         struct timeval tv = timeval_current();
2099
2100         /* we need some events to trigger so we can timeout and restart
2101            the loop
2102         */
2103         event_add_timed(ctdb->ev, ctdb, 
2104                                 timeval_current_ofs(1, 0),
2105                                 ctdb_every_second, ctdb);
2106
2107         rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2108         if (rd.pnn == -1) {
2109                 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
2110                 return -1;
2111         }
2112         rd.srvid = getpid();
2113
2114         /* register a message port for receiveing the reply so that we
2115            can receive the reply
2116         */
2117         ctdb_client_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
2118
2119         data.dptr = (uint8_t *)&rd;
2120         data.dsize = sizeof(rd);
2121
2122 again:
2123         /* check that there are valid nodes available */
2124         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2125                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2126                 return -1;
2127         }
2128         for (i=0; i<nodemap->num;i++) {
2129                 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2130                         break;
2131                 }
2132         }
2133         if (i==nodemap->num) {
2134                 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2135                 return 0;
2136         }
2137
2138
2139         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2140         if (ret != 0) {
2141                 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2142                 return ret;
2143         }
2144
2145         /* verify the node exists */
2146         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2147                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2148                 return -1;
2149         }
2150
2151
2152         /* check tha there are nodes available that can act as a recmaster */
2153         for (i=0; i<nodemap->num; i++) {
2154                 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2155                         continue;
2156                 }
2157                 break;
2158         }
2159         if (i == nodemap->num) {
2160                 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2161                 return 0;
2162         }
2163
2164         /* verify the recovery master is not STOPPED, nor BANNED */
2165         if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2166                 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2167                 retries++;
2168                 sleep(1);
2169                 goto again;
2170         } 
2171
2172         
2173         /* verify the recovery master is not STOPPED, nor BANNED */
2174         if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2175                 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2176                 retries++;
2177                 sleep(1);
2178                 goto again;
2179         } 
2180
2181         ipreallocate_finished = 0;
2182         ret = ctdb_client_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2183         if (ret != 0) {
2184                 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2185                 return -1;
2186         }
2187
2188         tv = timeval_current();
2189         /* this loop will terminate when we have received the reply */
2190         while (timeval_elapsed(&tv) < 3.0) {
2191                 event_loop_once(ctdb->ev);
2192         }
2193         if (ipreallocate_finished == 1) {
2194                 return 0;
2195         }
2196
2197         DEBUG(DEBUG_ERR,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2198         retries++;
2199         sleep(1);
2200         goto again;
2201
2202         return 0;
2203 }
2204
2205
2206 /*
2207   disable a remote node
2208  */
2209 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2210 {
2211         int ret;
2212         struct ctdb_node_map *nodemap=NULL;
2213
2214         /* check if the node is already disabled */
2215         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2216                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2217                 exit(10);
2218         }
2219         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2220                 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2221                 return 0;
2222         }
2223
2224         do {
2225                 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2226                 if (ret != 0) {
2227                         DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2228                         return ret;
2229                 }
2230
2231                 sleep(1);
2232
2233                 /* read the nodemap and verify the change took effect */
2234                 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2235                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2236                         exit(10);
2237                 }
2238
2239         } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2240         ret = control_ipreallocate(ctdb, argc, argv);
2241         if (ret != 0) {
2242                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2243                 return ret;
2244         }
2245
2246         return 0;
2247 }
2248
2249 /*
2250   enable a disabled remote node
2251  */
2252 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2253 {
2254         int ret;
2255
2256         struct ctdb_node_map *nodemap=NULL;
2257
2258
2259         /* check if the node is already enabled */
2260         if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2261                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2262                 exit(10);
2263         }
2264         if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2265                 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2266                 return 0;
2267         }
2268
2269         do {
2270                 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2271                 if (ret != 0) {
2272                         DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2273                         return ret;
2274                 }
2275
2276                 sleep(1);
2277
2278                 /* read the nodemap and verify the change took effect */
2279                 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2280                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2281                         exit(10);
2282                 }
2283
2284         } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2285
2286         ret = control_ipreallocate(ctdb, argc, argv);
2287         if (ret != 0) {
2288                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2289                 return ret;
2290         }
2291
2292         return 0;
2293 }
2294
2295 /*
2296   stop a remote node
2297  */
2298 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2299 {
2300         int ret;
2301         struct ctdb_node_map *nodemap=NULL;
2302
2303         do {
2304                 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2305                 if (ret != 0) {
2306                         DEBUG(DEBUG_ERR, ("Unable to stop node %u   try again\n", options.pnn));
2307                 }
2308         
2309                 sleep(1);
2310
2311                 /* read the nodemap and verify the change took effect */
2312                 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2313                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2314                         exit(10);
2315                 }
2316
2317         } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2318         ret = control_ipreallocate(ctdb, argc, argv);
2319         if (ret != 0) {
2320                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2321                 return ret;
2322         }
2323
2324         return 0;
2325 }
2326
2327 /*
2328   restart a stopped remote node
2329  */
2330 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2331 {
2332         int ret;
2333
2334         struct ctdb_node_map *nodemap=NULL;
2335
2336         do {
2337                 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2338                 if (ret != 0) {
2339                         DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2340                         return ret;
2341                 }
2342         
2343                 sleep(1);
2344
2345                 /* read the nodemap and verify the change took effect */
2346                 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2347                         DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2348                         exit(10);
2349                 }
2350
2351         } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2352         ret = control_ipreallocate(ctdb, argc, argv);
2353         if (ret != 0) {
2354                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2355                 return ret;
2356         }
2357
2358         return 0;
2359 }
2360
2361 static uint32_t get_generation(struct ctdb_context *ctdb)
2362 {
2363         struct ctdb_vnn_map *vnnmap=NULL;
2364         int ret;
2365
2366         /* wait until the recmaster is not in recovery mode */
2367         while (1) {
2368                 uint32_t recmode, recmaster;
2369                 
2370                 if (vnnmap != NULL) {
2371                         talloc_free(vnnmap);
2372                         vnnmap = NULL;
2373                 }
2374
2375                 /* get the recmaster */
2376                 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2377                 if (ret != 0) {
2378                         DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2379                         exit(10);
2380                 }
2381
2382                 /* get recovery mode */
2383                 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2384                 if (ret != 0) {
2385                         DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2386                         exit(10);
2387                 }
2388
2389                 /* get the current generation number */
2390                 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2391                 if (ret != 0) {
2392                         DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2393                         exit(10);
2394                 }
2395
2396                 if ((recmode == CTDB_RECOVERY_NORMAL)
2397                 &&  (vnnmap->generation != 1)){
2398                         return vnnmap->generation;
2399                 }
2400                 sleep(1);
2401         }
2402 }
2403
2404 /*
2405   ban a node from the cluster
2406  */
2407 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2408 {
2409         int ret;
2410         struct ctdb_node_map *nodemap=NULL;
2411         struct ctdb_ban_time bantime;
2412
2413         if (argc < 1) {
2414                 usage();
2415         }
2416         
2417         /* verify the node exists */
2418         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2419         if (ret != 0) {
2420                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2421                 return ret;
2422         }
2423
2424         if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2425                 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2426                 return -1;
2427         }
2428
2429         bantime.pnn  = options.pnn;
2430         bantime.time = strtoul(argv[0], NULL, 0);
2431
2432         ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2433         if (ret != 0) {
2434                 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2435                 return -1;
2436         }       
2437
2438         ret = control_ipreallocate(ctdb, argc, argv);
2439         if (ret != 0) {
2440                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2441                 return ret;
2442         }
2443
2444         return 0;
2445 }
2446
2447
2448 /*
2449   unban a node from the cluster
2450  */
2451 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2452 {
2453         int ret;
2454         struct ctdb_node_map *nodemap=NULL;
2455         struct ctdb_ban_time bantime;
2456
2457         /* verify the node exists */
2458         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2459         if (ret != 0) {
2460                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2461                 return ret;
2462         }
2463
2464         if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2465                 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2466                 return -1;
2467         }
2468
2469         bantime.pnn  = options.pnn;
2470         bantime.time = 0;
2471
2472         ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2473         if (ret != 0) {
2474                 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2475                 return -1;
2476         }       
2477
2478         ret = control_ipreallocate(ctdb, argc, argv);
2479         if (ret != 0) {
2480                 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2481                 return ret;
2482         }
2483
2484         return 0;
2485 }
2486
2487
2488 /*
2489   show ban information for a node
2490  */
2491 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2492 {
2493         int ret;
2494         struct ctdb_node_map *nodemap=NULL;
2495         struct ctdb_ban_time *bantime;
2496
2497         /* verify the node exists */
2498         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2499         if (ret != 0) {
2500                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2501                 return ret;
2502         }
2503
2504         ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2505         if (ret != 0) {
2506                 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2507                 return -1;
2508         }       
2509
2510         if (bantime->time == 0) {
2511                 printf("Node %u is not banned\n", bantime->pnn);
2512         } else {
2513                 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2514         }
2515
2516         return 0;
2517 }
2518
2519 /*
2520   shutdown a daemon
2521  */
2522 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2523 {
2524         int ret;
2525
2526         ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2527         if (ret != 0) {
2528                 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2529                 return ret;
2530         }
2531
2532         return 0;
2533 }
2534
2535 /*
2536   trigger a recovery
2537  */
2538 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2539 {
2540         int ret;
2541         uint32_t generation, next_generation;
2542
2543         /* record the current generation number */
2544         generation = get_generation(ctdb);
2545
2546         ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2547         if (ret != 0) {
2548                 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2549                 return ret;
2550         }
2551
2552         ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2553         if (ret != 0) {
2554                 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2555                 return ret;
2556         }
2557
2558         /* wait until we are in a new generation */
2559         while (1) {
2560                 next_generation = get_generation(ctdb);
2561                 if (next_generation != generation) {
2562                         return 0;
2563                 }
2564                 sleep(1);
2565         }
2566
2567         return 0;
2568 }
2569
2570
2571 /*
2572   display monitoring mode of a remote node
2573  */
2574 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2575 {
2576         uint32_t monmode;
2577         int ret;
2578
2579         ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2580         if (ret != 0) {
2581                 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2582                 return ret;
2583         }
2584         if (!options.machinereadable){
2585                 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2586         } else {
2587                 printf(":mode:\n");
2588                 printf(":%d:\n",monmode);
2589         }
2590         return 0;
2591 }
2592
2593
2594 /*
2595   display capabilities of a remote node
2596  */
2597 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2598 {
2599         uint32_t capabilities;
2600         int ret;
2601
2602         ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2603         if (ret != 0) {
2604                 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2605                 return ret;
2606         }
2607         
2608         if (!options.machinereadable){
2609                 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2610                 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2611                 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2612                 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2613         } else {
2614                 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2615                 printf(":%d:%d:%d:%d:\n",
2616                         !!(capabilities&CTDB_CAP_RECMASTER),
2617                         !!(capabilities&CTDB_CAP_LMASTER),
2618                         !!(capabilities&CTDB_CAP_LVS),
2619                         !!(capabilities&CTDB_CAP_NATGW));
2620         }
2621         return 0;
2622 }
2623
2624 /*
2625   display lvs configuration
2626  */
2627 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2628 {
2629         uint32_t *capabilities;
2630         struct ctdb_node_map *nodemap=NULL;
2631         int i, ret;
2632         int healthy_count = 0;
2633
2634         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2635         if (ret != 0) {
2636                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2637                 return ret;
2638         }
2639
2640         capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2641         CTDB_NO_MEMORY(ctdb, capabilities);
2642         
2643         /* collect capabilities for all connected nodes */
2644         for (i=0; i<nodemap->num; i++) {
2645                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2646                         continue;
2647                 }
2648                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2649                         continue;
2650                 }
2651         
2652                 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2653                 if (ret != 0) {
2654                         DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2655                         return ret;
2656                 }
2657
2658                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2659                         continue;
2660                 }
2661
2662                 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2663                         healthy_count++;
2664                 }
2665         }
2666
2667         /* Print all LVS nodes */
2668         for (i=0; i<nodemap->num; i++) {
2669                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2670                         continue;
2671                 }
2672                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2673                         continue;
2674                 }
2675                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2676                         continue;
2677                 }
2678
2679                 if (healthy_count != 0) {
2680                         if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2681                                 continue;
2682                         }
2683                 }
2684
2685                 printf("%d:%s\n", i, 
2686                         ctdb_addr_to_str(&nodemap->nodes[i].addr));
2687         }
2688
2689         return 0;
2690 }
2691
2692 /*
2693   display who is the lvs master
2694  */
2695 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2696 {
2697         uint32_t *capabilities;
2698         struct ctdb_node_map *nodemap=NULL;
2699         int i, ret;
2700         int healthy_count = 0;
2701
2702         ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2703         if (ret != 0) {
2704                 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2705                 return ret;
2706         }
2707
2708         capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2709         CTDB_NO_MEMORY(ctdb, capabilities);
2710         
2711         /* collect capabilities for all connected nodes */
2712         for (i=0; i<nodemap->num; i++) {
2713                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2714                         continue;
2715                 }
2716                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2717                         continue;
2718                 }
2719         
2720                 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2721                 if (ret != 0) {
2722                         DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2723                         return ret;
2724                 }
2725
2726                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2727                         continue;
2728                 }
2729
2730                 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2731                         healthy_count++;
2732                 }
2733         }
2734
2735         /* find and show the lvsmaster */
2736         for (i=0; i<nodemap->num; i++) {
2737                 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2738                         continue;
2739                 }
2740                 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2741                         continue;
2742                 }
2743                 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2744                         continue;
2745                 }
2746
2747                 if (healthy_count != 0) {
2748                         if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2749                                 continue;
2750                         }
2751                 }
2752
2753                 if (options.machinereadable){
2754                         printf("%d\n", i);
2755                 } else {
2756                         printf("Node %d is LVS master\n", i);
2757                 }
2758                 return 0;
2759         }
2760
2761         printf("There is no LVS master\n");
2762         return -1;
2763 }
2764
2765 /*
2766   disable monitoring on a  node
2767  */
2768 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2769 {
2770         
2771         int ret;
2772
2773         ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2774         if (ret != 0) {
2775                 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2776                 return ret;
2777         }
2778         printf("Monitoring mode:%s\n","DISABLED");
2779
2780         return 0;
2781 }
2782
2783 /*
2784   enable monitoring on a  node
2785  */
2786 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2787 {
2788         
2789         int ret;
2790
2791         ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2792         if (ret != 0) {
2793                 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2794                 return ret;
2795         }
2796         printf("Monitoring mode:%s\n","ACTIVE");
2797
2798         return 0;
2799 }
2800
2801 /*
2802   display remote list of keys/data for a db
2803  */
2804 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2805 {
2806         const char *db_name;
2807         struct ctdb_db_context *ctdb_db;
2808         int ret;
2809
2810         if (argc < 1) {
2811                 usage();
2812         }
2813
2814         db_name = argv[0];
2815
2816
2817         if (db_exists(ctdb, db_name)) {
2818                 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2819                 return -1;
2820         }
2821
2822         ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2823
2824         if (ctdb_db == NULL) {
2825                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2826                 return -1;
2827         }
2828
2829         /* traverse and dump the cluster tdb */
2830         ret = ctdb_dump_db(ctdb_db, stdout);
2831         if (ret == -1) {
2832                 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2833                 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2834                                   " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2835                                   db_name));
2836                 return -1;
2837         }
2838         talloc_free(ctdb_db);
2839
2840         printf("Dumped %d records\n", ret);
2841         return 0;
2842 }
2843
2844
2845 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid, 
2846                              TDB_DATA data, void *private_data)
2847 {
2848         DEBUG(DEBUG_ERR,("Log data received\n"));
2849         if (data.dsize > 0) {
2850                 printf("%s", data.dptr);
2851         }
2852
2853         exit(0);
2854 }
2855
2856 /*
2857   display a list of log messages from the in memory ringbuffer
2858  */
2859 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2860 {
2861         int ret;
2862         int32_t res;
2863         struct ctdb_get_log_addr log_addr;
2864         TDB_DATA data;
2865         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2866         char *errmsg;
2867         struct timeval tv;
2868
2869         if (argc != 1) {
2870                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2871                 talloc_free(tmp_ctx);
2872                 return -1;
2873         }
2874
2875         log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2876         log_addr.srvid = getpid();
2877         if (isalpha(argv[0][0]) || argv[0][0] == '-') { 
2878                 log_addr.level = get_debug_by_desc(argv[0]);
2879         } else {
2880                 log_addr.level = strtol(argv[0], NULL, 0);
2881         }
2882
2883
2884         data.dptr = (unsigned char *)&log_addr;
2885         data.dsize = sizeof(log_addr);
2886
2887         DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2888
2889         ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2890         sleep(1);
2891
2892         DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2893
2894         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2895                            0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2896         if (ret != 0 || res != 0) {
2897                 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2898                 talloc_free(tmp_ctx);
2899                 return -1;
2900         }
2901
2902
2903         tv = timeval_current();
2904         /* this loop will terminate when we have received the reply */
2905         while (timeval_elapsed(&tv) < 3.0) {    
2906                 event_loop_once(ctdb->ev);
2907         }
2908
2909         DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2910
2911         talloc_free(tmp_ctx);
2912         return 0;
2913 }
2914
2915 /*
2916   clear the in memory log area
2917  */
2918 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2919 {
2920         int ret;
2921         int32_t res;
2922         char *errmsg;
2923         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2924
2925         ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2926                            0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2927         if (ret != 0 || res != 0) {
2928                 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2929                 talloc_free(tmp_ctx);
2930                 return -1;
2931         }
2932
2933         talloc_free(tmp_ctx);
2934         return 0;
2935 }
2936
2937
2938
2939 /*
2940   display a list of the databases on a remote ctdb
2941  */
2942 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2943 {
2944         int i, ret;
2945         struct ctdb_dbid_map *dbmap=NULL;
2946
2947         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2948         if (ret != 0) {
2949                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2950                 return ret;
2951         }
2952
2953         if(options.machinereadable){
2954                 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2955                 for(i=0;i<dbmap->num;i++){
2956                         const char *path;
2957                         const char *name;
2958                         const char *health;
2959                         bool persistent;
2960
2961                         ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2962                                             dbmap->dbs[i].dbid, ctdb, &path);
2963                         ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2964                                             dbmap->dbs[i].dbid, ctdb, &name);
2965                         ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2966                                               dbmap->dbs[i].dbid, ctdb, &health);
2967                         persistent = dbmap->dbs[i].persistent;
2968                         printf(":0x%08X:%s:%s:%d:%d:\n",
2969                                dbmap->dbs[i].dbid, name, path,
2970                                !!(persistent), !!(health));
2971                 }
2972                 return 0;
2973         }
2974
2975         printf("Number of databases:%d\n", dbmap->num);
2976         for(i=0;i<dbmap->num;i++){
2977                 const char *path;
2978                 const char *name;
2979                 const char *health;
2980                 bool persistent;
2981
2982                 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2983                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2984                 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2985                 persistent = dbmap->dbs[i].persistent;
2986                 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2987                        dbmap->dbs[i].dbid, name, path,
2988                        persistent?" PERSISTENT":"",
2989                        health?" UNHEALTHY":"");
2990         }
2991
2992         return 0;
2993 }
2994
2995 /*
2996   display the status of a database on a remote ctdb
2997  */
2998 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2999 {
3000         int i, ret;
3001         struct ctdb_dbid_map *dbmap=NULL;
3002         const char *db_name;
3003
3004         if (argc < 1) {
3005                 usage();
3006         }
3007
3008         db_name = argv[0];
3009
3010         ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3011         if (ret != 0) {
3012                 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3013                 return ret;
3014         }
3015
3016         for(i=0;i<dbmap->num;i++){
3017                 const char *path;
3018                 const char *name;
3019                 const char *health;
3020                 bool persistent;
3021
3022                 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3023                 if (strcmp(name, db_name) != 0) {
3024                         continue;
3025                 }
3026
3027                 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3028                 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3029                 persistent = dbmap->dbs[i].persistent;
3030                 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
3031                        dbmap->dbs[i].dbid, name, path,
3032                        persistent?"yes":"no",
3033                        health?health:"OK");
3034                 return 0;
3035         }
3036
3037         DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
3038         return 0;
3039 }
3040
3041 /*
3042   check if the local node is recmaster or not
3043   it will return 1 if this node is the recmaster and 0 if it is not
3044   or if the local ctdb daemon could not be contacted
3045  */
3046 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
3047 {
3048         uint32_t mypnn, recmaster;
3049         int ret;
3050
3051         mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3052         if (mypnn == -1) {
3053                 printf("Failed to get pnn of node\n");
3054                 return 1;
3055         }
3056
3057         ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
3058         if (ret != 0) {
3059                 printf("Failed to get the recmaster\n");
3060                 return 1;
3061         }
3062
3063         if (recmaster != mypnn) {
3064                 printf("this node is not the recmaster\n");
3065                 return 1;
3066         }
3067
3068         printf("this node is the recmaster\n");
3069         return 0;
3070 }
3071
3072 /*
3073   ping a node
3074  */
3075 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
3076 {
3077         int ret;
3078         struct timeval tv = timeval_current();
3079         ret = ctdb_ctrl_ping(ctdb, options.pnn);
3080         if (ret == -1) {
3081                 printf("Unable to get ping response from node %u\n", options.pnn);
3082                 return -1;
3083         } else {
3084                 printf("response from %u time=%.6f sec  (%d clients)\n", 
3085                        options.pnn, timeval_elapsed(&tv), ret);
3086         }
3087         return 0;
3088 }
3089
3090
3091 /*
3092   get a tunable
3093  */
3094 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
3095 {
3096         const char *name;
3097         uint32_t value;
3098         int ret;
3099
3100         if (argc < 1) {
3101                 usage();
3102         }
3103
3104         name = argv[0];
3105         ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
3106         if (ret == -1) {
3107                 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
3108                 return -1;
3109         }
3110
3111         printf("%-19s = %u\n", name, value);
3112         return 0;
3113 }
3114
3115 /*
3116   set a tunable
3117  */
3118 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3119 {
3120         const char *name;
3121         uint32_t value;
3122         int ret;
3123
3124         if (argc < 2) {
3125                 usage();
3126         }
3127
3128         name = argv[0];
3129         value = strtoul(argv[1], NULL, 0);
3130
3131         ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3132         if (ret == -1) {
3133                 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3134                 return -1;
3135         }
3136         return 0;
3137 }
3138
3139 /*
3140   list all tunables
3141  */
3142 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3143 {
3144         uint32_t count;
3145         const char **list;
3146         int ret, i;
3147
3148         ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3149         if (ret == -1) {
3150                 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3151                 return -1;
3152         }
3153
3154         for (i=0;i<count;i++) {
3155                 control_getvar(ctdb, 1, &list[i]);
3156         }
3157
3158         talloc_free(list);
3159         
3160         return 0;
3161 }
3162
3163 /*
3164   display debug level on a node
3165  */
3166 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3167 {
3168         int ret;
3169         int32_t level;
3170
3171         ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3172         if (ret != 0) {
3173                 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3174                 return ret;
3175         } else {
3176                 if (options.machinereadable){
3177                         printf(":Name:Level:\n");
3178                         printf(":%s:%d:\n",get_debug_by_level(level),level);
3179                 } else {
3180                         printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3181                 }
3182         }
3183         return 0;
3184 }
3185
3186 /*
3187   display reclock file of a node
3188  */
3189 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3190 {
3191         int ret;
3192         const char *reclock;
3193
3194         ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3195         if (ret != 0) {
3196                 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3197                 return ret;
3198         } else {
3199                 if (options.machinereadable){
3200                         if (reclock != NULL) {
3201                                 printf("%s", reclock);
3202                         }
3203                 } else {
3204                         if (reclock == NULL) {
3205                                 printf("No reclock file used.\n");
3206                         } else {
3207                                 printf("Reclock file:%s\n", reclock);
3208                         }
3209                 }
3210         }
3211         return 0;
3212 }
3213
3214 /*
3215   set the reclock file of a node
3216  */
3217 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3218 {
3219         int ret;
3220         const char *reclock;
3221
3222         if (argc == 0) {
3223                 reclock = NULL;
3224         } else if (argc == 1) {
3225                 reclock = argv[0];
3226         } else {
3227                 usage();
3228         }
3229
3230         ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3231         if (ret != 0) {
3232                 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3233                 return ret;
3234         }
3235         return 0;
3236 }
3237
3238 /*
3239   set the natgw state on/off
3240  */
3241 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3242 {
3243         int ret;
3244         uint32_t natgwstate;
3245
3246         if (argc == 0) {
3247                 usage();
3248         }
3249
3250         if (!strcmp(argv[0], "on")) {
3251                 natgwstate = 1;
3252         } else if (!strcmp(argv[0], "off")) {
3253                 natgwstate = 0;
3254         } else {
3255                 usage();
3256         }
3257
3258         ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3259         if (ret != 0) {
3260                 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3261                 return ret;
3262         }
3263
3264         return 0;
3265 }
3266
3267 /*
3268   set the lmaster role on/off
3269  */
3270 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3271 {
3272         int ret;
3273         uint32_t lmasterrole;
3274
3275         if (argc == 0) {
3276                 usage();
3277         }
3278
3279         if (!strcmp(argv[0], "on")) {
3280                 lmasterrole = 1;
3281         } else if (!strcmp(argv[0], "off")) {
3282                 lmasterrole = 0;
3283         } else {
3284                 usage();
3285         }
3286
3287         ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3288         if (ret != 0) {
3289                 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3290                 return ret;
3291         }
3292
3293         return 0;
3294 }
3295
3296 /*
3297   set the recmaster role on/off
3298  */
3299 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3300 {
3301         int ret;
3302         uint32_t recmasterrole;
3303
3304         if (argc == 0) {
3305                 usage();
3306         }
3307
3308         if (!strcmp(argv[0], "on")) {
3309                 recmasterrole = 1;
3310         } else if (!strcmp(argv[0], "off")) {
3311                 recmasterrole = 0;
3312         } else {
3313                 usage();
3314         }
3315
3316         ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3317         if (ret != 0) {
3318                 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3319                 return ret;
3320         }
3321
3322         return 0;
3323 }
3324
3325 /*
3326   set debug level on a node or all nodes
3327  */
3328 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3329 {
3330         int i, ret;
3331         int32_t level;
3332
3333         if (argc == 0) {
3334                 printf("You must specify the debug level. Valid levels are:\n");
3335                 for (i=0; debug_levels[i].description != NULL; i++) {
3336                         printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3337                 }
3338
3339                 return 0;
3340         }
3341
3342         if (isalpha(argv[0][0]) || argv[0][0] == '-') { 
3343                 level = get_debug_by_desc(argv[0]);
3344         } else {
3345                 level = strtol(argv[0], NULL, 0);
3346         }
3347
3348         for (i=0; debug_levels[i].description != NULL; i++) {
3349                 if (level == debug_levels[i].level) {
3350                         break;
3351                 }
3352         }
3353         if (debug_levels[i].description == NULL) {
3354                 printf("Invalid debug level, must be one of\n");
3355                 for (i=0; debug_levels[i].description != NULL; i++) {
3356                         printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3357                 }
3358                 return -1;
3359         }
3360
3361         ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3362         if (ret != 0) {
3363                 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3364         }
3365         return 0;
3366 }
3367
3368
3369 /*
3370   thaw a node
3371  */
3372 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3373 {
3374         int ret;
3375         uint32_t priority;
3376         
3377         if (argc == 1) {
3378                 priority = strtol(argv[0], NULL, 0);
3379         } else {
3380                 priority = 0;
3381         }
3382         DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3383
3384         ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3385         if (ret != 0) {
3386                 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3387         }               
3388         return 0;
3389 }
3390
3391
3392 /*
3393   attach to a database
3394  */
3395 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3396 {
3397         const char *db_name;
3398         struct ctdb_db_context *ctdb_db;
3399
3400         if (argc < 1) {
3401                 usage();
3402         }
3403         db_name = argv[0];
3404
3405         ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3406         if (ctdb_db == NULL) {
3407                 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3408                 return -1;
3409         }
3410
3411         return 0;
3412 }
3413
3414 /*
3415   set db priority
3416  */
3417 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3418 {
3419         struct ctdb_db_priority db_prio;
3420         int ret;
3421
3422         if (argc < 2) {
3423                 usage();
3424         }
3425
3426         db_prio.db_id    = strtoul(argv[0], NULL, 0);
3427         db_prio.priority = strtoul(argv[1], NULL, 0);
3428
3429         ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3430         if (ret != 0) {
3431                 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3432                 return -1;
3433         }
3434
3435         return 0;
3436 }
3437
3438 /*
3439   get db priority
3440  */
3441 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3442 {
3443         uint32_t db_id, priority;
3444         int ret;
3445
3446         if (argc < 1) {
3447                 usage();
3448         }
3449
3450         db_id = strtoul(argv[0], NULL, 0);
3451
3452         ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3453         if (ret != 0) {
3454                 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3455                 return -1;
3456         }
3457
3458         DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3459
3460         return 0;
3461 }
3462
3463 /*
3464   run an eventscript on a node
3465  */
3466 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3467 {
3468         TDB_DATA data;
3469         int ret;
3470         int32_t res;
3471         char *errmsg;
3472         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3473
3474         if (argc != 1) {
3475                 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3476                 return -1;
3477         }
3478
3479         data.dptr = (unsigned char *)discard_const(argv[0]);
3480         data.dsize = strlen((char *)data.dptr) + 1;
3481