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 "system/network.h"
26 #include "lib/util/debug.h"
28 #include "protocol/protocol.h"
29 #include "protocol/protocol_util.h"
30 #include "common/logging.h"
31 #include "common/system.h"
33 #include "server/ipalloc.h"
35 #include "ipalloc_read_known_ips.h"
37 static void print_ctdb_public_ip_list(TALLOC_CTX *mem_ctx,
38 struct public_ip_list * ips)
42 ctdb_sock_addr_to_string(mem_ctx, &(ips->addr), false),
48 static uint32_t *get_tunable_values(TALLOC_CTX *tmp_ctx,
51 static enum ctdb_runstate *get_runstate(TALLOC_CTX *tmp_ctx,
54 static void read_ctdb_public_ip_info(TALLOC_CTX *ctx,
57 struct ctdb_public_ip_list ** known,
58 struct ctdb_public_ip_list ** avail)
61 enum ctdb_runstate *runstate;
63 *known = ipalloc_read_known_ips(ctx, numnodes, multi);
64 assert(*known != NULL);
66 *avail = talloc_zero_array(ctx, struct ctdb_public_ip_list,
68 assert(*avail != NULL);
70 runstate = get_runstate(ctx, numnodes);
71 for (n = 0; n < numnodes; n++) {
72 if (runstate[n] == CTDB_RUNSTATE_RUNNING) {
73 (*avail)[n] = (*known)[n];
78 static uint32_t *get_tunable_values(TALLOC_CTX *tmp_ctx,
84 uint32_t *tvals = talloc_zero_array(tmp_ctx, uint32_t, numnodes);
85 char *t = getenv(tunable);
88 if (strcmp(t, "1") == 0) {
89 for (i=0; i<numnodes; i++) {
97 (uint32_t) strtol(tok, NULL, 0);
99 tok = strtok(NULL, ",");
102 fprintf(stderr, "ERROR: Wrong number of values in %s\n", tunable);
111 static enum ctdb_runstate *get_runstate(TALLOC_CTX *tmp_ctx,
116 enum ctdb_runstate *runstate =
117 talloc_zero_array(tmp_ctx, enum ctdb_runstate, numnodes);
118 char *t = getenv("CTDB_TEST_RUNSTATE");
121 for (i=0; i<numnodes; i++) {
122 runstate[i] = CTDB_RUNSTATE_RUNNING;
125 tvals = get_tunable_values(tmp_ctx, numnodes, "CTDB_TEST_RUNSTATE");
126 for (i=0; i<numnodes; i++) {
127 runstate[i] = (enum ctdb_runstate) tvals[i];
135 /* Fake up enough CTDB state to be able to run the IP allocation
136 * algorithm. Usually this sets up some standard state, sets the node
137 * states from the command-line and reads the current IP layout from
140 * However, if read_ips_for_multiple_nodes is true then each node's
141 * idea of the IP layout is read separately from stdin. In this mode
142 * is doesn't make much sense to use read_ctdb_public_ip_info's
143 * optional ALLOWED_PNN,... list in the input, since each node is
144 * being handled separately anyway. IPs for each node are separated
145 * by a blank line. This mode is for testing weird behaviours where
146 * the IP layouts differs across nodes and we want to improve
147 * create_merged_ip_list(), so should only be used in tests of
148 * ipalloc(). Yes, it is a hack... :-)
150 static void ctdb_test_init(TALLOC_CTX *mem_ctx,
151 const char nodestates[],
152 struct ipalloc_state **ipalloc_state,
153 bool read_ips_for_multiple_nodes)
155 struct ctdb_public_ip_list *known;
156 struct ctdb_public_ip_list *avail;
159 struct ctdb_node_map *nodemap;
160 uint32_t noiptakeover;
161 ctdb_sock_addr sa_zero = { .ip = { 0 } };
162 enum ipalloc_algorithm algorithm;
165 /* Avoid that const */
166 ns = talloc_strdup(mem_ctx, nodestates);
168 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
169 assert(nodemap != NULL);
171 tok = strtok(ns, ",");
172 while (tok != NULL) {
174 nodemap->node = talloc_realloc(nodemap, nodemap->node,
175 struct ctdb_node_and_flags, n+1);
176 nodemap->node[n].pnn = n;
177 nodemap->node[n].flags = (uint32_t) strtol(tok, NULL, 0);
178 nodemap->node[n].addr = sa_zero;
180 tok = strtok(NULL, ",");
183 algorithm = IPALLOC_LCP2;
184 if ((t = getenv("CTDB_IP_ALGORITHM"))) {
185 if (strcmp(t, "lcp2") == 0) {
186 algorithm = IPALLOC_LCP2;
187 } else if (strcmp(t, "nondet") == 0) {
188 algorithm = IPALLOC_NONDETERMINISTIC;
189 } else if (strcmp(t, "det") == 0) {
190 algorithm = IPALLOC_DETERMINISTIC;
193 ("ERROR: unknown IP algorithm %s\n", t));
198 t = getenv("CTDB_SET_NoIPTakeover");
200 noiptakeover = (uint32_t) strtol(t, NULL, 0);
205 *ipalloc_state = ipalloc_state_init(mem_ctx, nodemap->num,
210 assert(*ipalloc_state != NULL);
212 read_ctdb_public_ip_info(mem_ctx, nodemap->num,
213 read_ips_for_multiple_nodes,
216 /* Drop available IPs for INACTIVE/DISABLED nodes */
217 for (n = 0; n < nodemap->num; n++) {
218 uint32_t flags = nodemap->node[n].flags;
219 if ((flags & (NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED)) != 0) {
224 ipalloc_set_public_ips(*ipalloc_state, known, avail);
227 /* IP layout is read from stdin. See comment for ctdb_test_init() for
228 * explanation of read_ips_for_multiple_nodes.
230 static void ctdb_test_ipalloc(const char nodestates[],
231 bool read_ips_for_multiple_nodes)
233 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
234 struct ipalloc_state *ipalloc_state;
236 ctdb_test_init(tmp_ctx, nodestates, &ipalloc_state,
237 read_ips_for_multiple_nodes);
239 print_ctdb_public_ip_list(tmp_ctx, ipalloc(ipalloc_state));
241 talloc_free(tmp_ctx);
244 static void usage(void)
246 fprintf(stderr, "usage: ctdb_takeover_tests <op>\n");
250 int main(int argc, const char *argv[])
253 const char *debuglevelstr = getenv("CTDB_TEST_LOGLEVEL");
255 setup_logging("ctdb_takeover_tests", DEBUG_STDERR);
257 if (! debug_level_parse(debuglevelstr, &loglevel)) {
258 loglevel = DEBUG_DEBUG;
260 debuglevel_set(loglevel);
267 strcmp(argv[1], "ipalloc") == 0) {
268 ctdb_test_ipalloc(argv[2], false);
269 } else if (argc == 4 &&
270 strcmp(argv[1], "ipalloc") == 0 &&
271 strcmp(argv[3], "multi") == 0) {
272 ctdb_test_ipalloc(argv[2], true);