2 Tests for ctdb_takeover.c
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/>.
21 #include "../include/ctdb_private.h"
24 * Need these, since they're defined in ctdbd.c but we can't link
29 void ctdb_load_nodes_file(struct ctdb_context *ctdb) {}
31 /* Format of each line is "IP pnn" - the separator has to be at least
32 * 1 space (not a tab or whatever - a space!).
34 static struct ctdb_public_ip_list *
35 read_ctdb_public_ip_list(TALLOC_CTX *ctx)
41 struct ctdb_public_ip_list *last = NULL;
43 struct ctdb_public_ip_list *ret = NULL;
45 while (fgets(line, sizeof(line), stdin) != NULL) {
47 if ((t = strchr(line, ' ')) != NULL) {
48 /* Make line contain just the address */
50 /* Point to PNN or leading whitespace... */
52 pnn = (int) strtol(t, (char **) NULL, 10);
54 /* Assume just an IP address, default to PNN -1 */
55 if ((t = strchr(line, '\n')) != NULL) {
61 if (parse_ip(line, NULL, 0, &addr)) {
63 last = talloc(ctx, struct ctdb_public_ip_list);
65 last->next = talloc(ctx, struct ctdb_public_ip_list);
70 memcpy(&(last->addr), &addr, sizeof(addr));
75 DEBUG(DEBUG_ERR, (__location__ " ERROR, bad address :%s\n", line));
82 void print_ctdb_public_ip_list(struct ctdb_public_ip_list * ips)
85 printf("%s %d\n", ctdb_addr_to_str(&(ips->addr)), ips->pnn);
90 /* Read some IPs from stdin, 1 per line, parse them and then print
92 void ctdb_test_read_ctdb_public_ip_list(void)
94 struct ctdb_public_ip_list *l;
96 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
98 l = read_ctdb_public_ip_list(tmp_ctx);
100 print_ctdb_public_ip_list(l);
102 talloc_free(tmp_ctx);
105 /* Read 2 IPs from stdin, calculate the IP distance and print it. */
106 void ctdb_test_ip_distance(void)
108 struct ctdb_public_ip_list *l;
111 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
113 l = read_ctdb_public_ip_list(tmp_ctx);
116 distance = ip_distance(&(l->addr), &(l->next->addr));
117 printf ("%lu\n", (unsigned long) distance);
120 talloc_free(tmp_ctx);
123 /* Read some IPs from stdin, calculate the sum of the squares of the
124 * IP distances between the 1st argument and those read that are on
125 * the given node. The given IP must one of the ones in the list. */
126 void ctdb_test_ip_distance_2_sum(const char ip[], int pnn)
128 struct ctdb_public_ip_list *l;
129 struct ctdb_public_ip_list *t;
133 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
136 l = read_ctdb_public_ip_list(tmp_ctx);
138 if (l && parse_ip(ip, NULL, 0, &addr)) {
139 /* find the entry for the specified IP */
140 for (t=l; t!=NULL; t=t->next) {
141 if (ctdb_same_ip(&(t->addr), &addr)) {
147 fprintf(stderr, "IP NOT PRESENT IN LIST");
151 distance = ip_distance_2_sum(&(t->addr), l, pnn);
152 printf ("%lu\n", (unsigned long) distance);
154 fprintf(stderr, "BAD INPUT");
158 talloc_free(tmp_ctx);
161 /* Read some IPs from stdin, calculate the sume of the squares of the
162 * IP distances between the first and the rest, and print it. */
163 void ctdb_test_lcp2_imbalance(int pnn)
165 struct ctdb_public_ip_list *l;
168 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
170 l = read_ctdb_public_ip_list(tmp_ctx);
172 imbalance = lcp2_imbalance(l, pnn);
173 printf ("%lu\n", (unsigned long) imbalance);
175 talloc_free(tmp_ctx);
178 void ctdb_test_init(const char nodestates[],
179 struct ctdb_context **ctdb,
180 struct ctdb_public_ip_list **all_ips,
181 struct ctdb_node_map **nodemap)
183 struct ctdb_public_ip_list *t;
184 struct ctdb_all_public_ips *available_public_ips;
185 int i, numips, numnodes;
186 /* This is test code and this is unreasonably big... :-) */
187 uint32_t nodeflags[256];
190 *ctdb = talloc_zero(NULL, struct ctdb_context);
192 /* Avoid that const */
193 ns = talloc_strdup(*ctdb, nodestates);
196 tok = strtok(ns, ",");
197 while (tok != NULL) {
198 nodeflags[numnodes] = (uint32_t) strtol(tok, NULL, 16);
200 tok = strtok(NULL, ",");
203 /* Fake things up... */
204 (*ctdb)->num_nodes = numnodes;
206 (*ctdb)->tunable.deterministic_public_ips = 0;
207 (*ctdb)->tunable.disable_ip_failover = 0;
208 (*ctdb)->tunable.no_ip_failback = 0;
210 if (getenv("CTDB_LCP2")) {
211 if (strcmp(getenv("CTDB_LCP2"), "yes") == 0) {
212 (*ctdb)->tunable.lcp2_public_ip_assignment = 1;
214 (*ctdb)->tunable.lcp2_public_ip_assignment = 0;
218 *nodemap = talloc_array(*ctdb, struct ctdb_node_map, numnodes);
219 (*nodemap)->num = numnodes;
221 *all_ips = read_ctdb_public_ip_list(*ctdb);
223 for (t = *all_ips; t != NULL; t = t->next) {
227 available_public_ips = talloc_array(*ctdb, struct ctdb_all_public_ips, numips); // FIXME: bogus size, overkill
228 available_public_ips->num = numips;
229 for (t = *all_ips, i=0; t != NULL && i < numips ; t = t->next, i++) {
230 available_public_ips->ips[i].pnn = t->pnn;
231 memcpy(&(available_public_ips->ips[i].addr), &(t->addr), sizeof(t->addr));
234 (*ctdb)->nodes = talloc_array(*ctdb, struct ctdb_node *, numnodes); // FIXME: bogus size, overkill
236 /* Setup both nodemap and ctdb->nodes. Mark all nodes as
237 * healthy - change this later. */
238 for (i=0; i < numnodes; i++) {
239 (*nodemap)->nodes[i].pnn = i;
240 (*nodemap)->nodes[i].flags = nodeflags[i];
241 /* nodemap->nodes[i].sockaddr is uninitialised */
243 (*ctdb)->nodes[i] = talloc(*ctdb, struct ctdb_node);
244 (*ctdb)->nodes[i]->pnn = i;
245 (*ctdb)->nodes[i]->flags = nodeflags[i];
246 (*ctdb)->nodes[i]->available_public_ips = available_public_ips;
247 (*ctdb)->nodes[i]->known_public_ips = available_public_ips;
251 /* IP layout is read from stdin. */
252 void ctdb_test_lcp2_allocate_unassigned(const char nodestates[])
254 struct ctdb_context *ctdb;
255 struct ctdb_public_ip_list *all_ips;
256 struct ctdb_node_map *nodemap;
258 uint32_t *lcp2_imbalances;
261 ctdb_test_init(nodestates, &ctdb, &all_ips, &nodemap);
263 lcp2_init(ctdb, nodemap,
264 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
265 all_ips, &lcp2_imbalances, &newly_healthy);
267 lcp2_allocate_unassigned(ctdb, nodemap,
268 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
269 all_ips, lcp2_imbalances);
271 print_ctdb_public_ip_list(all_ips);
276 /* IP layout is read from stdin. */
277 void ctdb_test_lcp2_failback(const char nodestates[])
279 struct ctdb_context *ctdb;
280 struct ctdb_public_ip_list *all_ips;
281 struct ctdb_node_map *nodemap;
283 uint32_t *lcp2_imbalances;
286 ctdb_test_init(nodestates, &ctdb, &all_ips, &nodemap);
288 lcp2_init(ctdb, nodemap,
289 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
290 all_ips, &lcp2_imbalances, &newly_healthy);
292 lcp2_failback(ctdb, nodemap,
293 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
294 all_ips, lcp2_imbalances, newly_healthy);
296 print_ctdb_public_ip_list(all_ips);
301 /* IP layout is read from stdin. */
302 void ctdb_test_lcp2_failback_loop(const char nodestates[])
304 struct ctdb_context *ctdb;
305 struct ctdb_public_ip_list *all_ips;
306 struct ctdb_node_map *nodemap;
308 uint32_t *lcp2_imbalances;
311 ctdb_test_init(nodestates, &ctdb, &all_ips, &nodemap);
313 lcp2_init(ctdb, nodemap,
314 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
315 all_ips, &lcp2_imbalances, &newly_healthy);
318 if (lcp2_failback(ctdb, nodemap,
319 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
320 all_ips, lcp2_imbalances, newly_healthy)) {
324 print_ctdb_public_ip_list(all_ips);
329 /* IP layout is read from stdin. */
330 void ctdb_test_ctdb_takeover_run_core(const char nodestates[])
332 struct ctdb_context *ctdb;
333 struct ctdb_public_ip_list *all_ips;
334 struct ctdb_node_map *nodemap;
336 ctdb_test_init(nodestates, &ctdb, &all_ips, &nodemap);
338 ctdb_takeover_run_core(ctdb, nodemap, &all_ips);
340 print_ctdb_public_ip_list(all_ips);
347 fprintf(stderr, "usage: ctdb_takeover_tests <op>\n");
351 int main(int argc, const char *argv[])
353 LogLevel = DEBUG_DEBUG;
354 if (getenv("CTDB_TEST_LOGLEVEL")) {
355 LogLevel = atoi(getenv("CTDB_TEST_LOGLEVEL"));
362 if (strcmp(argv[1], "ip_list") == 0) {
363 ctdb_test_read_ctdb_public_ip_list();
364 } else if (strcmp(argv[1], "ip_distance") == 0) {
365 ctdb_test_ip_distance();
366 } else if (argc == 4 && strcmp(argv[1], "ip_distance_2_sum") == 0) {
367 ctdb_test_ip_distance_2_sum(argv[2], atoi(argv[3]));
368 } else if (argc >= 3 && strcmp(argv[1], "lcp2_imbalance") == 0) {
369 ctdb_test_lcp2_imbalance(atoi(argv[2]));
370 } else if (argc == 3 && strcmp(argv[1], "lcp2_allocate_unassigned") == 0) {
371 ctdb_test_lcp2_allocate_unassigned(argv[2]);
372 } else if (argc == 3 && strcmp(argv[1], "lcp2_failback") == 0) {
373 ctdb_test_lcp2_failback(argv[2]);
374 } else if (argc == 3 && strcmp(argv[1], "lcp2_failback_loop") == 0) {
375 ctdb_test_lcp2_failback_loop(argv[2]);
376 } else if (argc == 3 && strcmp(argv[1], "ctdb_takeover_run_core") == 0) {
377 ctdb_test_ctdb_takeover_run_core(argv[2]);