auto-determine listen address by attempting to bind to each address in the cluster...
[sahlberg/ctdb.git] / common / cmdline.c
1 /* 
2    common commandline code to ctdb test tools
3
4    Copyright (C) Andrew Tridgell  2007
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "includes.h"
22 #include "lib/events/events.h"
23 #include "system/filesys.h"
24 #include "popt.h"
25 #include "../include/ctdb.h"
26 #include "../include/ctdb_private.h"
27
28 /* Handle common command line options for ctdb test progs
29  */
30
31 static struct {
32         const char *nlist;
33         const char *transport;
34         const char *myaddress;
35         const char *socketname;
36         int self_connect;
37         const char *db_dir;
38         int torture;
39         const char *logfile;
40 } ctdb_cmdline = {
41         .nlist = NULL,
42         .transport = "tcp",
43         .myaddress = NULL,
44         .socketname = CTDB_PATH,
45         .self_connect = 0,
46         .db_dir = NULL,
47         .torture = 0,
48         .logfile = NULL
49 };
50
51
52 struct poptOption popt_ctdb_cmdline[] = {
53         { "nlist", 0, POPT_ARG_STRING, &ctdb_cmdline.nlist, 0, "node list file", "filename" },
54         { "listen", 0, POPT_ARG_STRING, &ctdb_cmdline.myaddress, 0, "address to listen on", "address" },
55         { "socket", 0, POPT_ARG_STRING, &ctdb_cmdline.socketname, 0, "local socket name", "filename" },
56         { "transport", 0, POPT_ARG_STRING, &ctdb_cmdline.transport, 0, "protocol transport", NULL },
57         { "self-connect", 0, POPT_ARG_NONE, &ctdb_cmdline.self_connect, 0, "enable self connect", "boolean" },
58         { "debug", 'd', POPT_ARG_INT, &LogLevel, 0, "debug level"},
59         { "dbdir", 0, POPT_ARG_STRING, &ctdb_cmdline.db_dir, 0, "directory for the tdb files", NULL },
60         { "torture", 0, POPT_ARG_NONE, &ctdb_cmdline.torture, 0, "enable nastiness in library", NULL },
61         { "logfile", 0, POPT_ARG_STRING, &ctdb_cmdline.logfile, 0, "log file location", "filename" },
62         { NULL }
63 };
64
65
66 /*
67   startup daemon side of ctdb according to command line options
68  */
69 struct ctdb_context *ctdb_cmdline_init(struct event_context *ev)
70 {
71         struct ctdb_context *ctdb;
72         int i, ret;
73
74         if (ctdb_cmdline.nlist == NULL) {
75                 printf("You must provide a node list with --nlist\n");
76                 exit(1);
77         }
78
79         /* initialise ctdb */
80         ctdb = ctdb_init(ev);
81         if (ctdb == NULL) {
82                 printf("Failed to init ctdb\n");
83                 exit(1);
84         }
85
86         ret = ctdb_set_logfile(ctdb, ctdb_cmdline.logfile);
87         if (ret == -1) {
88                 printf("ctdb_set_logfile failed - %s\n", ctdb_errstr(ctdb));
89                 exit(1);
90         }
91
92         if (ctdb_cmdline.self_connect) {
93                 ctdb_set_flags(ctdb, CTDB_FLAG_SELF_CONNECT);
94         }
95         if (ctdb_cmdline.torture) {
96                 ctdb_set_flags(ctdb, CTDB_FLAG_TORTURE);
97         }
98
99         ret = ctdb_set_transport(ctdb, ctdb_cmdline.transport);
100         if (ret == -1) {
101                 printf("ctdb_set_transport failed - %s\n", ctdb_errstr(ctdb));
102                 exit(1);
103         }
104
105         /* tell ctdb what address to listen on */
106         if (ctdb_cmdline.myaddress) {
107                 ret = ctdb_set_address(ctdb, ctdb_cmdline.myaddress);
108                 if (ret == -1) {
109                         printf("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb));
110                         exit(1);
111                 }
112         }
113
114         /* tell ctdb the socket address */
115         ret = ctdb_set_socketname(ctdb, ctdb_cmdline.socketname);
116         if (ret == -1) {
117                 printf("ctdb_set_socketname failed - %s\n", ctdb_errstr(ctdb));
118                 exit(1);
119         }
120
121         /* tell ctdb what nodes are available */
122         ret = ctdb_set_nlist(ctdb, ctdb_cmdline.nlist);
123         if (ret == -1) {
124                 printf("ctdb_set_nlist failed - %s\n", ctdb_errstr(ctdb));
125                 exit(1);
126         }
127
128         if (ctdb_cmdline.db_dir) {
129                 ret = ctdb_set_tdb_dir(ctdb, ctdb_cmdline.db_dir);
130                 if (ret == -1) {
131                         printf("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb));
132                         exit(1);
133                 }
134         }
135
136         /* initialize the vnn mapping table */
137 /*
138 XXX we currently initialize it to the maximum number of nodes to 
139 XXX make it behave the same way as previously.  
140 XXX Once we have recovery working we should initialize this always to 
141 XXX generation==0 (==invalid) and let the recovery tool populate this 
142 XXX table for the daemons. 
143 */
144         ctdb->vnn_map = talloc_zero(ctdb, struct ctdb_vnn_map);
145         if (ctdb->vnn_map == NULL) {
146                 DEBUG(0,(__location__ " Unable to allocate vnn_map structure\n"));
147                 exit(1);
148         }
149         ctdb->vnn_map->generation = 1;
150         ctdb->vnn_map->size = 1024;
151         ctdb->vnn_map->map = talloc_array(ctdb->vnn_map, uint32_t, ctdb->vnn_map->size);
152         if (ctdb->vnn_map->map == NULL) {
153                 DEBUG(0,(__location__ " Unable to allocate vnn_map->map structure\n"));
154                 exit(1);
155         }
156         for(i=0;i<ctdb->vnn_map->size;i++){
157                 ctdb->vnn_map->map[i] = i%ctdb->num_nodes;
158         }
159
160
161         return ctdb;
162 }
163
164
165 /*
166   startup a client only ctdb context
167  */
168 struct ctdb_context *ctdb_cmdline_client(struct event_context *ev)
169 {
170         struct ctdb_context *ctdb;
171         int ret;
172
173         /* initialise ctdb */
174         ctdb = ctdb_init(ev);
175         if (ctdb == NULL) {
176                 printf("Failed to init ctdb\n");
177                 exit(1);
178         }
179
180         /* tell ctdb the socket address */
181         ret = ctdb_set_socketname(ctdb, ctdb_cmdline.socketname);
182         if (ret == -1) {
183                 printf("ctdb_set_socketname failed - %s\n", ctdb_errstr(ctdb));
184                 exit(1);
185         }
186
187         ret = ctdb_socket_connect(ctdb);
188         if (ret != 0) {
189                 DEBUG(0,(__location__ " Failed to connect to daemon\n"));
190                 talloc_free(ctdb);
191                 return NULL;
192         }
193
194         /* get our config */
195         ret = ctdb_get_config(ctdb);
196         if (ret != 0) {
197                 DEBUG(0,(__location__ " Failed to get ctdb config\n"));
198                 talloc_free(ctdb);
199                 return NULL;
200         }
201
202         return ctdb;
203 }