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
30 void ctdb_test_stubs_read_nodemap(struct ctdb_context
*ctdb
)
34 TALLOC_FREE(ctdb
->nodes
);
40 while ((fgets(line
, sizeof(line
), stdin
) != NULL
) &&
42 uint32_t pnn
, flags
, capabilities
;
47 /* Get rid of pesky newline */
48 if ((t
= strchr(line
, '\n')) != NULL
) {
53 tok
= strtok(line
, " \t");
55 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line (PNN) ignored \"%s\"\n", line
));
58 pnn
= (uint32_t)strtoul(tok
, NULL
, 0);
61 tok
= strtok(NULL
, " \t");
63 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line (no IP) ignored \"%s\"\n", line
));
66 if (!parse_ip(tok
, NULL
, 0, &saddr
)) {
67 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line (IP) ignored \"%s\"\n", line
));
70 ip
= talloc_strdup(ctdb
, tok
);
73 tok
= strtok(NULL
, " \t");
75 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line (flags) ignored \"%s\"\n", line
));
78 flags
= (uint32_t)strtoul(tok
, NULL
, 0);
79 capabilities
= CTDB_CAP_RECMASTER
|CTDB_CAP_LMASTER
|CTDB_CAP_NATGW
;
81 tok
= strtok(NULL
, " \t");
83 if (strcmp(tok
, "CURRENT") == 0) {
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"));
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"));
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
;
121 void ctdb_test_stubs_print_nodemap(struct ctdb_context
*ctdb
)
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"
136 * :Name:LinkStatus:References:
142 struct ctdb_iface
*prev
, *next
;
148 void ctdb_test_stubs_read_ifaces(struct ctdb_context
*ctdb
)
151 struct ctdb_iface
*iface
;
153 while ((fgets(line
, sizeof(line
), stdin
) != NULL
) &&
157 char *tok
, *t
, *name
;
159 /* Get rid of pesky newline */
160 if ((t
= strchr(line
, '\n')) != NULL
) {
164 if (strcmp(line
, ":Name:LinkStatus:References:") == 0) {
169 //tok = strtok(line, ":"); /* Leading colon... */
170 tok
= strtok(line
, ":");
172 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line ignored \"%s\"\n", line
));
178 tok
= strtok(NULL
, ":");
180 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line ignored \"%s\"\n", line
));
183 link_state
= (uint16_t)strtoul(tok
, NULL
, 0);
186 tok
= strtok(NULL
, ":");
188 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line ignored \"%s\"\n", line
));
191 references
= (uint32_t)strtoul(tok
, NULL
, 0);
193 iface
= talloc_zero(ctdb
, struct ctdb_iface
);
196 DEBUG(DEBUG_ERR
, ("OOM allocating iface\n"));
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",
230 struct ctdb_vnn_map {
236 void ctdb_test_stubs_read_vnnmap(struct ctdb_context
*ctdb
)
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"));
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
) &&
256 /* Get rid of pesky newline */
257 if ((t
= strchr(line
, '\n')) != NULL
) {
261 n
= (uint32_t) strtol(line
, NULL
, 0);
264 if (ctdb
->vnn_map
->generation
== INVALID_GENERATION
) {
265 ctdb
->vnn_map
->generation
= n
;
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"));
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
)
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
)
294 while (fgets(line
, sizeof(line
), stdin
) != NULL
) {
297 /* Get rid of pesky newline */
298 if ((t
= strchr(line
, '\n')) != NULL
) {
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
);
309 printf("Unknown line %s\n", line
);
316 static bool current_node_is_connected (struct ctdb_context
*ctdb
)
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
)) {
330 /* Shouldn't really happen, so fag an error */
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
);
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"));
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
;
387 ctdb_ctrl_getnodemap_stub(struct ctdb_context
*ctdb
,
388 struct timeval timeout
, uint32_t destnode
,
390 struct ctdb_node_map
**nodemap
)
397 if (!current_node_is_connected(ctdb
)) {
404 outdata
= talloc_zero(ctdb
, TDB_DATA
);
406 ret
= ctdb_control_getnodemap(ctdb
, CTDB_CONTROL_GET_NODEMAP
,
410 *nodemap
= (struct ctdb_node_map
*) outdata
->dptr
;
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"));
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
);
436 ctdb_ctrl_getrecmode_stub(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
,
437 struct timeval timeout
, uint32_t destnode
,
440 *recmode
= ctdb
->recovery_mode
;
446 ctdb_ctrl_getrecmaster_stub(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
,
447 struct timeval timeout
, uint32_t destnode
,
450 *recmaster
= ctdb
->recovery_master
;
456 ctdb_ctrl_getpnn_stub(struct ctdb_context
*ctdb
, struct timeval timeout
,
459 if (!current_node_is_connected(ctdb
)) {
463 if (destnode
== CTDB_CURRENT_NODE
) {
470 /* From ctdb_takeover.c */
471 int32_t ctdb_control_get_ifaces(struct ctdb_context
*ctdb
,
472 struct ctdb_req_control
*c
,
476 struct ctdb_control_get_ifaces
*ifaces
;
477 struct ctdb_iface
*cur
;
479 /* count how many public ip structures we have */
481 for (cur
=ctdb
->ifaces
;cur
;cur
=cur
->next
) {
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
);
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
;
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
;
508 ctdb_ctrl_get_ifaces_stub(struct ctdb_context
*ctdb
,
509 struct timeval timeout
, uint32_t destnode
,
511 struct ctdb_control_get_ifaces
**ifaces
)
516 if (!current_node_is_connected(ctdb
)) {
520 outdata
= talloc(mem_ctx
, TDB_DATA
);
522 ret
= ctdb_control_get_ifaces(ctdb
, NULL
, outdata
);
525 *ifaces
= (struct ctdb_control_get_ifaces
*)outdata
->dptr
;
531 int ctdb_client_check_message_handlers_stub(struct ctdb_context
*ctdb
,
532 uint64_t *ids
, uint32_t num
,
535 DEBUG(DEBUG_ERR
, (__location__
" NOT IMPLEMENTED\n"));
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
;