ctdb-server: Use find_public_ip_vnn() in a couple of extra places
[samba4-gss.git] / ctdb / server / ipalloc_deterministic.c
blob43680ba5c2fcde87f36d200d6a59ec7c042627b7
1 /*
2 ctdb ip takeover code
4 Copyright (C) Ronnie Sahlberg 2007
5 Copyright (C) Andrew Tridgell 2007
6 Copyright (C) Martin Schwenke 2011
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "replace.h"
23 #include "system/network.h"
25 #include "lib/util/debug.h"
26 #include "common/logging.h"
27 #include "common/path.h"
29 #include "protocol/protocol_util.h"
30 #include "lib/util/smb_strtox.h"
31 #include "lib/util/memory.h"
33 #include "server/ipalloc_private.h"
35 struct home_node {
36 ctdb_sock_addr addr;
37 uint32_t pnn;
40 static struct home_node *ipalloc_get_home_nodes(TALLOC_CTX *mem_ctx)
42 char *line = NULL;
43 size_t len = 0;
44 char *fname = NULL;
45 FILE *fp = NULL;
46 struct home_node *result = NULL;
48 fname = path_etcdir_append(mem_ctx, "home_nodes");
49 if (fname == NULL) {
50 goto fail;
53 fp = fopen(fname, "r");
54 if (fp == NULL) {
55 goto fail;
57 TALLOC_FREE(fname);
59 while (true) {
60 size_t num_nodes = talloc_array_length(result);
61 char *saveptr = NULL, *addrstr = NULL, *nodestr = NULL;
62 struct home_node hn = {
63 .pnn = CTDB_UNKNOWN_PNN,
65 struct home_node *tmp = NULL;
66 ssize_t n = 0;
67 int ret;
69 n = getline(&line, &len, fp);
70 if (n < 0) {
71 if (!feof(fp)) {
72 /* real error */
73 goto fail;
75 break;
77 if ((n > 0) && (line[n - 1] == '\n')) {
78 line[n - 1] = '\0';
81 addrstr = strtok_r(line, " \t", &saveptr);
82 if (addrstr == NULL) {
83 continue;
85 nodestr = strtok_r(NULL, " \t", &saveptr);
86 if (nodestr == NULL) {
87 continue;
90 ret = ctdb_sock_addr_from_string(addrstr, &hn.addr, false);
91 if (ret != 0) {
92 DBG_WARNING("Could not parse %s: %s\n",
93 addrstr,
94 strerror(ret));
95 goto fail;
98 hn.pnn = smb_strtoul(nodestr,
99 NULL,
101 &ret,
102 SMB_STR_FULL_STR_CONV);
103 if (ret != 0) {
104 DBG_WARNING("Could not parse \"%s\"\n", nodestr);
105 goto fail;
108 tmp = talloc_realloc(mem_ctx,
109 result,
110 struct home_node,
111 num_nodes + 1);
112 if (tmp == NULL) {
113 goto fail;
115 result = tmp;
116 result[num_nodes] = hn;
119 fclose(fp);
120 fp = NULL;
121 return result;
123 fail:
124 if (fp != NULL) {
125 fclose(fp);
126 fp = NULL;
128 SAFE_FREE(line);
129 TALLOC_FREE(fname);
130 TALLOC_FREE(result);
131 return NULL;
134 bool ipalloc_deterministic(struct ipalloc_state *ipalloc_state)
136 struct home_node *home_nodes = ipalloc_get_home_nodes(ipalloc_state);
137 size_t num_home_nodes = talloc_array_length(home_nodes);
138 struct public_ip_list *t;
139 int i;
140 uint32_t numnodes;
142 numnodes = ipalloc_state->num;
144 DEBUG(DEBUG_NOTICE,("Deterministic IPs enabled. Resetting all ip allocations\n"));
145 /* Allocate IPs to nodes in a modulo fashion so that IPs will
146 * always be allocated the same way for a specific set of
147 * available/unavailable nodes.
150 for (i = 0, t = ipalloc_state->all_ips; t!= NULL; t = t->next, i++) {
151 size_t j;
153 t->pnn = i % numnodes;
155 for (j = 0; j < num_home_nodes; j++) {
156 struct home_node *hn = &home_nodes[j];
158 if (ctdb_sock_addr_same_ip(&t->addr, &hn->addr)) {
160 if (hn->pnn >= numnodes) {
161 DBG_WARNING("pnn %" PRIu32
162 " too large\n",
163 hn->pnn);
164 break;
167 t->pnn = hn->pnn;
168 break;
173 /* IP failback doesn't make sense with deterministic
174 * IPs, since the modulo step above implicitly fails
175 * back IPs to their "home" node.
177 if (ipalloc_state->no_ip_failback) {
178 D_WARNING("WARNING: 'NoIPFailback' set but ignored - "
179 "incompatible with 'Deterministic IPs\n");
182 unassign_unsuitable_ips(ipalloc_state);
184 basic_allocate_unassigned(ipalloc_state);
186 /* No failback here! */
188 TALLOC_FREE(home_nodes);
190 return true;