Esempio n. 1
0
void
cli_resource_print_location(resource_t * rsc, const char *prefix)
{
    GListPtr lpc = NULL;
    GListPtr list = rsc->rsc_location;
    int offset = 0;

    if (prefix) {
        offset = strlen(prefix) - 2;
    }

    for (lpc = list; lpc != NULL; lpc = lpc->next) {
        rsc_to_node_t *cons = (rsc_to_node_t *) lpc->data;

        GListPtr lpc2 = NULL;

        for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
            node_t *node = (node_t *) lpc2->data;
            char *score = score2char(node->weight);

            fprintf(stdout, "%s: Node %-*s (score=%s, id=%s)\n",
                    prefix ? prefix : "  ", 71 - offset, node->details->uname, score, cons->id);
            free(score);
        }
    }
}
Esempio n. 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;
}
Esempio n. 3
0
static void
master_promotion_order(resource_t * rsc, pe_working_set_t * data_set)
{
    GListPtr gIter = NULL;
    node_t *node = NULL;
    node_t *chosen = NULL;
    clone_variant_data_t *clone_data = NULL;

    get_clone_variant_data(clone_data, rsc);

    if (clone_data->merged_master_weights) {
        return;
    }
    clone_data->merged_master_weights = TRUE;
    crm_trace("Merging weights for %s", rsc->id);
    set_bit(rsc->flags, pe_rsc_merging);

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

        crm_trace("Sort index: %s = %d", child->id, child->sort_index);
    }
    dump_node_scores(LOG_DEBUG_3, rsc, "Before", rsc->allowed_nodes);

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

        chosen = child->fns->location(child, NULL, FALSE);
        if (chosen == NULL || child->sort_index < 0) {
            crm_trace("Skipping %s", child->id);
            continue;
        }

        node = (node_t *) pe_hash_table_lookup(rsc->allowed_nodes, chosen->details->id);
        CRM_ASSERT(node != NULL);
        /* adds in master preferences and rsc_location.role=Master */
        crm_trace("Adding %s to %s from %s", score2char(child->sort_index), node->details->uname,
                  child->id);
        node->weight = merge_weights(child->sort_index, node->weight);
    }

    dump_node_scores(LOG_DEBUG_3, rsc, "Middle", rsc->allowed_nodes);

    gIter = rsc->rsc_cons;
    for (; gIter != NULL; gIter = gIter->next) {
        rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;

        /* (re-)adds location preferences of resources that the
         * master instance should/must be colocated with
         */
        if (constraint->role_lh == RSC_ROLE_MASTER) {
            crm_trace("RHS: %s with %s: %d", constraint->rsc_lh->id, constraint->rsc_rh->id,
                        constraint->score);
            rsc->allowed_nodes =
                constraint->rsc_rh->cmds->merge_weights(constraint->rsc_rh, rsc->id,
                                                        rsc->allowed_nodes,
                                                        constraint->node_attribute,
                                                        constraint->score / INFINITY,
                                                        constraint->score ==
                                                        INFINITY ? FALSE : TRUE, FALSE);
        }
    }

    gIter = rsc->rsc_cons_lhs;
    for (; gIter != NULL; gIter = gIter->next) {
        rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;

        /* (re-)adds location preferences of resource that wish to be
         * colocated with the master instance
         */
        if (constraint->role_rh == RSC_ROLE_MASTER) {
            crm_trace("LHS: %s with %s: %d", constraint->rsc_lh->id, constraint->rsc_rh->id,
                        constraint->score);
            rsc->allowed_nodes =
                constraint->rsc_lh->cmds->merge_weights(constraint->rsc_lh, rsc->id,
                                                        rsc->allowed_nodes,
                                                        constraint->node_attribute,
                                                        constraint->score / INFINITY, TRUE, TRUE);
        }
    }

    gIter = rsc->rsc_tickets;
    for (; gIter != NULL; gIter = gIter->next) {
        rsc_ticket_t *rsc_ticket = (rsc_ticket_t *) gIter->data;

        if (rsc_ticket->role_lh == RSC_ROLE_MASTER && rsc_ticket->ticket->granted == FALSE) {
            resource_location(rsc, NULL, -INFINITY, "__stateful_without_ticket__", data_set);
        }
    }

    dump_node_scores(LOG_DEBUG_3, rsc, "After", rsc->allowed_nodes);

    /* write them back and sort */

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

        chosen = child->fns->location(child, NULL, FALSE);
        if (is_not_set(child->flags, pe_rsc_managed) && child->next_role == RSC_ROLE_MASTER) {
            child->sort_index = INFINITY;

        } else if (chosen == NULL || child->sort_index < 0) {
            crm_trace("%s: %d", child->id, child->sort_index);

        } else {
            node = (node_t *) pe_hash_table_lookup(rsc->allowed_nodes, chosen->details->id);
            CRM_ASSERT(node != NULL);

            child->sort_index = node->weight;
        }
        crm_trace("Set sort index: %s = %d", child->id, child->sort_index);
    }

    rsc->children = g_list_sort_with_data(rsc->children, sort_master_instance, data_set);
    clear_bit(rsc->flags, pe_rsc_merging);
}
Esempio n. 4
0
void
dump_node_scores_worker(int level, const char *file, const char *function, int line,
                        resource_t * rsc, const char *comment, GHashTable * nodes)
{
    GHashTable *hash = nodes;
    GHashTableIter iter;
    node_t *node = NULL;

    if (rsc) {
        hash = rsc->allowed_nodes;
    }

    if (rsc && is_set(rsc->flags, pe_rsc_orphan)) {
        /* Don't show the allocation scores for orphans */
        return;
    }

    if (level == 0) {
        /* For now we want this in sorted order to keep the regression tests happy */
        GListPtr gIter = NULL;
        GListPtr list = g_hash_table_get_values(hash);

        list = g_list_sort(list, sort_node_uname);

        gIter = list;
        for (; gIter != NULL; gIter = gIter->next) {
            node_t *node = (node_t *) gIter->data;
            char *score = score2char(node->weight);

            if (rsc) {
                printf("%s: %s allocation score on %s: %s\n",
                       comment, rsc->id, node->details->uname, score);
            } else {
                printf("%s: %s = %s\n", comment, node->details->uname, score);
            }
            free(score);
        }

        g_list_free(list);

    } else if (hash) {
        g_hash_table_iter_init(&iter, hash);
        while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
            char *score = score2char(node->weight);

            if (rsc) {
                do_crm_log_alias(LOG_TRACE, file, function, line,
                                 "%s: %s allocation score on %s: %s", comment, rsc->id,
                                 node->details->uname, score);
            } else {
                do_crm_log_alias(LOG_TRACE, file, function, line + 1, "%s: %s = %s", comment,
                                 node->details->uname, score);
            }
            free(score);
        }
    }

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

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

            dump_node_scores_worker(level, file, function, line, child, comment, nodes);
        }
    }
}
Esempio n. 5
0
int
pe_get_failcount(node_t *node, resource_t *rsc, time_t *last_failure,
                 uint32_t flags, xmlNode *xml_op, pe_working_set_t *data_set)
{
    char *key = NULL;
    const char *value = NULL;
    regex_t failcount_re, lastfailure_re;
    int failcount = 0;
    time_t last = 0;
    GHashTableIter iter;

    generate_fail_regexes(rsc, data_set, &failcount_re, &lastfailure_re);

    /* Resource fail count is sum of all matching operation fail counts */
    g_hash_table_iter_init(&iter, node->details->attrs);
    while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) {
        if (regexec(&failcount_re, key, 0, NULL, 0) == 0) {
            failcount = merge_weights(failcount, char2score(value));
        } else if (regexec(&lastfailure_re, key, 0, NULL, 0) == 0) {
            last = QB_MAX(last, crm_int_helper(value, NULL));
        }
    }

    regfree(&failcount_re);
    regfree(&lastfailure_re);

    if ((failcount > 0) && (last > 0) && (last_failure != NULL)) {
        *last_failure = last;
    }

    /* If failure blocks the resource, disregard any failure timeout */
    if ((failcount > 0) && rsc->failure_timeout
        && block_failure(node, rsc, xml_op, data_set)) {

        pe_warn("Ignoring failure timeout %d for %s because it conflicts with on-fail=block",
                rsc->id, rsc->failure_timeout);
        rsc->failure_timeout = 0;
    }

    /* If all failures have expired, ignore fail count */
    if (is_set(flags, pe_fc_effective) && (failcount > 0) && (last > 0)
        && rsc->failure_timeout) {

        time_t now = get_effective_time(data_set);

        if (now > (last + rsc->failure_timeout)) {
            crm_debug("Failcount for %s on %s expired after %ds",
                      rsc->id, node->details->uname, rsc->failure_timeout);
            failcount = 0;
        }
    }

    if (is_set(flags, pe_fc_fillers) && rsc->fillers) {
        GListPtr gIter = NULL;

        for (gIter = rsc->fillers; gIter != NULL; gIter = gIter->next) {
            resource_t *filler = (resource_t *) gIter->data;
            time_t filler_last_failure = 0;

            failcount += pe_get_failcount(node, filler, &filler_last_failure,
                                          flags, xml_op, data_set);

            if (last_failure && filler_last_failure > *last_failure) {
                *last_failure = filler_last_failure;
            }
        }

        if (failcount > 0) {
            char *score = score2char(failcount);

            crm_info("Container %s and the resources within it have failed %s times on %s",
                     rsc->id, score, node->details->uname);
            free(score);
        }

    } else if (failcount > 0) {
        char *score = score2char(failcount);

        crm_info("%s has failed %s times on %s",
                 rsc->id, score, node->details->uname);
        free(score);
    }


    return failcount;
}
Esempio n. 6
0
void
cli_resource_print_colocation(resource_t * rsc, bool dependents, bool recursive, int offset)
{
    char *prefix = NULL;
    GListPtr lpc = NULL;
    GListPtr list = rsc->rsc_cons;

    prefix = calloc(1, (offset * 4) + 1);
    memset(prefix, ' ', offset * 4);

    if (dependents) {
        list = rsc->rsc_cons_lhs;
    }

    if (is_set(rsc->flags, pe_rsc_allocating)) {
        /* Break colocation loops */
        printf("loop %s\n", rsc->id);
        free(prefix);
        return;
    }

    set_bit(rsc->flags, pe_rsc_allocating);
    for (lpc = list; lpc != NULL; lpc = lpc->next) {
        rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;

        char *score = NULL;
        resource_t *peer = cons->rsc_rh;

        if (dependents) {
            peer = cons->rsc_lh;
        }

        if (is_set(peer->flags, pe_rsc_allocating)) {
            if (dependents == FALSE) {
                fprintf(stdout, "%s%-*s (id=%s - loop)\n", prefix, 80 - (4 * offset), peer->id,
                        cons->id);
            }
            continue;
        }

        if (dependents && recursive) {
            cli_resource_print_colocation(peer, dependents, recursive, offset + 1);
        }

        score = score2char(cons->score);
        if (cons->role_rh > RSC_ROLE_STARTED) {
            fprintf(stdout, "%s%-*s (score=%s, %s role=%s, id=%s)\n", prefix, 80 - (4 * offset),
                    peer->id, score, dependents ? "needs" : "with", role2text(cons->role_rh),
                    cons->id);
        } else {
            fprintf(stdout, "%s%-*s (score=%s, id=%s)\n", prefix, 80 - (4 * offset),
                    peer->id, score, cons->id);
        }
        cli_resource_print_location(peer, prefix);
        free(score);

        if (!dependents && recursive) {
            cli_resource_print_colocation(peer, dependents, recursive, offset + 1);
        }
    }
    free(prefix);
}