diff --git a/ctdb/doc/ctdbd.1.xml b/ctdb/doc/ctdbd.1.xml
index cf5b142c2b9..5919675b81f 100644
--- a/ctdb/doc/ctdbd.1.xml
+++ b/ctdb/doc/ctdbd.1.xml
@@ -841,7 +841,7 @@
DisableIPFailover
Default: 0
- When enabled, ctdb weill not perform failover or failback. Even if a
+ When enabled, ctdb will not perform failover or failback. Even if a
node fails while holding public IPs, ctdb will not recover the IPs or
assign them to another node.
@@ -853,6 +853,15 @@
+ NoIPTakeover
+ Default: 0
+
+ When set to 1, ctdb will allow ip addresses to be failed over onto this
+ node. Any ip addresses that the node currently hosts will remain on the
+ node but no new ip addresses can be failed over onto the node.
+
+
+
VerboseMemoryNames
Default: 0
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index c80cac550f6..3d5751b9808 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -130,6 +130,7 @@ struct ctdb_tunable {
uint32_t hopcount_make_sticky;
uint32_t sticky_duration;
uint32_t sticky_pindown;
+ uint32_t no_ip_takeover;
};
/*
diff --git a/ctdb/include/ctdb_protocol.h b/ctdb/include/ctdb_protocol.h
index ae989a95c9e..cb34fd5cf15 100644
--- a/ctdb/include/ctdb_protocol.h
+++ b/ctdb/include/ctdb_protocol.h
@@ -559,7 +559,7 @@ 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 */
+#define NODE_FLAGS_NOIPTAKEOVER 0x01000000 /* this node can takeover any new ip addresses, this flag is ONLY valid within the recovery daemon */
struct ctdb_public_ip {
diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c
index 0ed5132ab1b..1037c2f6bb1 100644
--- a/ctdb/server/ctdb_takeover.c
+++ b/ctdb/server/ctdb_takeover.c
@@ -1175,7 +1175,7 @@ static int find_takeover_node(struct ctdb_context *ctdb,
pnn = -1;
for (i=0;inum;i++) {
- if (nodemap->nodes[i].flags & NODE_FLAGS_NOIPFAILBACK) {
+ if (nodemap->nodes[i].flags & NODE_FLAGS_NOIPTAKEOVER) {
/* This node is not allowed to takeover any addresses
*/
continue;
@@ -1472,7 +1472,7 @@ static bool basic_failback(struct ctdb_context *ctdb,
}
/* Only check nodes that are allowed to takeover an ip */
- if (nodemap->nodes[i].flags & NODE_FLAGS_NOIPFAILBACK) {
+ if (nodemap->nodes[i].flags & NODE_FLAGS_NOIPTAKEOVER) {
continue;
}
@@ -1652,7 +1652,7 @@ static void lcp2_allocate_unassigned(struct ctdb_context *ctdb,
for (dstnode=0; dstnode < nodemap->num; dstnode++) {
/* Only check nodes that are allowed to takeover an ip */
- if (nodemap->nodes[dstnode].flags & NODE_FLAGS_NOIPFAILBACK) {
+ if (nodemap->nodes[dstnode].flags & NODE_FLAGS_NOIPTAKEOVER) {
continue;
}
@@ -1766,7 +1766,7 @@ static bool lcp2_failback_candidate(struct ctdb_context *ctdb,
}
/* Only check nodes that are allowed to takeover an ip */
- if (nodemap->nodes[dstnode].flags & NODE_FLAGS_NOIPFAILBACK) {
+ if (nodemap->nodes[dstnode].flags & NODE_FLAGS_NOIPTAKEOVER) {
continue;
}
@@ -2002,6 +2002,19 @@ 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.
*/
@@ -2016,35 +2029,36 @@ try_again:
}
/* finished distributing the public addresses, now just send the
- info out to the nodes
- at this point ->pnn is the node which will own each IP
+ info out to the nodes */
+finished:
+ /* 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)
+static void noiptakeover_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));
+ DEBUG(DEBUG_ERR,("Failure to read NoIPTakeover 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));
+ DEBUG(DEBUG_ERR,("Wrong size of returned data when reading NoIPTakeover 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));
+ DEBUG(DEBUG_ERR,("Got NoIPTakeover 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;
+ nodemap->nodes[pnn].flags |= NODE_FLAGS_NOIPTAKEOVER;
}
}
@@ -2076,20 +2090,20 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap)
/* assume all nodes do support failback */
for (i=0;inum;i++) {
- nodemap->nodes[i].flags &= ~NODE_FLAGS_NOIPFAILBACK;
+ nodemap->nodes[i].flags &= ~NODE_FLAGS_NOIPTAKEOVER;
}
- data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen("NoIPFailback") + 1;
+ data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen("NoIPTakeover") + 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);
+ t->length = strlen("NoIPTakeover")+1;
+ memcpy(t->name, "NoIPTakeover", 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,
+ noiptakeover_cb, NULL,
nodemap) != 0) {
- DEBUG(DEBUG_ERR, (__location__ " ctdb_control to get noipfailback tunable failed\n"));
+ DEBUG(DEBUG_ERR, (__location__ " ctdb_control to get noiptakeover tunable failed\n"));
}
talloc_free(nodes);
talloc_free(data.dptr);
diff --git a/ctdb/server/ctdb_tunables.c b/ctdb/server/ctdb_tunables.c
index 6a913e98008..41ff7ae7e89 100644
--- a/ctdb/server/ctdb_tunables.c
+++ b/ctdb/server/ctdb_tunables.c
@@ -78,7 +78,8 @@ static const struct {
{ "MaxLACount", 20, offsetof(struct ctdb_tunable, max_lacount) },
{ "HopcountMakeSticky", 50, offsetof(struct ctdb_tunable, hopcount_make_sticky) },
{ "StickyDuration", 600, offsetof(struct ctdb_tunable, sticky_duration) },
- { "StickyPindown", 200, offsetof(struct ctdb_tunable, sticky_pindown) }
+ { "StickyPindown", 200, offsetof(struct ctdb_tunable, sticky_pindown) },
+ { "NoIPTakeover", 0, offsetof(struct ctdb_tunable, no_ip_takeover), false }
};
/*