source: vendor/current/ctdb/server/ipalloc_common.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 4.8 KB
Line 
1/*
2 ctdb ip takeover code
3
4 Copyright (C) Ronnie Sahlberg 2007
5 Copyright (C) Andrew Tridgell 2007
6 Copyright (C) Martin Schwenke 2011
7
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.
12
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.
17
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/>.
20*/
21
22#include "replace.h"
23#include "system/network.h"
24
25#include "ctdb_private.h"
26
27#include "lib/util/time.h"
28
29#include "lib/util/debug.h"
30#include "common/logging.h"
31
32#include "common/common.h"
33#include "common/rb_tree.h"
34
35#include "include/ctdb_protocol.h"
36
37#include "server/ipalloc_private.h"
38
39#define TAKEOVER_TIMEOUT() timeval_current_ofs(ctdb->tunable.takeover_timeout,0)
40
41/* Given a physical node, return the number of
42 public addresses that is currently assigned to this node.
43*/
44int node_ip_coverage(int32_t pnn, struct public_ip_list *ips)
45{
46 int num=0;
47
48 for (;ips;ips=ips->next) {
49 if (ips->pnn == pnn) {
50 num++;
51 }
52 }
53 return num;
54}
55
56
57/* Can the given node host the given IP: is the public IP known to the
58 * node and is NOIPHOST unset?
59*/
60static bool can_node_host_ip(struct ipalloc_state *ipalloc_state,
61 int32_t pnn,
62 struct public_ip_list *ip)
63{
64 struct ctdb_public_ip_list_old *public_ips;
65 int i;
66
67 if (ipalloc_state->noiphost[pnn]) {
68 return false;
69 }
70
71 public_ips = ipalloc_state->available_public_ips[pnn];
72
73 if (public_ips == NULL) {
74 return false;
75 }
76
77 for (i=0; i<public_ips->num; i++) {
78 if (ctdb_same_ip(&ip->addr, &public_ips->ips[i].addr)) {
79 /* yes, this node can serve this public ip */
80 return true;
81 }
82 }
83
84 return false;
85}
86
87bool can_node_takeover_ip(struct ipalloc_state *ipalloc_state,
88 int32_t pnn,
89 struct public_ip_list *ip)
90{
91 if (ipalloc_state->noiptakeover[pnn]) {
92 return false;
93 }
94
95 return can_node_host_ip(ipalloc_state, pnn, ip);
96}
97
98/* search the node lists list for a node to takeover this ip.
99 pick the node that currently are serving the least number of ips
100 so that the ips get spread out evenly.
101*/
102int find_takeover_node(struct ipalloc_state *ipalloc_state,
103 struct public_ip_list *ip)
104{
105 int pnn, min=0, num;
106 int i, numnodes;
107
108 numnodes = ipalloc_state->num;
109 pnn = -1;
110 for (i=0; i<numnodes; i++) {
111 /* verify that this node can serve this ip */
112 if (!can_node_takeover_ip(ipalloc_state, i, ip)) {
113 /* no it couldnt so skip to the next node */
114 continue;
115 }
116
117 num = node_ip_coverage(i, ipalloc_state->all_ips);
118 /* was this the first node we checked ? */
119 if (pnn == -1) {
120 pnn = i;
121 min = num;
122 } else {
123 if (num < min) {
124 pnn = i;
125 min = num;
126 }
127 }
128 }
129 if (pnn == -1) {
130 DEBUG(DEBUG_WARNING,(__location__ " Could not find node to take over public address '%s'\n",
131 ctdb_addr_to_str(&ip->addr)));
132
133 return -1;
134 }
135
136 ip->pnn = pnn;
137 return 0;
138}
139
140uint32_t *ip_key(ctdb_sock_addr *ip)
141{
142 static uint32_t key[IP_KEYLEN];
143
144 bzero(key, sizeof(key));
145
146 switch (ip->sa.sa_family) {
147 case AF_INET:
148 key[3] = htonl(ip->ip.sin_addr.s_addr);
149 break;
150 case AF_INET6: {
151 uint32_t *s6_a32 = (uint32_t *)&(ip->ip6.sin6_addr.s6_addr);
152 key[0] = htonl(s6_a32[0]);
153 key[1] = htonl(s6_a32[1]);
154 key[2] = htonl(s6_a32[2]);
155 key[3] = htonl(s6_a32[3]);
156 break;
157 }
158 default:
159 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
160 return key;
161 }
162
163 return key;
164}
165
166/* Allocate any unassigned IPs just by looping through the IPs and
167 * finding the best node for each.
168 */
169void basic_allocate_unassigned(struct ipalloc_state *ipalloc_state)
170{
171 struct public_ip_list *t;
172
173 /* loop over all ip's and find a physical node to cover for
174 each unassigned ip.
175 */
176 for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
177 if (t->pnn == -1) {
178 if (find_takeover_node(ipalloc_state, t)) {
179 DEBUG(DEBUG_WARNING,
180 ("Failed to find node to cover ip %s\n",
181 ctdb_addr_to_str(&t->addr)));
182 }
183 }
184 }
185}
186
187void unassign_unsuitable_ips(struct ipalloc_state *ipalloc_state)
188{
189 struct public_ip_list *t;
190
191 /* verify that the assigned nodes can serve that public ip
192 and set it to -1 if not
193 */
194 for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
195 if (t->pnn == -1) {
196 continue;
197 }
198 if (!can_node_host_ip(ipalloc_state, t->pnn, t) != 0) {
199 /* this node can not serve this ip. */
200 DEBUG(DEBUG_DEBUG,("Unassign IP: %s from %d\n",
201 ctdb_addr_to_str(&(t->addr)),
202 t->pnn));
203 t->pnn = -1;
204 }
205 }
206}
Note: See TracBrowser for help on using the repository browser.