summaryrefslogtreecommitdiffstats
path: root/ctdb/server/ipalloc_deterministic.c
diff options
context:
space:
mode:
Diffstat (limited to 'ctdb/server/ipalloc_deterministic.c')
-rw-r--r--ctdb/server/ipalloc_deterministic.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/ctdb/server/ipalloc_deterministic.c b/ctdb/server/ipalloc_deterministic.c
new file mode 100644
index 0000000..43680ba
--- /dev/null
+++ b/ctdb/server/ipalloc_deterministic.c
@@ -0,0 +1,191 @@
+/*
+ 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;
+}