Example #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;
            }
        }
    }
}
Example #2
0
node_t *
master_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
{
    int promoted = 0;
    GListPtr gIter = NULL;
    GListPtr gIter2 = NULL;

    GHashTableIter iter;
    node_t *node = NULL;
    node_t *chosen = NULL;
    node_t *cons_node = NULL;
    enum rsc_role_e next_role = RSC_ROLE_UNKNOWN;

    clone_variant_data_t *clone_data = NULL;

    get_clone_variant_data(clone_data, rsc);

    if (is_not_set(rsc->flags, pe_rsc_provisional)) {
        return NULL;

    } else if (is_set(rsc->flags, pe_rsc_allocating)) {
        crm_debug("Dependency loop detected involving %s", rsc->id);
        return NULL;
    }

    apply_master_prefs(rsc);

    clone_color(rsc, prefer, data_set);

    set_bit(rsc->flags, pe_rsc_allocating);

    /* count now tracks the number of masters allocated */
    g_hash_table_iter_init(&iter, rsc->allowed_nodes);
    while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
        node->count = 0;
    }

    /*
     * assign priority
     */
    gIter = rsc->children;
    for (; gIter != NULL; gIter = gIter->next) {
        GListPtr list = NULL;
        resource_t *child_rsc = (resource_t *) gIter->data;

        crm_trace("Assigning priority for %s: %s", child_rsc->id,
                    role2text(child_rsc->next_role));

        if (child_rsc->fns->state(child_rsc, TRUE) == RSC_ROLE_STARTED) {
            set_role_slave(child_rsc, TRUE);
        }

        chosen = child_rsc->fns->location(child_rsc, &list, FALSE);
        if (g_list_length(list) > 1) {
            crm_config_err("Cannot promote non-colocated child %s", child_rsc->id);
        }

        g_list_free(list);
        if (chosen == NULL) {
            continue;
        }

        next_role = child_rsc->fns->state(child_rsc, FALSE);
        switch (next_role) {
            case RSC_ROLE_STARTED:
            case RSC_ROLE_UNKNOWN:
                CRM_CHECK(chosen != NULL, break);
                /*
                 * Default to -1 if no value is set
                 *
                 * This allows master locations to be specified
                 * based solely on rsc_location constraints,
                 * but prevents anyone from being promoted if
                 * neither a constraint nor a master-score is present
                 */
                child_rsc->priority = master_score(child_rsc, chosen, -1);
                break;

            case RSC_ROLE_SLAVE:
            case RSC_ROLE_STOPPED:
                child_rsc->priority = -INFINITY;
                break;
            case RSC_ROLE_MASTER:
                /* We will arrive here if we're re-creating actions after a stonith
                 */
                break;
            default:
                CRM_CHECK(FALSE /* unhandled */ ,
                          crm_err("Unknown resource role: %d for %s", next_role, child_rsc->id));
        }

        apply_master_location(child_rsc->rsc_location);
        apply_master_location(rsc->rsc_location);

        gIter2 = child_rsc->rsc_cons;
        for (; gIter2 != NULL; gIter2 = gIter2->next) {
            rsc_colocation_t *cons = (rsc_colocation_t *) gIter2->data;

            child_rsc->cmds->rsc_colocation_lh(child_rsc, cons->rsc_rh, cons);
        }

        child_rsc->sort_index = child_rsc->priority;
        crm_trace("Assigning priority for %s: %d", child_rsc->id, child_rsc->priority);

        if (next_role == RSC_ROLE_MASTER) {
            child_rsc->sort_index = INFINITY;
        }
    }

    dump_node_scores(LOG_DEBUG_3, rsc, "Pre merge", rsc->allowed_nodes);
    master_promotion_order(rsc, data_set);

    /* mark the first N as masters */

    gIter = rsc->children;
    for (; gIter != NULL; gIter = gIter->next) {
        resource_t *child_rsc = (resource_t *) gIter->data;
        char *score = score2char(child_rsc->sort_index);

        chosen = child_rsc->fns->location(child_rsc, NULL, FALSE);
        if (show_scores) {
            fprintf(stdout, "%s promotion score on %s: %s\n",
                    child_rsc->id, chosen ? chosen->details->uname : "none", score);

        } else {
            do_crm_log(scores_log_level, "%s promotion score on %s: %s",
                                child_rsc->id, chosen ? chosen->details->uname : "none", score);
        }
        crm_free(score);

        chosen = NULL;          /* nuke 'chosen' so that we don't promote more than the
                                 * required number of instances
                                 */

        if (child_rsc->sort_index < 0) {
            crm_trace("Not supposed to promote child: %s", child_rsc->id);

        } else if (promoted < clone_data->master_max || is_not_set(rsc->flags, pe_rsc_managed)) {
            chosen = can_be_master(child_rsc);
        }

        crm_debug("%s master score: %d", child_rsc->id, child_rsc->priority);

        if (chosen == NULL) {
            set_role_slave(child_rsc, FALSE);
            continue;
        }

        chosen->count++;
        crm_info("Promoting %s (%s %s)",
                 child_rsc->id, role2text(child_rsc->role), chosen->details->uname);
        set_role_master(child_rsc);
        promoted++;
    }

    clone_data->masters_allocated = promoted;
    crm_info("%s: Promoted %d instances of a possible %d to master",
             rsc->id, promoted, clone_data->master_max);

    clear_bit(rsc->flags, pe_rsc_provisional);
    clear_bit(rsc->flags, pe_rsc_allocating);

    return NULL;
}
Example #3
0
int
master_score(resource_t * rsc, node_t * node, int not_set_value)
{
    char *attr_name;
    char *name = rsc->id;
    const char *attr_value = NULL;
    int score = not_set_value, len = 0;

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

        for (; gIter != NULL; gIter = gIter->next) {
            resource_t *child = (resource_t *) gIter->data;
            int c_score = master_score(child, node, not_set_value);

            if (score == not_set_value) {
                score = c_score;
            } else {
                score += c_score;
            }
        }
        return score;
    }

    if (rsc->fns->state(rsc, TRUE) < RSC_ROLE_STARTED) {
        return score;
    }

    if (node != NULL) {
        node_t *match = pe_find_node_id(rsc->running_on, node->details->id);

        if (match == NULL) {
            crm_trace("%s is not active on %s - ignoring", rsc->id, node->details->uname);
            return score;
        }

        match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
        if (match == NULL) {
            return score;

        } else if (match->weight < 0) {
            crm_trace("%s on %s has score: %d - ignoring",
                      rsc->id, match->details->uname, match->weight);
            return score;
        }
    }

    if (rsc->clone_name) {
        /* Use the name the lrm knows this resource as,
         * since that's what crm_master would have used too
         */
        name = rsc->clone_name;
    }

    len = 8 + strlen(name);
    crm_malloc0(attr_name, len);
    sprintf(attr_name, "master-%s", name);

    if (node) {
        attr_value = g_hash_table_lookup(node->details->attrs, attr_name);
        crm_trace("%s: %s[%s] = %s", rsc->id, attr_name, node->details->uname, crm_str(attr_value));
    }

    if (attr_value != NULL) {
        score = char2score(attr_value);
    }

    crm_free(attr_name);
    return score;
}
Example #4
0
static int
master_score(resource_t * rsc, node_t * node, int not_set_value)
{
    char *attr_name;
    char *name = rsc->id;
    const char *attr_value = NULL;
    int score = not_set_value, len = 0;

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

        for (; gIter != NULL; gIter = gIter->next) {
            resource_t *child = (resource_t *) gIter->data;
            int c_score = master_score(child, node, not_set_value);

            if (score == not_set_value) {
                score = c_score;
            } else {
                score += c_score;
            }
        }
        return score;
    }

    if (node == NULL) {
        if (rsc->fns->state(rsc, TRUE) < RSC_ROLE_STARTED) {
            pe_rsc_trace(rsc, "Ingoring master score for %s: unknown state", rsc->id);
            return score;
        }

    } else {
        node_t *match = pe_find_node_id(rsc->running_on, node->details->id);
        node_t *known = pe_hash_table_lookup(rsc->known_on, node->details->id);

        if (is_not_set(rsc->flags, pe_rsc_unique) && filter_anonymous_instance(rsc, node)) {
            pe_rsc_trace(rsc, "Anonymous clone %s is allowed on %s", rsc->id, node->details->uname);

        } else if (match == NULL && known == NULL) {
            pe_rsc_trace(rsc, "%s (aka. %s) has been filtered on %s - ignoring", rsc->id,
                         rsc->clone_name, node->details->uname);
            return score;
        }

        match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
        if (match == NULL) {
            return score;

        } else if (match->weight < 0) {
            pe_rsc_trace(rsc, "%s on %s has score: %d - ignoring",
                         rsc->id, match->details->uname, match->weight);
            return score;
        }
    }

    if (rsc->clone_name) {
        /* Use the name the lrm knows this resource as,
         * since that's what crm_master would have used too
         */
        name = rsc->clone_name;
    }

    len = 8 + strlen(name);
    attr_name = calloc(1, len);
    sprintf(attr_name, "master-%s", name);

    if (node) {
        attr_value = g_hash_table_lookup(node->details->attrs, attr_name);
        pe_rsc_trace(rsc, "%s: %s[%s] = %s", rsc->id, attr_name, node->details->uname,
                     crm_str(attr_value));
    }

    if (attr_value != NULL) {
        score = char2score(attr_value);
    }

    free(attr_name);
    return score;
}