ctdb-tests: Support fake capabilities in CTDB tool stub
[Samba.git] / ctdb / tests / src / ctdb_test_stubs.c
blob3ca7b9112ea577a91c11f39ac1281db0016b4bdb
1 /*
2 Test stubs and support functions for some CTDB client functions
4 Copyright (C) Martin Schwenke 2011
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program 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
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
20 /* Read a nodemap from stdin. Each line looks like:
21 * <PNN> <FLAGS> [RECMASTER] [CURRENT] [CAPABILITIES]
22 * EOF or a blank line terminates input.
24 * By default, capablities for each node are
25 * CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER|CTDB_CAP_NATGW. These 3
26 * capabilities can be faked off by adding, for example,
27 * -CTDB_CAP_RECMASTER. LVS can be faked on by adding
28 * CTDB_CAP_LVS.
30 void ctdb_test_stubs_read_nodemap(struct ctdb_context *ctdb)
32 char line[1024];
34 TALLOC_FREE(ctdb->nodes);
35 ctdb->pnn = -1;
36 ctdb->num_nodes = 0;
38 ctdb->nodes = NULL;
40 while ((fgets(line, sizeof(line), stdin) != NULL) &&
41 (line[0] != '\n')) {
42 uint32_t pnn, flags, capabilities;
43 char *tok, *t;
44 const char *ip;
45 ctdb_sock_addr saddr;
47 /* Get rid of pesky newline */
48 if ((t = strchr(line, '\n')) != NULL) {
49 *t = '\0';
52 /* Get PNN */
53 tok = strtok(line, " \t");
54 if (tok == NULL) {
55 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line (PNN) ignored \"%s\"\n", line));
56 continue;
58 pnn = (uint32_t)strtoul(tok, NULL, 0);
60 /* Get IP */
61 tok = strtok(NULL, " \t");
62 if (tok == NULL) {
63 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line (no IP) ignored \"%s\"\n", line));
64 continue;
66 if (!parse_ip(tok, NULL, 0, &saddr)) {
67 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line (IP) ignored \"%s\"\n", line));
68 continue;
70 ip = talloc_strdup(ctdb, tok);
72 /* Get flags */
73 tok = strtok(NULL, " \t");
74 if (tok == NULL) {
75 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line (flags) ignored \"%s\"\n", line));
76 continue;
78 flags = (uint32_t)strtoul(tok, NULL, 0);
79 capabilities = CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER|CTDB_CAP_NATGW;
81 tok = strtok(NULL, " \t");
82 while (tok != NULL) {
83 if (strcmp(tok, "CURRENT") == 0) {
84 ctdb->pnn = pnn;
85 } else if (strcmp(tok, "RECMASTER") == 0) {
86 ctdb->recovery_master = pnn;
87 } else if (strcmp(tok, "-CTDB_CAP_RECMASTER") == 0) {
88 capabilities &= ~CTDB_CAP_RECMASTER;
89 } else if (strcmp(tok, "-CTDB_CAP_LMASTER") == 0) {
90 capabilities &= ~CTDB_CAP_LMASTER;
91 } else if (strcmp(tok, "-CTDB_CAP_NATGW") == 0) {
92 capabilities &= ~CTDB_CAP_NATGW;
93 } else if (strcmp(tok, "CTDB_CAP_LVS") == 0) {
94 capabilities |= CTDB_CAP_LVS;
96 tok = strtok(NULL, " \t");
99 ctdb->nodes = talloc_realloc(ctdb, ctdb->nodes, struct ctdb_node *, ctdb->num_nodes + 1);
100 if (ctdb->nodes == NULL) {
101 DEBUG(DEBUG_ERR, ("OOM allocating nodes array\n"));
102 exit (1);
104 ctdb->nodes[ctdb->num_nodes] = talloc_zero(ctdb, struct ctdb_node);
105 if (ctdb->nodes[ctdb->num_nodes] == NULL) {
106 DEBUG(DEBUG_ERR, ("OOM allocating node structure\n"));
107 exit (1);
110 ctdb->nodes[ctdb->num_nodes]->ctdb = ctdb;
111 ctdb->nodes[ctdb->num_nodes]->name = "fakectdb";
112 ctdb->nodes[ctdb->num_nodes]->pnn = pnn;
113 ctdb->nodes[ctdb->num_nodes]->address.address = ip;
114 ctdb->nodes[ctdb->num_nodes]->address.port = 0;
115 ctdb->nodes[ctdb->num_nodes]->flags = flags;
116 ctdb->nodes[ctdb->num_nodes]->capabilities = capabilities;
117 ctdb->num_nodes++;
121 void ctdb_test_stubs_print_nodemap(struct ctdb_context *ctdb)
123 int i;
125 for (i = 0; i < ctdb->num_nodes; i++) {
126 printf("%ld\t0x%lx%s%s\n",
127 (unsigned long) ctdb->nodes[i]->pnn,
128 (unsigned long) ctdb->nodes[i]->flags,
129 ctdb->nodes[i]->pnn == ctdb->pnn ? "\tCURRENT" : "",
130 ctdb->nodes[i]->pnn == ctdb->recovery_master ? "\tRECMASTER" : "");
134 /* Read interfaces information. Same format as "ctdb ifaces -Y"
135 * output:
136 * :Name:LinkStatus:References:
137 * :eth2:1:4294967294
138 * :eth1:1:4294967292
141 struct ctdb_iface {
142 struct ctdb_iface *prev, *next;
143 const char *name;
144 bool link_up;
145 uint32_t references;
148 void ctdb_test_stubs_read_ifaces(struct ctdb_context *ctdb)
150 char line[1024];
151 struct ctdb_iface *iface;
153 while ((fgets(line, sizeof(line), stdin) != NULL) &&
154 (line[0] != '\n')) {
155 uint16_t link_state;
156 uint32_t references;
157 char *tok, *t, *name;
159 /* Get rid of pesky newline */
160 if ((t = strchr(line, '\n')) != NULL) {
161 *t = '\0';
164 if (strcmp(line, ":Name:LinkStatus:References:") == 0) {
165 continue;
168 /* name */
169 //tok = strtok(line, ":"); /* Leading colon... */
170 tok = strtok(line, ":");
171 if (tok == NULL) {
172 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line ignored \"%s\"\n", line));
173 continue;
175 name = tok;
177 /* link_state */
178 tok = strtok(NULL, ":");
179 if (tok == NULL) {
180 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line ignored \"%s\"\n", line));
181 continue;
183 link_state = (uint16_t)strtoul(tok, NULL, 0);
185 /* references... */
186 tok = strtok(NULL, ":");
187 if (tok == NULL) {
188 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line ignored \"%s\"\n", line));
189 continue;
191 references = (uint32_t)strtoul(tok, NULL, 0);
193 iface = talloc_zero(ctdb, struct ctdb_iface);
195 if (iface == NULL) {
196 DEBUG(DEBUG_ERR, ("OOM allocating iface\n"));
197 exit (1);
200 iface->name = talloc_strdup(iface, name);
201 iface->link_up = link_state;
202 iface->references = references;
204 DLIST_ADD(ctdb->ifaces, iface);
208 void ctdb_test_stubs_print_ifaces(struct ctdb_context *ctdb)
210 struct ctdb_iface *iface;
212 printf(":Name:LinkStatus:References:\n");
213 for (iface = ctdb->ifaces; iface != NULL; iface = iface->next) {
214 printf(":%s:%u:%u:\n",
215 iface->name,
216 iface->link_up,
217 iface->references);
221 /* Read vnn map.
222 * output:
223 * <GENERATION>
224 * <LMASTER0>
225 * <LMASTER1>
226 * ...
230 struct ctdb_vnn_map {
231 uint32_t generation;
232 uint32_t size;
233 uint32_t *map;
236 void ctdb_test_stubs_read_vnnmap(struct ctdb_context *ctdb)
238 char line[1024];
240 TALLOC_FREE(ctdb->vnn_map);
242 ctdb->vnn_map = talloc_zero(ctdb, struct ctdb_vnn_map);
243 if (ctdb->vnn_map == NULL) {
244 DEBUG(DEBUG_ERR, ("OOM allocating vnnmap\n"));
245 exit (1);
247 ctdb->vnn_map->generation = INVALID_GENERATION;
248 ctdb->vnn_map->size = 0;
249 ctdb->vnn_map->map = NULL;
251 while ((fgets(line, sizeof(line), stdin) != NULL) &&
252 (line[0] != '\n')) {
253 uint32_t n;
254 char *t;
256 /* Get rid of pesky newline */
257 if ((t = strchr(line, '\n')) != NULL) {
258 *t = '\0';
261 n = (uint32_t) strtol(line, NULL, 0);
263 /* generation */
264 if (ctdb->vnn_map->generation == INVALID_GENERATION) {
265 ctdb->vnn_map->generation = n;
266 continue;
269 ctdb->vnn_map->map = talloc_realloc(ctdb, ctdb->vnn_map->map, uint32_t, ctdb->vnn_map->size + 1);
270 if (ctdb->vnn_map->map == NULL) {
271 DEBUG(DEBUG_ERR, ("OOM allocating vnn_map->map\n"));
272 exit (1);
275 ctdb->vnn_map->map[ctdb->vnn_map->size] = n;
276 ctdb->vnn_map->size++;
280 void ctdb_test_stubs_print_vnnmap(struct ctdb_context *ctdb)
282 int i;
284 printf("%d\n", ctdb->vnn_map->generation);
285 for (i = 0; i < ctdb->vnn_map->size; i++) {
286 printf("%d\n", ctdb->vnn_map->map[i]);
290 void ctdb_test_stubs_fake_setup(struct ctdb_context *ctdb)
292 char line[1024];
294 while (fgets(line, sizeof(line), stdin) != NULL) {
295 char *t;
297 /* Get rid of pesky newline */
298 if ((t = strchr(line, '\n')) != NULL) {
299 *t = '\0';
302 if (strcmp(line, "NODEMAP") == 0) {
303 ctdb_test_stubs_read_nodemap(ctdb);
304 } else if (strcmp(line, "IFACES") == 0) {
305 ctdb_test_stubs_read_ifaces(ctdb);
306 } else if (strcmp(line, "VNNMAP") == 0) {
307 ctdb_test_stubs_read_vnnmap(ctdb);
308 } else {
309 printf("Unknown line %s\n", line);
310 exit(1);
315 /* Support... */
316 static bool current_node_is_connected (struct ctdb_context *ctdb)
318 int i;
319 for (i = 0; i < ctdb->num_nodes; i++) {
320 if (ctdb->nodes[i]->pnn == ctdb->pnn) {
321 if (ctdb->nodes[i]->flags &
322 (NODE_FLAGS_DISCONNECTED | NODE_FLAGS_DELETED)) {
323 return false;
324 } else {
325 return true;
330 /* Shouldn't really happen, so fag an error */
331 return false;
334 /* Stubs... */
336 struct ctdb_context *ctdb_cmdline_client_stub(struct tevent_context *ev,
337 struct timeval req_timeout)
339 struct ctdb_context *ctdb;
341 ctdb = talloc_zero(NULL, struct ctdb_context);
343 ctdb_set_socketname(ctdb, "fake");
345 ctdb_test_stubs_fake_setup(ctdb);
347 return ctdb;
350 /* Copied from ctdb_recover.c */
352 ctdb_control_getnodemap(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA indata, TDB_DATA *outdata)
354 uint32_t i, num_nodes;
355 struct ctdb_node_map *node_map;
357 CHECK_CONTROL_DATA_SIZE(0);
359 num_nodes = ctdb->num_nodes;
361 outdata->dsize = offsetof(struct ctdb_node_map, nodes) + num_nodes*sizeof(struct ctdb_node_and_flags);
362 outdata->dptr = (unsigned char *)talloc_zero_size(outdata, outdata->dsize);
363 if (!outdata->dptr) {
364 DEBUG(DEBUG_ALERT, (__location__ " Failed to allocate nodemap array\n"));
365 exit(1);
368 node_map = (struct ctdb_node_map *)outdata->dptr;
369 node_map->num = num_nodes;
370 for (i=0; i<num_nodes; i++) {
371 if (parse_ip(ctdb->nodes[i]->address.address,
372 NULL, /* TODO: pass in the correct interface here*/
374 &node_map->nodes[i].addr) == 0)
376 DEBUG(DEBUG_ERR, (__location__ " Failed to parse %s into a sockaddr\n", ctdb->nodes[i]->address.address));
379 node_map->nodes[i].pnn = ctdb->nodes[i]->pnn;
380 node_map->nodes[i].flags = ctdb->nodes[i]->flags;
383 return 0;
387 ctdb_ctrl_getnodemap_stub(struct ctdb_context *ctdb,
388 struct timeval timeout, uint32_t destnode,
389 TALLOC_CTX *mem_ctx,
390 struct ctdb_node_map **nodemap)
392 int ret;
394 TDB_DATA indata;
395 TDB_DATA *outdata;
397 if (!current_node_is_connected(ctdb)) {
398 return -1;
401 indata.dsize = 0;
402 indata.dptr = NULL;
404 outdata = talloc_zero(ctdb, TDB_DATA);
406 ret = ctdb_control_getnodemap(ctdb, CTDB_CONTROL_GET_NODEMAP,
407 indata, outdata);
409 if (ret == 0) {
410 *nodemap = (struct ctdb_node_map *) outdata->dptr;
413 return ret;
417 ctdb_ctrl_getvnnmap_stub(struct ctdb_context *ctdb,
418 struct timeval timeout, uint32_t destnode,
419 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
421 *vnnmap = talloc(ctdb, struct ctdb_vnn_map);
422 if (*vnnmap == NULL) {
423 DEBUG(DEBUG_ERR, (__location__ "OOM\n"));
424 exit (1);
426 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, ctdb->vnn_map->size);
428 (*vnnmap)->generation = ctdb->vnn_map->generation;
429 (*vnnmap)->size = ctdb->vnn_map->size;
430 memcpy((*vnnmap)->map, ctdb->vnn_map->map, sizeof(uint32_t) * (*vnnmap)->size);
432 return 0;
436 ctdb_ctrl_getrecmode_stub(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
437 struct timeval timeout, uint32_t destnode,
438 uint32_t *recmode)
440 *recmode = ctdb->recovery_mode;
442 return 0;
446 ctdb_ctrl_getrecmaster_stub(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
447 struct timeval timeout, uint32_t destnode,
448 uint32_t *recmaster)
450 *recmaster = ctdb->recovery_master;
452 return 0;
456 ctdb_ctrl_getpnn_stub(struct ctdb_context *ctdb, struct timeval timeout,
457 uint32_t destnode)
459 if (!current_node_is_connected(ctdb)) {
460 return -1;
463 if (destnode == CTDB_CURRENT_NODE) {
464 return ctdb->pnn;
465 } else {
466 return destnode;
470 /* From ctdb_takeover.c */
471 int32_t ctdb_control_get_ifaces(struct ctdb_context *ctdb,
472 struct ctdb_req_control *c,
473 TDB_DATA *outdata)
475 int i, num, len;
476 struct ctdb_control_get_ifaces *ifaces;
477 struct ctdb_iface *cur;
479 /* count how many public ip structures we have */
480 num = 0;
481 for (cur=ctdb->ifaces;cur;cur=cur->next) {
482 num++;
485 len = offsetof(struct ctdb_control_get_ifaces, ifaces) +
486 num*sizeof(struct ctdb_control_iface_info);
487 ifaces = talloc_zero_size(outdata, len);
488 CTDB_NO_MEMORY(ctdb, ifaces);
490 i = 0;
491 for (cur=ctdb->ifaces;cur;cur=cur->next) {
492 strcpy(ifaces->ifaces[i].name, cur->name);
493 ifaces->ifaces[i].link_state = cur->link_up;
494 ifaces->ifaces[i].references = cur->references;
495 i++;
497 ifaces->num = i;
498 len = offsetof(struct ctdb_control_get_ifaces, ifaces) +
499 i*sizeof(struct ctdb_control_iface_info);
501 outdata->dsize = len;
502 outdata->dptr = (uint8_t *)ifaces;
504 return 0;
508 ctdb_ctrl_get_ifaces_stub(struct ctdb_context *ctdb,
509 struct timeval timeout, uint32_t destnode,
510 TALLOC_CTX *mem_ctx,
511 struct ctdb_control_get_ifaces **ifaces)
513 TDB_DATA *outdata;
514 int ret;
516 if (!current_node_is_connected(ctdb)) {
517 return -1;
520 outdata = talloc(mem_ctx, TDB_DATA);
522 ret = ctdb_control_get_ifaces(ctdb, NULL, outdata);
524 if (ret == 0) {
525 *ifaces = (struct ctdb_control_get_ifaces *)outdata->dptr;
528 return ret;
531 int ctdb_client_check_message_handlers_stub(struct ctdb_context *ctdb,
532 uint64_t *ids, uint32_t num,
533 uint8_t *result)
535 DEBUG(DEBUG_ERR, (__location__ " NOT IMPLEMENTED\n"));
536 return -1;
539 int ctdb_ctrl_getcapabilities_stub(struct ctdb_context *ctdb,
540 struct timeval timeout, uint32_t destnode,
541 uint32_t *capabilities)
543 *capabilities = ctdb->nodes[destnode]->capabilities;
544 return 0;