during ip allocation, there are failure modes where a node might hold a ip address
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Fri, 3 Dec 2010 02:28:35 +0000 (13:28 +1100)
committerMichael Adam <obnox@samba.org>
Fri, 6 Jun 2014 13:00:36 +0000 (15:00 +0200)
but thinks it is still unassigned (-1).

add code to the recovery daemon to detect this case and trigger a reallocation
so that the ip gets covered

and change the takeip code to allow for this condition, taking on an ip address that is
already hosted.

cq s1021073
(cherry picked from commit 9020baf27cab7821c9094cda185206fb7af0fee7)

server/ctdb_recoverd.c
server/ctdb_takeover.c

index ac96ccd3d247f63bd8ed51b1f0654c767458ecf6..d4232e001924568b516a873f97c1e2302350c9d6 100644 (file)
@@ -2480,7 +2480,7 @@ static enum monitor_result verify_recmaster(struct ctdb_recoverd *rec, struct ct
 
 /* called to check that the local allocation of public ip addresses is ok.
 */
-static int verify_local_ip_allocation(struct ctdb_context *ctdb, struct ctdb_recoverd *rec, uint32_t pnn)
+static int verify_local_ip_allocation(struct ctdb_context *ctdb, struct ctdb_recoverd *rec, uint32_t pnn, struct ctdb_node_map *nodemap)
 {
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
        struct ctdb_control_get_ifaces *ifaces = NULL;
@@ -2571,11 +2571,17 @@ static int verify_local_ip_allocation(struct ctdb_context *ctdb, struct ctdb_rec
           and we dont have ones we shouldnt have.
           if we find an inconsistency we set recmode to
           active on the local node and wait for the recmaster
-          to do a full blown recovery
+          to do a full blown recovery.
+          also if the pnn is -1 and we are healthy and can host the ip
+          we also request a ip reallocation.
        */
        if (ctdb->tunable.disable_ip_failover == 0) {
                for (j=0; j<ips->num; j++) {
-                       if (ips->ips[j].pnn == pnn) {
+                       if (ips->ips[j].pnn == -1 && nodemap->nodes[pnn].flags == 0) {
+                               DEBUG(DEBUG_CRIT,("Public address '%s' is not assigned and we could serve this ip\n",
+                                               ctdb_addr_to_str(&ips->ips[j].addr)));
+                               need_takeover_run = true;
+                       } else if (ips->ips[j].pnn == pnn) {
                                if (!ctdb_sys_have_ip(&ips->ips[j].addr)) {
                                        DEBUG(DEBUG_CRIT,("Public address '%s' is missing and we should serve this ip\n",
                                                ctdb_addr_to_str(&ips->ips[j].addr)));
@@ -3107,7 +3113,7 @@ static void main_loop(struct ctdb_context *ctdb, struct ctdb_recoverd *rec,
         */ 
        if (ctdb->tunable.disable_ip_failover == 0) {
                if (rec->ip_check_disable_ctx == NULL) {
-                       if (verify_local_ip_allocation(ctdb, rec, pnn) != 0) {
+                       if (verify_local_ip_allocation(ctdb, rec, pnn, nodemap) != 0) {
                                DEBUG(DEBUG_ERR, (__location__ " Public IPs were inconsistent.\n"));
                        }
                }
index 5533f0cf65ec8d8e6f97833c59cb4e20e47a967f..650da207da05f67a9c5e8f13a8aa99601d120d84 100644 (file)
@@ -607,6 +607,15 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
                return -1;
        }
 
+       if (vnn->pnn == -1 && have_ip) {
+               vnn->pnn = ctdb->pnn;
+               DEBUG(DEBUG_CRIT,(__location__ " takeoverip of IP %s is known to the kernel, "
+                                 "and we already have it on iface[%s], update local daemon\n",
+                                ctdb_addr_to_str(&vnn->public_address),
+                                 ctdb_vnn_iface_string(vnn)));
+               return 0;
+       }
+
        if (vnn->iface) {
                if (vnn->iface->link_up) {
                        /* only move when the rebalance gains something */