mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
a6b66661c7
With a file "home_nodes" next to "public_addresses" you can assign public IPs to specific nodes when using the deterministic allocation algorithm. Whenever the "home node" is up, the IP address will be assigned to that node, independent of any other deterministic calculation. The line 192.168.21.254 2 in the file "home_nodes" assigns the IP address to node 2. Only when node 2 is not able to host IP addresses, 192.168.21.254 undergoes the normal deterministic IP allocation algorithm. Signed-off-by: Volker Lendecke <vl@samba.org> add home_nodes Reviewed-by: Ralph Boehme <slow@samba.org> Autobuild-User(master): Volker Lendecke <vl@samba.org> Autobuild-Date(master): Tue Oct 10 14:17:19 UTC 2023 on atb-devel-224
192 lines
4.1 KiB
C
192 lines
4.1 KiB
C
/*
|
|
ctdb ip takeover code
|
|
|
|
Copyright (C) Ronnie Sahlberg 2007
|
|
Copyright (C) Andrew Tridgell 2007
|
|
Copyright (C) Martin Schwenke 2011
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "replace.h"
|
|
#include "system/network.h"
|
|
|
|
#include "lib/util/debug.h"
|
|
#include "common/logging.h"
|
|
#include "common/path.h"
|
|
|
|
#include "protocol/protocol_util.h"
|
|
#include "lib/util/smb_strtox.h"
|
|
#include "lib/util/memory.h"
|
|
|
|
#include "server/ipalloc_private.h"
|
|
|
|
struct home_node {
|
|
ctdb_sock_addr addr;
|
|
uint32_t pnn;
|
|
};
|
|
|
|
static struct home_node *ipalloc_get_home_nodes(TALLOC_CTX *mem_ctx)
|
|
{
|
|
char *line = NULL;
|
|
size_t len = 0;
|
|
char *fname = NULL;
|
|
FILE *fp = NULL;
|
|
struct home_node *result = NULL;
|
|
|
|
fname = path_etcdir_append(mem_ctx, "home_nodes");
|
|
if (fname == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
fp = fopen(fname, "r");
|
|
if (fp == NULL) {
|
|
goto fail;
|
|
}
|
|
TALLOC_FREE(fname);
|
|
|
|
while (true) {
|
|
size_t num_nodes = talloc_array_length(result);
|
|
char *saveptr = NULL, *addrstr = NULL, *nodestr = NULL;
|
|
struct home_node hn = {
|
|
.pnn = CTDB_UNKNOWN_PNN,
|
|
};
|
|
struct home_node *tmp = NULL;
|
|
ssize_t n = 0;
|
|
int ret;
|
|
|
|
n = getline(&line, &len, fp);
|
|
if (n < 0) {
|
|
if (!feof(fp)) {
|
|
/* real error */
|
|
goto fail;
|
|
}
|
|
break;
|
|
}
|
|
if ((n > 0) && (line[n - 1] == '\n')) {
|
|
line[n - 1] = '\0';
|
|
}
|
|
|
|
addrstr = strtok_r(line, " \t", &saveptr);
|
|
if (addrstr == NULL) {
|
|
continue;
|
|
}
|
|
nodestr = strtok_r(NULL, " \t", &saveptr);
|
|
if (nodestr == NULL) {
|
|
continue;
|
|
}
|
|
|
|
ret = ctdb_sock_addr_from_string(addrstr, &hn.addr, false);
|
|
if (ret != 0) {
|
|
DBG_WARNING("Could not parse %s: %s\n",
|
|
addrstr,
|
|
strerror(ret));
|
|
goto fail;
|
|
}
|
|
|
|
hn.pnn = smb_strtoul(nodestr,
|
|
NULL,
|
|
10,
|
|
&ret,
|
|
SMB_STR_FULL_STR_CONV);
|
|
if (ret != 0) {
|
|
DBG_WARNING("Could not parse \"%s\"\n", nodestr);
|
|
goto fail;
|
|
}
|
|
|
|
tmp = talloc_realloc(mem_ctx,
|
|
result,
|
|
struct home_node,
|
|
num_nodes + 1);
|
|
if (tmp == NULL) {
|
|
goto fail;
|
|
}
|
|
result = tmp;
|
|
result[num_nodes] = hn;
|
|
}
|
|
|
|
fclose(fp);
|
|
fp = NULL;
|
|
return result;
|
|
|
|
fail:
|
|
if (fp != NULL) {
|
|
fclose(fp);
|
|
fp = NULL;
|
|
}
|
|
SAFE_FREE(line);
|
|
TALLOC_FREE(fname);
|
|
TALLOC_FREE(result);
|
|
return NULL;
|
|
}
|
|
|
|
bool ipalloc_deterministic(struct ipalloc_state *ipalloc_state)
|
|
{
|
|
struct home_node *home_nodes = ipalloc_get_home_nodes(ipalloc_state);
|
|
size_t num_home_nodes = talloc_array_length(home_nodes);
|
|
struct public_ip_list *t;
|
|
int i;
|
|
uint32_t numnodes;
|
|
|
|
numnodes = ipalloc_state->num;
|
|
|
|
DEBUG(DEBUG_NOTICE,("Deterministic IPs enabled. Resetting all ip allocations\n"));
|
|
/* Allocate IPs to nodes in a modulo fashion so that IPs will
|
|
* always be allocated the same way for a specific set of
|
|
* available/unavailable nodes.
|
|
*/
|
|
|
|
for (i = 0, t = ipalloc_state->all_ips; t!= NULL; t = t->next, i++) {
|
|
size_t j;
|
|
|
|
t->pnn = i % numnodes;
|
|
|
|
for (j = 0; j < num_home_nodes; j++) {
|
|
struct home_node *hn = &home_nodes[j];
|
|
|
|
if (ctdb_sock_addr_same_ip(&t->addr, &hn->addr)) {
|
|
|
|
if (hn->pnn >= numnodes) {
|
|
DBG_WARNING("pnn %" PRIu32
|
|
" too large\n",
|
|
hn->pnn);
|
|
break;
|
|
}
|
|
|
|
t->pnn = hn->pnn;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* IP failback doesn't make sense with deterministic
|
|
* IPs, since the modulo step above implicitly fails
|
|
* back IPs to their "home" node.
|
|
*/
|
|
if (ipalloc_state->no_ip_failback) {
|
|
D_WARNING("WARNING: 'NoIPFailback' set but ignored - "
|
|
"incompatible with 'Deterministic IPs\n");
|
|
}
|
|
|
|
unassign_unsuitable_ips(ipalloc_state);
|
|
|
|
basic_allocate_unassigned(ipalloc_state);
|
|
|
|
/* No failback here! */
|
|
|
|
TALLOC_FREE(home_nodes);
|
|
|
|
return true;
|
|
}
|