In the recovery daemon, keep track of which node we have assigned public ip
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Thu, 8 Apr 2010 04:07:57 +0000 (14:07 +1000)
committerMichael Adam <obnox@samba.org>
Mon, 26 Aug 2013 11:34:20 +0000 (13:34 +0200)
addresses and verify that the remote nodes have/keep a consistent view of
assigned addresses.

If a remote node has an inconsistent view of addresses visavi the recovery
master this will trigger a full ip reallocation.
(cherry picked from commit f3bf2ab61f8dbbc806ec23a68a87aaedd458e712)

Conflicts:

include/ctdb_private.h

common/rb_tree.h
include/ctdb_private.h
server/ctdb_recoverd.c
server/ctdb_takeover.c

index 984666614a533de1082560f1ad6e99a4397c5b54..4f2ab22d36dd8b846f7b32130f980cac064d9ac5 100644 (file)
 
 #define TRBT_RED               0x00
 #define TRBT_BLACK             0x01
-typedef struct _trbt_node_t {
-       struct _trbt_tree_t *tree;
-       struct _trbt_node_t *parent;
-       struct _trbt_node_t *left;
-       struct _trbt_node_t *right;
+typedef struct trbt_node {
+       struct trbt_tree *tree;
+       struct trbt_node *parent;
+       struct trbt_node *left;
+       struct trbt_node *right;
        uint32_t rb_color;
        uint32_t key32;
        void *data;
 } trbt_node_t;
 
-typedef struct _trbt_tree_t {
+typedef struct trbt_tree {
        trbt_node_t *root;
 /* automatically free the tree when the last node has been deleted */
 #define TRBT_AUTOFREE          0x00000001
index a2af9bb52b6d621e6fe73d4122b3af6715e76670..49bec6311d5eab75b39ae5eb014bc5ecba411db1 100644 (file)
@@ -443,7 +443,7 @@ struct ctdb_context {
        struct ctdb_call_state *pending_calls;
        struct ctdb_client_ip *client_ip_list;
        bool do_checkpublicip;
-       struct _trbt_tree_t *server_ids;        
+       struct trbt_tree *server_ids;   
        const char *event_script_dir;
        const char *notification_script;
        const char *default_public_interface;
@@ -472,6 +472,9 @@ struct ctdb_context {
 
        /* mapping from pid to ctdb_client * */
        struct ctdb_client_pid_list *client_pids;
+
+       /* used in the recovery daemon to remember the ip allocation */
+       struct trbt_tree *ip_tree;
 };
 
 struct ctdb_db_context {
@@ -1678,6 +1681,8 @@ void ctdb_run_notification_script(struct ctdb_context *ctdb, const char *event);
 
 void ctdb_fault_setup(void);
 
+int verify_remote_ip_allocation(struct ctdb_context *ctdb, 
+                               struct ctdb_all_public_ips *ips);
 
 /**
  * structure to pass to a schedule_for_deletion_control
index db2a2caa27d17abfb37c058548bd52ce9e1aaa04..7dcc29a6c6cca195b1c55c2259169e2dd0c0f023 100644 (file)
@@ -1234,6 +1234,7 @@ static void reload_nodes_file(struct ctdb_context *ctdb)
 }
 
 static int ctdb_reload_remote_public_ips(struct ctdb_context *ctdb,
+                                        struct ctdb_recoverd *rec,
                                         struct ctdb_node_map *nodemap,
                                         uint32_t *culprit)
 {
@@ -1280,6 +1281,11 @@ static int ctdb_reload_remote_public_ips(struct ctdb_context *ctdb,
                        return -1;
                }
 
+               if (verify_remote_ip_allocation(ctdb, ctdb->nodes[j]->known_public_ips)) {
+                       DEBUG(DEBUG_ERR,("Node %d has inconsistent public ip allocation and needs update.\n", ctdb->nodes[j]->pnn));
+                       rec->need_takeover_run = true;
+               }
+
                /* grab a new shiny list of public ips from the node */
                ret = ctdb_ctrl_get_public_ips_flags(ctdb,
                                        CONTROL_TIMEOUT(),
@@ -1576,7 +1582,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
        /*
          tell nodes to takeover their public IPs
         */
-       ret = ctdb_reload_remote_public_ips(ctdb, nodemap, &culprit);
+       ret = ctdb_reload_remote_public_ips(ctdb, rec, nodemap, &culprit);
        if (ret != 0) {
                DEBUG(DEBUG_ERR,("Failed to read public ips from remote node %d\n",
                                 culprit));
@@ -1969,7 +1975,7 @@ static void process_ipreallocate_requests(struct ctdb_context *ctdb, struct ctdb
        /* update the list of public ips that a node can handle for
           all connected nodes
        */
-       ret = ctdb_reload_remote_public_ips(ctdb, rec->nodemap, &culprit);
+       ret = ctdb_reload_remote_public_ips(ctdb, rec, rec->nodemap, &culprit);
        if (ret != 0) {
                DEBUG(DEBUG_ERR,("Failed to read public ips from remote node %d\n",
                                 culprit));
@@ -2422,9 +2428,9 @@ static enum monitor_result verify_recmaster(struct ctdb_recoverd *rec, struct ct
 }
 
 
-/* called to check that the allocation of public ip addresses is ok.
+/* called to check that the local allocation of public ip addresses is ok.
 */
-static int verify_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)
 {
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
        struct ctdb_control_get_ifaces *ifaces = NULL;
@@ -3112,7 +3118,7 @@ again:
         */ 
        if (ctdb->do_checkpublicip) {
                if (rec->ip_check_disable_ctx == NULL) {
-                       if (verify_ip_allocation(ctdb, rec, pnn) != 0) {
+                       if (verify_local_ip_allocation(ctdb, rec, pnn) != 0) {
                                DEBUG(DEBUG_ERR, (__location__ " Public IPs were inconsistent.\n"));
                        }
                }
@@ -3382,7 +3388,7 @@ again:
                /* update the list of public ips that a node can handle for
                   all connected nodes
                */
-               ret = ctdb_reload_remote_public_ips(ctdb, nodemap, &culprit);
+               ret = ctdb_reload_remote_public_ips(ctdb, rec, nodemap, &culprit);
                if (ret != 0) {
                        DEBUG(DEBUG_ERR,("Failed to read public ips from remote node %d\n",
                                         culprit));
index 672dd4dc295699e4a6d90b5135dc4f9f80e333d5..c06c595bfaabd4bb54d9685d0438031464f259c7 100644 (file)
@@ -1160,14 +1160,17 @@ static int getips_count_callback(void *param, void *data)
 }
 
 struct ctdb_public_ip_list *
-create_merged_ip_list(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx)
+create_merged_ip_list(struct ctdb_context *ctdb)
 {
        int i, j;
        struct ctdb_public_ip_list *ip_list;
        struct ctdb_all_public_ips *public_ips;
-       trbt_tree_t *ip_tree;
 
-       ip_tree = trbt_create(tmp_ctx, 0);
+       if (ctdb->ip_tree != NULL) {
+               talloc_free(ctdb->ip_tree);
+               ctdb->ip_tree = NULL;
+       }
+       ctdb->ip_tree = trbt_create(ctdb, 0);
 
        for (i=0;i<ctdb->num_nodes;i++) {
                public_ips = ctdb->nodes[i]->known_public_ips;
@@ -1184,13 +1187,13 @@ create_merged_ip_list(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx)
                for (j=0;j<public_ips->num;j++) {
                        struct ctdb_public_ip_list *tmp_ip; 
 
-                       tmp_ip = talloc_zero(tmp_ctx, struct ctdb_public_ip_list);
+                       tmp_ip = talloc_zero(ctdb->ip_tree, struct ctdb_public_ip_list);
                        CTDB_NO_MEMORY_NULL(ctdb, tmp_ip);
                        tmp_ip->pnn  = public_ips->ips[j].pnn;
                        tmp_ip->addr = public_ips->ips[j].addr;
                        tmp_ip->next = NULL;
 
-                       trbt_insertarray32_callback(ip_tree,
+                       trbt_insertarray32_callback(ctdb->ip_tree,
                                IP_KEYLEN, ip_key(&public_ips->ips[j].addr),
                                add_ip_callback,
                                tmp_ip);
@@ -1198,7 +1201,7 @@ create_merged_ip_list(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx)
        }
 
        ip_list = NULL;
-       trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &ip_list);
+       trbt_traversearray32(ctdb->ip_tree, IP_KEYLEN, getips_count_callback, &ip_list);
 
        return ip_list;
 }
@@ -1248,8 +1251,10 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap)
           a full list of all public addresses that exist in the cluster.
           Walk over all node structures and create a merged list of
           all public addresses that exist in the cluster.
+
+          keep the tree of ips around as ctdb->ip_tree
        */
-       all_ips = create_merged_ip_list(ctdb, tmp_ctx);
+       all_ips = create_merged_ip_list(ctdb);
 
        /* If we want deterministic ip allocations, i.e. that the ip addresses
           will always be allocated the same way for a specific set of
@@ -2811,3 +2816,41 @@ int32_t ctdb_control_del_public_address(struct ctdb_context *ctdb, TDB_DATA inda
        return -1;
 }
 
+/* This function is called from the recovery daemon to verify that a remote
+   node has the expected ip allocation.
+   This is verified against ctdb->ip_tree
+*/
+int verify_remote_ip_allocation(struct ctdb_context *ctdb, struct ctdb_all_public_ips *ips)
+{
+       struct ctdb_public_ip_list *tmp_ip; 
+       int i;
+
+       if (ctdb->ip_tree == NULL) {
+               /* dont know the expected allocation yet, assume remote node
+                  is correct. */
+               return 0;
+       }
+
+       if (ips == NULL) {
+               return 0;
+       }
+
+       for (i=0; i<ips->num; i++) {
+               tmp_ip = trbt_lookuparray32(ctdb->ip_tree, IP_KEYLEN, ip_key(&ips->ips[i].addr));
+               if (tmp_ip == NULL) {
+                       DEBUG(DEBUG_ERR,(__location__ " Could not find host for address %s, reassign ips\n", ctdb_addr_to_str(&ips->ips[i].addr)));
+                       return -1;
+               }
+
+               if (tmp_ip->pnn == -1 || ips->ips[i].pnn == -1) {
+                       continue;
+               }
+
+               if (tmp_ip->pnn != ips->ips[i].pnn) {
+                       DEBUG(DEBUG_ERR,("Inconsistent ip allocation. Trigger reallocation.\n"));
+                       return -1;
+               }
+       }
+
+       return 0;
+}