#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;
*/
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
/* No failback here! */
+ TALLOC_FREE(home_nodes);
+
return true;
}
--- /dev/null
+#!/bin/sh
+
+. "${TEST_SCRIPTS_DIR}/unit.sh"
+
+setup_ctdb_base "$CTDB_TEST_TMP_DIR" "ctdb-etc"
+
+define_test "3 nodes, 2 healthy with home_nodes"
+
+home_nodes="$CTDB_BASE"/home_nodes
+
+cat > "$home_nodes" <<EOF
+192.168.21.254 2
+192.168.20.251 1
+EOF
+
+required_result <<EOF
+${TEST_DATE_STAMP}Deterministic IPs enabled. Resetting all ip allocations
+${TEST_DATE_STAMP}Unassign IP: 192.168.21.253 from 1
+${TEST_DATE_STAMP}Unassign IP: 192.168.20.253 from 1
+${TEST_DATE_STAMP}Unassign IP: 192.168.20.251 from 1
+${TEST_DATE_STAMP}Unassign IP: 192.168.20.250 from 1
+192.168.21.254 2
+192.168.21.253 0
+192.168.21.252 2
+192.168.20.254 0
+192.168.20.253 0
+192.168.20.252 2
+192.168.20.251 0
+192.168.20.250 0
+192.168.20.249 2
+EOF
+
+simple_test 0,2,0 <<EOF
+192.168.20.249 0
+192.168.20.250 1
+192.168.20.251 2
+192.168.20.252 0
+192.168.20.253 1
+192.168.20.254 2
+192.168.21.252 0
+192.168.21.253 1
+192.168.21.254 2
+EOF
+
+rm "$home_nodes"
--- /dev/null
+#!/bin/sh
+
+. "${TEST_SCRIPTS_DIR}/unit.sh"
+
+setup_ctdb_base "$CTDB_TEST_TMP_DIR" "ctdb-etc"
+
+define_test "3 nodes, 1 healthy with home_nodes"
+
+home_nodes="$CTDB_BASE"/home_nodes
+
+cat > "$home_nodes" <<EOF
+192.168.21.254 2
+192.168.20.251 1
+EOF
+
+required_result <<EOF
+${TEST_DATE_STAMP}Deterministic IPs enabled. Resetting all ip allocations
+${TEST_DATE_STAMP}Unassign IP: 192.168.21.253 from 1
+${TEST_DATE_STAMP}Unassign IP: 192.168.20.254 from 0
+${TEST_DATE_STAMP}Unassign IP: 192.168.20.253 from 1
+${TEST_DATE_STAMP}Unassign IP: 192.168.20.251 from 1
+${TEST_DATE_STAMP}Unassign IP: 192.168.20.250 from 1
+192.168.21.254 2
+192.168.21.253 2
+192.168.21.252 2
+192.168.20.254 2
+192.168.20.253 2
+192.168.20.252 2
+192.168.20.251 2
+192.168.20.250 2
+192.168.20.249 2
+EOF
+
+simple_test 2,2,0 <<EOF
+192.168.20.249 0
+192.168.20.250 1
+192.168.20.251 2
+192.168.20.252 0
+192.168.20.253 1
+192.168.20.254 2
+192.168.21.252 0
+192.168.21.253 1
+192.168.21.254 2
+EOF
+
+rm "$home_nodes"