s3: smbd: Cleanup. smb2_file_rename_information() can never have a @GMT path in the...
[Samba.git] / ctdb / server / ipalloc_common.c
bloba5177d41dc6bd8a0657b0640f98d704db224bfc1
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 "ctdb_private.h"
27 #include "lib/util/time.h"
29 #include "lib/util/debug.h"
30 #include "common/logging.h"
32 #include "common/common.h"
34 #include "protocol/protocol_util.h"
36 #include "server/ipalloc_private.h"
38 #define TAKEOVER_TIMEOUT() timeval_current_ofs(ctdb->tunable.takeover_timeout,0)
40 /* Given a physical node, return the number of
41 public addresses that is currently assigned to this node.
43 int node_ip_coverage(uint32_t pnn, struct public_ip_list *ips)
45 int num=0;
47 for (;ips;ips=ips->next) {
48 if (ips->pnn == pnn) {
49 num++;
52 return num;
56 /* Can the given node host the given IP: is the public IP known to the
57 * node and is NOIPHOST unset?
59 static bool can_node_host_ip(struct ipalloc_state *ipalloc_state,
60 int32_t pnn,
61 struct public_ip_list *ip)
63 return bitmap_query(ip->available_on, pnn);
66 bool can_node_takeover_ip(struct ipalloc_state *ipalloc_state,
67 int32_t pnn,
68 struct public_ip_list *ip)
70 if (ipalloc_state->no_ip_takeover) {
71 return false;
74 return can_node_host_ip(ipalloc_state, pnn, ip);
77 /* search the node lists list for a node to takeover this ip.
78 pick the node that currently are serving the least number of ips
79 so that the ips get spread out evenly.
81 int find_takeover_node(struct ipalloc_state *ipalloc_state,
82 struct public_ip_list *ip)
84 unsigned int pnn;
85 int min=0, num;
86 unsigned int i, numnodes;
88 numnodes = ipalloc_state->num;
89 pnn = CTDB_UNKNOWN_PNN;
90 for (i=0; i<numnodes; i++) {
91 /* verify that this node can serve this ip */
92 if (!can_node_takeover_ip(ipalloc_state, i, ip)) {
93 /* no it couldn't so skip to the next node */
94 continue;
97 num = node_ip_coverage(i, ipalloc_state->all_ips);
98 /* was this the first node we checked ? */
99 if (pnn == CTDB_UNKNOWN_PNN) {
100 pnn = i;
101 min = num;
102 } else {
103 if (num < min) {
104 pnn = i;
105 min = num;
109 if (pnn == CTDB_UNKNOWN_PNN) {
110 DEBUG(DEBUG_WARNING,(__location__ " Could not find node to take over public address '%s'\n",
111 ctdb_sock_addr_to_string(ipalloc_state,
112 &ip->addr,
113 false)));
115 return -1;
118 ip->pnn = pnn;
119 return 0;
122 uint32_t *ip_key(ctdb_sock_addr *ip)
124 static uint32_t key[IP_KEYLEN];
126 bzero(key, sizeof(key));
128 switch (ip->sa.sa_family) {
129 case AF_INET:
130 key[3] = htonl(ip->ip.sin_addr.s_addr);
131 break;
132 case AF_INET6: {
133 uint32_t *s6_a32 = (uint32_t *)&(ip->ip6.sin6_addr.s6_addr);
134 key[0] = htonl(s6_a32[0]);
135 key[1] = htonl(s6_a32[1]);
136 key[2] = htonl(s6_a32[2]);
137 key[3] = htonl(s6_a32[3]);
138 break;
140 default:
141 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
142 return key;
145 return key;
148 /* Allocate any unassigned IPs just by looping through the IPs and
149 * finding the best node for each.
151 void basic_allocate_unassigned(struct ipalloc_state *ipalloc_state)
153 struct public_ip_list *t;
155 /* loop over all ip's and find a physical node to cover for
156 each unassigned ip.
158 for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
159 if (t->pnn == CTDB_UNKNOWN_PNN) {
160 if (find_takeover_node(ipalloc_state, t)) {
161 DEBUG(DEBUG_WARNING,
162 ("Failed to find node to cover ip %s\n",
163 ctdb_sock_addr_to_string(ipalloc_state,
164 &t->addr,
165 false)));
171 void unassign_unsuitable_ips(struct ipalloc_state *ipalloc_state)
173 struct public_ip_list *t;
175 /* verify that the assigned nodes can serve that public ip
176 and set it to CTDB_UNKNOWN_PNN if not
178 for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
179 if (t->pnn == CTDB_UNKNOWN_PNN) {
180 continue;
182 if (!can_node_host_ip(ipalloc_state, t->pnn, t) != 0) {
183 /* this node can not serve this ip. */
184 DEBUG(DEBUG_DEBUG,("Unassign IP: %s from %d\n",
185 ctdb_sock_addr_to_string(
186 ipalloc_state,
187 &t->addr, false),
188 t->pnn));
189 t->pnn = CTDB_UNKNOWN_PNN;