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;
187 numnodes = strlen(nodestates);
189 *ctdb = talloc_zero(NULL, struct ctdb_context);
191 /* Fake things up... */
192 (*ctdb)->num_nodes = numnodes;
194 (*ctdb)->tunable.deterministic_public_ips = 0;
195 (*ctdb)->tunable.disable_ip_failover = 0;
196 (*ctdb)->tunable.no_ip_failback = 0;
198 if (getenv("CTDB_LCP2")) {
199 if (strcmp(getenv("CTDB_LCP2"), "yes") == 0) {
200 (*ctdb)->tunable.lcp2_public_ip_assignment = 1;
202 (*ctdb)->tunable.lcp2_public_ip_assignment = 0;
206 *nodemap = talloc_array(*ctdb, struct ctdb_node_map, numnodes);
207 (*nodemap)->num = numnodes;
209 for (i=0; i < numnodes; i++) {
210 (*nodemap)->nodes[i].pnn = i;
211 (*nodemap)->nodes[i].flags = nodestates[i] - '0';
212 /* *nodemap->nodes[i].sockaddr is uninitialised */
215 *all_ips = read_ctdb_public_ip_list(*ctdb);
217 for (t = *all_ips; t != NULL; t = t->next) {
221 available_public_ips = talloc_array(*ctdb, struct ctdb_all_public_ips, numips); // FIXME: bogus size, overkill
222 available_public_ips->num = numips;
223 for (t = *all_ips, i=0; t != NULL && i < numips ; t = t->next, i++) {
224 available_public_ips->ips[i].pnn = t->pnn;
225 memcpy(&(available_public_ips->ips[i].addr), &(t->addr), sizeof(t->addr));
228 (*ctdb)->nodes = talloc_array(*ctdb, struct ctdb_node *, numnodes); // FIXME: bogus size, overkill
230 /* Setup both nodemap and ctdb->nodes. Mark all nodes as
231 * healthy - change this later. */
232 for (i=0; i < numnodes; i++) {
233 uint32_t flags = nodestates[i] - '0' ? NODE_FLAGS_UNHEALTHY : 0;
234 (*nodemap)->nodes[i].pnn = i;
235 (*nodemap)->nodes[i].flags = flags;
236 /* nodemap->nodes[i].sockaddr is uninitialised */
238 (*ctdb)->nodes[i] = talloc(*ctdb, struct ctdb_node);
239 (*ctdb)->nodes[i]->pnn = i;
240 (*ctdb)->nodes[i]->flags = flags;
241 (*ctdb)->nodes[i]->available_public_ips = available_public_ips;
242 (*ctdb)->nodes[i]->known_public_ips = available_public_ips;
246 /* IP layout is read from stdin. */
247 void ctdb_test_lcp2_allocate_unassigned(const char nodestates[])
249 struct ctdb_context *ctdb;
250 struct ctdb_public_ip_list *all_ips;
251 struct ctdb_node_map *nodemap;
253 uint32_t *lcp2_imbalances;
256 ctdb_test_init(nodestates, &ctdb, &all_ips, &nodemap);
258 lcp2_init(ctdb, nodemap,
259 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
260 all_ips, &lcp2_imbalances, &newly_healthy);
262 lcp2_allocate_unassigned(ctdb, nodemap,
263 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
264 all_ips, lcp2_imbalances);
266 print_ctdb_public_ip_list(all_ips);
271 /* IP layout is read from stdin. */
272 void ctdb_test_lcp2_failback(const char nodestates[])
274 struct ctdb_context *ctdb;
275 struct ctdb_public_ip_list *all_ips;
276 struct ctdb_node_map *nodemap;
278 uint32_t *lcp2_imbalances;
281 ctdb_test_init(nodestates, &ctdb, &all_ips, &nodemap);
283 lcp2_init(ctdb, nodemap,
284 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
285 all_ips, &lcp2_imbalances, &newly_healthy);
287 lcp2_failback(ctdb, nodemap,
288 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
289 all_ips, lcp2_imbalances, newly_healthy);
291 print_ctdb_public_ip_list(all_ips);
296 /* IP layout is read from stdin. */
297 void ctdb_test_lcp2_failback_loop(const char nodestates[])
299 struct ctdb_context *ctdb;
300 struct ctdb_public_ip_list *all_ips;
301 struct ctdb_node_map *nodemap;
303 uint32_t *lcp2_imbalances;
306 ctdb_test_init(nodestates, &ctdb, &all_ips, &nodemap);
308 lcp2_init(ctdb, nodemap,
309 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
310 all_ips, &lcp2_imbalances, &newly_healthy);
313 if (lcp2_failback(ctdb, nodemap,
314 NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED,
315 all_ips, lcp2_imbalances, newly_healthy)) {
319 print_ctdb_public_ip_list(all_ips);
324 /* IP layout is read from stdin. */
325 void ctdb_test_ctdb_takeover_run_core(const char nodestates[])
327 struct ctdb_context *ctdb;
328 struct ctdb_public_ip_list *all_ips;
329 struct ctdb_node_map *nodemap;
331 ctdb_test_init(nodestates, &ctdb, &all_ips, &nodemap);
333 ctdb_takeover_run_core(ctdb, nodemap, &all_ips);
335 print_ctdb_public_ip_list(all_ips);
342 fprintf(stderr, "usage: ctdb_takeover_tests <op>\n");
346 int main(int argc, const char *argv[])
348 LogLevel = DEBUG_DEBUG;
349 if (getenv("CTDB_TEST_LOGLEVEL")) {
350 LogLevel = atoi(getenv("CTDB_TEST_LOGLEVEL"));
357 if (strcmp(argv[1], "ip_list") == 0) {
358 ctdb_test_read_ctdb_public_ip_list();
359 } else if (strcmp(argv[1], "ip_distance") == 0) {
360 ctdb_test_ip_distance();
361 } else if (argc == 4 && strcmp(argv[1], "ip_distance_2_sum") == 0) {
362 ctdb_test_ip_distance_2_sum(argv[2], atoi(argv[3]));
363 } else if (argc >= 3 && strcmp(argv[1], "lcp2_imbalance") == 0) {
364 ctdb_test_lcp2_imbalance(atoi(argv[2]));
365 } else if (argc == 3 && strcmp(argv[1], "lcp2_allocate_unassigned") == 0) {
366 ctdb_test_lcp2_allocate_unassigned(argv[2]);
367 } else if (argc == 3 && strcmp(argv[1], "lcp2_failback") == 0) {
368 ctdb_test_lcp2_failback(argv[2]);
369 } else if (argc == 3 && strcmp(argv[1], "lcp2_failback_loop") == 0) {
370 ctdb_test_lcp2_failback_loop(argv[2]);
371 } else if (argc == 3 && strcmp(argv[1], "ctdb_takeover_run_core") == 0) {
372 ctdb_test_ctdb_takeover_run_core(argv[2]);