static void
child_ordering_constraints(resource_t * rsc, pe_working_set_t * data_set)
{
    char *key = NULL;
    action_t *stop = NULL;
    action_t *start = NULL;
    action_t *last_stop = NULL;
    action_t *last_start = NULL;
    GListPtr gIter = NULL;
    gboolean active_only = TRUE;        /* change to false to get the old behavior */
    clone_variant_data_t *clone_data = NULL;

    get_clone_variant_data(clone_data, rsc);

    if (clone_data->ordered == FALSE) {
        return;
    }
    /* 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 = (resource_t *) gIter->data;

        key = stop_key(child);
        stop = find_rsc_action(child, key, active_only, NULL);
        free(key);

        key = start_key(child);
        start = find_rsc_action(child, key, active_only, NULL);
        free(key);

        if (stop) {
            if (last_stop) {
                /* child/child relative stop */
                order_actions(stop, last_stop, pe_order_optional);
            }
            last_stop = stop;
        }

        if (start) {
            if (last_start) {
                /* child/child relative start */
                order_actions(last_start, start, pe_order_optional);
            }
            last_start = start;
        }
    }
}
Exemple #2
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;
}
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);
        }
    }
}
Exemple #4
0
notify_data_t *
create_notification_boundaries(resource_t * rsc, const char *action, action_t * start,
                               action_t * end, pe_working_set_t * data_set)
{
    /* Create the pseudo ops that preceed and follow the actual notifications */

    /*
     * Creates two sequences (conditional on start and end being supplied):
     *   pre_notify -> pre_notify_complete -> start, and
     *   end -> post_notify -> post_notify_complete
     *
     * 'start' and 'end' may be the same event or ${X} and ${X}ed as per clones
     */
    char *key = NULL;
    notify_data_t *n_data = NULL;

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

    n_data = calloc(1, sizeof(notify_data_t));
    n_data->action = action;
    n_data->keys =
        g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);

    if (start) {
        /* create pre-event notification wrappers */
        key = generate_notify_key(rsc->id, "pre", start->task);
        n_data->pre =
            custom_action(rsc, key, RSC_NOTIFY, NULL, is_set(start->flags, pe_action_optional),
                          TRUE, data_set);

        update_action_flags(n_data->pre, pe_action_pseudo, __FUNCTION__);
        update_action_flags(n_data->pre, pe_action_runnable, __FUNCTION__);

        add_hash_param(n_data->pre->meta, "notify_type", "pre");
        add_hash_param(n_data->pre->meta, "notify_operation", n_data->action);

        add_hash_param(n_data->pre->meta, "notify_key_type", "pre");
        add_hash_param(n_data->pre->meta, "notify_key_operation", start->task);

        /* create pre_notify_complete */
        key = generate_notify_key(rsc->id, "confirmed-pre", start->task);
        n_data->pre_done =
            custom_action(rsc, key, RSC_NOTIFIED, NULL, is_set(start->flags, pe_action_optional),
                          TRUE, data_set);

        update_action_flags(n_data->pre_done, pe_action_pseudo, __FUNCTION__);
        update_action_flags(n_data->pre_done, pe_action_runnable, __FUNCTION__);

        add_hash_param(n_data->pre_done->meta, "notify_type", "pre");
        add_hash_param(n_data->pre_done->meta, "notify_operation", n_data->action);

        add_hash_param(n_data->pre_done->meta, "notify_key_type", "confirmed-pre");
        add_hash_param(n_data->pre_done->meta, "notify_key_operation", start->task);

        order_actions(n_data->pre_done, start, pe_order_optional);
        order_actions(n_data->pre, n_data->pre_done, pe_order_optional);
    }

    if (end) {
        /* create post-event notification wrappers */
        key = generate_notify_key(rsc->id, "post", end->task);
        n_data->post =
            custom_action(rsc, key, RSC_NOTIFY, NULL, is_set(end->flags, pe_action_optional), TRUE,
                          data_set);

        n_data->post->priority = INFINITY;
        update_action_flags(n_data->post, pe_action_pseudo, __FUNCTION__);
        if (is_set(end->flags, pe_action_runnable)) {
            update_action_flags(n_data->post, pe_action_runnable, __FUNCTION__);
        } else {
            update_action_flags(n_data->post, pe_action_runnable | pe_action_clear, __FUNCTION__);
        }

        add_hash_param(n_data->post->meta, "notify_type", "post");
        add_hash_param(n_data->post->meta, "notify_operation", n_data->action);

        add_hash_param(n_data->post->meta, "notify_key_type", "post");
        add_hash_param(n_data->post->meta, "notify_key_operation", end->task);

        /* create post_notify_complete */
        key = generate_notify_key(rsc->id, "confirmed-post", end->task);
        n_data->post_done =
            custom_action(rsc, key, RSC_NOTIFIED, NULL, is_set(end->flags, pe_action_optional),
                          TRUE, data_set);

        n_data->post_done->priority = INFINITY;
        update_action_flags(n_data->post_done, pe_action_pseudo, __FUNCTION__);
        if (is_set(end->flags, pe_action_runnable)) {
            update_action_flags(n_data->post_done, pe_action_runnable, __FUNCTION__);
        } else {
            update_action_flags(n_data->post_done, pe_action_runnable | pe_action_clear, __FUNCTION__);
        }

        add_hash_param(n_data->post_done->meta, "notify_type", "post");
        add_hash_param(n_data->post_done->meta, "notify_operation", n_data->action);

        add_hash_param(n_data->post_done->meta, "notify_key_type", "confirmed-post");
        add_hash_param(n_data->post_done->meta, "notify_key_operation", end->task);

        order_actions(end, n_data->post, pe_order_implies_then);
        order_actions(n_data->post, n_data->post_done, pe_order_implies_then);
    }

    if (start && end) {
        order_actions(n_data->pre_done, n_data->post, pe_order_optional);
    }

    if (safe_str_eq(action, RSC_STOP)) {
        action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set);

        order_actions(n_data->post_done, all_stopped, pe_order_optional);
    }

    return n_data;
}
Exemple #5
0
gboolean
update_action(action_t * then)
{
    GListPtr lpc = NULL;
    enum pe_graph_flags changed = pe_graph_none;
    int last_flags = then->flags;

    crm_trace("Processing %s (%s %s %s)",
              then->uuid,
              is_set(then->flags, pe_action_optional) ? "optional" : "required",
              is_set(then->flags, pe_action_runnable) ? "runnable" : "unrunnable",
              is_set(then->flags,
                     pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->uname : "");

    if (is_set(then->flags, pe_action_requires_any)) {
        clear_bit(then->flags, pe_action_runnable);
    }

    for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) {
        action_wrapper_t *other = (action_wrapper_t *) lpc->data;
        action_t *first = other->action;

        node_t *then_node = then->node;
        node_t *first_node = first->node;

        enum pe_action_flags then_flags = 0;
        enum pe_action_flags first_flags = 0;

        if (first->rsc && first->rsc->variant == pe_group && safe_str_eq(first->task, RSC_START)) {
            first_node = first->rsc->fns->location(first->rsc, NULL, FALSE);
            if (first_node) {
                crm_trace("First: Found node %s for %s", first_node->details->uname, first->uuid);
            }
        }

        if (then->rsc && then->rsc->variant == pe_group && safe_str_eq(then->task, RSC_START)) {
            then_node = then->rsc->fns->location(then->rsc, NULL, FALSE);
            if (then_node) {
                crm_trace("Then: Found node %s for %s", then_node->details->uname, then->uuid);
            }
        }

        clear_bit(changed, pe_graph_updated_first);

        if (first->rsc != then->rsc
            && first->rsc != NULL && then->rsc != NULL && first->rsc != then->rsc->parent) {
            first = rsc_expand_action(first);
        }
        if (first != other->action) {
            crm_trace("Ordering %s afer %s instead of %s", then->uuid, first->uuid,
                      other->action->uuid);
        }

        first_flags = get_action_flags(first, then_node);
        then_flags = get_action_flags(then, first_node);

        crm_trace("Checking %s (%s %s %s) against %s (%s %s %s) filter=0x%.6x type=0x%.6x",
                  then->uuid,
                  is_set(then_flags, pe_action_optional) ? "optional" : "required",
                  is_set(then_flags, pe_action_runnable) ? "runnable" : "unrunnable",
                  is_set(then_flags,
                         pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->
                  uname : "", first->uuid, is_set(first_flags,
                                                  pe_action_optional) ? "optional" : "required",
                  is_set(first_flags, pe_action_runnable) ? "runnable" : "unrunnable",
                  is_set(first_flags,
                         pe_action_pseudo) ? "pseudo" : first->node ? first->node->details->
                  uname : "", first_flags, other->type);

        if (first == other->action) {
            /*
             * 'first' was not expanded (ie. from 'start' to 'running'), which could mean it:
             * - has no associated resource,
             * - was a primitive,
             * - was pre-expanded (ie. 'running' instead of 'start')
             *
             * The third argument here to graph_update_action() is a node which is used under two conditions:
             * - Interleaving, in which case first->node and
             *   then->node are equal (and NULL)
             * - If 'then' is a clone, to limit the scope of the
             *   constraint to instances on the supplied node
             *
             */
            int otype = other->type;
            node_t *node = then->node;

            if(is_set(otype, pe_order_implies_then_on_node)) {
                /* Normally we want the _whole_ 'then' clone to
                 * restart if 'first' is restarted, so then->node is
                 * needed.
                 *
                 * However for unfencing, we want to limit this to
                 * instances on the same node as 'first' (the
                 * unfencing operation), so first->node is supplied.
                 *
                 * Swap the node, from then on we can can treat it
                 * like any other 'pe_order_implies_then'
                 */

                clear_bit(otype, pe_order_implies_then_on_node);
                set_bit(otype, pe_order_implies_then);
                node = first->node;
            }
            clear_bit(first_flags, pe_action_pseudo);
            changed |= graph_update_action(first, then, node, first_flags, otype);

            /* 'first' was for a complex resource (clone, group, etc),
             * create a new dependancy if necessary
             */
        } else if (order_actions(first, then, other->type)) {
            /* This was the first time 'first' and 'then' were associated,
             * start again to get the new actions_before list
             */
            changed |= (pe_graph_updated_then | pe_graph_disable);
        }

        if (changed & pe_graph_disable) {
            crm_trace("Disabled constraint %s -> %s", other->action->uuid, then->uuid);
            clear_bit(changed, pe_graph_disable);
            other->type = pe_order_none;
        }

        if (changed & pe_graph_updated_first) {
            GListPtr lpc2 = NULL;

            crm_trace("Updated %s (first %s %s %s), processing dependants ",
                      first->uuid,
                      is_set(first->flags, pe_action_optional) ? "optional" : "required",
                      is_set(first->flags, pe_action_runnable) ? "runnable" : "unrunnable",
                      is_set(first->flags,
                             pe_action_pseudo) ? "pseudo" : first->node ? first->node->details->
                      uname : "");
            for (lpc2 = first->actions_after; lpc2 != NULL; lpc2 = lpc2->next) {
                action_wrapper_t *other = (action_wrapper_t *) lpc2->data;

                update_action(other->action);
            }
            update_action(first);
        }
    }

    if (is_set(then->flags, pe_action_requires_any)) {
        if (last_flags != then->flags) {
            changed |= pe_graph_updated_then;
        } else {
            clear_bit(changed, pe_graph_updated_then);
        }
    }

    if (changed & pe_graph_updated_then) {
        crm_trace("Updated %s (then %s %s %s), processing dependants ",
                  then->uuid,
                  is_set(then->flags, pe_action_optional) ? "optional" : "required",
                  is_set(then->flags, pe_action_runnable) ? "runnable" : "unrunnable",
                  is_set(then->flags,
                         pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->
                  uname : "");

        update_action(then);
        for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) {
            action_wrapper_t *other = (action_wrapper_t *) lpc->data;

            update_action(other->action);
        }
    }

    return FALSE;
}
Exemple #6
0
void
master_create_actions(resource_t * rsc, pe_working_set_t * data_set)
{
    action_t *action = NULL;
    GListPtr gIter = rsc->children;
    action_t *action_complete = NULL;
    gboolean any_promoting = FALSE;
    gboolean any_demoting = FALSE;
    resource_t *last_promote_rsc = NULL;
    resource_t *last_demote_rsc = NULL;

    clone_variant_data_t *clone_data = NULL;

    get_clone_variant_data(clone_data, rsc);

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

    /* create actions as normal */
    clone_create_actions(rsc, data_set);

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

        crm_trace("Creating actions for %s", child_rsc->id);
        child_rsc->cmds->create_actions(child_rsc, data_set);
        master_update_pseudo_status(child_rsc, &child_demoting, &child_promoting);

        any_demoting = any_demoting || child_demoting;
        any_promoting = any_promoting || child_promoting;
        crm_trace("Created actions for %s: %d %d", child_rsc->id, child_promoting,
                    child_demoting);
    }

    /* promote */
    action = promote_action(rsc, NULL, !any_promoting);
    action_complete = custom_action(rsc, promoted_key(rsc),
                                    RSC_PROMOTED, NULL, !any_promoting, TRUE, data_set);

    action_complete->priority = INFINITY;
    update_action_flags(action, pe_action_pseudo);
    update_action_flags(action, pe_action_runnable);
    update_action_flags(action_complete, pe_action_pseudo);
    update_action_flags(action_complete, pe_action_runnable);

    if (clone_data->masters_allocated > 0) {
        update_action_flags(action, pe_action_runnable);
        update_action_flags(action_complete, pe_action_runnable);
    }

    child_promoting_constraints(clone_data, pe_order_optional,
                                rsc, NULL, last_promote_rsc, data_set);

    if (clone_data->promote_notify == NULL) {
        clone_data->promote_notify =
            create_notification_boundaries(rsc, RSC_PROMOTE, action, action_complete, data_set);
    }

    /* demote */
    action = demote_action(rsc, NULL, !any_demoting);
    action_complete = custom_action(rsc, demoted_key(rsc),
                                    RSC_DEMOTED, NULL, !any_demoting, TRUE, data_set);
    action_complete->priority = INFINITY;

    update_action_flags(action, pe_action_pseudo);
    update_action_flags(action, pe_action_runnable);
    update_action_flags(action_complete, pe_action_pseudo);
    update_action_flags(action_complete, pe_action_runnable);

    child_demoting_constraints(clone_data, pe_order_optional, rsc, NULL, last_demote_rsc, data_set);

    if (clone_data->demote_notify == NULL) {
        clone_data->demote_notify =
            create_notification_boundaries(rsc, RSC_DEMOTE, action, action_complete, data_set);

        if (clone_data->promote_notify) {
            /* If we ever wanted groups to have notifications we'd need to move this to native_internal_constraints() one day
             * Requires exposing *_notify
             */
            order_actions(clone_data->stop_notify->post_done, clone_data->promote_notify->pre,
                          pe_order_optional);
            order_actions(clone_data->start_notify->post_done, clone_data->promote_notify->pre,
                          pe_order_optional);
            order_actions(clone_data->demote_notify->post_done, clone_data->promote_notify->pre,
                          pe_order_optional);
            order_actions(clone_data->demote_notify->post_done, clone_data->start_notify->pre,
                          pe_order_optional);
            order_actions(clone_data->demote_notify->post_done, clone_data->stop_notify->pre,
                          pe_order_optional);
        }
    }

    /* restore the correct priority */

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

        child_rsc->priority = rsc->priority;
    }
}
void
clone_create_pseudo_actions(
    resource_t * rsc, GListPtr children, notify_data_t **start_notify, notify_data_t **stop_notify,  pe_working_set_t * data_set)
{
    gboolean child_active = FALSE;
    gboolean child_starting = FALSE;
    gboolean child_stopping = FALSE;
    gboolean allow_dependent_migrations = TRUE;

    action_t *stop = NULL;
    action_t *stopped = NULL;

    action_t *start = NULL;
    action_t *started = NULL;

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

    for (GListPtr gIter = children; gIter != NULL; gIter = gIter->next) {
        resource_t *child_rsc = (resource_t *) gIter->data;
        gboolean starting = FALSE;
        gboolean stopping = FALSE;

        child_rsc->cmds->create_actions(child_rsc, data_set);
        clone_update_pseudo_status(child_rsc, &stopping, &starting, &child_active);
        if (stopping && starting) {
            allow_dependent_migrations = FALSE;
        }

        child_stopping |= stopping;
        child_starting |= starting;
    }

    /* start */
    start = create_pseudo_resource_op(rsc, RSC_START, !child_starting, TRUE, data_set);
    started = create_pseudo_resource_op(rsc, RSC_STARTED, !child_starting, FALSE, data_set);
    started->priority = INFINITY;

    if (child_active || child_starting) {
        update_action_flags(started, pe_action_runnable, __FUNCTION__, __LINE__);
    }

    if (start_notify != NULL && *start_notify == NULL) {
        *start_notify = create_notification_boundaries(rsc, RSC_START, start, started, data_set);
    }

    /* stop */
    stop = create_pseudo_resource_op(rsc, RSC_STOP, !child_stopping, TRUE, data_set);
    stopped = create_pseudo_resource_op(rsc, RSC_STOPPED, !child_stopping, TRUE, data_set);
    stopped->priority = INFINITY;
    if (allow_dependent_migrations) {
        update_action_flags(stop, pe_action_migrate_runnable, __FUNCTION__, __LINE__);
    }

    if (stop_notify != NULL && *stop_notify == NULL) {
        *stop_notify = create_notification_boundaries(rsc, RSC_STOP, stop, stopped, data_set);

        if (start_notify && *start_notify && *stop_notify) {
            order_actions((*stop_notify)->post_done, (*start_notify)->pre, pe_order_optional);
        }
    }
}
Exemple #8
0
static enum pe_graph_flags
container_update_interleave_actions(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags,
                     enum pe_action_flags filter, enum pe_ordering type)
{
    GListPtr gIter = NULL;
    GListPtr children = NULL;
    gboolean current = FALSE;
    enum pe_graph_flags changed = pe_graph_none;

    /* Fix this - lazy */
    if (crm_ends_with(first->uuid, "_stopped_0")
        || crm_ends_with(first->uuid, "_demoted_0")) {
        current = TRUE;
    }

    children = get_containers_or_children(then->rsc);
    for (gIter = children; gIter != NULL; gIter = gIter->next) {
        resource_t *then_child = (resource_t *) gIter->data;
        resource_t *first_child = find_compatible_child(then_child, first->rsc, RSC_ROLE_UNKNOWN, current);
        if (first_child == NULL && current) {
            crm_trace("Ignore");

        } else if (first_child == NULL) {
            crm_debug("No match found for %s (%d / %s / %s)", then_child->id, current, first->uuid, then->uuid);

            /* Me no like this hack - but what else can we do?
             *
             * If there is no-one active or about to be active
             *   on the same node as then_child, then they must
             *   not be allowed to start
             */
            if (type & (pe_order_runnable_left | pe_order_implies_then) /* Mandatory */ ) {
                pe_rsc_info(then->rsc, "Inhibiting %s from being active", then_child->id);
                if(assign_node(then_child, NULL, TRUE)) {
                    changed |= pe_graph_updated_then;
                }
            }

        } else {
            pe_action_t *first_action = NULL;
            pe_action_t *then_action = NULL;

            enum action_tasks task = clone_child_action(first);
            const char *first_task = task2text(task);

            container_grouping_t *first_tuple = tuple_for_docker(first->rsc, first_child, node);
            container_grouping_t *then_tuple = tuple_for_docker(then->rsc, then_child, node);

            if(strstr(first->task, "stop") && first_tuple && first_tuple->child) {
                /* Except for 'stopped' we should be looking at the
                 * in-container resource, actions for the child will
                 * happen later and are therefor more likely to align
                 * with the user's intent.
                 */
                first_action = find_first_action(first_tuple->child->actions, NULL, task2text(task), node);
            } else {
                first_action = find_first_action(first_child->actions, NULL, task2text(task), node);
            }

            if(strstr(then->task, "mote") && then_tuple && then_tuple->child) {
                /* Promote/demote actions will never be found for the
                 * docker resource, look in the child instead
                 *
                 * Alternatively treat:
                 *  'XXXX then promote YYYY' as 'XXXX then start container for YYYY', and
                 *  'demote XXXX then stop YYYY' as 'stop container for XXXX then stop YYYY'
                 */
                then_action = find_first_action(then_tuple->child->actions, NULL, then->task, node);
            } else {
                then_action = find_first_action(then_child->actions, NULL, then->task, node);
            }

            if (first_action == NULL) {
                if (is_not_set(first_child->flags, pe_rsc_orphan)
                    && crm_str_eq(first_task, RSC_STOP, TRUE) == FALSE
                    && crm_str_eq(first_task, RSC_DEMOTE, TRUE) == FALSE) {
                    crm_err("Internal error: No action found for %s in %s (first)",
                            first_task, first_child->id);

                } else {
                    crm_trace("No action found for %s in %s%s (first)",
                              first_task, first_child->id,
                              is_set(first_child->flags, pe_rsc_orphan) ? " (ORPHAN)" : "");
                }
                continue;
            }

            /* We're only interested if 'then' is neither stopping nor being demoted */ 
            if (then_action == NULL) {
                if (is_not_set(then_child->flags, pe_rsc_orphan)
                    && crm_str_eq(then->task, RSC_STOP, TRUE) == FALSE
                    && crm_str_eq(then->task, RSC_DEMOTE, TRUE) == FALSE) {
                    crm_err("Internal error: No action found for %s in %s (then)",
                            then->task, then_child->id);

                } else {
                    crm_trace("No action found for %s in %s%s (then)",
                              then->task, then_child->id,
                              is_set(then_child->flags, pe_rsc_orphan) ? " (ORPHAN)" : "");
                }
                continue;
            }

            if (order_actions(first_action, then_action, type)) {
                crm_debug("Created constraint for %s (%d) -> %s (%d) %.6x",
                          first_action->uuid, is_set(first_action->flags, pe_action_optional),
                          then_action->uuid, is_set(then_action->flags, pe_action_optional), type);
                changed |= (pe_graph_updated_first | pe_graph_updated_then);
            }
            if(first_action && then_action) {
                changed |= then_child->cmds->update_actions(first_action, then_action, node,
                                                            first_child->cmds->action_flags(first_action, node),
                                                            filter, type);
            } else {
                crm_err("Nothing found either for %s (%p) or %s (%p) %s",
                        first_child->id, first_action,
                        then_child->id, then_action, task2text(task));
            }
        }
    }

    if(children != then->rsc->children) {
        g_list_free(children);
    }
    return changed;
}
Exemple #9
0
gboolean
update_action(action_t * then)
{
    GListPtr lpc = NULL;
    enum pe_graph_flags changed = pe_graph_none;
    int last_flags = then->flags;

    crm_trace("Processing %s (%s %s %s)",
              then->uuid,
              is_set(then->flags, pe_action_optional) ? "optional" : "required",
              is_set(then->flags, pe_action_runnable) ? "runnable" : "unrunnable",
              is_set(then->flags,
                     pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->uname : "");

    if (is_set(then->flags, pe_action_requires_any)) {
        clear_bit(then->flags, pe_action_runnable);
    }

    for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) {
        action_wrapper_t *other = (action_wrapper_t *) lpc->data;
        action_t *first = other->action;

        node_t *then_node = then->node;
        node_t *first_node = first->node;

        enum pe_action_flags then_flags = 0;
        enum pe_action_flags first_flags = 0;

        if (first->rsc && first->rsc->variant == pe_group && safe_str_eq(first->task, RSC_START)) {
            first_node = first->rsc->fns->location(first->rsc, NULL, FALSE);
            if (first_node) {
                crm_trace("First: Found node %s for %s", first_node->details->uname, first->uuid);
            }
        }

        if (then->rsc && then->rsc->variant == pe_group && safe_str_eq(then->task, RSC_START)) {
            then_node = then->rsc->fns->location(then->rsc, NULL, FALSE);
            if (then_node) {
                crm_trace("Then: Found node %s for %s", then_node->details->uname, then->uuid);
            }
        }

        clear_bit(changed, pe_graph_updated_first);

        if (first->rsc != then->rsc
            && first->rsc != NULL && then->rsc != NULL && first->rsc != then->rsc->parent) {
            first = rsc_expand_action(first);
        }
        if (first != other->action) {
            crm_trace("Ordering %s afer %s instead of %s", then->uuid, first->uuid,
                      other->action->uuid);
        }

        first_flags = get_action_flags(first, then_node);
        then_flags = get_action_flags(then, first_node);

        crm_trace("Checking %s (%s %s %s) against %s (%s %s %s) filter=0x%.6x type=0x%.6x",
                  then->uuid,
                  is_set(then_flags, pe_action_optional) ? "optional" : "required",
                  is_set(then_flags, pe_action_runnable) ? "runnable" : "unrunnable",
                  is_set(then_flags,
                         pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->
                  uname : "", first->uuid, is_set(first_flags,
                                                  pe_action_optional) ? "optional" : "required",
                  is_set(first_flags, pe_action_runnable) ? "runnable" : "unrunnable",
                  is_set(first_flags,
                         pe_action_pseudo) ? "pseudo" : first->node ? first->node->details->
                  uname : "", first_flags, other->type);

        if (first == other->action) {
            clear_bit(first_flags, pe_action_pseudo);
            changed |= graph_update_action(first, then, then->node, first_flags, other->type);

        } else if (order_actions(first, then, other->type)) {
            /* Start again to get the new actions_before list */
            changed |= (pe_graph_updated_then | pe_graph_disable);
        }

        if (changed & pe_graph_disable) {
            crm_trace("Disabled constraint %s -> %s", other->action->uuid, then->uuid);
            clear_bit(changed, pe_graph_disable);
            other->type = pe_order_none;
        }

        if (changed & pe_graph_updated_first) {
            GListPtr lpc2 = NULL;

            crm_trace("Updated %s (first %s %s %s), processing dependants ",
                      first->uuid,
                      is_set(first->flags, pe_action_optional) ? "optional" : "required",
                      is_set(first->flags, pe_action_runnable) ? "runnable" : "unrunnable",
                      is_set(first->flags,
                             pe_action_pseudo) ? "pseudo" : first->node ? first->node->details->
                      uname : "");
            for (lpc2 = first->actions_after; lpc2 != NULL; lpc2 = lpc2->next) {
                action_wrapper_t *other = (action_wrapper_t *) lpc2->data;

                update_action(other->action);
            }
            update_action(first);
        }
    }

    if (is_set(then->flags, pe_action_requires_any)) {
        if (last_flags != then->flags) {
            changed |= pe_graph_updated_then;
        } else {
            clear_bit(changed, pe_graph_updated_then);
        }
    }

    if (changed & pe_graph_updated_then) {
        crm_trace("Updated %s (then %s %s %s), processing dependants ",
                  then->uuid,
                  is_set(then->flags, pe_action_optional) ? "optional" : "required",
                  is_set(then->flags, pe_action_runnable) ? "runnable" : "unrunnable",
                  is_set(then->flags,
                         pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->
                  uname : "");

        update_action(then);
        for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) {
            action_wrapper_t *other = (action_wrapper_t *) lpc->data;

            update_action(other->action);
        }
    }

    return FALSE;
}