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