when we load the public address file, at the same time check if we are already hosti...
[metze/ctdb/wip.git] / server / ctdb_takeover.c
index 9a8f16fe46884a7086a9ee02d25796bdc41c0128..27c9ac07234ec419fd2476d39ac78d21cb9dd836 100644 (file)
@@ -18,7 +18,7 @@
    along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 #include "includes.h"
-#include "lib/events/events.h"
+#include "lib/tevent/tevent.h"
 #include "lib/tdb/include/tdb.h"
 #include "lib/util/dlinklist.h"
 #include "system/network.h"
@@ -331,6 +331,7 @@ static void ctdb_do_takeip_callback(struct ctdb_context *ctdb, int status,
        struct ctdb_do_takeip_state *state =
                talloc_get_type(private_data, struct ctdb_do_takeip_state);
        int32_t ret;
+       TDB_DATA data;
 
        if (status != 0) {
                if (status == -ETIME) {
@@ -351,6 +352,13 @@ static void ctdb_do_takeip_callback(struct ctdb_context *ctdb, int status,
                return;
        }
 
+       data.dptr  = (uint8_t *)ctdb_addr_to_str(&state->vnn->public_address);
+       data.dsize = strlen((char *)data.dptr) + 1;
+       DEBUG(DEBUG_INFO,(__location__ " sending TAKE_IP for '%s'\n", data.dptr));
+
+       ctdb_daemon_send_message(ctdb, ctdb->pnn, CTDB_SRVID_TAKE_IP, data);
+
+
        /* the control succeeded */
        ctdb_request_control_reply(ctdb, state->c, NULL, 0, NULL);
        talloc_free(state);
@@ -887,6 +895,10 @@ static int ctdb_add_public_address(struct ctdb_context *ctdb,
        vnn->public_address      = *addr;
        vnn->public_netmask_bits = mask;
        vnn->pnn                 = -1;
+       if (ctdb_sys_have_ip(addr)) {
+               DEBUG(DEBUG_ERR,("We are already hosting public address '%s'\n", ctdb_addr_to_str(addr)));
+               vnn->pnn = ctdb->pnn;
+       }
 
        for (i=0; vnn->ifaces[i]; i++) {
                ret = ctdb_add_local_iface(ctdb, vnn->ifaces[i]);
@@ -897,6 +909,9 @@ static int ctdb_add_public_address(struct ctdb_context *ctdb,
                        talloc_free(vnn);
                        return -1;
                }
+               if (i == 0) {
+                       vnn->iface = ctdb_find_iface(ctdb, vnn->ifaces[i]);
+               }
        }
 
        DLIST_ADD(ctdb->vnn, vnn);
@@ -1218,7 +1233,7 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap)
        int i, num_healthy, retries;
        struct ctdb_public_ip ip;
        struct ctdb_public_ipv4 ipv4;
-       uint32_t mask;
+       uint32_t mask, *nodes;
        struct ctdb_public_ip_list *all_ips, *tmp_ip;
        int maxnode, maxnum=0, minnode, minnum=0, num;
        TDB_DATA data;
@@ -1227,6 +1242,13 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap)
        struct ctdb_client_control_state *state;
        TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
 
+       /*
+        * ip failover is completely disabled, just send out the 
+        * ipreallocated event.
+        */
+       if (ctdb->tunable.disable_ip_failover != 0) {
+               goto ipreallocated;
+       }
 
        ZERO_STRUCT(ip);
 
@@ -1529,6 +1551,20 @@ finished:
                return -1;
        }
 
+ipreallocated:
+       /* tell all nodes to update natwg */
+       /* send the flags update natgw on all connected nodes */
+       data.dptr  = discard_const("ipreallocated");
+       data.dsize = strlen((char *)data.dptr) + 1; 
+       nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
+       if (ctdb_client_async_control(ctdb, CTDB_CONTROL_RUN_EVENTSCRIPTS,
+                                     nodes, 0, TAKEOVER_TIMEOUT(),
+                                     false, data,
+                                     NULL, NULL,
+                                     NULL) != 0) {
+               DEBUG(DEBUG_ERR, (__location__ " ctdb_control to updatenatgw failed\n"));
+       }
+
        talloc_free(tmp_ctx);
        return 0;
 }
@@ -1562,7 +1598,7 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
        struct ctdb_control_tcp_addr new_addr;
        struct ctdb_control_tcp_addr *tcp_sock = NULL;
        struct ctdb_tcp_list *tcp;
-       struct ctdb_control_tcp_vnn t;
+       struct ctdb_tcp_connection t;
        int ret;
        TDB_DATA data;
        struct ctdb_client_ip *ip;
@@ -1642,8 +1678,8 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
 
        DLIST_ADD(client->tcp_list, tcp);
 
-       t.src  = tcp_sock->src;
-       t.dest = tcp_sock->dest;
+       t.src_addr = tcp_sock->src;
+       t.dst_addr = tcp_sock->dest;
 
        data.dptr = (uint8_t *)&t;
        data.dsize = sizeof(t);
@@ -1699,22 +1735,24 @@ static struct ctdb_tcp_connection *ctdb_tcp_find(struct ctdb_tcp_array *array,
        return NULL;
 }
 
+
+
 /*
   called by a daemon to inform us of a TCP connection that one of its
   clients managing that should tickled with an ACK when IP takeover is
   done
  */
-int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
+int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata, bool tcp_update_needed)
 {
-       struct ctdb_control_tcp_vnn *p = (struct ctdb_control_tcp_vnn *)indata.dptr;
+       struct ctdb_tcp_connection *p = (struct ctdb_tcp_connection *)indata.dptr;
        struct ctdb_tcp_array *tcparray;
        struct ctdb_tcp_connection tcp;
        struct ctdb_vnn *vnn;
 
-       vnn = find_public_ip_vnn(ctdb, &p->dest);
+       vnn = find_public_ip_vnn(ctdb, &p->dst_addr);
        if (vnn == NULL) {
                DEBUG(DEBUG_INFO,(__location__ " got TCP_ADD control for an address which is not a public address '%s'\n",
-                       ctdb_addr_to_str(&p->dest)));
+                       ctdb_addr_to_str(&p->dst_addr)));
 
                return -1;
        }
@@ -1734,16 +1772,20 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
                tcparray->connections = talloc_size(tcparray, sizeof(struct ctdb_tcp_connection));
                CTDB_NO_MEMORY(ctdb, tcparray->connections);
 
-               tcparray->connections[tcparray->num].src_addr = p->src;
-               tcparray->connections[tcparray->num].dst_addr = p->dest;
+               tcparray->connections[tcparray->num].src_addr = p->src_addr;
+               tcparray->connections[tcparray->num].dst_addr = p->dst_addr;
                tcparray->num++;
+
+               if (tcp_update_needed) {
+                       vnn->tcp_update_needed = true;
+               }
                return 0;
        }
 
 
        /* Do we already have this tickle ?*/
-       tcp.src_addr = p->src;
-       tcp.dst_addr = p->dest;
+       tcp.src_addr = p->src_addr;
+       tcp.dst_addr = p->dst_addr;
        if (ctdb_tcp_find(vnn->tcp_array, &tcp) != NULL) {
                DEBUG(DEBUG_DEBUG,("Already had tickle info for %s:%u for vnn:%u\n",
                        ctdb_addr_to_str(&tcp.dst_addr),
@@ -1759,8 +1801,8 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
        CTDB_NO_MEMORY(ctdb, tcparray->connections);
 
        vnn->tcp_array = tcparray;
-       tcparray->connections[tcparray->num].src_addr = p->src;
-       tcparray->connections[tcparray->num].dst_addr = p->dest;
+       tcparray->connections[tcparray->num].src_addr = p->src_addr;
+       tcparray->connections[tcparray->num].dst_addr = p->dst_addr;
        tcparray->num++;
                                
        DEBUG(DEBUG_INFO,("Added tickle info for %s:%u from vnn %u\n",
@@ -1768,6 +1810,10 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
                ntohs(tcp.dst_addr.ip.sin_port),
                vnn->pnn));
 
+       if (tcp_update_needed) {
+               vnn->tcp_update_needed = true;
+       }
+
        return 0;
 }
 
@@ -1835,6 +1881,20 @@ static void ctdb_remove_tcp_connection(struct ctdb_context *ctdb, struct ctdb_tc
 }
 
 
+/*
+  called by a daemon to inform us of a TCP connection that one of its
+  clients used are no longer needed in the tickle database
+ */
+int32_t ctdb_control_tcp_remove(struct ctdb_context *ctdb, TDB_DATA indata)
+{
+       struct ctdb_tcp_connection *conn = (struct ctdb_tcp_connection *)indata.dptr;
+
+       ctdb_remove_tcp_connection(ctdb, conn);
+
+       return 0;
+}
+
+
 /*
   called when a daemon restarts - send all tickes for all public addresses
   we are serving immediately to the new node.
@@ -2411,8 +2471,9 @@ static int ctdb_killtcp_add_connection(struct ctdb_context *ctdb,
 
        if (killtcp->fde == NULL) {
                killtcp->fde = event_add_fd(ctdb->ev, killtcp, killtcp->capture_fd, 
-                                           EVENT_FD_READ | EVENT_FD_AUTOCLOSE, 
+                                           EVENT_FD_READ,
                                            capture_tcp_handler, killtcp);
+               tevent_fd_set_auto_close(killtcp->fde);
 
                /* We also need to set up some events to tickle all these connections
                   until they are all reset