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