Esempio n. 1
0
static void
child_promoting_constraints(clone_variant_data_t * clone_data, enum pe_ordering type,
                            resource_t * rsc, resource_t * child, resource_t * last,
                            pe_working_set_t * data_set)
{
    if (child == NULL) {
        if (clone_data->ordered && last != NULL) {
            pe_rsc_trace(rsc, "Ordered version (last node)");
            /* last child promote before promoted started */
            new_rsc_order(last, RSC_PROMOTE, rsc, RSC_PROMOTED, type, data_set);
        }
        return;
    }

    /* child promote before global promoted */
    new_rsc_order(child, RSC_PROMOTE, rsc, RSC_PROMOTED, type, data_set);

    /* global promote before child promote */
    new_rsc_order(rsc, RSC_PROMOTE, child, RSC_PROMOTE, type, data_set);

    if (clone_data->ordered) {
        pe_rsc_trace(rsc, "Ordered version");
        if (last == NULL) {
            /* global promote before first child promote */
            last = rsc;

        }
        /* else: child/child relative promote */
        order_start_start(last, child, type);
        new_rsc_order(last, RSC_PROMOTE, child, RSC_PROMOTE, type, data_set);

    } else {
        pe_rsc_trace(rsc, "Un-ordered version");
    }
}
Esempio n. 2
0
void
clone_free(resource_t * rsc)
{
    GListPtr gIter = rsc->children;
    clone_variant_data_t *clone_data = NULL;

    get_clone_variant_data(clone_data, rsc);

    pe_rsc_trace(rsc, "Freeing %s", rsc->id);

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

        CRM_ASSERT(child_rsc);
        pe_rsc_trace(child_rsc, "Freeing child %s", child_rsc->id);
        free_xml(child_rsc->xml);
        child_rsc->xml = NULL;
        /* There could be a saved unexpanded xml */
        free_xml(child_rsc->orig_xml);
        child_rsc->orig_xml = NULL;
        child_rsc->fns->free(child_rsc);
    }

    g_list_free(rsc->children);

    if (clone_data) {
        CRM_ASSERT(clone_data->demote_notify == NULL);
        CRM_ASSERT(clone_data->stop_notify == NULL);
        CRM_ASSERT(clone_data->start_notify == NULL);
        CRM_ASSERT(clone_data->promote_notify == NULL);
    }

    common_free(rsc);
}
Esempio n. 3
0
static void
child_demoting_constraints(clone_variant_data_t * clone_data, enum pe_ordering type,
                           resource_t * rsc, resource_t * child, resource_t * last,
                           pe_working_set_t * data_set)
{
    if (child == NULL) {
        if (clone_data->ordered && last != NULL) {
            pe_rsc_trace(rsc, "Ordered version (last node)");
            /* global demote before first child demote */
            new_rsc_order(rsc, RSC_DEMOTE, last, RSC_DEMOTE, pe_order_optional, data_set);
        }
        return;
    }

    /* child demote before global demoted */
    new_rsc_order(child, RSC_DEMOTE, rsc, RSC_DEMOTED, pe_order_implies_then_printed, data_set);

    /* global demote before child demote */
    new_rsc_order(rsc, RSC_DEMOTE, child, RSC_DEMOTE, pe_order_implies_first_printed, data_set);

    if (clone_data->ordered && last != NULL) {
        pe_rsc_trace(rsc, "Ordered version");

        /* child/child relative demote */
        new_rsc_order(child, RSC_DEMOTE, last, RSC_DEMOTE, type, data_set);

    } else if (clone_data->ordered) {
        pe_rsc_trace(rsc, "Ordered version (1st node)");
        /* first child stop before global stopped */
        new_rsc_order(child, RSC_DEMOTE, rsc, RSC_DEMOTED, type, data_set);

    } else {
        pe_rsc_trace(rsc, "Un-ordered version");
    }
}
Esempio n. 4
0
node_t *
clone_color(resource_t *rsc, node_t *prefer, pe_working_set_t *data_set)
{
    GListPtr nodes = NULL;
    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)) {
        pe_rsc_debug(rsc, "Dependency loop detected involving %s", rsc->id);
        return NULL;
    }

    if (is_set(rsc->flags, pe_rsc_promotable)) {
        apply_master_prefs(rsc);
    }

    set_bit(rsc->flags, pe_rsc_allocating);
    pe_rsc_trace(rsc, "Processing %s", rsc->id);

    /* this information is used by sort_clone_instance() when deciding in which 
     * order to allocate clone instances
     */
    for (GListPtr gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) {
        rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;

        pe_rsc_trace(rsc, "%s: Coloring %s first", rsc->id, constraint->rsc_rh->id);
        constraint->rsc_rh->cmds->allocate(constraint->rsc_rh, prefer, data_set);
    }

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

        rsc->allowed_nodes =
            constraint->rsc_lh->cmds->merge_weights(constraint->rsc_lh, rsc->id, rsc->allowed_nodes,
                                                    constraint->node_attribute,
                                                    (float)constraint->score / INFINITY,
                                                    (pe_weights_rollback | pe_weights_positive));
    }

    dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __FUNCTION__, rsc->allowed_nodes);

    nodes = g_hash_table_get_values(rsc->allowed_nodes);
    nodes = sort_nodes_by_weight(nodes, NULL, data_set);
    rsc->children = g_list_sort_with_data(rsc->children, sort_clone_instance, data_set);
    distribute_children(rsc, rsc->children, nodes, clone_data->clone_max, clone_data->clone_node_max, data_set);
    g_list_free(nodes);

    if (is_set(rsc->flags, pe_rsc_promotable)) {
        color_promotable(rsc, data_set);
    }

    clear_bit(rsc->flags, pe_rsc_provisional);
    clear_bit(rsc->flags, pe_rsc_allocating);
    pe_rsc_trace(rsc, "Done allocating %s", rsc->id);
    return NULL;
}
Esempio n. 5
0
void
group_update_pseudo_status(resource_t * parent, resource_t * child)
{
    GListPtr gIter = child->actions;
    group_variant_data_t *group_data = NULL;

    get_group_variant_data(group_data, parent);

    if (group_data->ordered == FALSE) {
        /* If this group is not ordered, then leave the meta-actions as optional */
        return;
    }

    if (group_data->child_stopping && group_data->child_starting) {
        return;
    }

    for (; gIter != NULL; gIter = gIter->next) {
        action_t *action = (action_t *) gIter->data;

        if (is_set(action->flags, pe_action_optional)) {
            continue;
        }
        if (safe_str_eq(RSC_STOP, action->task) && is_set(action->flags, pe_action_runnable)) {
            group_data->child_stopping = TRUE;
            pe_rsc_trace(action->rsc, "Based on %s the group is stopping", action->uuid);

        } else if (safe_str_eq(RSC_START, action->task)
                   && is_set(action->flags, pe_action_runnable)) {
            group_data->child_starting = TRUE;
            pe_rsc_trace(action->rsc, "Based on %s the group is starting", action->uuid);
        }
    }
}
Esempio n. 6
0
static void
add_unallocated_utilization(GHashTable * all_utilization, resource_t * rsc,
                    GListPtr all_rscs, resource_t * orig_rsc)
{
    if(is_set(rsc->flags, pe_rsc_provisional) == FALSE) {
        return;
    }

    if (rsc->variant == pe_native) {
        pe_rsc_trace(orig_rsc, "%s: Adding %s as colocated utilization",
                     orig_rsc->id, rsc->id);
        native_add_unallocated_utilization(all_utilization, rsc);

    } else if (rsc->variant == pe_group) {
        pe_rsc_trace(orig_rsc, "%s: Adding %s as colocated utilization",
                     orig_rsc->id, rsc->id);
        group_add_unallocated_utilization(all_utilization, rsc, all_rscs);

    } else if (rsc->variant == pe_clone ||
               rsc->variant == pe_master) {
        GListPtr gIter1 = NULL;
        gboolean existing = FALSE;

        /* Check if there's any child already existing in the list */
        gIter1 = rsc->children;
        for (; gIter1 != NULL; gIter1 = gIter1->next) {
            resource_t *child = (resource_t *) gIter1->data;
            GListPtr gIter2 = NULL;

            if (g_list_find(all_rscs, child)) {
                existing = TRUE;

            } else {
                /* Check if there's any child of another cloned group already existing in the list */
                gIter2 = child->children;
                for (; gIter2 != NULL; gIter2 = gIter2->next) {
                    resource_t *grandchild = (resource_t *) gIter2->data;

                    if (g_list_find(all_rscs, grandchild)) {
                        pe_rsc_trace(orig_rsc, "%s: Adding %s as colocated utilization",
                                     orig_rsc->id, child->id);
                        add_unallocated_utilization(all_utilization, child, all_rscs, orig_rsc);
                        existing = TRUE;
                        break;
                    }
                }
            }
        }

        if (existing == FALSE) {
            resource_t *first_child = (resource_t *) rsc->children->data;

            pe_rsc_trace(orig_rsc, "%s: Adding %s as colocated utilization",
                         orig_rsc->id, ID(first_child->xml));
            add_unallocated_utilization(all_utilization, first_child, all_rscs, orig_rsc);
        }
    }
}
Esempio n. 7
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) {
                    pe_rsc_trace(rsc, "\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) {
                pe_rsc_trace(rsc, "\t%s: Updating priority (%d->%d)",
                             child_rsc->id, child_rsc->priority, new_score);
                child_rsc->priority = new_score;
            }
        }
    }
}
Esempio n. 8
0
static gboolean
filter_anonymous_instance(resource_t * rsc, node_t * node)
{
    GListPtr rIter = NULL;
    char *key = clone_strip(rsc->id);
    resource_t *parent = uber_parent(rsc);

    for (rIter = parent->children; rIter; rIter = rIter->next) {
        resource_t *child = rIter->data;
        resource_t *active = parent->fns->find_rsc(child, key, node, pe_find_clone|pe_find_current);

        /*
         * Look for an active instance on $node, if there is one, only it receives the master score
         * Use ->find_rsc() because we might be a cloned group
         */
        if(rsc == active) {
            pe_rsc_trace(rsc, "Found %s for %s active on %s: done", active->id, key, node->details->uname);
            free(key);
            return TRUE;
        } else if(active) {
            pe_rsc_trace(rsc, "Found %s for %s on %s: not %s", active->id, key, node->details->uname, rsc->id);
            free(key);
            return FALSE;
        } else {
            pe_rsc_trace(rsc, "%s on %s: not active", key, node->details->uname);
        }
    }

    for (rIter = parent->children; rIter; rIter = rIter->next) {
        resource_t *child = rIter->data;

        /*
         * We know its not running, but any score will still count if
         * the instance has been probed on $node
         *
         * Again use ->find_rsc() because we might be a cloned group
         * and knowing that other members of the group are known here
         * implies nothing
         */
        rsc = parent->fns->find_rsc(child, key, NULL, pe_find_clone);
        pe_rsc_trace(rsc, "Checking %s for %s on %s", rsc->id, key, node->details->uname);
        if (g_hash_table_lookup(rsc->known_on, node->details->id)) {
            free(key);
            return TRUE;
        }
    }
    free(key);
    return FALSE;
}
Esempio n. 9
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;
}
Esempio n. 10
0
static enum pe_action_flags
get_action_flags(action_t * action, node_t * node)
{
    enum pe_action_flags flags = action->flags;

    if (action->rsc) {
        flags = action->rsc->cmds->action_flags(action, NULL);

        if (action->rsc->variant >= pe_clone && node) {

            /* We only care about activity on $node */
            enum pe_action_flags clone_flags = action->rsc->cmds->action_flags(action, node);

            /* Go to great lengths to ensure the correct value for pe_action_runnable...
             *
             * If we are a clone, then for _ordering_ constraints, its only relevant
             * if we are runnable _anywhere_.
             *
             * This only applies to _runnable_ though, and only for ordering constraints.
             * If this function is ever used during colocation, then we'll need additional logic
             *
             * Not very satisfying, but its logical and appears to work well.
             */
            if (is_not_set(clone_flags, pe_action_runnable)
                && is_set(flags, pe_action_runnable)) {
                pe_rsc_trace(action->rsc, "Fixing up runnable flag for %s", action->uuid);
                set_bit(clone_flags, pe_action_runnable);
            }
            flags = clone_flags;
        }
    }
    return flags;
}
Esempio n. 11
0
static action_t *
rsc_expand_action(action_t * action)
{
    action_t *result = action;

    if (action->rsc && action->rsc->variant >= pe_group) {
        /* Expand 'start' -> 'started' */
        char *uuid = NULL;
        gboolean notify = FALSE;

        if (action->rsc->parent == NULL) {
            /* Only outter-most resources have notification actions */
            notify = is_set(action->rsc->flags, pe_rsc_notify);
        }

        uuid = convert_non_atomic_uuid(action->uuid, action->rsc, notify, FALSE);
        if (uuid) {
            pe_rsc_trace(action->rsc, "Converting %s to %s %d", action->uuid, uuid,
                         is_set(action->rsc->flags, pe_rsc_notify));
            result = find_first_action(action->rsc->actions, uuid, NULL, NULL);
            if (result == NULL) {
                crm_err("Couldn't expand %s", action->uuid);
                result = action;
            }
            free(uuid);
        }
    }
    return result;
}
Esempio n. 12
0
static GHashTable *
sum_unallocated_utilization(resource_t * rsc, GListPtr colocated_rscs)
{
    GListPtr gIter = NULL;
    GListPtr all_rscs = NULL;
    GHashTable *all_utilization = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                          g_hash_destroy_str, g_hash_destroy_str);

    all_rscs = g_list_copy(colocated_rscs);
    if (g_list_find(all_rscs, rsc) == FALSE) {
        all_rscs = g_list_append(all_rscs, rsc);
    }

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

        if(is_set(listed_rsc->flags, pe_rsc_provisional) == FALSE) {
            continue;
        }

        pe_rsc_trace(rsc, "%s: Processing unallocated colocated %s", rsc->id, listed_rsc->id);
        add_unallocated_utilization(all_utilization, listed_rsc, all_rscs, rsc);
    }

    g_list_free(all_rscs);

    return all_utilization;
}
Esempio n. 13
0
void
container_rsc_location(resource_t * rsc, rsc_to_node_t * constraint)
{
    container_variant_data_t *container_data = NULL;
    get_container_variant_data(container_data, rsc);

    pe_rsc_trace(rsc, "Processing location constraint %s for %s", constraint->id, rsc->id);

    native_rsc_location(rsc, constraint);

    for (GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) {
        container_grouping_t *tuple = (container_grouping_t *)gIter->data;

        if (tuple->docker) {
            tuple->docker->cmds->rsc_location(tuple->docker, constraint);
        }
        if(tuple->ip) {
            tuple->ip->cmds->rsc_location(tuple->ip, constraint);
        }
    }

    if(container_data->child && (constraint->role_filter == RSC_ROLE_SLAVE || constraint->role_filter == RSC_ROLE_MASTER)) {
        container_data->child->cmds->rsc_location(container_data->child, constraint);
        container_data->child->rsc_location = g_list_prepend(container_data->child->rsc_location, constraint);
    }
}
Esempio n. 14
0
node_t *
group_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
{
    node_t *node = NULL;
    node_t *group_node = NULL;
    GListPtr gIter = NULL;
    group_variant_data_t *group_data = NULL;

    get_group_variant_data(group_data, rsc);

    if (is_not_set(rsc->flags, pe_rsc_provisional)) {
        return rsc->allocated_to;
    }
    pe_rsc_trace(rsc, "Processing %s", rsc->id);
    if (is_set(rsc->flags, pe_rsc_allocating)) {
        pe_rsc_debug(rsc, "Dependency loop detected involving %s", rsc->id);
        return NULL;
    }

    if (group_data->first_child == NULL) {
        /* nothign to allocate */
        clear_bit(rsc->flags, pe_rsc_provisional);
        return NULL;
    }

    set_bit(rsc->flags, pe_rsc_allocating);
    rsc->role = group_data->first_child->role;

    group_data->first_child->rsc_cons =
        g_list_concat(group_data->first_child->rsc_cons, rsc->rsc_cons);
    rsc->rsc_cons = NULL;

    group_data->last_child->rsc_cons_lhs =
        g_list_concat(group_data->last_child->rsc_cons_lhs, rsc->rsc_cons_lhs);
    rsc->rsc_cons_lhs = NULL;

    dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __FUNCTION__,
                     rsc->allowed_nodes);

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

        node = child_rsc->cmds->allocate(child_rsc, prefer, data_set);
        if (group_node == NULL) {
            group_node = node;
        }
    }

    rsc->next_role = group_data->first_child->next_role;
    clear_bit(rsc->flags, pe_rsc_allocating);
    clear_bit(rsc->flags, pe_rsc_provisional);

    if (group_data->colocated) {
        return group_node;
    }
    return NULL;
}
Esempio n. 15
0
static action_t *
pe_notify(resource_t * rsc, node_t * node, action_t * op, action_t * confirm,
          notify_data_t * n_data, pe_working_set_t * data_set)
{
    char *key = NULL;
    action_t *trigger = NULL;
    const char *value = NULL;
    const char *task = NULL;

    if (op == NULL || confirm == NULL) {
        pe_rsc_trace(rsc, "Op=%p confirm=%p", op, confirm);
        return NULL;
    }

    CRM_CHECK(rsc != NULL, return NULL);
    CRM_CHECK(node != NULL, return NULL);

    if (node->details->online == FALSE) {
        pe_rsc_trace(rsc, "Skipping notification for %s: node offline", rsc->id);
        return NULL;
    } else if (is_set(op->flags, pe_action_runnable) == FALSE) {
        pe_rsc_trace(rsc, "Skipping notification for %s: not runnable", op->uuid);
        return NULL;
    }

    value = g_hash_table_lookup(op->meta, "notify_type");
    task = g_hash_table_lookup(op->meta, "notify_operation");

    pe_rsc_trace(rsc, "Creating notify actions for %s: %s (%s-%s)", op->uuid, rsc->id, value, task);

    key = generate_notify_key(rsc->id, value, task);
    trigger = custom_action(rsc, key, op->task, node,
                            is_set(op->flags, pe_action_optional), TRUE, data_set);
    g_hash_table_foreach(op->meta, dup_attr, trigger->meta);
    g_hash_table_foreach(n_data->keys, dup_attr, trigger->meta);

    /* pseudo_notify before notify */
    pe_rsc_trace(rsc, "Ordering %s before %s (%d->%d)", op->uuid, trigger->uuid, trigger->id,
                 op->id);

    order_actions(op, trigger, pe_order_optional);
    order_actions(trigger, confirm, pe_order_optional);
    return trigger;
}
Esempio n. 16
0
enum pe_action_flags
summary_action_flags(action_t * action, GListPtr children, node_t * node)
{
    GListPtr gIter = NULL;
    gboolean any_runnable = FALSE;
    gboolean check_runnable = TRUE;
    enum action_tasks task = clone_child_action(action);
    enum pe_action_flags flags = (pe_action_optional | pe_action_runnable | pe_action_pseudo);
    const char *task_s = task2text(task);

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

        child_action = find_first_action(child->actions, NULL, task_s, child->children ? NULL : node);
        pe_rsc_trace(action->rsc, "Checking for %s in %s on %s (%s)", task_s, child->id,
                     node ? node->details->uname : "none", child_action?child_action->uuid:"NA");
        if (child_action) {
            enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node);

            if (is_set(flags, pe_action_optional)
                && is_set(child_flags, pe_action_optional) == FALSE) {
                pe_rsc_trace(child, "%s is mandatory because of %s", action->uuid,
                             child_action->uuid);
                flags = crm_clear_bit(__FUNCTION__, __LINE__, action->rsc->id, flags, pe_action_optional);
                pe_clear_action_bit(action, pe_action_optional);
            }
            if (is_set(child_flags, pe_action_runnable)) {
                any_runnable = TRUE;
            }
        }
    }

    if (check_runnable && any_runnable == FALSE) {
        pe_rsc_trace(action->rsc, "%s is not runnable because no children are", action->uuid);
        flags = crm_clear_bit(__FUNCTION__, __LINE__, action->rsc->id, flags, pe_action_runnable);
        if (node == NULL) {
            pe_clear_action_bit(action, pe_action_runnable);
        }
    }

    return flags;
}
Esempio n. 17
0
gboolean
shutdown_constraints(node_t * node, action_t * shutdown_op, pe_working_set_t * data_set)
{
    /* add the stop to the before lists so it counts as a pre-req
     * for the shutdown
     */
    GListPtr lpc = NULL;

    for (lpc = data_set->actions; lpc != NULL; lpc = lpc->next) {
        action_t *action = (action_t *) lpc->data;

        if (action->rsc == NULL || action->node == NULL) {
            continue;
        } else if (action->node->details != node->details) {
            continue;
        } else if (is_set(action->rsc->flags, pe_rsc_maintenance)) {
            pe_rsc_trace(action->rsc, "Skipping %s: maintainence mode", action->uuid);
            continue;
        } else if (node->details->maintenance) {
            pe_rsc_trace(action->rsc, "Skipping %s: node %s is in maintenance mode",
                         action->uuid, node->details->uname);
            continue;
        } else if (safe_str_neq(action->task, RSC_STOP)) {
            continue;
        } else if (is_not_set(action->rsc->flags, pe_rsc_managed)
                   && is_not_set(action->rsc->flags, pe_rsc_block)) {
            /*
             * If another action depends on this one, we may still end up blocking
             */
            pe_rsc_trace(action->rsc, "Skipping %s: unmanaged", action->uuid);
            continue;
        }

        pe_rsc_trace(action->rsc, "Ordering %s before shutdown on %s", action->uuid,
                     node->details->uname);
        pe_clear_action_bit(action, pe_action_optional);
        custom_action_order(action->rsc, NULL, action,
                            NULL, strdup(CRM_OP_SHUTDOWN), shutdown_op,
                            pe_order_optional | pe_order_runnable_left, data_set);
    }

    return TRUE;
}
Esempio n. 18
0
void
group_free(resource_t * rsc)
{
    GListPtr gIter = rsc->children;

    CRM_CHECK(rsc != NULL, return);

    pe_rsc_trace(rsc, "Freeing %s", rsc->id);

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

        pe_rsc_trace(child_rsc, "Freeing child %s", child_rsc->id);
        child_rsc->fns->free(child_rsc);
    }

    pe_rsc_trace(rsc, "Freeing child list");
    g_list_free(rsc->children);

    common_free(rsc);
}
Esempio n. 19
0
enum pe_action_flags
group_action_flags(action_t * action, node_t * node)
{
    GListPtr gIter = NULL;
    enum pe_action_flags flags = (pe_action_optional | pe_action_runnable | pe_action_pseudo);

    for (gIter = action->rsc->children; gIter != NULL; gIter = gIter->next) {
        resource_t *child = (resource_t *) gIter->data;
        enum action_tasks task = get_complex_task(child, action->task, TRUE);
        const char *task_s = task2text(task);
        action_t *child_action = find_first_action(child->actions, NULL, task_s, node);

        if (child_action) {
            enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node);

            if (is_set(flags, pe_action_optional)
                && is_set(child_flags, pe_action_optional) == FALSE) {
                pe_rsc_trace(action->rsc, "%s is mandatory because of %s", action->uuid,
                             child_action->uuid);
                clear_bit(flags, pe_action_optional);
                pe_clear_action_bit(action, pe_action_optional);
            }
            if (safe_str_neq(task_s, action->task)
                && is_set(flags, pe_action_runnable)
                && is_set(child_flags, pe_action_runnable) == FALSE) {
                pe_rsc_trace(action->rsc, "%s is not runnable because of %s", action->uuid,
                             child_action->uuid);
                clear_bit(flags, pe_action_runnable);
                pe_clear_action_bit(action, pe_action_runnable);
            }

        } else if (task != stop_rsc && task != action_demote) {
            pe_rsc_trace(action->rsc, "%s is not runnable because of %s (not found in %s)",
                         action->uuid, task_s, child->id);
            clear_bit(flags, pe_action_runnable);
        }
    }

    return flags;
}
Esempio n. 20
0
resource_t *
create_child_clone(resource_t * rsc, int sub_id, pe_working_set_t * data_set)
{
    gboolean as_orphan = FALSE;
    char *inc_num = NULL;
    char *inc_max = NULL;
    resource_t *child_rsc = NULL;
    xmlNode *child_copy = NULL;
    clone_variant_data_t *clone_data = NULL;

    get_clone_variant_data(clone_data, rsc);

    CRM_CHECK(clone_data->xml_obj_child != NULL, return FALSE);

    if (sub_id < 0) {
        as_orphan = TRUE;
        sub_id = clone_data->total_clones;
    }
    inc_num = crm_itoa(sub_id);
    inc_max = crm_itoa(clone_data->clone_max);

    child_copy = copy_xml(clone_data->xml_obj_child);

    crm_xml_add(child_copy, XML_RSC_ATTR_INCARNATION, inc_num);

    if (common_unpack(child_copy, &child_rsc, rsc, data_set) == FALSE) {
        pe_err("Failed unpacking resource %s", crm_element_value(child_copy, XML_ATTR_ID));
        child_rsc = NULL;
        goto bail;
    }
/*  child_rsc->globally_unique = rsc->globally_unique; */

    CRM_ASSERT(child_rsc);
    clone_data->total_clones += 1;
    pe_rsc_trace(child_rsc, "Setting clone attributes for: %s", child_rsc->id);
    rsc->children = g_list_append(rsc->children, child_rsc);
    if (as_orphan) {
        mark_as_orphan(child_rsc);
    }

    add_hash_param(child_rsc->meta, XML_RSC_ATTR_INCARNATION_MAX, inc_max);

    print_resource(LOG_DEBUG_3, "Added ", child_rsc, FALSE);

  bail:
    free(inc_num);
    free(inc_max);

    return child_rsc;
}
Esempio n. 21
0
static void
pe_post_notify(resource_t * rsc, node_t * node, notify_data_t * n_data, pe_working_set_t * data_set)
{
    action_t *notify = NULL;

    CRM_CHECK(rsc != NULL, return);

    if (n_data->post == NULL) {
        return;                 /* Nothing to do */
    }

    notify = pe_notify(rsc, node, n_data->post, n_data->post_done, n_data, data_set);

    if (notify != NULL) {
        notify->priority = INFINITY;
    }

    if (n_data->post_done) {
        GListPtr gIter = rsc->actions;

        for (; gIter != NULL; gIter = gIter->next) {
            action_t *mon = (action_t *) gIter->data;
            const char *interval_ms_s = g_hash_table_lookup(mon->meta,
                                                            XML_LRM_ATTR_INTERVAL_MS);

            if ((interval_ms_s == NULL) || safe_str_eq(interval_ms_s, "0")) {
                pe_rsc_trace(rsc, "Skipping %s: interval", mon->uuid);
                continue;
            } else if (safe_str_eq(mon->task, RSC_CANCEL)) {
                pe_rsc_trace(rsc, "Skipping %s: cancel", mon->uuid);
                continue;
            }

            order_actions(n_data->post_done, mon, pe_order_optional);
        }
    }
}
Esempio n. 22
0
void
clone_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
{
    GListPtr gIter = rsc->children;

    pe_rsc_trace(rsc, "Processing location constraint %s for %s", constraint->id, rsc->id);

    native_rsc_location(rsc, constraint);

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

        child_rsc->cmds->rsc_location(child_rsc, constraint);
    }
}
Esempio n. 23
0
void
clone_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
{
    resource_t *last_rsc = NULL;
    GListPtr gIter;
    clone_variant_data_t *clone_data = NULL;

    get_clone_variant_data(clone_data, rsc);

    pe_rsc_trace(rsc, "Internal constraints for %s", rsc->id);
    new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set);
    new_rsc_order(rsc, RSC_START, rsc, RSC_STARTED, pe_order_runnable_left, data_set);
    new_rsc_order(rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_runnable_left, data_set);

    if (is_set(rsc->flags, pe_rsc_promotable)) {
        new_rsc_order(rsc, RSC_DEMOTED, rsc, RSC_STOP, pe_order_optional, data_set);
        new_rsc_order(rsc, RSC_STARTED, rsc, RSC_PROMOTE, pe_order_runnable_left, data_set);
    }

    if (clone_data->ordered) {
        /* we have to maintain a consistent sorted child list when building order constraints */
        rsc->children = g_list_sort(rsc->children, sort_rsc_id);
    }
    for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
        resource_t *child_rsc = (resource_t *) gIter->data;

        child_rsc->cmds->internal_constraints(child_rsc, data_set);

        order_start_start(rsc, child_rsc, pe_order_runnable_left | pe_order_implies_first_printed);
        new_rsc_order(child_rsc, RSC_START, rsc, RSC_STARTED, pe_order_implies_then_printed,
                      data_set);
        if (clone_data->ordered && last_rsc) {
            order_start_start(last_rsc, child_rsc, pe_order_optional);
        }

        order_stop_stop(rsc, child_rsc, pe_order_implies_first_printed);
        new_rsc_order(child_rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_implies_then_printed,
                      data_set);
        if (clone_data->ordered && last_rsc) {
            order_stop_stop(child_rsc, last_rsc, pe_order_optional);
        }

        last_rsc = child_rsc;
    }
    if (is_set(rsc->flags, pe_rsc_promotable)) {
        promotable_constraints(rsc, data_set);
    }
}
Esempio n. 24
0
void
group_expand(resource_t * rsc, pe_working_set_t * data_set)
{
    GListPtr gIter = rsc->children;

    pe_rsc_trace(rsc, "Processing actions from %s", rsc->id);

    CRM_CHECK(rsc != NULL, return);
    native_expand(rsc, data_set);

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

        child_rsc->cmds->expand(child_rsc, data_set);
    }
}
Esempio n. 25
0
void
group_rsc_colocation_rh(pe_resource_t *rsc_lh, pe_resource_t *rsc_rh,
                        rsc_colocation_t *constraint,
                        pe_working_set_t *data_set)
{
    GListPtr gIter = rsc_rh->children;
    group_variant_data_t *group_data = NULL;

    get_group_variant_data(group_data, rsc_rh);
    CRM_CHECK(rsc_lh->variant == pe_native, return);

    pe_rsc_trace(rsc_rh, "Processing RH of constraint %s", constraint->id);
    print_resource(LOG_TRACE, "LHS", rsc_lh, TRUE);

    if (is_set(rsc_rh->flags, pe_rsc_provisional)) {
        return;

    } else if (group_data->colocated && group_data->first_child) {
        if (constraint->score >= INFINITY) {
            /* Ensure RHS is _fully_ up before can start LHS */
            group_data->last_child->cmds->rsc_colocation_rh(rsc_lh,
                                                            group_data->last_child,
                                                            constraint,
                                                            data_set);
        } else {
            /* A partially active RHS is fine */
            group_data->first_child->cmds->rsc_colocation_rh(rsc_lh,
                                                             group_data->first_child,
                                                             constraint,
                                                             data_set);
        }

        return;

    } else if (constraint->score >= INFINITY) {
        crm_config_err("%s: Cannot perform mandatory colocation with"
                       " non-colocated group: %s", rsc_lh->id, rsc_rh->id);
        return;
    }

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

        child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint,
                                           data_set);
    }
}
Esempio n. 26
0
void
group_create_actions(resource_t * rsc, pe_working_set_t * data_set)
{
    action_t *op = NULL;
    const char *value = NULL;
    GListPtr gIter = rsc->children;

    pe_rsc_trace(rsc, "Creating actions for %s", rsc->id);

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

        child_rsc->cmds->create_actions(child_rsc, data_set);
        group_update_pseudo_status(rsc, child_rsc);
    }

    op = start_action(rsc, NULL, TRUE /* !group_data->child_starting */ );
    set_bit(op->flags, pe_action_pseudo | pe_action_runnable);

    op = custom_action(rsc, started_key(rsc),
                       RSC_STARTED, NULL, TRUE /* !group_data->child_starting */ , TRUE, data_set);
    set_bit(op->flags, pe_action_pseudo | pe_action_runnable);

    op = stop_action(rsc, NULL, TRUE /* !group_data->child_stopping */ );
    set_bit(op->flags, pe_action_pseudo | pe_action_runnable);

    op = custom_action(rsc, stopped_key(rsc),
                       RSC_STOPPED, NULL, TRUE /* !group_data->child_stopping */ , TRUE, data_set);
    set_bit(op->flags, pe_action_pseudo | pe_action_runnable);

    value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_PROMOTABLE);
    if (crm_is_true(value)) {
        op = custom_action(rsc, demote_key(rsc), RSC_DEMOTE, NULL, TRUE, TRUE, data_set);
        set_bit(op->flags, pe_action_pseudo);
        set_bit(op->flags, pe_action_runnable);
        op = custom_action(rsc, demoted_key(rsc), RSC_DEMOTED, NULL, TRUE, TRUE, data_set);
        set_bit(op->flags, pe_action_pseudo);
        set_bit(op->flags, pe_action_runnable);

        op = custom_action(rsc, promote_key(rsc), RSC_PROMOTE, NULL, TRUE, TRUE, data_set);
        set_bit(op->flags, pe_action_pseudo);
        set_bit(op->flags, pe_action_runnable);
        op = custom_action(rsc, promoted_key(rsc), RSC_PROMOTED, NULL, TRUE, TRUE, data_set);
        set_bit(op->flags, pe_action_pseudo);
        set_bit(op->flags, pe_action_runnable);
    }
}
Esempio n. 27
0
enum rsc_role_e
group_resource_state(const resource_t * rsc, gboolean current)
{
    enum rsc_role_e group_role = RSC_ROLE_UNKNOWN;
    GListPtr gIter = rsc->children;

    for (; gIter != NULL; gIter = gIter->next) {
        resource_t *child_rsc = (resource_t *) gIter->data;
        enum rsc_role_e role = child_rsc->fns->state(child_rsc, current);

        if (role > group_role) {
            group_role = role;
        }
    }

    pe_rsc_trace(rsc, "%s role: %s", rsc->id, role2text(group_role));
    return group_role;
}
Esempio n. 28
0
void
group_rsc_colocation_lh(pe_resource_t *rsc_lh, pe_resource_t *rsc_rh,
                        rsc_colocation_t *constraint,
                        pe_working_set_t *data_set)
{
    GListPtr gIter = NULL;
    group_variant_data_t *group_data = NULL;

    if (rsc_lh == NULL) {
        pe_err("rsc_lh was NULL for %s", constraint->id);
        return;

    } else if (rsc_rh == NULL) {
        pe_err("rsc_rh was NULL for %s", constraint->id);
        return;
    }

    gIter = rsc_lh->children;
    pe_rsc_trace(rsc_lh, "Processing constraints from %s", rsc_lh->id);

    get_group_variant_data(group_data, rsc_lh);

    if (group_data->colocated) {
        group_data->first_child->cmds->rsc_colocation_lh(group_data->first_child,
                                                         rsc_rh, constraint,
                                                         data_set);
        return;

    } else if (constraint->score >= INFINITY) {
        crm_config_err("%s: Cannot perform mandatory colocation"
                       " between non-colocated group and %s", rsc_lh->id, rsc_rh->id);
        return;
    }

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

        child_rsc->cmds->rsc_colocation_lh(child_rsc, rsc_rh, constraint,
                                           data_set);
    }
}
Esempio n. 29
0
void
create_notifications(resource_t * rsc, notify_data_t * n_data, pe_working_set_t * data_set)
{
    GListPtr gIter = NULL;
    action_t *stop = NULL;
    action_t *start = NULL;
    enum action_tasks task = text2task(n_data->action);

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

            create_notifications(child, n_data, data_set);
        }
        return;
    }

    /* Copy notification details into standard ops */

    gIter = rsc->actions;
    for (; gIter != NULL; gIter = gIter->next) {
        action_t *op = (action_t *) gIter->data;

        if (is_set(op->flags, pe_action_optional) == FALSE && op->node != NULL) {
            enum action_tasks t = text2task(op->task);

            switch (t) {
                case start_rsc:
                case stop_rsc:
                case action_promote:
                case action_demote:
                    g_hash_table_foreach(n_data->keys, dup_attr, op->meta);
                    break;
                default:
                    break;
            }
        }
    }

    pe_rsc_trace(rsc, "Creating notifications for: %s.%s (%s->%s)",
                 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));

    stop = find_first_action(rsc->actions, NULL, RSC_STOP, NULL);
    start = find_first_action(rsc->actions, NULL, RSC_START, NULL);

    /* stop / demote */
    if (rsc->role != RSC_ROLE_STOPPED) {
        if (task == stop_rsc || task == action_demote) {
            gIter = rsc->running_on;
            for (; gIter != NULL; gIter = gIter->next) {
                node_t *current_node = (node_t *) gIter->data;

                /* if this stop action is a pseudo action as a result of the current
                 * node being fenced, this stop action is implied by the fencing 
                 * action. There's no reason to send the fenced node a stop notification */ 
                if (stop &&
                    is_set(stop->flags, pe_action_pseudo) &&
                    current_node->details->unclean) {

                    continue;
                }

                pe_notify(rsc, current_node, n_data->pre, n_data->pre_done, n_data, data_set);
                if (task == action_demote || stop == NULL
                    || is_set(stop->flags, pe_action_optional)) {
                    pe_post_notify(rsc, current_node, n_data, data_set);
                }
            }
        }
    }

    /* start / promote */
    if (rsc->next_role != RSC_ROLE_STOPPED) {
        if (rsc->allocated_to == NULL) {
            pe_proc_err("Next role '%s' but %s is not allocated", role2text(rsc->next_role),
                        rsc->id);

        } else if (task == start_rsc || task == action_promote) {
            if (task != start_rsc || start == NULL || is_set(start->flags, pe_action_optional)) {
                pe_notify(rsc, rsc->allocated_to, n_data->pre, n_data->pre_done, n_data, data_set);
            }
            pe_post_notify(rsc, rsc->allocated_to, n_data, data_set);
        }
    }
}
Esempio n. 30
0
void
collect_notification_data(resource_t * rsc, gboolean state, gboolean activity,
                          notify_data_t * n_data)
{

    if(n_data->allowed_nodes == NULL) {
        n_data->allowed_nodes = rsc->allowed_nodes;
    }

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

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

            collect_notification_data(child, state, activity, n_data);
        }
        return;
    }

    if (state) {
        notify_entry_t *entry = NULL;

        entry = calloc(1, sizeof(notify_entry_t));
        entry->rsc = rsc;
        if (rsc->running_on) {
            /* we only take the first one */
            entry->node = rsc->running_on->data;
        }

        pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(rsc->role));

        switch (rsc->role) {
            case RSC_ROLE_STOPPED:
                n_data->inactive = g_list_prepend(n_data->inactive, entry);
                break;
            case RSC_ROLE_STARTED:
                n_data->active = g_list_prepend(n_data->active, entry);
                break;
            case RSC_ROLE_SLAVE:
                n_data->slave = g_list_prepend(n_data->slave, entry);
                n_data->active = g_list_prepend(n_data->active,
                                                dup_notify_entry(entry));
                break;
            case RSC_ROLE_MASTER:
                n_data->master = g_list_prepend(n_data->master, entry);
                n_data->active = g_list_prepend(n_data->active,
                                                dup_notify_entry(entry));
                break;
            default:
                crm_err("Unsupported notify role");
                free(entry);
                break;
        }
    }

    if (activity) {
        notify_entry_t *entry = NULL;
        enum action_tasks task;

        GListPtr gIter = rsc->actions;

        for (; gIter != NULL; gIter = gIter->next) {
            action_t *op = (action_t *) gIter->data;

            if (is_set(op->flags, pe_action_optional) == FALSE && op->node != NULL) {

                entry = calloc(1, sizeof(notify_entry_t));
                entry->node = op->node;
                entry->rsc = rsc;

                task = text2task(op->task);
                switch (task) {
                    case start_rsc:
                        n_data->start = g_list_prepend(n_data->start, entry);
                        break;
                    case stop_rsc:
                        n_data->stop = g_list_prepend(n_data->stop, entry);
                        break;
                    case action_promote:
                        n_data->promote = g_list_prepend(n_data->promote, entry);
                        break;
                    case action_demote:
                        n_data->demote = g_list_prepend(n_data->demote, entry);
                        break;
                    default:
                        free(entry);
                        break;
                }
            }
        }
    }
}