diff options
-rw-r--r-- | ctdb/include/ctdb_protocol.h | 2 | ||||
-rw-r--r-- | ctdb/server/ctdb_takeover.c | 65 |
2 files changed, 50 insertions, 17 deletions
diff --git a/ctdb/include/ctdb_protocol.h b/ctdb/include/ctdb_protocol.h index a153f017fc..ae989a95c9 100644 --- a/ctdb/include/ctdb_protocol.h +++ b/ctdb/include/ctdb_protocol.h @@ -559,6 +559,8 @@ struct ctdb_node_map { #define NODE_FLAGS_DISABLED (NODE_FLAGS_UNHEALTHY|NODE_FLAGS_PERMANENTLY_DISABLED) #define NODE_FLAGS_INACTIVE (NODE_FLAGS_DELETED|NODE_FLAGS_DISCONNECTED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED) +#define NODE_FLAGS_NOIPFAILBACK 0x01000000 /* this node can not be failed back onto, this flag is ONLY valid within the recovery daemon */ + struct ctdb_public_ip { uint32_t pnn; diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c index bff22a8240..dba375b08e 100644 --- a/ctdb/server/ctdb_takeover.c +++ b/ctdb/server/ctdb_takeover.c @@ -1980,19 +1980,6 @@ try_again: basic_allocate_unassigned(ctdb, nodemap, mask, all_ips); } - /* If we dont want ips to fail back after a node becomes healthy - again, we wont even try to reallocat the ip addresses so that - they are evenly spread out. - This can NOT be used at the same time as DeterministicIPs ! - */ - if (1 == ctdb->tunable.no_ip_failback) { - if (1 == ctdb->tunable.deterministic_public_ips) { - DEBUG(DEBUG_ERR, ("ERROR: You can not use 'DeterministicIPs' and 'NoIPFailback' at the same time\n")); - } - goto finished; - } - - /* now, try to make sure the ip adresses are evenly distributed across the node. */ @@ -2008,16 +1995,37 @@ try_again: /* finished distributing the public addresses, now just send the info out to the nodes - */ -finished: - - /* at this point ->pnn is the node which will own each IP + at this point ->pnn is the node which will own each IP or -1 if there is no node that can cover this ip */ return; } +static void noipfailback_cb(struct ctdb_context *ctdb, uint32_t pnn, int32_t res, TDB_DATA outdata, void *callback) +{ + struct ctdb_node_map *nodemap = (struct ctdb_node_map *)callback; + + if (res != 0) { + DEBUG(DEBUG_ERR,("Failure to read NoIPFailback tunable from remote node %d\n", pnn)); + return; + } + + if (outdata.dsize != sizeof(uint32_t)) { + DEBUG(DEBUG_ERR,("Wrong size of returned data when reading NoIPFailback tunable from node %d. Expected %d bytes but received %d bytes\n", pnn, (int)sizeof(uint32_t), (int)outdata.dsize)); + return; + } + + if (pnn >= nodemap->num) { + DEBUG(DEBUG_ERR,("Got NoIPFailback reply from node %d but nodemap only has %d entries\n", pnn, nodemap->num)); + return; + } + + if (*(uint32_t *)outdata.dptr != 0) { + nodemap->nodes[pnn].flags |= NODE_FLAGS_NOIPFAILBACK; + } +} + /* make any IP alias changes for public addresses that are necessary */ @@ -2026,6 +2034,7 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap) int i; struct ctdb_public_ip ip; struct ctdb_public_ipv4 ipv4; + struct ctdb_control_get_tunable *t; uint32_t *nodes; struct ctdb_public_ip_list *all_ips, *tmp_ip; TDB_DATA data; @@ -2042,6 +2051,28 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap) goto ipreallocated; } + + /* assume all nodes do support failback */ + for (i=0;i<nodemap->num;i++) { + nodemap->nodes[i].flags &= ~NODE_FLAGS_NOIPFAILBACK; + } + data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen("NoIPFailback") + 1; + data.dptr = talloc_size(tmp_ctx, data.dsize); + t = (struct ctdb_control_get_tunable *)data.dptr; + t->length = strlen("NoIPFailback")+1; + memcpy(t->name, "NoIPFailback", t->length); + nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true); + if (ctdb_client_async_control(ctdb, CTDB_CONTROL_GET_TUNABLE, + nodes, 0, TAKEOVER_TIMEOUT(), + false, data, + noipfailback_cb, NULL, + nodemap) != 0) { + DEBUG(DEBUG_ERR, (__location__ " ctdb_control to get noipfailback tunable failed\n")); + } + talloc_free(nodes); + talloc_free(data.dptr); + + ZERO_STRUCT(ip); /* Do the IP reassignment calculations */ |