ctdb-ipalloc: Move create_merged_ip_list() into ipalloc
authorMartin Schwenke <martin@meltin.net>
Mon, 23 May 2016 10:23:18 +0000 (20:23 +1000)
committerAmitay Isaacs <amitay@samba.org>
Mon, 4 Jul 2016 13:42:25 +0000 (15:42 +0200)
How the existing IP layout is constructed and how the merged IP list is
sorted are important aspects of the IP allocation algorithm.  Construct the
merged IP list when known and available IPs are assigned.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
ctdb/server/ctdb_takeover.c
ctdb/server/ipalloc.c
ctdb/tests/src/ctdb_takeover_tests.c

index b40bbadbf56fe421eec74085337bac2d75a608d1..c45b218cc384d4c984dbac1cfb7168b63ea9ea56 100644 (file)
@@ -1129,31 +1129,6 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, bool check_addresses)
        return 0;
 }
 
-static void *add_ip_callback(void *parm, void *data)
-{
-       struct public_ip_list *this_ip = parm;
-       struct public_ip_list *prev_ip = data;
-
-       if (prev_ip == NULL) {
-               return parm;
-       }
-       if (this_ip->pnn == -1) {
-               this_ip->pnn = prev_ip->pnn;
-       }
-
-       return parm;
-}
-
-static int getips_count_callback(void *param, void *data)
-{
-       struct public_ip_list **ip_list = (struct public_ip_list **)param;
-       struct public_ip_list *new_ip = (struct public_ip_list *)data;
-
-       new_ip->next = *ip_list;
-       *ip_list     = new_ip;
-       return 0;
-}
-
 static struct ctdb_public_ip_list *
 ctdb_fetch_remote_public_ips(struct ctdb_context *ctdb,
                             TALLOC_CTX *mem_ctx,
@@ -1210,61 +1185,6 @@ ctdb_fetch_remote_public_ips(struct ctdb_context *ctdb,
        return public_ips;
 }
 
-static struct public_ip_list *
-create_merged_ip_list(struct ipalloc_state *ipalloc_state)
-{
-       int i, j;
-       struct public_ip_list *ip_list;
-       struct ctdb_public_ip_list *public_ips;
-       struct trbt_tree *ip_tree;
-
-       ip_tree = trbt_create(ipalloc_state, 0);
-
-       if (ipalloc_state->known_public_ips == NULL) {
-               DEBUG(DEBUG_ERR, ("Known public IPs not set\n"));
-               return NULL;
-       }
-
-       for (i=0; i < ipalloc_state->num; i++) {
-
-               public_ips = &ipalloc_state->known_public_ips[i];
-
-               for (j=0; j < public_ips->num; j++) {
-                       struct public_ip_list *tmp_ip;
-
-                       /* This is returned as part of ip_list */
-                       tmp_ip = talloc_zero(ipalloc_state, struct public_ip_list);
-                       if (tmp_ip == NULL) {
-                               DEBUG(DEBUG_ERR,
-                                     (__location__ " out of memory\n"));
-                               talloc_free(ip_tree);
-                               return NULL;
-                       }
-
-                       /* Do not use information about IP addresses hosted
-                        * on other nodes, it may not be accurate */
-                       if (public_ips->ip[j].pnn == i) {
-                               tmp_ip->pnn = public_ips->ip[j].pnn;
-                       } else {
-                               tmp_ip->pnn = -1;
-                       }
-                       tmp_ip->addr = public_ips->ip[j].addr;
-                       tmp_ip->next = NULL;
-
-                       trbt_insertarray32_callback(ip_tree,
-                               IP_KEYLEN, ip_key(&public_ips->ip[j].addr),
-                               add_ip_callback,
-                               tmp_ip);
-               }
-       }
-
-       ip_list = NULL;
-       trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &ip_list);
-       talloc_free(ip_tree);
-
-       return ip_list;
-}
-
 static bool all_nodes_are_disabled(struct ctdb_node_map_old *nodemap)
 {
        int i;
@@ -1624,7 +1544,6 @@ static void takeover_run_process_failures(struct ctdb_context *ctdb,
  * - Use ipalloc_set_public_ips() to set known and available IP
      addresses for allocation
  * - If no available IP addresses then early exit
- * - Build list of (known IPs, currently assigned node)
  * - Populate list of nodes to force rebalance - internal structure,
  *   currently no way to fetch, only used by LCP2 for nodes that have
  *   had new IP addresses added
@@ -1717,23 +1636,15 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map_old *nodem
                goto ipreallocated;
        }
 
-       /* since nodes only know about those public addresses that
-          can be served by that particular node, no single node has
-          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.
-       */
-       all_ips = create_merged_ip_list(ipalloc_state);
-       if (all_ips == NULL) {
-               talloc_free(tmp_ctx);
-               return -1;
-       }
-       ipalloc_state->all_ips = all_ips;
-
        ipalloc_state->force_rebalance_nodes = force_rebalance_nodes;
 
        /* Do the IP reassignment calculations */
        ipalloc(ipalloc_state);
+       if (ipalloc_state->all_ips == NULL) {
+               talloc_free(tmp_ctx);
+               return -1;
+       }
+       all_ips = ipalloc_state->all_ips;
 
        /* Now tell all nodes to release any public IPs should not
         * host.  This will be a NOOP on nodes that don't currently
index fa2503db42b84b6f8828b95ca166fda4571c28ec..d60da0315c852e9b430d2235d39e6f23dad1117f 100644 (file)
    along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <talloc.h>
+
 #include "replace.h"
 #include "system/network.h"
 
 #include "lib/util/debug.h"
 
 #include "common/logging.h"
+#include "common/rb_tree.h"
 
 #include "server/ipalloc_private.h"
 
+static void *add_ip_callback(void *parm, void *data)
+{
+       struct public_ip_list *this_ip = parm;
+       struct public_ip_list *prev_ip = data;
+
+       if (prev_ip == NULL) {
+               return parm;
+       }
+       if (this_ip->pnn == -1) {
+               this_ip->pnn = prev_ip->pnn;
+       }
+
+       return parm;
+}
+
+static int getips_count_callback(void *param, void *data)
+{
+       struct public_ip_list **ip_list = (struct public_ip_list **)param;
+       struct public_ip_list *new_ip = (struct public_ip_list *)data;
+
+       new_ip->next = *ip_list;
+       *ip_list     = new_ip;
+       return 0;
+}
+
+/* Nodes only know about those public addresses that they are
+ * configured to serve and no individual node has a full list of all
+ * public addresses configured across the cluster.  Therefore, a
+ * merged list of all public addresses needs to be built so that IP
+ * allocation can be done. */
+static struct public_ip_list *
+create_merged_ip_list(struct ipalloc_state *ipalloc_state)
+{
+       int i, j;
+       struct public_ip_list *ip_list;
+       struct ctdb_public_ip_list *public_ips;
+       struct trbt_tree *ip_tree;
+
+       ip_tree = trbt_create(ipalloc_state, 0);
+
+       if (ipalloc_state->known_public_ips == NULL) {
+               DEBUG(DEBUG_ERR, ("Known public IPs not set\n"));
+               return NULL;
+       }
+
+       for (i=0; i < ipalloc_state->num; i++) {
+
+               public_ips = &ipalloc_state->known_public_ips[i];
+
+               for (j=0; j < public_ips->num; j++) {
+                       struct public_ip_list *tmp_ip;
+
+                       /* This is returned as part of ip_list */
+                       tmp_ip = talloc_zero(ipalloc_state, struct public_ip_list);
+                       if (tmp_ip == NULL) {
+                               DEBUG(DEBUG_ERR,
+                                     (__location__ " out of memory\n"));
+                               talloc_free(ip_tree);
+                               return NULL;
+                       }
+
+                       /* Do not use information about IP addresses hosted
+                        * on other nodes, it may not be accurate */
+                       if (public_ips->ip[j].pnn == i) {
+                               tmp_ip->pnn = public_ips->ip[j].pnn;
+                       } else {
+                               tmp_ip->pnn = -1;
+                       }
+                       tmp_ip->addr = public_ips->ip[j].addr;
+                       tmp_ip->next = NULL;
+
+                       trbt_insertarray32_callback(ip_tree,
+                               IP_KEYLEN, ip_key(&public_ips->ip[j].addr),
+                               add_ip_callback,
+                               tmp_ip);
+               }
+       }
+
+       ip_list = NULL;
+       trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &ip_list);
+       talloc_free(ip_tree);
+
+       return ip_list;
+}
+
 bool ipalloc_set_public_ips(struct ipalloc_state *ipalloc_state,
                            struct ctdb_public_ip_list *known_ips,
                            struct ctdb_public_ip_list *available_ips)
@@ -35,7 +123,9 @@ bool ipalloc_set_public_ips(struct ipalloc_state *ipalloc_state,
        ipalloc_state->known_public_ips = known_ips;
        ipalloc_state->available_public_ips = available_ips;
 
-       return true;
+       ipalloc_state->all_ips = create_merged_ip_list(ipalloc_state);
+
+       return (ipalloc_state->all_ips != NULL);
 }
 
 /* The calculation part of the IP allocation algorithm. */
index 162de2b73599ea078ed1dd7eae32bfa4376c6711..5189e252728dce316f3cbdc9fdde4bf6ce57a19b 100644 (file)
@@ -318,8 +318,6 @@ static void ctdb_test_init(const char nodestates[],
                             tval_noiptakeover,
                             tval_noiptakeoverondisabled);
 
-       (*ipalloc_state)->all_ips = create_merged_ip_list(*ipalloc_state);
-
        (*ipalloc_state)->force_rebalance_nodes = NULL;
 }