/* Can the given node host the given IP: is the public IP known to the
* node and is NOIPHOST unset?
*/
-static bool can_node_host_ip(struct ctdb_context *ctdb, int32_t pnn,
+static bool can_node_host_ip(struct ipalloc_state *ipalloc_state,
+ int32_t pnn,
struct ctdb_ipflags ipflags,
struct public_ip_list *ip)
{
return false;
}
- public_ips = ctdb->ipalloc_state->available_public_ips[pnn];
+ public_ips = ipalloc_state->available_public_ips[pnn];
if (public_ips == NULL) {
return false;
return false;
}
-static bool can_node_takeover_ip(struct ctdb_context *ctdb, int32_t pnn,
+static bool can_node_takeover_ip(struct ipalloc_state *ipalloc_state,
+ int32_t pnn,
struct ctdb_ipflags ipflags,
struct public_ip_list *ip)
{
return false;
}
- return can_node_host_ip(ctdb, pnn, ipflags, ip);
+ return can_node_host_ip(ipalloc_state, pnn, ipflags, ip);
}
/* search the node lists list for a node to takeover this ip.
pick the node that currently are serving the least number of ips
so that the ips get spread out evenly.
*/
-static int find_takeover_node(struct ctdb_context *ctdb,
+static int find_takeover_node(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *ip,
struct public_ip_list *all_ips)
pnn = -1;
for (i=0; i<numnodes; i++) {
/* verify that this node can serve this ip */
- if (!can_node_takeover_ip(ctdb, i, ipflags[i], ip)) {
+ if (!can_node_takeover_ip(ipalloc_state, i, ipflags[i], ip)) {
/* no it couldnt so skip to the next node */
continue;
}
min = num;
}
}
- }
+ }
if (pnn == -1) {
DEBUG(DEBUG_WARNING,(__location__ " Could not find node to take over public address '%s'\n",
ctdb_addr_to_str(&ip->addr)));
}
static struct public_ip_list *
-create_merged_ip_list(struct ctdb_context *ctdb)
+create_merged_ip_list(struct ctdb_context *ctdb, struct ipalloc_state *ipalloc_state)
{
int i, j;
struct public_ip_list *ip_list;
ctdb->ip_tree = trbt_create(ctdb, 0);
for (i=0; i < ctdb->num_nodes; i++) {
- public_ips = ctdb->ipalloc_state->known_public_ips[i];
+ public_ips = ipalloc_state->known_public_ips[i];
if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) {
continue;
/* Allocate any unassigned IPs just by looping through the IPs and
* finding the best node for each.
*/
-static void basic_allocate_unassigned(struct ctdb_context *ctdb,
+static void basic_allocate_unassigned(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips)
{
struct public_ip_list *tmp_ip;
- /* loop over all ip's and find a physical node to cover for
+ /* loop over all ip's and find a physical node to cover for
each unassigned ip.
*/
for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
if (tmp_ip->pnn == -1) {
- if (find_takeover_node(ctdb, ipflags, tmp_ip, all_ips)) {
- DEBUG(DEBUG_WARNING,("Failed to find node to cover ip %s\n",
- ctdb_addr_to_str(&tmp_ip->addr)));
+ if (find_takeover_node(ipalloc_state, ipflags,
+ tmp_ip, all_ips)) {
+ DEBUG(DEBUG_WARNING,
+ ("Failed to find node to cover ip %s\n",
+ ctdb_addr_to_str(&tmp_ip->addr)));
}
}
}
/* Basic non-deterministic rebalancing algorithm.
*/
-static void basic_failback(struct ctdb_context *ctdb,
+static void basic_failback(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips,
int num_ips)
minnode = -1;
for (i=0; i<numnodes; i++) {
/* only check nodes that can actually serve this ip */
- if (!can_node_takeover_ip(ctdb, i, ipflags[i], tmp_ip)) {
+ if (!can_node_takeover_ip(ipalloc_state, i,
+ ipflags[i], tmp_ip)) {
/* no it couldnt so skip to the next node */
continue;
}
/* Reassign one of maxnode's VNNs */
for (tmp=all_ips;tmp;tmp=tmp->next) {
if (tmp->pnn == maxnode) {
- (void)find_takeover_node(ctdb, ipflags, tmp, all_ips);
+ (void)find_takeover_node(ipalloc_state,
+ ipflags,
+ tmp,
+ all_ips);
retries++;
goto try_again;;
}
}
}
-static void lcp2_init(struct ctdb_context *tmp_ctx,
+static void lcp2_init(TALLOC_CTX *tmp_ctx,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips,
uint32_t *force_rebalance_nodes,
/* Allocate any unassigned addresses using the LCP2 algorithm to find
* the IP/node combination that will cost the least.
*/
-static void lcp2_allocate_unassigned(struct ctdb_context *ctdb,
+static void lcp2_allocate_unassigned(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips,
uint32_t *lcp2_imbalances)
for (dstnode=0; dstnode<numnodes; dstnode++) {
/* only check nodes that can actually takeover this ip */
- if (!can_node_takeover_ip(ctdb, dstnode,
+ if (!can_node_takeover_ip(ipalloc_state,
+ dstnode,
ipflags[dstnode],
tmp_ip)) {
/* no it couldnt so skip to the next node */
* to move IPs from, determines the best IP/destination node
* combination to move from the source node.
*/
-static bool lcp2_failback_candidate(struct ctdb_context *ctdb,
+static bool lcp2_failback_candidate(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips,
int srcnode,
}
/* only check nodes that can actually takeover this ip */
- if (!can_node_takeover_ip(ctdb, dstnode,
+ if (!can_node_takeover_ip(ipalloc_state, dstnode,
ipflags[dstnode], tmp_ip)) {
/* no it couldnt so skip to the next node */
continue;
* node with the highest LCP2 imbalance, and then determines the best
* IP/destination node combination to move from the source node.
*/
-static void lcp2_failback(struct ctdb_context *ctdb,
+static void lcp2_failback(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips,
uint32_t *lcp2_imbalances,
*/
DEBUG(DEBUG_DEBUG,("+++++++++++++++++++++++++++++++++++++++++\n"));
DEBUG(DEBUG_DEBUG,("Selecting most imbalanced node from:\n"));
- lips = talloc_array(ctdb, struct lcp2_imbalance_pnn, numnodes);
+ lips = talloc_array(ipalloc_state, struct lcp2_imbalance_pnn, numnodes);
for (i=0; i<numnodes; i++) {
lips[i].imbalance = lcp2_imbalances[i];
lips[i].pnn = i;
break;
}
- if (lcp2_failback_candidate(ctdb,
+ if (lcp2_failback_candidate(ipalloc_state,
ipflags,
all_ips,
lips[i].pnn,
}
}
-static void unassign_unsuitable_ips(struct ctdb_context *ctdb,
+static void unassign_unsuitable_ips(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips)
{
if (tmp_ip->pnn == -1) {
continue;
}
- if (!can_node_host_ip(ctdb, tmp_ip->pnn,
+ if (!can_node_host_ip(ipalloc_state, tmp_ip->pnn,
ipflags[tmp_ip->pnn], tmp_ip) != 0) {
/* this node can not serve this ip. */
DEBUG(DEBUG_DEBUG,("Unassign IP: %s from %d\n",
}
}
-static void ip_alloc_deterministic_ips(struct ctdb_context *ctdb,
+static void ip_alloc_deterministic_ips(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips)
{
* IPs, since the modulo step above implicitly fails
* back IPs to their "home" node.
*/
- if (1 == ctdb->ipalloc_state->no_ip_failback) {
+ if (1 == ipalloc_state->no_ip_failback) {
DEBUG(DEBUG_WARNING, ("WARNING: 'NoIPFailback' set but ignored - incompatible with 'DeterministicIPs\n"));
}
- unassign_unsuitable_ips(ctdb, ipflags, all_ips);
+ unassign_unsuitable_ips(ipalloc_state, ipflags, all_ips);
- basic_allocate_unassigned(ctdb, ipflags, all_ips);
+ basic_allocate_unassigned(ipalloc_state, ipflags, all_ips);
/* No failback here! */
}
-static void ip_alloc_nondeterministic_ips(struct ctdb_context *ctdb,
+static void ip_alloc_nondeterministic_ips(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips)
{
num_ips++;
}
- unassign_unsuitable_ips(ctdb, ipflags, all_ips);
+ unassign_unsuitable_ips(ipalloc_state, ipflags, all_ips);
- basic_allocate_unassigned(ctdb, ipflags, all_ips);
+ basic_allocate_unassigned(ipalloc_state, ipflags, all_ips);
/* If we don't want IPs to fail back then don't rebalance IPs. */
- if (1 == ctdb->ipalloc_state->no_ip_failback) {
+ if (1 == ipalloc_state->no_ip_failback) {
return;
}
/* Now, try to make sure the ip adresses are evenly distributed
across the nodes.
*/
- basic_failback(ctdb, ipflags, all_ips, num_ips);
+ basic_failback(ipalloc_state, ipflags, all_ips, num_ips);
}
-static void ip_alloc_lcp2(struct ctdb_context *ctdb,
+static void ip_alloc_lcp2(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips,
uint32_t *force_rebalance_nodes)
bool *rebalance_candidates;
int numnodes, num_rebalance_candidates, i;
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+ TALLOC_CTX *tmp_ctx = talloc_new(ipalloc_state);
- unassign_unsuitable_ips(ctdb, ipflags, all_ips);
+ unassign_unsuitable_ips(ipalloc_state, ipflags, all_ips);
lcp2_init(tmp_ctx, ipflags, all_ips,force_rebalance_nodes,
&lcp2_imbalances, &rebalance_candidates);
- lcp2_allocate_unassigned(ctdb, ipflags, all_ips, lcp2_imbalances);
+ lcp2_allocate_unassigned(ipalloc_state, ipflags, all_ips, lcp2_imbalances);
/* If we don't want IPs to fail back then don't rebalance IPs. */
- if (1 == ctdb->ipalloc_state->no_ip_failback) {
+ if (1 == ipalloc_state->no_ip_failback) {
goto finished;
}
/* Now, try to make sure the ip adresses are evenly distributed
across the nodes.
*/
- lcp2_failback(ctdb, ipflags, all_ips,
+ lcp2_failback(ipalloc_state, ipflags, all_ips,
lcp2_imbalances, rebalance_candidates);
finished:
}
/* The calculation part of the IP allocation algorithm. */
-static void ctdb_takeover_run_core(struct ctdb_context *ctdb,
+static void ctdb_takeover_run_core(struct ipalloc_state *ipalloc_state,
struct ctdb_ipflags *ipflags,
struct public_ip_list *all_ips,
uint32_t *force_rebalance_nodes)
{
- switch (ctdb->ipalloc_state->algorithm) {
+ switch (ipalloc_state->algorithm) {
case IPALLOC_LCP2:
- ip_alloc_lcp2(ctdb, ipflags, all_ips, force_rebalance_nodes);
+ ip_alloc_lcp2(ipalloc_state, ipflags, all_ips,
+ force_rebalance_nodes);
break;
case IPALLOC_DETERMINISTIC:
- ip_alloc_deterministic_ips(ctdb, ipflags, all_ips);
+ ip_alloc_deterministic_ips(ipalloc_state, ipflags, all_ips);
break;
case IPALLOC_NONDETERMINISTIC:
- ip_alloc_nondeterministic_ips(ctdb, ipflags, all_ips);
+ ip_alloc_nondeterministic_ips(ipalloc_state, ipflags, all_ips);
break;
}
talloc_free(tmp_ctx);
return -1;
}
- ctdb->ipalloc_state = ipalloc_state;
ipflags = set_ipflags(ctdb, tmp_ctx, nodemap);
if (ipflags == NULL) {
keep the tree of ips around as ctdb->ip_tree
*/
- all_ips = create_merged_ip_list(ctdb);
+ all_ips = create_merged_ip_list(ctdb, ipalloc_state);
/* Do the IP reassignment calculations */
- ctdb_takeover_run_core(ctdb, ipflags, all_ips, force_rebalance_nodes);
+ ctdb_takeover_run_core(ipalloc_state, ipflags,
+ all_ips, force_rebalance_nodes);
/* Now tell all nodes to release any public IPs should not
* host. This will be a NOOP on nodes that don't currently
static void ctdb_test_init(const char nodestates[],
struct ctdb_context **ctdb,
struct public_ip_list **all_ips,
+ struct ipalloc_state **ipalloc_state,
struct ctdb_ipflags **ipflags,
bool read_ips_for_multiple_nodes)
{
(*ctdb)->nodes = talloc_array(*ctdb, struct ctdb_node *, numnodes); // FIXME: bogus size, overkill
- (*ctdb)->ipalloc_state = ipalloc_state_init(*ctdb, *ctdb);
+ *ipalloc_state = ipalloc_state_init(*ctdb, *ctdb);
for (i=0; i < numnodes; i++) {
nodemap->nodes[i].pnn = i;
(*ctdb)->nodes[i]->pnn = i;
(*ctdb)->nodes[i]->flags = nodeflags[i];
- (*ctdb)->ipalloc_state->available_public_ips[i] = avail[i];
- (*ctdb)->ipalloc_state->known_public_ips[i] = known[i];
+ (*ipalloc_state)->available_public_ips[i] = avail[i];
+ (*ipalloc_state)->known_public_ips[i] = known[i];
}
*ipflags = set_ipflags_internal(*ctdb, *ctdb, nodemap,
{
struct ctdb_context *ctdb;
struct public_ip_list *all_ips;
+ struct ipalloc_state *ipalloc_state;
struct ctdb_ipflags *ipflags;
uint32_t *lcp2_imbalances;
bool *newly_healthy;
- ctdb_test_init(nodestates, &ctdb, &all_ips, &ipflags, false);
+ ctdb_test_init(nodestates, &ctdb, &all_ips, &ipalloc_state, &ipflags,
+ false);
- lcp2_init(ctdb, ipflags, all_ips, NULL,
+ lcp2_init(ipalloc_state, ipflags, all_ips, NULL,
&lcp2_imbalances, &newly_healthy);
- lcp2_allocate_unassigned(ctdb, ipflags,
+ lcp2_allocate_unassigned(ipalloc_state, ipflags,
all_ips, lcp2_imbalances);
print_ctdb_public_ip_list(all_ips);
{
struct ctdb_context *ctdb;
struct public_ip_list *all_ips;
+ struct ipalloc_state *ipalloc_state;
struct ctdb_ipflags *ipflags;
uint32_t *lcp2_imbalances;
bool *newly_healthy;
- ctdb_test_init(nodestates, &ctdb, &all_ips, &ipflags, false);
+ ctdb_test_init(nodestates, &ctdb, &all_ips, &ipalloc_state, &ipflags,
+ false);
- lcp2_init(ctdb, ipflags, all_ips, NULL,
+ lcp2_init(ipalloc_state, ipflags, all_ips, NULL,
&lcp2_imbalances, &newly_healthy);
- lcp2_failback(ctdb, ipflags,
+ lcp2_failback(ipalloc_state, ipflags,
all_ips, lcp2_imbalances, newly_healthy);
print_ctdb_public_ip_list(all_ips);
{
struct ctdb_context *ctdb;
struct public_ip_list *all_ips;
+ struct ipalloc_state *ipalloc_state;
struct ctdb_ipflags *ipflags;
uint32_t *lcp2_imbalances;
bool *newly_healthy;
- ctdb_test_init(nodestates, &ctdb, &all_ips, &ipflags, false);
+ ctdb_test_init(nodestates, &ctdb, &all_ips, &ipalloc_state, &ipflags,
+ false);
- lcp2_init(ctdb, ipflags, all_ips, NULL,
+ lcp2_init(ipalloc_state, ipflags, all_ips, NULL,
&lcp2_imbalances, &newly_healthy);
- lcp2_failback(ctdb, ipflags,
+ lcp2_failback(ipalloc_state, ipflags,
all_ips, lcp2_imbalances, newly_healthy);
print_ctdb_public_ip_list(all_ips);
{
struct ctdb_context *ctdb;
struct public_ip_list *all_ips;
+ struct ipalloc_state *ipalloc_state;
struct ctdb_ipflags *ipflags;
- ctdb_test_init(nodestates, &ctdb, &all_ips, &ipflags,
+ ctdb_test_init(nodestates, &ctdb, &all_ips, &ipalloc_state, &ipflags,
read_ips_for_multiple_nodes);
- all_ips = create_merged_ip_list(ctdb);
+ all_ips = create_merged_ip_list(ctdb, ipalloc_state);
- ctdb_takeover_run_core(ctdb, ipflags, all_ips, NULL);
+ ctdb_takeover_run_core(ipalloc_state, ipflags, all_ips, NULL);
print_ctdb_public_ip_list(all_ips);