Пример #1
0
static void
apply_master_prefs(resource_t * rsc)
{
    int score, new_score;
    GListPtr gIter = rsc->children;
    clone_variant_data_t *clone_data = NULL;

    get_clone_variant_data(clone_data, rsc);

    if (clone_data->applied_master_prefs) {
        /* Make sure we only do this once */
        return;
    }

    clone_data->applied_master_prefs = TRUE;

    for (; gIter != NULL; gIter = gIter->next) {
        GHashTableIter iter;
        node_t *node = NULL;
        resource_t *child_rsc = (resource_t *) gIter->data;

        g_hash_table_iter_init(&iter, child_rsc->allowed_nodes);
        while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
            if (can_run_resources(node) == FALSE) {
                /* This node will never be promoted to master,
                 *  so don't apply the master score as that may
                 *  lead to clone shuffling
                 */
                continue;
            }

            score = master_score(child_rsc, node, 0);
            if (score > 0) {
                new_score = merge_weights(node->weight, score);
                if (new_score != node->weight) {
                    crm_trace("\t%s: Updating preference for %s (%d->%d)",
                                child_rsc->id, node->details->uname, node->weight, new_score);
                    node->weight = new_score;
                }
            }

            new_score = max(child_rsc->priority, score);
            if (new_score != child_rsc->priority) {
                crm_trace("\t%s: Updating priority (%d->%d)",
                            child_rsc->id, child_rsc->priority, new_score);
                child_rsc->priority = new_score;
            }
        }
    }
}
Пример #2
0
static node_t *
can_run_instance(resource_t * rsc, node_t * node, int limit)
{
    node_t *local_node = NULL;

    if (node == NULL && rsc->allowed_nodes) {
        GHashTableIter iter;
        g_hash_table_iter_init(&iter, rsc->allowed_nodes);
        while (g_hash_table_iter_next(&iter, NULL, (void **)&local_node)) {
            can_run_instance(rsc, local_node, limit);
        }
        return NULL;
    }

    if (can_run_resources(node) == FALSE) {
        goto bail;

    } else if (is_set(rsc->flags, pe_rsc_orphan)) {
        goto bail;
    }

    local_node = parent_node_instance(rsc, node);

    if (local_node == NULL) {
        crm_warn("%s cannot run on %s: node not allowed", rsc->id, node->details->uname);
        goto bail;

    } else if (local_node->weight < 0) {
        common_update_score(rsc, node->details->id, local_node->weight);
        pe_rsc_trace(rsc, "%s cannot run on %s: Parent node weight doesn't allow it.",
                     rsc->id, node->details->uname);

    } else if (local_node->count < limit) {
        pe_rsc_trace(rsc, "%s can run on %s (already running %d)",
                     rsc->id, node->details->uname, local_node->count);
        return local_node;

    } else {
        pe_rsc_trace(rsc, "%s cannot run on %s: node full (%d >= %d)",
                     rsc->id, node->details->uname, local_node->count, limit);
    }

  bail:
    if (node) {
        common_update_score(rsc, node->details->id, -INFINITY);
    }
    return NULL;
}
Пример #3
0
static node_t *
can_be_master(resource_t * rsc)
{
    node_t *node = NULL;
    node_t *local_node = NULL;
    resource_t *parent = uber_parent(rsc);
    clone_variant_data_t *clone_data = NULL;

#if 0
    enum rsc_role_e role = RSC_ROLE_UNKNOWN;

    role = rsc->fns->state(rsc, FALSE);
    crm_info("%s role: %s", rsc->id, role2text(role));
#endif

    if (rsc->children) {
        GListPtr gIter = rsc->children;

        for (; gIter != NULL; gIter = gIter->next) {
            resource_t *child = (resource_t *) gIter->data;

            if (can_be_master(child) == NULL) {
                crm_trace( "Child %s of %s can't be promoted", child->id, rsc->id);
                return NULL;
            }
        }
    }

    node = rsc->fns->location(rsc, NULL, FALSE);
    if (node == NULL) {
        crm_trace( "%s cannot be master: not allocated", rsc->id);
        return NULL;

    } else if (is_not_set(rsc->flags, pe_rsc_managed)) {
        if (rsc->fns->state(rsc, TRUE) == RSC_ROLE_MASTER) {
            crm_notice("Forcing unmanaged master %s to remain promoted on %s",
                       rsc->id, node->details->uname);

        } else {
            return NULL;
        }

    } else if (rsc->priority < 0) {
        crm_trace( "%s cannot be master: preference: %d", rsc->id, rsc->priority);
        return NULL;

    } else if (can_run_resources(node) == FALSE) {
        crm_trace( "Node cant run any resources: %s", node->details->uname);
        return NULL;
    }

    get_clone_variant_data(clone_data, parent);
    local_node = pe_hash_table_lookup(parent->allowed_nodes, node->details->id);

    if (local_node == NULL) {
        crm_err("%s cannot run on %s: node not allowed", rsc->id, node->details->uname);
        return NULL;

    } else if (local_node->count < clone_data->master_node_max
               || is_not_set(rsc->flags, pe_rsc_managed)) {
        return local_node;

    } else {
        crm_trace( "%s cannot be master on %s: node full",
                            rsc->id, node->details->uname);
    }

    return NULL;
}
Пример #4
0
gint
sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
{
    int rc = 0;
    node_t *node1 = NULL;
    node_t *node2 = NULL;
    node_t *current_node1 = NULL;
    node_t *current_node2 = NULL;
    unsigned int nnodes1 = 0;
    unsigned int nnodes2 = 0;

    gboolean can1 = TRUE;
    gboolean can2 = TRUE;

    const resource_t *resource1 = (const resource_t *)a;
    const resource_t *resource2 = (const resource_t *)b;

    CRM_ASSERT(resource1 != NULL);
    CRM_ASSERT(resource2 != NULL);

    /* allocation order:
     *  - active instances
     *  - instances running on nodes with the least copies
     *  - active instances on nodes that can't support them or are to be fenced
     *  - failed instances
     *  - inactive instances
     */

    current_node1 = pe__find_active_on(resource1, &nnodes1, NULL);
    current_node2 = pe__find_active_on(resource2, &nnodes2, NULL);

    if (nnodes1 && nnodes2) {
        if (nnodes1 < nnodes2) {
            crm_trace("%s < %s: running_on", resource1->id, resource2->id);
            return -1;

        } else if (nnodes1 > nnodes2) {
            crm_trace("%s > %s: running_on", resource1->id, resource2->id);
            return 1;
        }
    }

    node1 = current_node1;
    node2 = current_node2;
    if (node1) {
        node_t *match = pe_hash_table_lookup(resource1->allowed_nodes, node1->details->id);

        if (match == NULL || match->weight < 0) {
            crm_trace("%s: current location is unavailable", resource1->id);
            node1 = NULL;
            can1 = FALSE;
        }
    }

    if (node2) {
        node_t *match = pe_hash_table_lookup(resource2->allowed_nodes, node2->details->id);

        if (match == NULL || match->weight < 0) {
            crm_trace("%s: current location is unavailable", resource2->id);
            node2 = NULL;
            can2 = FALSE;
        }
    }

    if (can1 != can2) {
        if (can1) {
            crm_trace("%s < %s: availability of current location", resource1->id, resource2->id);
            return -1;
        }
        crm_trace("%s > %s: availability of current location", resource1->id, resource2->id);
        return 1;
    }

    if (resource1->priority < resource2->priority) {
        crm_trace("%s < %s: priority", resource1->id, resource2->id);
        return 1;

    } else if (resource1->priority > resource2->priority) {
        crm_trace("%s > %s: priority", resource1->id, resource2->id);
        return -1;
    }

    if (node1 == NULL && node2 == NULL) {
        crm_trace("%s == %s: not active", resource1->id, resource2->id);
        return 0;
    }

    if (node1 != node2) {
        if (node1 == NULL) {
            crm_trace("%s > %s: active", resource1->id, resource2->id);
            return 1;
        } else if (node2 == NULL) {
            crm_trace("%s < %s: active", resource1->id, resource2->id);
            return -1;
        }
    }

    can1 = can_run_resources(node1);
    can2 = can_run_resources(node2);
    if (can1 != can2) {
        if (can1) {
            crm_trace("%s < %s: can", resource1->id, resource2->id);
            return -1;
        }
        crm_trace("%s > %s: can", resource1->id, resource2->id);
        return 1;
    }

    node1 = parent_node_instance(resource1, node1);
    node2 = parent_node_instance(resource2, node2);
    if (node1 != NULL && node2 == NULL) {
        crm_trace("%s < %s: not allowed", resource1->id, resource2->id);
        return -1;
    } else if (node1 == NULL && node2 != NULL) {
        crm_trace("%s > %s: not allowed", resource1->id, resource2->id);
        return 1;
    }

    if (node1 == NULL || node2 == NULL) {
        crm_trace("%s == %s: not allowed", resource1->id, resource2->id);
        return 0;
    }

    if (node1->count < node2->count) {
        crm_trace("%s < %s: count", resource1->id, resource2->id);
        return -1;

    } else if (node1->count > node2->count) {
        crm_trace("%s > %s: count", resource1->id, resource2->id);
        return 1;
    }

    can1 = did_fail(resource1);
    can2 = did_fail(resource2);
    if (can1 != can2) {
        if (can1) {
            crm_trace("%s > %s: failed", resource1->id, resource2->id);
            return 1;
        }
        crm_trace("%s < %s: failed", resource1->id, resource2->id);
        return -1;
    }

    if (node1 && node2) {
        int lpc = 0;
        int max = 0;
        node_t *n = NULL;
        GListPtr gIter = NULL;
        GListPtr list1 = NULL;
        GListPtr list2 = NULL;
        GHashTable *hash1 =
            g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free);
        GHashTable *hash2 =
            g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free);

        n = node_copy(current_node1);
        g_hash_table_insert(hash1, (gpointer) n->details->id, n);

        n = node_copy(current_node2);
        g_hash_table_insert(hash2, (gpointer) n->details->id, n);

        if(resource1->parent) {
            for (gIter = resource1->parent->rsc_cons; gIter; gIter = gIter->next) {
                rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;

                crm_trace("Applying %s to %s", constraint->id, resource1->id);

                hash1 = native_merge_weights(constraint->rsc_rh, resource1->id, hash1,
                                             constraint->node_attribute,
                                             (float)constraint->score / INFINITY, 0);
            }

            for (gIter = resource1->parent->rsc_cons_lhs; gIter; gIter = gIter->next) {
                rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;

                crm_trace("Applying %s to %s", constraint->id, resource1->id);

                hash1 = native_merge_weights(constraint->rsc_lh, resource1->id, hash1,
                                             constraint->node_attribute,
                                             (float)constraint->score / INFINITY, pe_weights_positive);
            }
        }

        if(resource2->parent) {
            for (gIter = resource2->parent->rsc_cons; gIter; gIter = gIter->next) {
                rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;

                crm_trace("Applying %s to %s", constraint->id, resource2->id);

                hash2 = native_merge_weights(constraint->rsc_rh, resource2->id, hash2,
                                             constraint->node_attribute,
                                             (float)constraint->score / INFINITY, 0);
            }

            for (gIter = resource2->parent->rsc_cons_lhs; gIter; gIter = gIter->next) {
                rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;

                crm_trace("Applying %s to %s", constraint->id, resource2->id);

                hash2 = native_merge_weights(constraint->rsc_lh, resource2->id, hash2,
                                             constraint->node_attribute,
                                             (float)constraint->score / INFINITY, pe_weights_positive);
            }
        }

        /* Current location score */
        node1 = g_hash_table_lookup(hash1, current_node1->details->id);
        node2 = g_hash_table_lookup(hash2, current_node2->details->id);

        if (node1->weight < node2->weight) {
            if (node1->weight < 0) {
                crm_trace("%s > %s: current score: %d %d", resource1->id, resource2->id, node1->weight, node2->weight);
                rc = -1;
                goto out;

            } else {
                crm_trace("%s < %s: current score: %d %d", resource1->id, resource2->id, node1->weight, node2->weight);
                rc = 1;
                goto out;
            }

        } else if (node1->weight > node2->weight) {
            crm_trace("%s > %s: current score: %d %d", resource1->id, resource2->id, node1->weight, node2->weight);
            rc = -1;
            goto out;
        }

        /* All location scores */
        list1 = g_hash_table_get_values(hash1);
        list2 = g_hash_table_get_values(hash2);

        list1 = sort_nodes_by_weight(list1, current_node1, data_set);
        list2 = sort_nodes_by_weight(list2, current_node2, data_set);
        max = g_list_length(list1);
        if (max < g_list_length(list2)) {
            max = g_list_length(list2);
        }

        for (; lpc < max; lpc++) {
            node1 = g_list_nth_data(list1, lpc);
            node2 = g_list_nth_data(list2, lpc);
            if (node1 == NULL) {
                crm_trace("%s < %s: colocated score NULL", resource1->id, resource2->id);
                rc = 1;
                break;

            } else if (node2 == NULL) {
                crm_trace("%s > %s: colocated score NULL", resource1->id, resource2->id);
                rc = -1;
                break;
            }

            if (node1->weight < node2->weight) {
                crm_trace("%s < %s: colocated score", resource1->id, resource2->id);
                rc = 1;
                break;

            } else if (node1->weight > node2->weight) {
                crm_trace("%s > %s: colocated score", resource1->id, resource2->id);
                rc = -1;
                break;
            }
        }

        /* Order by reverse uname - same as sort_node_weight() does? */
  out:
        g_hash_table_destroy(hash1);    /* Free mem */
        g_hash_table_destroy(hash2);    /* Free mem */
        g_list_free(list1);
        g_list_free(list2);

        if (rc != 0) {
            return rc;
        }
    }

    rc = strcmp(resource1->id, resource2->id);
    crm_trace("%s %c %s: default", resource1->id, rc < 0 ? '<' : '>', resource2->id);
    return rc;
}
Пример #5
0
void
distribute_children(resource_t *rsc, GListPtr children, GListPtr nodes,
                    int max, int per_host_max, pe_working_set_t * data_set) 
{
    int loop_max = 0;
    int allocated = 0;
    int available_nodes = 0;

    /* count now tracks the number of clones currently allocated */
    for(GListPtr nIter = nodes; nIter != NULL; nIter = nIter->next) {
        pe_node_t *node = nIter->data;

        node->count = 0;
        if (can_run_resources(node)) {
            available_nodes++;
        }
    }

    if(available_nodes) {
        loop_max = max / available_nodes;
    }
    if (loop_max < 1) {
        loop_max = 1;
    }

    pe_rsc_debug(rsc, "Allocating up to %d %s instances to a possible %d nodes (at most %d per host, %d optimal)",
                 max, rsc->id, available_nodes, per_host_max, loop_max);

    /* Pre-allocate as many instances as we can to their current location */
    for (GListPtr gIter = children; gIter != NULL && allocated < max; gIter = gIter->next) {
        resource_t *child = (resource_t *) gIter->data;

        if (child->running_on && is_set(child->flags, pe_rsc_provisional)
            && is_not_set(child->flags, pe_rsc_failed)) {
            node_t *child_node = pe__current_node(child);
            node_t *local_node = parent_node_instance(child, child_node);

            pe_rsc_trace(rsc, "Checking pre-allocation of %s to %s (%d remaining of %d)",
                         child->id, child_node->details->uname, max - allocated, max);

            if (can_run_resources(child_node) == FALSE || child_node->weight < 0) {
                pe_rsc_trace(rsc, "Not pre-allocating because %s can not run %s",
                             child_node->details->uname, child->id);

            } else if(local_node && local_node->count >= loop_max) {
                pe_rsc_trace(rsc,
                             "Not pre-allocating because %s already allocated optimal instances",
                             child_node->details->uname);

            } else if (color_instance(child, child_node, max < available_nodes, per_host_max, data_set)) {
                pe_rsc_trace(rsc, "Pre-allocated %s to %s", child->id,
                             child_node->details->uname);
                allocated++;
            }
        }
    }

    pe_rsc_trace(rsc, "Done pre-allocating (%d of %d)", allocated, max);

    for (GListPtr gIter = children; gIter != NULL; gIter = gIter->next) {
        resource_t *child = (resource_t *) gIter->data;

        if (child->running_on != NULL) {
            node_t *child_node = pe__current_node(child);
            node_t *local_node = parent_node_instance(child, child_node);

            if (local_node == NULL) {
                crm_err("%s is running on %s which isn't allowed",
                        child->id, child_node->details->uname);
            }
        }

        if (is_not_set(child->flags, pe_rsc_provisional)) {
        } else if (allocated >= max) {
            pe_rsc_debug(rsc, "Child %s not allocated - limit reached %d %d", child->id, allocated, max);
            resource_location(child, NULL, -INFINITY, "clone_color:limit_reached", data_set);
        } else {
            if (color_instance(child, NULL, max < available_nodes, per_host_max, data_set)) {
                allocated++;
            }
        }
    }

    pe_rsc_debug(rsc, "Allocated %d %s instances of a possible %d",
                 allocated, rsc->id, max);
}