Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/crm/pengine/clone.c b/crm/pengine/clone.c
index 2c724c29f9..175ca1ba41 100644
--- a/crm/pengine/clone.c
+++ b/crm/pengine/clone.c
@@ -1,1270 +1,1270 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <lha_internal.h>
#include <crm/msg_xml.h>
#include <allocate.h>
#include <utils.h>
#include <lib/crm/pengine/utils.h>
#define VARIANT_CLONE 1
#include <lib/crm/pengine/variant.h>
gint sort_clone_instance(gconstpointer a, gconstpointer b);
void clone_create_notifications(
resource_t *rsc, action_t *action, action_t *action_complete,
pe_working_set_t *data_set);
void child_stopping_constraints(
clone_variant_data_t *clone_data,
resource_t *self, resource_t *child, resource_t *last,
pe_working_set_t *data_set);
void child_starting_constraints(
clone_variant_data_t *clone_data,
resource_t *self, resource_t *child, resource_t *last,
pe_working_set_t *data_set);
static node_t *
parent_node_instance(const resource_t *rsc, node_t *node)
{
node_t *ret = NULL;
if(node != NULL) {
ret = pe_find_node_id(
rsc->parent->allowed_nodes, node->details->id);
}
return ret;
}
gint sort_clone_instance(gconstpointer a, gconstpointer b)
{
int level = LOG_DEBUG_3;
node_t *node1 = NULL;
node_t *node2 = NULL;
gboolean can1 = TRUE;
gboolean can2 = TRUE;
const resource_t *resource1 = (const resource_t*)a;
const resource_t *resource2 = (const resource_t*)b;
CRM_ASSERT(resource1 != NULL);
CRM_ASSERT(resource2 != NULL);
/* allocation order:
* - active instances
* - instances running on nodes with the least copies
* - active instances on nodes that cant support them or are to be fenced
* - failed instances
* - inactive instances
*/
do_crm_log(level+1, "%s ? %s", resource1->id, resource2->id);
if(resource1->running_on && resource2->running_on) {
if(g_list_length(resource1->running_on) < g_list_length(resource2->running_on)) {
do_crm_log(level, "%s < %s: running_on", resource1->id, resource2->id);
return -1;
} else if(g_list_length(resource1->running_on) > g_list_length(resource2->running_on)) {
do_crm_log(level, "%s > %s: running_on", resource1->id, resource2->id);
return 1;
}
}
if(resource1->running_on) {
node1 = resource1->running_on->data;
}
if(resource2->running_on) {
node2 = resource2->running_on->data;
}
if(resource1->priority < resource2->priority) {
do_crm_log(level, "%s < %s: score", resource1->id, resource2->id);
return 1;
} else if(resource1->priority > resource2->priority) {
do_crm_log(level, "%s > %s: score", resource1->id, resource2->id);
return -1;
}
if(node1 == NULL && node2 == NULL) {
do_crm_log(level, "%s == %s: not active",
resource1->id, resource2->id);
return 0;
}
if(node1 != node2) {
if(node1 == NULL) {
do_crm_log(level, "%s > %s: active", resource1->id, resource2->id);
return 1;
} else if(node2 == NULL) {
do_crm_log(level, "%s < %s: active", resource1->id, resource2->id);
return -1;
}
}
can1 = can_run_resources(node1);
can2 = can_run_resources(node2);
if(can1 != can2) {
if(can1) {
do_crm_log(level, "%s < %s: can", resource1->id, resource2->id);
return -1;
}
do_crm_log(level, "%s > %s: can", resource1->id, resource2->id);
return 1;
}
node1 = parent_node_instance(resource1, node1);
node2 = parent_node_instance(resource2, node2);
if(node1 != NULL && node2 == NULL) {
do_crm_log(level, "%s < %s: not allowed", resource1->id, resource2->id);
return -1;
} else if(node1 == NULL && node2 != NULL) {
do_crm_log(level, "%s > %s: not allowed", resource1->id, resource2->id);
return 1;
}
if(node1 == NULL) {
do_crm_log(level, "%s == %s: not allowed", resource1->id, resource2->id);
return 0;
}
if(node1->count < node2->count) {
do_crm_log(level, "%s < %s: count", resource1->id, resource2->id);
return -1;
} else if(node1->count > node2->count) {
do_crm_log(level, "%s > %s: count", resource1->id, resource2->id);
return 1;
}
if(node1->weight < node2->weight) {
do_crm_log(level, "%s < %s: node score", resource1->id, resource2->id);
return 1;
} else if(node1->weight > node2->weight) {
do_crm_log(level, "%s > %s: node score", resource1->id, resource2->id);
return -1;
}
do_crm_log(level, "%s == %s: default %d", resource1->id, resource2->id, node2->weight);
return 0;
}
static node_t *
can_run_instance(resource_t *rsc, node_t *node)
{
node_t *local_node = NULL;
clone_variant_data_t *clone_data = NULL;
if(can_run_resources(node) == FALSE) {
goto bail;
}
local_node = parent_node_instance(rsc, node);
get_clone_variant_data(clone_data, rsc->parent);
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->count < clone_data->clone_node_max) {
return local_node;
} else {
crm_debug_2("%s cannot run on %s: node full",
rsc->id, node->details->uname);
}
bail:
if(node) {
common_update_score(rsc, node->details->id, -INFINITY);
}
return NULL;
}
static node_t *
color_instance(resource_t *rsc, pe_working_set_t *data_set)
{
node_t *local_node = NULL;
node_t *chosen = NULL;
crm_debug_2("Processing %s", rsc->id);
if(rsc->provisional == FALSE) {
return rsc->allocated_to;
} else if(rsc->is_allocating) {
crm_debug("Dependancy loop detected involving %s", rsc->id);
return NULL;
}
if(rsc->allowed_nodes) {
slist_iter(try_node, node_t, rsc->allowed_nodes, lpc,
can_run_instance(rsc, try_node);
);
}
chosen = rsc->cmds->color(rsc, data_set);
if(chosen) {
local_node = pe_find_node_id(
rsc->parent->allowed_nodes, chosen->details->id);
if(local_node) {
local_node->count++;
} else if(rsc->is_managed) {
/* what to do? we can't enforce per-node limits in this case */
crm_config_err("%s not found in %s (list=%d)",
chosen->details->id, rsc->parent->id,
g_list_length(rsc->parent->allowed_nodes));
}
}
return chosen;
}
static void append_parent_colocation(resource_t *rsc, resource_t *child)
{
slist_iter(cons, rsc_colocation_t, rsc->rsc_cons, lpc,
child->rsc_cons = g_list_append(child->rsc_cons, cons));
slist_iter(cons, rsc_colocation_t, rsc->rsc_cons_lhs, lpc,
child->rsc_cons_lhs = g_list_append(child->rsc_cons_lhs, cons));
}
node_t *
clone_color(resource_t *rsc, pe_working_set_t *data_set)
{
int allocated = 0;
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
if(rsc->provisional == FALSE) {
return NULL;
} else if(rsc->is_allocating) {
crm_debug("Dependancy loop detected involving %s", rsc->id);
return NULL;
}
rsc->is_allocating = TRUE;
crm_debug_2("Processing %s", rsc->id);
/* this information is used by sort_clone_instance() when deciding in which
* order to allocate clone instances
*/
slist_iter(
constraint, rsc_colocation_t, rsc->rsc_cons_lhs, lpc,
rsc->allowed_nodes = constraint->rsc_lh->cmds->merge_weights(
constraint->rsc_lh, rsc->id, rsc->allowed_nodes,
constraint->score/INFINITY, TRUE);
);
dump_node_scores(LOG_DEBUG_2, rsc, __FUNCTION__, rsc->allowed_nodes);
/* count now tracks the number of clones currently allocated */
slist_iter(node, node_t, rsc->allowed_nodes, lpc,
node->count = 0;
);
slist_iter(child, resource_t, rsc->children, lpc,
if(g_list_length(child->running_on) > 0) {
node_t *child_node = child->running_on->data;
node_t *local_node = parent_node_instance(
child, child->running_on->data);
if(local_node) {
local_node->count++;
} else {
crm_err("%s is running on %s which isn't allowed",
child->id, child_node->details->uname);
}
}
);
rsc->children = g_list_sort(rsc->children, sort_clone_instance);
/* count now tracks the number of clones we have allocated */
slist_iter(node, node_t, rsc->allowed_nodes, lpc,
node->count = 0;
);
rsc->allowed_nodes = g_list_sort(
rsc->allowed_nodes, sort_node_weight);
slist_iter(child, resource_t, rsc->children, lpc,
if(allocated >= clone_data->clone_max) {
crm_debug("Child %s not allocated - limit reached", child->id);
resource_location(child, NULL, -INFINITY, "clone_color:limit_reached", data_set);
} else {
append_parent_colocation(rsc, child);
}
if(color_instance(child, data_set)) {
allocated++;
}
);
crm_debug("Allocated %d %s instances of a possible %d",
allocated, rsc->id, clone_data->clone_max);
rsc->provisional = FALSE;
rsc->is_allocating = FALSE;
return NULL;
}
static void
clone_update_pseudo_status(
resource_t *child, gboolean *stopping, gboolean *starting)
{
CRM_ASSERT(stopping != NULL);
CRM_ASSERT(starting != NULL);
slist_iter(
action, action_t, child->actions, lpc,
if(*starting && *stopping) {
return;
} else if(action->optional) {
crm_debug_3("Skipping optional: %s", action->uuid);
continue;
} else if(action->pseudo == FALSE && action->runnable == FALSE){
crm_debug_3("Skipping unrunnable: %s", action->uuid);
continue;
} else if(safe_str_eq(CRMD_ACTION_STOP, action->task)) {
crm_debug_2("Stopping due to: %s", action->uuid);
*stopping = TRUE;
} else if(safe_str_eq(CRMD_ACTION_START, action->task)) {
if(action->runnable == FALSE) {
crm_debug_3("Skipping pseudo-op: %s run=%d, pseudo=%d",
action->uuid, action->runnable, action->pseudo);
} else {
crm_debug_2("Starting due to: %s", action->uuid);
crm_debug_3("%s run=%d, pseudo=%d",
action->uuid, action->runnable, action->pseudo);
*starting = TRUE;
}
}
);
}
void clone_create_actions(resource_t *rsc, pe_working_set_t *data_set)
{
gboolean child_starting = FALSE;
gboolean child_stopping = FALSE;
action_t *stop = NULL;
action_t *start = NULL;
action_t *action_complete = NULL;
resource_t *last_start_rsc = NULL;
resource_t *last_stop_rsc = NULL;
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
crm_debug_2("Creating actions for %s", rsc->id);
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->create_actions(child_rsc, data_set);
clone_update_pseudo_status(
child_rsc, &child_stopping, &child_starting);
if(child_rsc->starting) {
last_start_rsc = child_rsc;
}
if(child_rsc->stopping) {
last_stop_rsc = child_rsc;
}
);
/* start */
start = start_action(rsc, NULL, !child_starting);
action_complete = custom_action(
rsc, started_key(rsc),
CRMD_ACTION_STARTED, NULL, !child_starting, TRUE, data_set);
start->pseudo = TRUE;
start->runnable = TRUE;
action_complete->pseudo = TRUE;
action_complete->runnable = TRUE;
action_complete->priority = INFINITY;
/* crm_err("Upgrading priority for %s to INFINITY", action_complete->uuid); */
child_starting_constraints(clone_data, rsc, NULL, last_start_rsc, data_set);
clone_create_notifications(
rsc, start, action_complete, data_set);
/* stop */
stop = stop_action(rsc, NULL, !child_stopping);
action_complete = custom_action(
rsc, stopped_key(rsc),
CRMD_ACTION_STOPPED, NULL, !child_stopping, TRUE, data_set);
stop->pseudo = TRUE;
stop->runnable = TRUE;
action_complete->pseudo = TRUE;
action_complete->runnable = TRUE;
action_complete->priority = INFINITY;
/* crm_err("Upgrading priority for %s to INFINITY", action_complete->uuid); */
child_stopping_constraints(clone_data, rsc, NULL, last_stop_rsc, data_set);
clone_create_notifications(rsc, stop, action_complete, data_set);
rsc->actions = rsc->actions;
if(stop->post_notified != NULL && start->pre_notify != NULL) {
order_actions(stop->post_notified, start->pre_notify, pe_order_optional);
}
}
void
clone_create_notifications(
resource_t *rsc, action_t *action, action_t *action_complete,
pe_working_set_t *data_set)
{
/*
* pre_notify -> pre_notify_complete -> pseudo_action
* -> (real actions) -> pseudo_action_complete
* -> post_notify -> post_notify_complete
*
* if the pre_noitfy requires confirmation,
* then a list of confirmations will be added as triggers
* to pseudo_action in clone_expand()
*/
action_t *notify = NULL;
action_t *notify_complete = NULL;
enum action_tasks task;
char *notify_key = NULL;
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
if(rsc->notify == FALSE) {
return;
}
task = text2task(action->task);
/* create pre_notify */
notify_key = generate_notify_key(
rsc->id, "pre", action->task);
notify = custom_action(rsc, notify_key,
CRMD_ACTION_NOTIFY, NULL,
action->optional, TRUE, data_set);
add_hash_param(notify->meta, "notify_type", "pre");
add_hash_param(notify->meta, "notify_operation", action->task);
if(clone_data->notify_confirm) {
add_hash_param(notify->meta, "notify_confirm", "yes");
} else {
add_hash_param(notify->meta, "notify_confirm", "no");
}
/* create pre_notify_complete */
notify_key = generate_notify_key(
rsc->id, "confirmed-pre", action->task);
notify_complete = custom_action(rsc, notify_key,
CRMD_ACTION_NOTIFIED, NULL,
action->optional, TRUE, data_set);
add_hash_param(notify_complete->meta, "notify_type", "pre");
add_hash_param(notify_complete->meta, "notify_operation", action->task);
if(clone_data->notify_confirm) {
add_hash_param(notify->meta, "notify_confirm", "yes");
} else {
add_hash_param(notify->meta, "notify_confirm", "no");
}
notify->pseudo = TRUE;
notify->runnable = TRUE;
notify_complete->pseudo = TRUE;
notify_complete->runnable = TRUE;
/* pre_notify before pre_notify_complete */
custom_action_order(
rsc, NULL, notify,
rsc, NULL, notify_complete,
pe_order_implies_left, data_set);
/* pre_notify_complete before action */
custom_action_order(
rsc, NULL, notify_complete,
rsc, NULL, action,
pe_order_implies_left, data_set);
action->pre_notify = notify;
action->pre_notified = notify_complete;
/* create post_notify */
notify_key = generate_notify_key
(rsc->id, "post", action->task);
notify = custom_action(rsc, notify_key,
CRMD_ACTION_NOTIFY, NULL,
action_complete->optional, TRUE, data_set);
add_hash_param(notify->meta, "notify_type", "post");
add_hash_param(notify->meta, "notify_operation", action->task);
if(clone_data->notify_confirm) {
add_hash_param(notify->meta, "notify_confirm", "yes");
} else {
add_hash_param(notify->meta, "notify_confirm", "no");
}
/* action_complete before post_notify */
custom_action_order(
rsc, NULL, action_complete,
rsc, NULL, notify,
pe_order_implies_right, data_set);
/* create post_notify_complete */
notify_key = generate_notify_key(
rsc->id, "confirmed-post", action->task);
notify_complete = custom_action(rsc, notify_key,
CRMD_ACTION_NOTIFIED, NULL,
action->optional, TRUE, data_set);
add_hash_param(notify_complete->meta, "notify_type", "pre");
add_hash_param(notify_complete->meta, "notify_operation", action->task);
if(clone_data->notify_confirm) {
add_hash_param(notify->meta, "notify_confirm", "yes");
} else {
add_hash_param(notify->meta, "notify_confirm", "no");
}
notify->pseudo = TRUE;
notify->runnable = TRUE;
notify->priority = INFINITY;
notify->runnable = action_complete->runnable;
notify_complete->pseudo = TRUE;
notify_complete->runnable = TRUE;
notify_complete->priority = INFINITY;
notify_complete->runnable = action_complete->runnable;
/* post_notify before post_notify_complete */
custom_action_order(
rsc, NULL, notify,
rsc, NULL, notify_complete,
pe_order_implies_left, data_set);
action->post_notify = notify;
action->post_notified = notify_complete;
if(safe_str_eq(action->task, CRMD_ACTION_STOP)) {
/* post_notify_complete before start */
custom_action_order(
rsc, NULL, notify_complete,
rsc, start_key(rsc), NULL,
pe_order_optional, data_set);
} else if(safe_str_eq(action->task, CRMD_ACTION_START)) {
/* post_notify_complete before promote */
custom_action_order(
rsc, NULL, notify_complete,
rsc, promote_key(rsc), NULL,
pe_order_optional, data_set);
} else if(safe_str_eq(action->task, CRMD_ACTION_DEMOTE)) {
/* post_notify_complete before promote */
custom_action_order(
rsc, NULL, notify_complete,
rsc, stop_key(rsc), NULL,
pe_order_optional, data_set);
}
}
void
child_starting_constraints(
clone_variant_data_t *clone_data,
resource_t *rsc, resource_t *child, resource_t *last,
pe_working_set_t *data_set)
{
if(child == NULL && last == NULL) {
crm_debug("%s has no active children", rsc->id);
return;
}
if(child != NULL) {
order_start_start(rsc, child, pe_order_runnable_left);
custom_action_order(
child, start_key(child), NULL,
rsc, started_key(rsc), NULL,
pe_order_optional, data_set);
}
if(clone_data->ordered) {
if(child == NULL) {
/* last child start before global started */
custom_action_order(
last, start_key(last), NULL,
rsc, started_key(rsc), NULL,
pe_order_runnable_left, data_set);
} else if(last == NULL) {
/* global start before first child start */
order_start_start(
rsc, child, pe_order_implies_left);
} else {
/* child/child relative start */
order_start_start(last, child, pe_order_implies_left);
}
}
}
void
child_stopping_constraints(
clone_variant_data_t *clone_data,
resource_t *rsc, resource_t *child, resource_t *last,
pe_working_set_t *data_set)
{
if(child == NULL && last == NULL) {
crm_debug("%s has no active children", rsc->id);
return;
}
if(child != NULL) {
- order_stop_stop(rsc, child, pe_order_optional);
+ order_stop_stop(rsc, child, pe_order_shutdown);
custom_action_order(
child, stop_key(child), NULL,
rsc, stopped_key(rsc), NULL,
pe_order_optional, data_set);
}
if(clone_data->ordered) {
if(last == NULL) {
/* first child stop before global stopped */
custom_action_order(
child, stop_key(child), NULL,
rsc, stopped_key(rsc), NULL,
pe_order_runnable_left, data_set);
} else if(child == NULL) {
/* global stop before last child stop */
order_stop_stop(
rsc, last, pe_order_implies_left);
} else {
/* child/child relative stop */
order_stop_stop(child, last, pe_order_implies_left);
}
}
}
void
clone_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
{
resource_t *last_rsc = NULL;
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
native_internal_constraints(rsc, data_set);
/* global stop before stopped */
custom_action_order(
rsc, stop_key(rsc), NULL,
rsc, stopped_key(rsc), NULL,
pe_order_runnable_left, data_set);
/* global start before started */
custom_action_order(
rsc, start_key(rsc), NULL,
rsc, started_key(rsc), NULL,
pe_order_runnable_left, data_set);
/* global stopped before start */
custom_action_order(
rsc, stopped_key(rsc), NULL,
rsc, start_key(rsc), NULL,
pe_order_optional, data_set);
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->internal_constraints(child_rsc, data_set);
child_starting_constraints(
clone_data, rsc, child_rsc, last_rsc, data_set);
child_stopping_constraints(
clone_data, rsc, child_rsc, last_rsc, data_set);
last_rsc = child_rsc;
);
}
static resource_t*
find_compatible_child(resource_t *local_child, resource_t *rsc)
{
node_t *local_node = NULL;
node_t *node = NULL;
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
local_node = local_child->allocated_to;
if(local_node == NULL) {
crm_debug("Can't colocate unrunnable child %s with %s",
local_child->id, rsc->id);
return NULL;
}
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
node = child_rsc->allocated_to;
if(node->details == local_node->details) {
crm_info("Colocating %s with %s on %s",
local_child->id, child_rsc->id, node->details->uname);
return child_rsc;
}
);
crm_debug("Can't colocate child %s with %s",
local_child->id, rsc->id);
return NULL;
}
void clone_rsc_colocation_lh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
gboolean do_interleave = FALSE;
resource_t *rsc = constraint->rsc_lh;
clone_variant_data_t *clone_data = NULL;
clone_variant_data_t *clone_data_rh = NULL;
if(rsc == NULL) {
pe_err("rsc_lh was NULL for %s", constraint->id);
return;
} else if(constraint->rsc_rh == NULL) {
pe_err("rsc_rh was NULL for %s", constraint->id);
return;
} else {
crm_debug_4("Processing constraints from %s", rsc->id);
}
get_clone_variant_data(clone_data, rsc);
if(constraint->rsc_rh->variant == pe_clone) {
get_clone_variant_data(
clone_data_rh, constraint->rsc_rh);
if(clone_data->clone_node_max
!= clone_data_rh->clone_node_max) {
crm_config_err("Cannot interleave "XML_CIB_TAG_INCARNATION
" %s and %s because"
" they do not support the same number of"
" resources per node",
constraint->rsc_lh->id, constraint->rsc_rh->id);
/* only the LHS side needs to be labeled as interleave */
} else if(clone_data->interleave) {
do_interleave = TRUE;
} else if(constraint->score >= INFINITY) {
GListPtr lhs = NULL, rhs = NULL;
lhs = rsc_lh->allowed_nodes;
slist_iter(
child_rsc, resource_t, rsc_rh->children, lpc,
if(child_rsc->allocated_to != NULL) {
rhs = g_list_append(rhs, child_rsc->allocated_to);
}
);
rsc_lh->allowed_nodes = node_list_and(lhs, rhs, FALSE);
pe_free_shallow_adv(rhs, FALSE);
pe_free_shallow(lhs);
return;
}
} else if(constraint->score >= INFINITY) {
crm_config_err("Manditory co-location of clones (%s) with other"
" non-clone (%s) resources is not supported",
rsc_lh->id, rsc_rh->id);
return;
}
if(do_interleave) {
resource_t *rh_child = NULL;
slist_iter(lh_child, resource_t, rsc->children, lpc,
CRM_ASSERT(lh_child != NULL);
rh_child = find_compatible_child(lh_child, rsc_rh);
if(rh_child == NULL) {
continue;
}
lh_child->cmds->rsc_colocation_lh(
lh_child, rh_child, constraint);
);
return;
}
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->rsc_colocation_lh(child_rsc, constraint->rsc_rh, constraint);
);
}
void clone_rsc_colocation_rh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
clone_variant_data_t *clone_data = NULL;
CRM_CHECK(rsc_lh != NULL, return);
CRM_CHECK(rsc_lh->variant == pe_native, return);
get_clone_variant_data(clone_data, rsc_rh);
crm_debug_3("Processing constraint %s: %d", constraint->id, constraint->score);
if(rsc_rh == NULL) {
pe_err("rsc_rh was NULL for %s", constraint->id);
return;
} else if(rsc_rh->provisional) {
crm_debug_3("%s is still provisional", rsc_rh->id);
return;
} else if(constraint->score >= INFINITY) {
GListPtr lhs = NULL, rhs = NULL;
lhs = rsc_lh->allowed_nodes;
slist_iter(
child_rsc, resource_t, rsc_rh->children, lpc,
if(child_rsc->allocated_to != NULL) {
rhs = g_list_append(rhs, child_rsc->allocated_to);
}
);
rsc_lh->allowed_nodes = node_list_and(lhs, rhs, FALSE);
pe_free_shallow_adv(rhs, FALSE);
pe_free_shallow(lhs);
return;
}
slist_iter(
child_rsc, resource_t, rsc_rh->children, lpc,
child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint);
);
}
void clone_rsc_order_lh(resource_t *rsc, order_constraint_t *order, pe_working_set_t *data_set)
{
resource_t *r1 = NULL;
resource_t *r2 = NULL;
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
crm_debug_2("%s->%s", order->lh_action_task, order->rh_action_task);
r1 = uber_parent(rsc);
r2 = uber_parent(order->rh_rsc);
if(r1 == r2) {
native_rsc_order_lh(rsc, order, data_set);
return;
}
#if 0
if(order->type != pe_order_optional) {
crm_debug("Upgraded ordering constraint %d - 0x%.6x", order->id, order->type);
native_rsc_order_lh(rsc, order, data_set);
}
#endif
if(order->type & pe_order_implies_left) {
if(rsc->variant == order->rh_rsc->variant) {
crm_debug_2("Clone-to-clone ordering: %s -> %s 0x%.6x",
order->lh_action_task, order->rh_action_task, order->type);
/* stop instances on the same nodes as stopping RHS instances */
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
native_rsc_order_lh(child_rsc, order, data_set);
);
} else {
/* stop everything */
crm_debug_2("Clone-to-* ordering: %s -> %s 0x%.6x",
order->lh_action_task, order->rh_action_task, order->type);
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
native_rsc_order_lh(child_rsc, order, data_set);
);
}
}
convert_non_atomic_task(rsc, order);
native_rsc_order_lh(rsc, order, data_set);
}
void clone_rsc_order_rh(
action_t *lh_action, resource_t *rsc, order_constraint_t *order)
{
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
crm_debug_2("%s->%s", lh_action->uuid, order->rh_action_task);
native_rsc_order_rh(lh_action, rsc, order);
}
void clone_rsc_location(resource_t *rsc, rsc_to_node_t *constraint)
{
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
crm_debug_3("Processing location constraint %s for %s",
constraint->id, rsc->id);
native_rsc_location(rsc, constraint);
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->rsc_location(child_rsc, constraint);
);
}
static gint
sort_notify_entries(gconstpointer a, gconstpointer b)
{
int tmp;
const notify_entry_t *entry_a = a;
const notify_entry_t *entry_b = b;
if(entry_a == NULL && entry_b == NULL) { return 0; }
if(entry_a == NULL) { return 1; }
if(entry_b == NULL) { return -1; }
if(entry_a->rsc == NULL && entry_b->rsc == NULL) { return 0; }
if(entry_a->rsc == NULL) { return 1; }
if(entry_b->rsc == NULL) { return -1; }
tmp = strcmp(entry_a->rsc->id, entry_b->rsc->id);
if(tmp != 0) {
return tmp;
}
if(entry_a->node == NULL && entry_b->node == NULL) { return 0; }
if(entry_a->node == NULL) { return 1; }
if(entry_b->node == NULL) { return -1; }
return strcmp(entry_a->node->details->id, entry_b->node->details->id);
}
static void
expand_list(GListPtr list, int clones,
char **rsc_list, char **node_list, char **uuid_list)
{
const char *uname = NULL;
const char *rsc_id = NULL;
const char *last_rsc_id = NULL;
CRM_CHECK(list != NULL, return);
if(rsc_list) {
CRM_CHECK(*rsc_list == NULL, *rsc_list = NULL);
}
if(node_list) {
CRM_CHECK(*node_list == NULL, *node_list = NULL);
}
slist_iter(entry, notify_entry_t, list, lpc,
CRM_CHECK(entry != NULL, continue);
CRM_CHECK(entry->rsc != NULL, continue);
CRM_CHECK(entry->node != NULL, continue);
rsc_id = entry->rsc->id;
uname = entry->node->details->uname;
CRM_ASSERT(uname != NULL);
CRM_ASSERT(rsc_id != NULL);
/* filter dups */
if(safe_str_eq(rsc_id, last_rsc_id)) {
continue;
}
last_rsc_id = rsc_id;
if(rsc_list != NULL) {
int existing_len = 0;
int len = 2 + strlen(rsc_id); /* +1 space, +1 EOS */
if(rsc_list && *rsc_list) {
existing_len = strlen(*rsc_list);
}
crm_debug_5("Adding %s (%dc) at offset %d",
rsc_id, len-2, existing_len);
crm_realloc(*rsc_list, len + existing_len);
sprintf(*rsc_list + existing_len, "%s ", rsc_id);
}
if(node_list != NULL) {
int existing_len = 0;
int len = 2 + strlen(uname);
if(node_list && *node_list) {
existing_len = strlen(*node_list);
}
crm_debug_5("Adding %s (%dc) at offset %d",
uname, len-2, existing_len);
crm_realloc(*node_list, len + existing_len);
sprintf(*node_list + existing_len, "%s ", uname);
}
);
}
void clone_expand(resource_t *rsc, pe_working_set_t *data_set)
{
char *rsc_list = NULL;
char *node_list = NULL;
char *uuid_list = NULL;
notify_data_t *n_data = NULL;
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
crm_malloc0(n_data, sizeof(notify_data_t));
n_data->keys = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
crm_debug_2("Processing actions from %s", rsc->id);
if(rsc->notify) {
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
slist_iter(
op, action_t, rsc->actions, lpc2,
child_rsc->cmds->create_notify_element(
child_rsc, op, n_data, data_set);
);
);
}
/* expand the notify data */
if(rsc->notify && n_data->stop) {
n_data->stop = g_list_sort(
n_data->stop, sort_notify_entries);
rsc_list = NULL; node_list = NULL;
expand_list(n_data->stop, clone_data->clone_max,
&rsc_list, &node_list, &uuid_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_stop_resource"), rsc_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_stop_uname"), node_list);
}
if(rsc->notify && n_data->start) {
n_data->start = g_list_sort(
n_data->start, sort_notify_entries);
rsc_list = NULL; node_list = NULL;
expand_list(n_data->start, clone_data->clone_max,
&rsc_list, &node_list, &uuid_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_start_resource"), rsc_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_start_uname"), node_list);
}
if(rsc->notify && n_data->demote) {
n_data->demote = g_list_sort(
n_data->demote, sort_notify_entries);
rsc_list = NULL; node_list = NULL;
expand_list(n_data->demote, clone_data->clone_max,
&rsc_list, &node_list, &uuid_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_demote_resource"), rsc_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_demote_uname"), node_list);
}
if(rsc->notify && n_data->promote) {
n_data->promote = g_list_sort(
n_data->promote, sort_notify_entries);
rsc_list = NULL; node_list = NULL; uuid_list = NULL;
expand_list(n_data->promote, clone_data->clone_max,
&rsc_list, &node_list, &uuid_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_promote_resource"), rsc_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_promote_uname"), node_list);
}
if(rsc->notify && n_data->active) {
n_data->active = g_list_sort(
n_data->active, sort_notify_entries);
rsc_list = NULL; node_list = NULL; uuid_list = NULL;
expand_list(n_data->active, clone_data->clone_max,
&rsc_list, &node_list, &uuid_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_active_resource"), rsc_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_active_uname"), node_list);
}
if(rsc->notify && n_data->slave) {
n_data->slave = g_list_sort(
n_data->slave, sort_notify_entries);
rsc_list = NULL; node_list = NULL; uuid_list = NULL;
expand_list(n_data->slave, clone_data->clone_max,
&rsc_list, &node_list, &uuid_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_slave_resource"), rsc_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_slave_uname"), node_list);
}
if(rsc->notify && n_data->master) {
n_data->master = g_list_sort(
n_data->master, sort_notify_entries);
rsc_list = NULL; node_list = NULL; uuid_list = NULL;
expand_list(n_data->master, clone_data->clone_max,
&rsc_list, &node_list, &uuid_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_master_resource"), rsc_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_master_uname"), node_list);
}
if(rsc->notify && n_data->inactive) {
n_data->inactive = g_list_sort(
n_data->inactive, sort_notify_entries);
rsc_list = NULL; node_list = NULL; uuid_list = NULL;
expand_list(n_data->inactive, clone_data->clone_max,
&rsc_list, &node_list, &uuid_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_inactive_resource"), rsc_list);
g_hash_table_insert(
n_data->keys,
crm_strdup("notify_inactive_uname"), node_list);
}
/* yes, we DO need this second loop */
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->expand(child_rsc, data_set);
);
/* slist_iter( */
/* action, action_t, rsc->actions, lpc2, */
/* if(safe_str_eq(action->task, CRMD_ACTION_NOTIFY)) { */
/* action->meta_xml = notify_xml; */
/* } */
/* ); */
native_expand(rsc, data_set);
/* destroy the notify_data */
pe_free_shallow(n_data->stop);
pe_free_shallow(n_data->start);
pe_free_shallow(n_data->demote);
pe_free_shallow(n_data->promote);
pe_free_shallow(n_data->master);
pe_free_shallow(n_data->slave);
pe_free_shallow(n_data->active);
pe_free_shallow(n_data->inactive);
g_hash_table_destroy(n_data->keys);
crm_free(n_data);
}
static gint sort_rsc_id(gconstpointer a, gconstpointer b)
{
const resource_t *resource1 = (const resource_t*)a;
const resource_t *resource2 = (const resource_t*)b;
CRM_ASSERT(resource1 != NULL);
CRM_ASSERT(resource2 != NULL);
return strcmp(resource1->id, resource2->id);
}
gboolean
clone_create_probe(resource_t *rsc, node_t *node, action_t *complete,
gboolean force, pe_working_set_t *data_set)
{
gboolean any_created = FALSE;
clone_variant_data_t *clone_data = NULL;
get_clone_variant_data(clone_data, rsc);
rsc->children = g_list_sort(rsc->children, sort_rsc_id);
if(rsc->globally_unique == FALSE && clone_data->clone_node_max == 1) {
/* only look for one copy */
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
if(pe_find_node_id(child_rsc->running_on, node->details->id)) {
return child_rsc->cmds->create_probe(
child_rsc, node, complete, force, data_set);
}
);
}
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
if(child_rsc->cmds->create_probe(
child_rsc, node, complete, force, data_set)) {
any_created = TRUE;
}
if(any_created
&& rsc->globally_unique == FALSE
&& clone_data->clone_node_max == 1) {
/* only look for one copy (clone :0) */
break;
}
);
return any_created;
}
diff --git a/crm/pengine/graph.c b/crm/pengine/graph.c
index af1d9686a6..e5e5ef0c83 100644
--- a/crm/pengine/graph.c
+++ b/crm/pengine/graph.c
@@ -1,607 +1,623 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <lha_internal.h>
#include <sys/param.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/msg.h>
#include <glib.h>
#include <allocate.h>
#include <lib/crm/pengine/utils.h>
#include <utils.h>
gboolean update_action(action_t *action);
gboolean
update_action_states(GListPtr actions)
{
crm_debug_2("Updating %d actions", g_list_length(actions));
slist_iter(
action, action_t, actions, lpc,
update_action(action);
);
return TRUE;
}
gboolean
update_action(action_t *action)
{
int local_type = 0;
int log_level = LOG_DEBUG_2;
gboolean changed = FALSE;
do_crm_log(log_level, "Processing action %s: %s %s %s",
action->uuid,
action->optional?"optional":"required",
action->runnable?"runnable":"unrunnable",
action->pseudo?"pseudo":action->task);
slist_iter(
other, action_wrapper_t, action->actions_before, lpc,
gboolean other_changed = FALSE;
node_t *node = other->action->node;
+ resource_t *other_rsc = other->action->rsc;
+ enum rsc_role_e other_role = RSC_ROLE_UNKNOWN;
+ if(other_rsc) {
+ other_role = other_rsc->fns->state(other_rsc, TRUE);
+ }
+
do_crm_log(log_level, " Checking action %s: %s %s %s (flags=0x%.6x)",
other->action->uuid,
other->action->optional?"optional":"required",
other->action->runnable?"runnable":"unrunnable",
other->action->pseudo?"pseudo":other->action->task,
other->type);
local_type = other->type;
- if(local_type & pe_order_demote
+ if((local_type & pe_order_demote)
&& other->action->pseudo == FALSE
- && other->action->rsc->role > RSC_ROLE_SLAVE
+ && other_role > RSC_ROLE_SLAVE
&& node != NULL
&& node->details->online) {
local_type |= pe_order_runnable_left;
do_crm_log(log_level,"Upgrading restart constraint to runnable_left");
}
-
- if(local_type & pe_order_restart
- && other->action->pseudo == FALSE
- && node != NULL
- && node->details->online) {
-
- local_type |= pe_order_implies_left;
- do_crm_log(log_level,"Upgrading restart constraint to implies_left");
+ if((local_type & pe_order_shutdown)
+ && other->action->optional == FALSE
+ && other_rsc->shutdown) {
+ action->optional = FALSE;
+ changed = TRUE;
+ do_crm_log(log_level-1,
+ " * Marking action %s manditory because of %s (complex)",
+ action->uuid, other->action->uuid);
+ }
+
+ if((local_type & pe_order_restart)
+ && other_role > RSC_ROLE_STOPPED) {
+
+ if(other_rsc->variant == pe_native) {
+ local_type |= pe_order_implies_left;
+ do_crm_log(log_level,"Upgrading restart constraint to implies_left");
+ }
+
if(other->action->optional
&& other->action->runnable
&& action->runnable == FALSE) {
do_crm_log(log_level-1,
" * Marking action %s manditory because %s is unrunnable",
other->action->uuid, action->uuid);
other->action->optional = FALSE;
+ other_rsc->shutdown = TRUE;
other_changed = TRUE;
}
}
if((local_type & pe_order_runnable_left)
&& other->action->runnable == FALSE) {
if(other->action->implied_by_stonith) {
do_crm_log(log_level, "Ignoring un-runnable - implied_by_stonith");
} else if(action->runnable == FALSE) {
do_crm_log(log_level+1, "Already un-runnable");
} else {
action->runnable = FALSE;
do_crm_log(log_level-1,
" * Marking action %s un-runnable because of %s",
action->uuid, other->action->uuid);
changed = TRUE;
}
}
if((local_type & pe_order_runnable_right)
&& action->runnable == FALSE) {
if(action->pseudo) {
do_crm_log(log_level, "Ignoring un-runnable - pseudo");
} else if(other->action->runnable == FALSE) {
do_crm_log(log_level+1, "Already un-runnable");
} else {
other->action->runnable = FALSE;
do_crm_log(log_level-1,
" * Marking action %s un-runnable because of %s",
other->action->uuid, action->uuid);
other_changed = TRUE;
}
}
if(local_type & pe_order_implies_left) {
if(other->action->optional == FALSE) {
/* nothing to do */
do_crm_log(log_level+1, " Ignoring implies left - redundant");
} else if(safe_str_eq(other->action->task, CRMD_ACTION_STOP)
- && other->action->rsc->fns->state(
- other->action->rsc, TRUE) == RSC_ROLE_STOPPED) {
+ && other_role == RSC_ROLE_STOPPED) {
do_crm_log(log_level-1, " Ignoring implies left - %s already stopped",
- other->action->rsc->id);
+ other_rsc->id);
} else if((local_type & pe_order_demote)
- && other->action->rsc->role < RSC_ROLE_MASTER) {
+ && other_rsc->role < RSC_ROLE_MASTER) {
do_crm_log(log_level-1, " Ignoring implies left - %s already demoted",
- other->action->rsc->id);
+ other_rsc->id);
} else if(action->optional == FALSE) {
other->action->optional = FALSE;
do_crm_log(log_level-1,
" * (implies left) Marking action %s mandatory because of %s",
other->action->uuid, action->uuid);
other_changed = TRUE;
} else {
do_crm_log(log_level, " Ignoring implies left");
}
}
if(local_type & pe_order_implies_right) {
if(action->optional == FALSE) {
/* nothing to do */
do_crm_log(log_level+1, " Ignoring implies right - redundant");
} else if(other->action->optional == FALSE) {
action->optional = FALSE;
do_crm_log(log_level-1,
" * (implies right) Marking action %s mandatory because of %s",
action->uuid, other->action->uuid);
changed = TRUE;
} else {
do_crm_log(log_level, " Ignoring implies right");
}
}
if(other_changed) {
do_crm_log(log_level, "%s changed, processing after list", other->action->uuid);
update_action(other->action);
slist_iter(
before_other, action_wrapper_t, other->action->actions_after, lpc2,
do_crm_log(log_level, "%s changed, processing %s", other->action->uuid, before_other->action->uuid);
update_action(before_other->action);
);
}
);
if(changed) {
do_crm_log(log_level, "%s changed, processing after list", action->uuid);
slist_iter(
other, action_wrapper_t, action->actions_after, lpc,
do_crm_log(log_level, "%s changed, processing %s", action->uuid, other->action->uuid);
update_action(other->action);
);
}
return FALSE;
}
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
*/
slist_iter(
rsc, resource_t, node->details->running_rsc, lpc,
if(rsc->is_managed == FALSE) {
continue;
}
custom_action_order(
rsc, stop_key(rsc), NULL,
NULL, crm_strdup(CRM_OP_SHUTDOWN), shutdown_op,
pe_order_implies_left, data_set);
);
return TRUE;
}
gboolean
stonith_constraints(
node_t *node, action_t *stonith_op, pe_working_set_t *data_set)
{
CRM_CHECK(stonith_op != NULL, return FALSE);
/*
* Make sure the stonith OP occurs before we start any shared resources
*/
if(stonith_op != NULL) {
slist_iter(
rsc, resource_t, data_set->resources, lpc,
rsc->cmds->stonith_ordering(rsc, stonith_op, data_set);
);
}
/* add the stonith OP as a stop pre-req and the mark the stop
* as a pseudo op - since its now redundant
*/
return TRUE;
}
static void dup_attr(gpointer key, gpointer value, gpointer user_data)
{
g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value));
}
crm_data_t *
action2xml(action_t *action, gboolean as_input)
{
gboolean needs_node_info = TRUE;
crm_data_t * action_xml = NULL;
crm_data_t * args_xml = NULL;
char *action_id_s = NULL;
if(action == NULL) {
return NULL;
}
crm_debug_4("Dumping action %d as XML", action->id);
if(safe_str_eq(action->task, CRM_OP_FENCE)) {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
/* needs_node_info = FALSE; */
} else if(safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
} else if(safe_str_eq(action->task, CRM_OP_LRM_REFRESH)) {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
/* } else if(safe_str_eq(action->task, CRMD_ACTION_PROBED)) { */
/* action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); */
} else if(action->pseudo) {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_PSEUDO_EVENT);
needs_node_info = FALSE;
} else {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
}
action_id_s = crm_itoa(action->id);
crm_xml_add(action_xml, XML_ATTR_ID, action_id_s);
crm_free(action_id_s);
crm_xml_add(action_xml, XML_LRM_ATTR_TASK, action->task);
if(action->rsc != NULL && action->rsc->clone_name != NULL) {
char *clone_key = NULL;
const char *interval_s = g_hash_table_lookup(action->meta, "interval");
int interval = crm_parse_int(interval_s, "0");
if(safe_str_eq(action->task, CRMD_ACTION_NOTIFY)) {
const char *n_type = g_hash_table_lookup(
action->extra, crm_meta_name("notify_type"));
const char *n_task = g_hash_table_lookup(
action->extra, crm_meta_name("notify_operation"));
CRM_CHECK(n_type != NULL, ;);
CRM_CHECK(n_task != NULL, ;);
clone_key = generate_notify_key(action->rsc->clone_name, n_type, n_task);
} else {
clone_key = generate_op_key(action->rsc->clone_name, action->task, interval);
}
crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, clone_key);
crm_xml_add(action_xml, "internal_"XML_LRM_ATTR_TASK_KEY, action->uuid);
crm_free(clone_key);
} else {
crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, action->uuid);
}
if(needs_node_info && action->node != NULL) {
crm_xml_add(action_xml, XML_LRM_ATTR_TARGET,
action->node->details->uname);
crm_xml_add(action_xml, XML_LRM_ATTR_TARGET_UUID,
action->node->details->id);
}
if(action->failure_is_fatal == FALSE) {
add_hash_param(action->meta,
XML_ATTR_TE_ALLOWFAIL, XML_BOOLEAN_TRUE);
}
if(as_input) {
return action_xml;
}
if(action->notify_keys != NULL) {
g_hash_table_foreach(
action->notify_keys, dup_attr, action->meta);
}
if(action->rsc != NULL && action->pseudo == FALSE) {
int lpc = 0;
crm_data_t *rsc_xml = create_xml_node(
action_xml, crm_element_name(action->rsc->xml));
const char *attr_list[] = {
XML_AGENT_ATTR_CLASS,
XML_AGENT_ATTR_PROVIDER,
XML_ATTR_TYPE
};
if(action->rsc->clone_name != NULL) {
crm_debug("Using clone name %s for %s", action->rsc->clone_name, action->rsc->id);
crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->clone_name);
crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
} else {
crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->id);
crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->long_name);
}
for(lpc = 0; lpc < DIMOF(attr_list); lpc++) {
crm_xml_add(rsc_xml, attr_list[lpc],
g_hash_table_lookup(action->rsc->meta, attr_list[lpc]));
}
}
args_xml = create_xml_node(action_xml, XML_TAG_ATTRS);
crm_xml_add(args_xml, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
g_hash_table_foreach(action->extra, hash2field, args_xml);
if(action->rsc != NULL && safe_str_neq(action->task, CRMD_ACTION_STOP)) {
g_hash_table_foreach(action->rsc->parameters, hash2field, args_xml);
}
g_hash_table_foreach(action->meta, hash2metafield, args_xml);
if(action->rsc != NULL) {
int lpc = 0;
const char *key = NULL;
const char *value = NULL;
const char *meta_list[] = {
XML_RSC_ATTR_UNIQUE,
XML_RSC_ATTR_INCARNATION,
XML_RSC_ATTR_INCARNATION_MAX,
XML_RSC_ATTR_INCARNATION_NODEMAX,
XML_RSC_ATTR_MASTER_MAX,
XML_RSC_ATTR_MASTER_NODEMAX,
};
for(lpc = 0; lpc < DIMOF(meta_list); lpc++) {
key = meta_list[lpc];
value = g_hash_table_lookup(action->rsc->meta, key);
if(value != NULL) {
char *crm_name = crm_concat(CRM_META, key, '_');
crm_xml_add(args_xml, crm_name, value);
crm_free(crm_name);
}
}
}
crm_log_xml_debug_4(action_xml, "dumped action");
return action_xml;
}
static gboolean
should_dump_action(action_t *action)
{
const char * interval = NULL;
CRM_CHECK(action != NULL, return FALSE);
interval = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL);
if(action->optional) {
crm_debug_5("action %d (%s) was optional",
action->id, action->uuid);
return FALSE;
} else if(action->runnable == FALSE) {
crm_debug_5("action %d (%s) was not runnable",
action->id, action->uuid);
return FALSE;
} else if(action->dumped) {
crm_debug_5("action %d (%s) was already dumped",
action->id, action->uuid);
return FALSE;
} else if(action->rsc != NULL
&& action->rsc->is_managed == FALSE) {
/* make sure probes go through */
if(safe_str_neq(action->task, CRMD_ACTION_STATUS)) {
pe_warn("action %d (%s) was for an unmanaged resource (%s)",
action->id, action->uuid, action->rsc->id);
return FALSE;
}
if(interval != NULL && safe_str_neq(interval, "0")) {
pe_warn("action %d (%s) was for an unmanaged resource (%s)",
action->id, action->uuid, action->rsc->id);
return FALSE;
}
}
if(action->pseudo
|| safe_str_eq(action->task, CRM_OP_FENCE)
|| safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
/* skip the next checks */
return TRUE;
}
if(action->node == NULL) {
pe_err("action %d (%s) was not allocated",
action->id, action->uuid);
log_action(LOG_DEBUG, "Unallocated action", action, FALSE);
return FALSE;
} else if(action->node->details->online == FALSE) {
pe_err("action %d was (%s) scheduled for offline node",
action->id, action->uuid);
log_action(LOG_DEBUG, "Action for offline node", action, FALSE);
return FALSE;
#if 0
/* but this would also affect resources that can be safely
* migrated before a fencing op
*/
} else if(action->node->details->unclean == FALSE) {
pe_err("action %d was (%s) scheduled for unclean node",
action->id, action->uuid);
log_action(LOG_DEBUG, "Action for unclean node", action, FALSE);
return FALSE;
#endif
}
return TRUE;
}
/* lowest to highest */
static gint sort_action_id(gconstpointer a, gconstpointer b)
{
const action_wrapper_t *action_wrapper2 = (const action_wrapper_t*)a;
const action_wrapper_t *action_wrapper1 = (const action_wrapper_t*)b;
if(a == NULL) { return 1; }
if(b == NULL) { return -1; }
if(action_wrapper1->action->id > action_wrapper2->action->id) {
return -1;
}
if(action_wrapper1->action->id < action_wrapper2->action->id) {
return 1;
}
return 0;
}
static gboolean
should_dump_input(int last_action, action_t *action, action_wrapper_t *wrapper)
{
wrapper->state = pe_link_not_dumped;
if(last_action == wrapper->action->id) {
crm_debug_2("Input (%d) %s duplicated",
wrapper->action->id,
wrapper->action->uuid);
wrapper->state = pe_link_dup;
return FALSE;
} else if(wrapper->type == pe_order_none) {
crm_debug_2("Input (%d) %s suppressed",
wrapper->action->id,
wrapper->action->uuid);
return FALSE;
} else if(wrapper->action->optional == TRUE) {
crm_debug_2("Input (%d) %s optional",
wrapper->action->id,
wrapper->action->uuid);
return FALSE;
} else if(wrapper->action->runnable == FALSE
&& wrapper->action->pseudo == FALSE
&& wrapper->type == pe_order_optional) {
crm_debug("Input (%d) %s optional (ordering)",
wrapper->action->id,
wrapper->action->uuid);
return FALSE;
} else if(action->pseudo
&& (wrapper->type & pe_order_stonith_stop)) {
crm_debug("Input (%d) %s suppressed",
wrapper->action->id,
wrapper->action->uuid);
return FALSE;
}
crm_debug_3("Input (%d) %s n=%p p=%d r=%d f=0x%.6x dumped for %s",
wrapper->action->id,
wrapper->action->uuid,
wrapper->action->node,
wrapper->action->pseudo,
wrapper->action->runnable,
wrapper->type,
action->uuid);
return TRUE;
}
void
graph_element_from_action(action_t *action, pe_working_set_t *data_set)
{
int last_action = -1;
int synapse_priority = 0;
crm_data_t * syn = NULL;
crm_data_t * set = NULL;
crm_data_t * in = NULL;
crm_data_t * input = NULL;
crm_data_t * xml_action = NULL;
if(should_dump_action(action) == FALSE) {
return;
}
action->dumped = TRUE;
syn = create_xml_node(data_set->graph, "synapse");
set = create_xml_node(syn, "action_set");
in = create_xml_node(syn, "inputs");
crm_xml_add_int(syn, XML_ATTR_ID, data_set->num_synapse);
data_set->num_synapse++;
if(action->rsc != NULL) {
synapse_priority = action->rsc->priority;
}
if(action->priority > synapse_priority) {
synapse_priority = action->priority;
}
if(synapse_priority > 0) {
crm_xml_add_int(syn, XML_CIB_ATTR_PRIORITY, synapse_priority);
}
xml_action = action2xml(action, FALSE);
add_node_nocopy(set, crm_element_name(xml_action), xml_action);
action->actions_before = g_list_sort(
action->actions_before, sort_action_id);
slist_iter(wrapper,action_wrapper_t,action->actions_before,lpc,
if(should_dump_input(last_action, action, wrapper) == FALSE) {
continue;
}
wrapper->state = pe_link_dumped;
CRM_CHECK(last_action < wrapper->action->id, ;);
last_action = wrapper->action->id;
input = create_xml_node(in, "trigger");
xml_action = action2xml(wrapper->action, TRUE);
add_node_nocopy(input, crm_element_name(xml_action), xml_action);
);
}
diff --git a/crm/pengine/group.c b/crm/pengine/group.c
index 44892e8269..83d1be8bdf 100644
--- a/crm/pengine/group.c
+++ b/crm/pengine/group.c
@@ -1,399 +1,400 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <lha_internal.h>
#include <pengine.h>
#include <lib/crm/pengine/utils.h>
#include <crm/msg_xml.h>
#include <clplumbing/cl_misc.h>
#include <allocate.h>
#include <utils.h>
#define VARIANT_GROUP 1
#include <lib/crm/pengine/variant.h>
node_t *
group_color(resource_t *rsc, pe_working_set_t *data_set)
{
node_t *node = NULL;
node_t *group_node = NULL;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
if(rsc->provisional == FALSE) {
return rsc->allocated_to;
}
crm_debug_2("Processing %s", rsc->id);
if(rsc->is_allocating) {
crm_debug("Dependancy loop detected involving %s", rsc->id);
return NULL;
}
if(group_data->first_child == NULL) {
/* nothign to allocate */
rsc->provisional = FALSE;
return NULL;
}
rsc->is_allocating = TRUE;
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;
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
node = child_rsc->cmds->color(child_rsc, data_set);
if(group_node == NULL) {
group_node = node;
}
);
rsc->next_role = group_data->first_child->next_role;
rsc->is_allocating = FALSE;
rsc->provisional = FALSE;
if(group_data->colocated) {
return group_node;
}
return NULL;
}
void group_update_pseudo_status(resource_t *parent, resource_t *child);
void group_create_actions(resource_t *rsc, pe_working_set_t *data_set)
{
action_t *op = NULL;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_2("Creating actions for %s", rsc->id);
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->create_actions(child_rsc, data_set);
group_update_pseudo_status(rsc, child_rsc);
);
op = start_action(rsc, NULL, !group_data->child_starting);
op->pseudo = TRUE;
op->runnable = TRUE;
op = custom_action(rsc, started_key(rsc),
CRMD_ACTION_STARTED, NULL,
!group_data->child_starting, TRUE, data_set);
op->pseudo = TRUE;
op->runnable = TRUE;
op = stop_action(rsc, NULL, !group_data->child_stopping);
op->pseudo = TRUE;
op->runnable = TRUE;
op = custom_action(rsc, stopped_key(rsc),
CRMD_ACTION_STOPPED, NULL,
!group_data->child_stopping, TRUE, data_set);
op->pseudo = TRUE;
op->runnable = TRUE;
rsc->actions = rsc->actions;
/* rsc->actions = NULL; */
}
void
group_update_pseudo_status(resource_t *parent, resource_t *child)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, parent);
if(group_data->child_stopping && group_data->child_starting) {
return;
}
slist_iter(
action, action_t, child->actions, lpc,
if(action->optional) {
continue;
}
if(safe_str_eq(CRMD_ACTION_STOP, action->task) && action->runnable) {
group_data->child_stopping = TRUE;
crm_debug_3("Based on %s the group is stopping", action->uuid);
} else if(safe_str_eq(CRMD_ACTION_START, action->task) && action->runnable) {
group_data->child_starting = TRUE;
crm_debug_3("Based on %s the group is starting", action->uuid);
}
);
}
void group_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
{
resource_t *last_rsc = NULL;
-
+ int stopstop = pe_order_shutdown;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
native_internal_constraints(rsc, data_set);
+
+ if(group_data->ordered == FALSE) {
+ stopstop |= pe_order_implies_right;
+ }
custom_action_order(
rsc, stopped_key(rsc), NULL,
rsc, start_key(rsc), NULL,
pe_order_optional, data_set);
custom_action_order(
rsc, stop_key(rsc), NULL,
rsc, stopped_key(rsc), NULL,
pe_order_runnable_left, data_set);
custom_action_order(
rsc, start_key(rsc), NULL,
rsc, started_key(rsc), NULL,
pe_order_runnable_left, data_set);
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->internal_constraints(child_rsc, data_set);
if(group_data->colocated && last_rsc != NULL) {
rsc_colocation_new(
"group:internal_colocation", NULL, INFINITY,
child_rsc, last_rsc, NULL, NULL, data_set);
}
- custom_action_order(rsc, stop_key(rsc), NULL,
- child_rsc, stop_key(child_rsc), NULL,
- pe_order_optional, data_set);
+ order_stop_stop(rsc, child_rsc, stopstop);
custom_action_order(child_rsc, stop_key(child_rsc), NULL,
rsc, stopped_key(rsc), NULL,
pe_order_optional, data_set);
custom_action_order(child_rsc, start_key(child_rsc), NULL,
rsc, started_key(rsc), NULL,
- pe_order_optional, data_set);
+ pe_order_runnable_left, data_set);
if(group_data->ordered == FALSE) {
order_start_start(rsc, child_rsc, pe_order_implies_right|pe_order_runnable_left);
- order_stop_stop(rsc, child_rsc, pe_order_implies_right);
} else if(last_rsc != NULL) {
order_start_start(last_rsc, child_rsc, pe_order_implies_right|pe_order_runnable_left);
order_stop_stop(child_rsc, last_rsc, pe_order_implies_left);
child_rsc->restart_type = pe_restart_restart;
} else {
/* If anyone in the group is starting, then
* pe_order_implies_right will cause _everyone_ in the group
* to be sent a start action
* But this is safe since starting something that is already
* started is required to be "safe"
*/
order_start_start(rsc, child_rsc,
pe_order_implies_right|pe_order_implies_left|pe_order_runnable_right|pe_order_runnable_left);
}
last_rsc = child_rsc;
);
if(group_data->ordered && last_rsc != NULL) {
order_stop_stop(rsc, last_rsc, pe_order_implies_right);
}
}
void group_rsc_colocation_lh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
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;
}
crm_debug_4("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);
return;
} else if(constraint->score >= INFINITY) {
crm_config_err("%s: Cannot perform manditory colocation"
" between non-colocated group and %s",
rsc_lh->id, rsc_rh->id);
return;
}
slist_iter(
child_rsc, resource_t, rsc_lh->children, lpc,
child_rsc->cmds->rsc_colocation_lh(
child_rsc, rsc_rh, constraint);
);
}
void group_rsc_colocation_rh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc_rh);
CRM_CHECK(rsc_lh->variant == pe_native, return);
crm_debug_3("Processing RH of constraint %s", constraint->id);
print_resource(LOG_DEBUG_3, "LHS", rsc_lh, TRUE);
if(rsc_rh->provisional) {
return;
} else if(group_data->colocated && group_data->first_child) {
group_data->first_child->cmds->rsc_colocation_rh(
rsc_lh, group_data->first_child, constraint);
return;
} else if(constraint->score >= INFINITY) {
crm_config_err("%s: Cannot perform manditory colocation with"
" non-colocated group: %s", rsc_lh->id, rsc_rh->id);
return;
}
slist_iter(
child_rsc, resource_t, rsc_rh->children, lpc,
child_rsc->cmds->rsc_colocation_rh(
rsc_lh, child_rsc, constraint);
);
}
void group_rsc_order_lh(resource_t *rsc, order_constraint_t *order, pe_working_set_t *data_set)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_2("%s->%s", order->lh_action_task, order->rh_action_task);
if(order->rh_rsc != NULL
&& (rsc == order->rh_rsc || rsc == order->rh_rsc->parent)) {
native_rsc_order_lh(rsc, order, data_set);
return;
}
if(order->type != pe_order_optional) {
native_rsc_order_lh(rsc, order, data_set);
}
if(order->type & pe_order_implies_left) {
native_rsc_order_lh(group_data->first_child, order, data_set);
}
convert_non_atomic_task(rsc, order);
native_rsc_order_lh(rsc, order, data_set);
}
void group_rsc_order_rh(
action_t *lh_action, resource_t *rsc, order_constraint_t *order)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_2("%s->%s", lh_action->uuid, order->rh_action_task);
if(rsc == NULL) {
return;
}
native_rsc_order_rh(lh_action, rsc, order);
}
void group_rsc_location(resource_t *rsc, rsc_to_node_t *constraint)
{
gboolean reset_scores = TRUE;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug("Processing rsc_location %s for %s",
constraint->id, rsc->id);
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->rsc_location(child_rsc, constraint);
if(group_data->colocated && reset_scores) {
reset_scores = FALSE;
slist_iter(node, node_t, constraint->node_list_rh, lpc2,
node->weight = 0;
);
}
);
}
void group_expand(resource_t *rsc, pe_working_set_t *data_set)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_3("Processing actions from %s", rsc->id);
CRM_CHECK(rsc != NULL, return);
native_expand(rsc, data_set);
slist_iter(
child_rsc, resource_t, rsc->children, lpc,
child_rsc->cmds->expand(child_rsc, data_set);
);
}
GListPtr
group_merge_weights(
resource_t *rsc, const char *rhs, GListPtr nodes, int factor, gboolean allow_rollback)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
if(rsc->is_merging) {
crm_debug("Breaking dependancy loop with %s at %s", rsc->id, rhs);
return nodes;
} else if(rsc->provisional == FALSE || can_run_any(nodes) == FALSE) {
return nodes;
}
rsc->is_merging = TRUE;
nodes = group_data->first_child->cmds->merge_weights(
group_data->first_child, rhs, nodes, factor, allow_rollback);
slist_iter(
constraint, rsc_colocation_t, rsc->rsc_cons_lhs, lpc,
nodes = native_merge_weights(
constraint->rsc_lh, rsc->id, nodes,
constraint->score/INFINITY, allow_rollback);
);
rsc->is_merging = FALSE;
return nodes;
}
diff --git a/crm/pengine/pengine.h b/crm/pengine/pengine.h
index 2bbfb8fa49..c2d5c3c110 100644
--- a/crm/pengine/pengine.h
+++ b/crm/pengine/pengine.h
@@ -1,174 +1,176 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PENGINE__H
#define PENGINE__H
#include <clplumbing/ipc.h>
typedef struct rsc_to_node_s rsc_to_node_t;
typedef struct rsc_colocation_s rsc_colocation_t;
typedef struct lrm_agent_s lrm_agent_t;
typedef struct order_constraint_s order_constraint_t;
#include <glib.h>
#include <crm/crm.h>
#include <crm/common/msg.h>
#include <crm/common/iso8601.h>
#include <crm/pengine/rules.h>
#include <crm/pengine/common.h>
#include <crm/pengine/status.h>
#include <crm/pengine/complex.h>
enum pe_stop_fail {
pesf_block,
pesf_stonith,
pesf_ignore
};
enum pe_ordering {
pe_order_none = 0x0, /* deleted */
pe_order_implies_left = 0x01, /* was: _mandatory */
pe_order_implies_right = 0x02, /* was: _recover */
pe_order_runnable_left = 0x10, /* needs the LHS side to be runnable */
pe_order_runnable_right = 0x20, /* needs the RHS side to be runnable */
pe_order_optional = 0x100, /* pure ordering, nothing implied */
pe_order_stonith_stop = 0x200, /* only applies if the action is non-pseudo */
pe_order_restart = 0x400, /* stop-start constraint */
pe_order_demote = 0x800, /* stop-start constraint */
- pe_order_test = 0x1000 /* test marker */
+ pe_order_shutdown = 0x1000, /* combines with pe_order_restart to make a complex resource shut down */
+
+ pe_order_test = 0x10000 /* test marker */
};
struct rsc_colocation_s {
const char *id;
const char *node_attribute;
resource_t *rsc_lh;
resource_t *rsc_rh;
int role_lh;
int role_rh;
int score;
};
struct rsc_to_node_s {
const char *id;
resource_t *rsc_lh;
enum rsc_role_e role_filter;
GListPtr node_list_rh; /* node_t* */
};
struct order_constraint_s
{
int id;
enum pe_ordering type;
void *lh_opaque;
resource_t *lh_rsc;
action_t *lh_action;
char *lh_action_task;
void *rh_opaque;
resource_t *rh_rsc;
action_t *rh_action;
char *rh_action_task;
/* (soon to be) variant specific */
/* int lh_rsc_incarnation; */
/* int rh_rsc_incarnation; */
};
enum pe_link_state {
pe_link_not_dumped,
pe_link_dumped,
pe_link_dup,
};
typedef struct action_wrapper_s action_wrapper_t;
struct action_wrapper_s
{
enum pe_ordering type;
enum pe_link_state state;
action_t *action;
};
extern gboolean stage0(pe_working_set_t *data_set);
extern gboolean stage1(pe_working_set_t *data_set);
extern gboolean stage2(pe_working_set_t *data_set);
extern gboolean stage3(pe_working_set_t *data_set);
extern gboolean stage4(pe_working_set_t *data_set);
extern gboolean stage5(pe_working_set_t *data_set);
extern gboolean stage6(pe_working_set_t *data_set);
extern gboolean stage7(pe_working_set_t *data_set);
extern gboolean stage8(pe_working_set_t *data_set);
extern gboolean summary(GListPtr resources);
extern gboolean pe_msg_dispatch(IPC_Channel *sender, void *user_data);
extern gboolean process_pe_message(
HA_Message *msg, crm_data_t *xml_data, IPC_Channel *sender);
extern gboolean unpack_constraints(
crm_data_t *xml_constraints, pe_working_set_t *data_set);
extern gboolean update_action_states(GListPtr actions);
extern gboolean shutdown_constraints(
node_t *node, action_t *shutdown_op, pe_working_set_t *data_set);
extern gboolean stonith_constraints(
node_t *node, action_t *stonith_op, pe_working_set_t *data_set);
extern int custom_action_order(
resource_t *lh_rsc, char *lh_task, action_t *lh_action,
resource_t *rh_rsc, char *rh_task, action_t *rh_action,
enum pe_ordering type, pe_working_set_t *data_set);
#define order_start_start(rsc1,rsc2, type) \
custom_action_order(rsc1, start_key(rsc1), NULL, \
rsc2, start_key(rsc2) ,NULL, \
type, data_set)
#define order_stop_stop(rsc1, rsc2, type) \
custom_action_order(rsc1, stop_key(rsc1), NULL, \
rsc2, stop_key(rsc2) ,NULL, \
type, data_set)
#define order_stop_start(rsc1, rsc2, type) \
custom_action_order(rsc1, stop_key(rsc1), NULL, \
rsc2, start_key(rsc2) ,NULL, \
type, data_set)
#define order_start_stop(rsc1, rsc2, type) \
custom_action_order(rsc1, start_key(rsc1), NULL, \
rsc2, stop_key(rsc2) ,NULL, \
type, data_set)
extern void graph_element_from_action(
action_t *action, pe_working_set_t *data_set);
extern const char* transition_idle_timeout;
#endif
diff --git a/crm/pengine/regression.sh b/crm/pengine/regression.sh
index d866b7d5d4..704331a0e3 100755
--- a/crm/pengine/regression.sh
+++ b/crm/pengine/regression.sh
@@ -1,268 +1,269 @@
#!/bin/bash
# Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
if [ -x /usr/bin/valgrind ]; then
export G_SLICE=always-malloc
VALGRIND_CMD="valgrind -q --show-reachable=yes --leak-check=full --trace-children=no --time-stamp=yes --num-callers=20 --suppressions=./ptest.supp"
fi
. regression.core.sh
create_mode="true"
echo Generating test outputs for these tests...
# do_test
echo Done.
echo ""
echo Performing the following tests...
create_mode="false"
echo ""
do_test simple1 "Offline "
do_test simple2 "Start "
do_test simple3 "Start 2 "
do_test simple4 "Start Failed"
do_test simple6 "Stop Start "
do_test simple7 "Shutdown "
#do_test simple8 "Stonith "
#do_test simple9 "Lower version"
#do_test simple10 "Higher version"
do_test simple11 "Priority (ne)"
do_test simple12 "Priority (eq)"
do_test simple8 "Stickiness"
echo ""
do_test params-0 "Params: No change"
do_test params-1 "Params: Changed"
do_test params-2 "Params: Resource definition"
do_test params-4 "Params: Reload"
do_test novell-251689 "Resource definition change + target_role=stopped"
echo ""
do_test orphan-0 "Orphan ignore"
do_test orphan-1 "Orphan stop"
echo ""
do_test target-0 "Target Role : baseline"
do_test target-1 "Target Role : test"
echo ""
do_test date-1 "Dates" -d "2005-020"
do_test date-2 "Date Spec - Pass" -d "2005-020T12:30"
do_test date-3 "Date Spec - Fail" -d "2005-020T11:30"
do_test probe-0 "Probe (anon clone)"
do_test probe-1 "Pending Probe"
do_test standby "Standby"
do_test comments "Comments"
echo ""
do_test rsc_dep1 "Must not "
do_test rsc_dep3 "Must "
do_test rsc_dep5 "Must not 3 "
do_test rsc_dep7 "Must 3 "
do_test rsc_dep10 "Must (but cant)"
do_test rsc_dep2 "Must (running) "
do_test rsc_dep8 "Must (running : alt) "
do_test rsc_dep4 "Must (running + move)"
echo ""
do_test order1 "Order start 1 "
do_test order2 "Order start 2 "
do_test order3 "Order stop "
do_test order4 "Order (multiple) "
do_test order5 "Order (move) "
do_test order6 "Order (move w/ restart) "
do_test order7 "Order (manditory) "
do_test order-optional "Order (score=0) "
do_test order-required "Order (score=INFINITY) "
echo ""
do_test coloc-loop "Colocation - loop"
do_test coloc-many-one "Colocation - many-to-one"
do_test coloc-list "Colocation - many-to-one with list"
do_test coloc-group "Colocation - groups"
#echo ""
#do_test agent1 "version: lt (empty)"
#do_test agent2 "version: eq "
#do_test agent3 "version: gt "
echo ""
do_test attrs1 "string: eq (and) "
do_test attrs2 "string: lt / gt (and)"
do_test attrs3 "string: ne (or) "
do_test attrs4 "string: exists "
do_test attrs5 "string: not_exists "
do_test attrs6 "is_dc: true "
do_test attrs7 "is_dc: false "
do_test attrs8 "score_attribute "
echo ""
do_test mon-rsc-1 "Schedule Monitor - start"
do_test mon-rsc-2 "Schedule Monitor - move "
do_test mon-rsc-3 "Schedule Monitor - pending start "
do_test mon-rsc-4 "Schedule Monitor - move/pending start"
echo ""
do_test rec-rsc-0 "Resource Recover - no start "
do_test rec-rsc-1 "Resource Recover - start "
do_test rec-rsc-2 "Resource Recover - monitor "
do_test rec-rsc-3 "Resource Recover - stop - ignore"
do_test rec-rsc-4 "Resource Recover - stop - block "
do_test rec-rsc-5 "Resource Recover - stop - fence "
do_test rec-rsc-6 "Resource Recover - multiple - restart"
do_test rec-rsc-7 "Resource Recover - multiple - stop "
do_test rec-rsc-8 "Resource Recover - multiple - block "
do_test rec-rsc-9 "Resource Recover - group/group"
echo ""
do_test quorum-1 "No quorum - ignore"
do_test quorum-2 "No quorum - freeze"
do_test quorum-3 "No quorum - stop "
do_test quorum-4 "No quorum - start anyway"
do_test quorum-5 "No quorum - start anyway (group)"
do_test quorum-6 "No quorum - start anyway (clone)"
echo ""
do_test rec-node-1 "Node Recover - Startup - no fence"
do_test rec-node-2 "Node Recover - Startup - fence "
do_test rec-node-3 "Node Recover - HA down - no fence"
do_test rec-node-4 "Node Recover - HA down - fence "
do_test rec-node-5 "Node Recover - CRM down - no fence"
do_test rec-node-6 "Node Recover - CRM down - fence "
do_test rec-node-7 "Node Recover - no quorum - ignore "
do_test rec-node-8 "Node Recover - no quorum - freeze "
do_test rec-node-9 "Node Recover - no quorum - stop "
do_test rec-node-10 "Node Recover - no quorum - stop w/fence"
do_test rec-node-11 "Node Recover - CRM down w/ group - fence "
do_test rec-node-12 "Node Recover - nothing active - fence "
do_test rec-node-13 "Node Recover - failed resource + shutdown - fence "
do_test rec-node-15 "Node Recover - unknown lrm section"
do_test rec-node-14 "Serialize all stonith's"
echo ""
do_test multi1 "Multiple Active (stop/start)"
echo ""
do_test migrate-1 "Migrate (migrate)"
do_test migrate-2 "Migrate (stable)"
do_test migrate-3 "Migrate (failed migrate_to)"
do_test migrate-4 "Migrate (failed migrate_from)"
do_test novell-252693 "Migration in a stopping stack"
do_test novell-252693-2 "Migration in a starting stack"
do_test novell-252693-3 "Non-Migration in a starting and stopping stack"
#echo ""
#do_test complex1 "Complex "
echo ""
do_test group1 "Group "
do_test group2 "Group + Native "
do_test group3 "Group + Group "
do_test group4 "Group + Native (nothing)"
do_test group5 "Group + Native (move) "
do_test group6 "Group + Group (move) "
do_test group7 "Group colocation"
do_test group13 "Group colocation (cant run)"
do_test group8 "Group anti-colocation"
do_test group9 "Group recovery"
do_test group10 "Group partial recovery"
do_test group11 "Group target_role"
do_test group14 "Group stop (graph terminated)"
do_test group15 "-ve group colocation"
do_test bug-1573 "Partial stop of a group with two children"
+do_test bug-1718 "Mandatory group ordering - Stop group_FUN"
echo ""
do_test inc0 "Incarnation start"
do_test inc1 "Incarnation start order"
do_test inc2 "Incarnation silent restart, stop, move"
do_test inc3 "Inter-incarnation ordering, silent restart, stop, move"
do_test inc4 "Inter-incarnation ordering, silent restart, stop, move (ordered)"
do_test inc5 "Inter-incarnation ordering, silent restart, stop, move (restart 1)"
do_test inc6 "Inter-incarnation ordering, silent restart, stop, move (restart 2)"
do_test inc7 "Clone colocation"
do_test inc8 "Clone anti-colocation"
do_test inc9 "Non-unique clone"
do_test inc10 "Non-unique clone (stop)"
do_test inc11 "Primitive colocation with clones"
do_test inc12 "Clone shutdown"
do_test cloned-group "Make sure only the correct number of cloned groups are started"
echo ""
do_test master-0 "Stopped -> Slave"
do_test master-1 "Stopped -> Promote"
do_test master-2 "Stopped -> Promote : notify"
do_test master-3 "Stopped -> Promote : master location"
do_test master-4 "Started -> Promote : master location"
do_test master-5 "Promoted -> Promoted"
do_test master-6 "Promoted -> Promoted (2)"
do_test master-7 "Promoted -> Fenced"
do_test master-8 "Promoted -> Fenced -> Moved"
do_test master-9 "Stopped + Promotable + No quorum"
do_test master-10 "Stopped -> Promotable : notify with monitor"
do_test master-11 "Stopped -> Promote : colocation"
do_test novell-239082 "Demote/Promote ordering"
do_test novell-239087 "Stable master placement"
do_test master-12 "Promotion based solely on rsc_location constraints"
do_test master-13 "Include preferences of colocated resources when placing master"
do_test master-demote "Ordering when actions depends on demoting a slave resource"
do_test master-ordering "Prevent resources from starting that need a master"
echo ""
do_test managed-0 "Managed (reference)"
do_test managed-1 "Not managed - down "
do_test managed-2 "Not managed - up "
echo ""
do_test interleave-0 "Interleave (reference)"
do_test interleave-1 "coloc - not interleaved"
do_test interleave-2 "coloc - interleaved "
do_test interleave-3 "coloc - interleaved (2)"
echo ""
do_test notify-0 "Notify reference"
do_test notify-1 "Notify simple"
do_test notify-2 "Notify simple, confirm"
do_test notify-3 "Notify move, confirm"
do_test novell-239079 "Notification priority"
#do_test notify-2 "Notify - 764"
echo ""
do_test 594 "OSDL #594"
do_test 662 "OSDL #662"
do_test 696 "OSDL #696"
do_test 726 "OSDL #726"
do_test 735 "OSDL #735"
do_test 764 "OSDL #764"
do_test 797 "OSDL #797"
do_test 829 "OSDL #829"
do_test 994 "OSDL #994"
do_test 1360 "OSDL #1360 - Clone stickiness"
do_test 1484 "OSDL #1484 - on_fail=stop"
do_test 1494 "OSDL #1494 - Clone stability"
do_test unrunnable-1 "Unrunnable"
do_test stonith-0 "Stonith loop - 1"
do_test stonith-1 "Stonith loop - 2"
do_test bug-1572-1 "Recovery of groups depending on master/slave"
do_test bug-1572-2 "Recovery of groups depending on master/slave when the master is never re-promoted"
do_test bug-1685 "Depends-on-master ordering"
echo ""
test_results
diff --git a/crm/pengine/testcases/bug-1718.dot b/crm/pengine/testcases/bug-1718.dot
new file mode 100644
index 0000000000..9e660623f8
--- /dev/null
+++ b/crm/pengine/testcases/bug-1718.dot
@@ -0,0 +1,19 @@
+digraph "g" {
+"all_stopped" [ style=bold color="green" fontcolor="orange" ]
+"group_fUN_start_0" -> "resource_IP3_start_0 ops.ds9" [ style = dashed]
+"group_fUN_start_0" [ style=dashed color="red" fontcolor="orange" ]
+"group_fUN_stop_0" -> "group_fUN_start_0" [ style = dashed]
+"group_fUN_stop_0" -> "resource_IP3_stop_0 ops.ds9" [ style = bold]
+"group_fUN_stop_0" -> "resource_dummy_stop_0 ops.ds9" [ style = bold]
+"group_fUN_stop_0" [ style=bold color="green" fontcolor="orange" ]
+"resource_IP3_start_0 ops.ds9" -> "resource_dummy_start_0 ops.ds9" [ style = dashed]
+"resource_IP3_start_0 ops.ds9" [ style=dashed color="red" fontcolor="black" ]
+"resource_IP3_stop_0 ops.ds9" -> "all_stopped" [ style = bold]
+"resource_IP3_stop_0 ops.ds9" -> "resource_IP3_start_0 ops.ds9" [ style = dashed]
+"resource_IP3_stop_0 ops.ds9" [ style=bold color="green" fontcolor="black" ]
+"resource_dummy_start_0 ops.ds9" [ style=dashed color="red" fontcolor="black" ]
+"resource_dummy_stop_0 ops.ds9" -> "all_stopped" [ style = bold]
+"resource_dummy_stop_0 ops.ds9" -> "resource_IP3_stop_0 ops.ds9" [ style = bold]
+"resource_dummy_stop_0 ops.ds9" -> "resource_dummy_start_0 ops.ds9" [ style = dashed]
+"resource_dummy_stop_0 ops.ds9" [ style=bold color="green" fontcolor="black" ]
+}
diff --git a/crm/pengine/testcases/bug-1718.exp b/crm/pengine/testcases/bug-1718.exp
new file mode 100644
index 0000000000..151ba878e8
--- /dev/null
+++ b/crm/pengine/testcases/bug-1718.exp
@@ -0,0 +1,55 @@
+ <transition_graph cluster-delay="60s" transition_id="0">
+ <synapse id="0">
+ <action_set>
+ <pseudo_event id="18" operation="stop" operation_key="group_fUN_stop_0">
+ <attributes crm_feature_set="2.0" CRM_meta_timeout="20000"/>
+ </pseudo_event>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="12" operation="stop" operation_key="resource_IP3_stop_0" on_node="ops.ds9" on_node_uuid="1e550a7a-16a2-453a-81c3-8d6e04919dad">
+ <primitive id="resource_IP3" long-id="group_fUN:resource_IP3" class="ocf" provider="heartbeat" type="IPaddr"/>
+ <attributes crm_feature_set="2.0" CRM_meta_timeout="20000"/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="14" operation="stop" operation_key="resource_dummy_stop_0" on_node="ops.ds9" on_node_uuid="1e550a7a-16a2-453a-81c3-8d6e04919dad"/>
+ </trigger>
+ <trigger>
+ <pseudo_event id="18" operation="stop" operation_key="group_fUN_stop_0"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <rsc_op id="14" operation="stop" operation_key="resource_dummy_stop_0" on_node="ops.ds9" on_node_uuid="1e550a7a-16a2-453a-81c3-8d6e04919dad">
+ <primitive id="resource_dummy" long-id="group_fUN:resource_dummy" class="ocf" provider="heartbeat" type="Dummy"/>
+ <attributes crm_feature_set="2.0" CRM_meta_timeout="20000"/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <pseudo_event id="18" operation="stop" operation_key="group_fUN_stop_0"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="3">
+ <action_set>
+ <pseudo_event id="5" operation="all_stopped" operation_key="all_stopped">
+ <attributes crm_feature_set="2.0"/>
+ </pseudo_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="12" operation="stop" operation_key="resource_IP3_stop_0" on_node="ops.ds9" on_node_uuid="1e550a7a-16a2-453a-81c3-8d6e04919dad"/>
+ </trigger>
+ <trigger>
+ <rsc_op id="14" operation="stop" operation_key="resource_dummy_stop_0" on_node="ops.ds9" on_node_uuid="1e550a7a-16a2-453a-81c3-8d6e04919dad"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/bug-1718.xml b/crm/pengine/testcases/bug-1718.xml
new file mode 100644
index 0000000000..9413d8b505
--- /dev/null
+++ b/crm/pengine/testcases/bug-1718.xml
@@ -0,0 +1,203 @@
+ <cib generated="true" admin_epoch="0" have_quorum="true" ignore_dtd="false" num_peers="5" cib_feature_revision="1.3" ccm_transition="6" dc_uuid="1e550a7a-16a2-453a-81c3-8d6e04919dad" epoch="98" num_updates="20">
+ <configuration>
+ <crm_config>
+ <cluster_property_set id="cib-bootstrap-options">
+ <attributes>
+ <nvpair name="last-lrm-refresh" id="cib-bootstrap-options-last-lrm-refresh" value="1192999094"/>
+ </attributes>
+ </cluster_property_set>
+ </crm_config>
+ <nodes>
+ <node id="11e02303-5984-4f6d-be06-37e137335612" uname="defiant.ds9" type="normal">
+ <instance_attributes id="nodes-11e02303-5984-4f6d-be06-37e137335612">
+ <attributes>
+ <nvpair id="standby-11e02303-5984-4f6d-be06-37e137335612" name="standby" value="on"/>
+ </attributes>
+ </instance_attributes>
+ </node>
+ <node id="d9fea871-5fc2-4c5d-b3bd-c830fc5a5d57" uname="heartbeat.ds9" type="normal"/>
+ <node id="1e550a7a-16a2-453a-81c3-8d6e04919dad" uname="ops.ds9" type="normal"/>
+ <node id="ed7370db-6624-4d23-a723-9fafcd031f21" uname="defiant.ds9" type="normal"/>
+ <node id="de2a634c-e405-42bb-9df2-292e36ad5970" uname="biggame.ds9" type="normal"/>
+ <node id="674234bf-84a9-4059-8d48-28e273cc280e" uname="warbird.ds9" type="normal"/>
+ </nodes>
+ <resources>
+ <group ordered="true" collocated="true" id="Web_Group">
+ <primitive class="ocf" type="IPaddr" provider="heartbeat" id="Apache_IP">
+ <instance_attributes id="Apache_IP_instance_attrs">
+ <attributes>
+ <nvpair name="target_role" id="Apache_IP_target_role" value="started"/>
+ <nvpair id="Apache_IP_ip" name="ip" value="10.0.0.180"/>
+ <nvpair id="Apache_IP_cidr_netmask" name="cidr_netmask" value="255.255.255.0"/>
+ <nvpair id="Apache_IP_broadcast" name="broadcast" value="10.0.0.255"/>
+ </attributes>
+ </instance_attributes>
+ </primitive>
+ <instance_attributes id="Web_Group_instance_attrs">
+ <attributes>
+ <nvpair id="Web_Group_target_role" name="target_role" value="started"/>
+ </attributes>
+ </instance_attributes>
+ <primitive class="ocf" type="IPaddr" provider="heartbeat" id="resource_IP2">
+ <instance_attributes id="resource_IP2_instance_attrs">
+ <attributes>
+ <nvpair name="target_role" id="resource_IP2_target_role" value="stopped"/>
+ <nvpair id="7680eb0a-0f4d-4369-89b8-f371d1224873" name="ip" value="10.0.0.67"/>
+ <nvpair id="e399715a-2fc4-44fc-a327-0e20b0ace704" name="cidr_netmask" value="255.255.255.0"/>
+ <nvpair id="c504e392-c889-450e-b035-95b5474233c8" name="broadcast" value="10.0.0.255"/>
+ </attributes>
+ </instance_attributes>
+ </primitive>
+ <primitive id="resource_dummyweb" class="ocf" type="Dummy" provider="heartbeat">
+ <instance_attributes id="resource_dummyweb_instance_attrs">
+ <attributes>
+ <nvpair id="resource_dummyweb_target_role" name="target_role" value="started"/>
+ </attributes>
+ </instance_attributes>
+ </primitive>
+ </group>
+ <group ordered="true" collocated="true" id="group_fUN">
+ <primitive id="resource_IP3" class="ocf" type="IPaddr" provider="heartbeat">
+ <instance_attributes id="resource_IP3_instance_attrs">
+ <attributes>
+ <nvpair id="resource_IP3_target_role" name="target_role" value="started"/>
+ <nvpair id="961cbc4e-fd17-4f30-a933-3db77ba69407" name="ip" value="10.0.0.68"/>
+ <nvpair id="d329e99a-456f-4689-8a5e-f80178349d4f" name="cidr_netmask" value="255.255.255.0"/>
+ <nvpair id="49f4cf40-6987-4e14-aace-28ab5d776953" name="broadcast" value="10.0.0.255"/>
+ </attributes>
+ </instance_attributes>
+ </primitive>
+ <primitive class="ocf" type="Dummy" provider="heartbeat" id="resource_dummy">
+ <instance_attributes id="resource_dummy_instance_attrs">
+ <attributes>
+ <nvpair name="target_role" id="resource_dummy_target_role" value="started"/>
+ </attributes>
+ </instance_attributes>
+ </primitive>
+ </group>
+ </resources>
+ <constraints>
+ <rsc_location id="Web_Place" rsc="Web_Group">
+ <rule id="prefered_Web_Place" score="100">
+ <expression attribute="#uname" id="f0c82530-5984-42f8-ac40-8ce32048f2f9" operation="eq" value="defiant.ds9"/>
+ </rule>
+ </rsc_location>
+ <rsc_order id="order_Web_before_fun" from="Web_Group" type="before" to="group_fUN"/>
+ </constraints>
+ </configuration>
+ <status>
+ <node_state uname="heartbeat.ds9" crmd="online" shutdown="0" in_ccm="true" join="member" ha="active" expected="member" id="d9fea871-5fc2-4c5d-b3bd-c830fc5a5d57" crm-debug-origin="do_update_resource">
+ <transient_attributes id="d9fea871-5fc2-4c5d-b3bd-c830fc5a5d57">
+ <instance_attributes id="status-d9fea871-5fc2-4c5d-b3bd-c830fc5a5d57">
+ <attributes>
+ <nvpair id="status-d9fea871-5fc2-4c5d-b3bd-c830fc5a5d57-probe_complete" name="probe_complete" value="true"/>
+ <nvpair id="status-d9fea871-5fc2-4c5d-b3bd-c830fc5a5d57-fail-count-OpenVPN" name="fail-count-OpenVPN" value="1"/>
+ </attributes>
+ </instance_attributes>
+ </transient_attributes>
+ <lrm id="d9fea871-5fc2-4c5d-b3bd-c830fc5a5d57">
+ <lrm_resources>
+ <lrm_resource id="OpenVPN_IP" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="OpenVPN_IP_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="7:5:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;7:5:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="6" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="1f0bbac744caf5cfdfd4c698739d09c5"/>
+ </lrm_resource>
+ <lrm_resource id="resource_IP2" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_IP2_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="3:74:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;3:74:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="49" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="368d7680070c38f8f2f40ddf5a434d45"/>
+ </lrm_resource>
+ <lrm_resource id="Apache_IP" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="Apache_IP_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="5:5:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;5:5:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="4" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="a3558b7ea398267ef1ea56b21f5d840a"/>
+ <lrm_rsc_op id="Apache_IP_start_0" operation="start" crm-debug-origin="do_update_resource" transition_key="6:0:5e45f285-3200-4d7f-966a-42c650d75a6c" transition_magic="0:0;6:0:5e45f285-3200-4d7f-966a-42c650d75a6c" call_id="75" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="a3558b7ea398267ef1ea56b21f5d840a"/>
+ <lrm_rsc_op id="Apache_IP_stop_0" operation="stop" crm-debug-origin="build_active_RAs" transition_key="19:22:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="0:0;19:22:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="17" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="a3558b7ea398267ef1ea56b21f5d840a"/>
+ </lrm_resource>
+ <lrm_resource id="resource_IP3" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_IP3_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="3:75:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;3:75:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="50" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="87f29a4a3d4a9a7ad6eadc46f37c1f64"/>
+ <lrm_rsc_op id="resource_IP3_stop_0" operation="stop" crm-debug-origin="do_update_resource" transition_key="31:0:5e45f285-3200-4d7f-966a-42c650d75a6c" transition_magic="0:0;31:0:5e45f285-3200-4d7f-966a-42c650d75a6c" call_id="77" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="87f29a4a3d4a9a7ad6eadc46f37c1f64"/>
+ <lrm_rsc_op id="resource_IP3_start_0" operation="start" crm-debug-origin="build_active_RAs" transition_key="40:87:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="0:0;40:87:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="73" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="87f29a4a3d4a9a7ad6eadc46f37c1f64"/>
+ </lrm_resource>
+ <lrm_resource id="Apache" type="apache13" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="Apache_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="3:22:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:1;3:22:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="16" crm_feature_set="2.0" rc_code="1" op_status="4" interval="0" op_digest="353bb677b42be27312c9f093a30268be"/>
+ <lrm_rsc_op id="Apache_stop_0" operation="stop" crm-debug-origin="build_active_RAs" transition_key="1:23:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="0:0;1:23:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="18" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="353bb677b42be27312c9f093a30268be"/>
+ </lrm_resource>
+ <lrm_resource id="resource_dummyweb" type="Dummy" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_dummyweb_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="3:83:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;3:83:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="62" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ </lrm_resource>
+ <lrm_resource id="resource_dummy" type="Dummy" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_dummy_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="3:79:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;3:79:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="52" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ <lrm_rsc_op id="resource_dummy_stop_0" operation="stop" crm-debug-origin="do_update_resource" transition_key="33:0:5e45f285-3200-4d7f-966a-42c650d75a6c" transition_magic="0:0;33:0:5e45f285-3200-4d7f-966a-42c650d75a6c" call_id="76" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ <lrm_rsc_op id="resource_dummy_start_0" operation="start" crm-debug-origin="build_active_RAs" transition_key="42:87:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="0:0;42:87:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="74" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8" op_force_restart=" state " op_restart_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ </lrm_resource>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state uname="ops.ds9" crmd="online" in_ccm="true" join="member" ha="active" expected="member" shutdown="0" id="1e550a7a-16a2-453a-81c3-8d6e04919dad" crm-debug-origin="do_update_resource">
+ <transient_attributes id="1e550a7a-16a2-453a-81c3-8d6e04919dad">
+ <instance_attributes id="status-1e550a7a-16a2-453a-81c3-8d6e04919dad">
+ <attributes>
+ <nvpair id="status-1e550a7a-16a2-453a-81c3-8d6e04919dad-probe_complete" name="probe_complete" value="true"/>
+ <nvpair id="status-1e550a7a-16a2-453a-81c3-8d6e04919dad-fail-count-OpenVPN" name="fail-count-OpenVPN" value="2"/>
+ </attributes>
+ </instance_attributes>
+ </transient_attributes>
+ <lrm id="1e550a7a-16a2-453a-81c3-8d6e04919dad">
+ <lrm_resources>
+ <lrm_resource id="OpenVPN_IP" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="OpenVPN_IP_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="14:5:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;14:5:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="6" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="1f0bbac744caf5cfdfd4c698739d09c5"/>
+ </lrm_resource>
+ <lrm_resource id="resource_IP2" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_IP2_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="5:74:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;5:74:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="46" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="368d7680070c38f8f2f40ddf5a434d45"/>
+ </lrm_resource>
+ <lrm_resource id="Apache_IP" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="Apache_IP_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="12:5:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;12:5:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="4" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="a3558b7ea398267ef1ea56b21f5d840a"/>
+ </lrm_resource>
+ <lrm_resource id="resource_IP3" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_IP3_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="5:75:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;5:75:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="47" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="87f29a4a3d4a9a7ad6eadc46f37c1f64"/>
+ <lrm_rsc_op id="resource_IP3_start_0" operation="start" crm-debug-origin="do_update_resource" transition_key="32:0:5e45f285-3200-4d7f-966a-42c650d75a6c" transition_magic="0:0;32:0:5e45f285-3200-4d7f-966a-42c650d75a6c" call_id="50" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="87f29a4a3d4a9a7ad6eadc46f37c1f64"/>
+ </lrm_resource>
+ <lrm_resource id="Apache" type="apache13" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="Apache_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="5:22:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:1;5:22:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="14" crm_feature_set="2.0" rc_code="1" op_status="4" interval="0" op_digest="353bb677b42be27312c9f093a30268be"/>
+ <lrm_rsc_op id="Apache_stop_0" operation="stop" crm-debug-origin="build_active_RAs" transition_key="2:23:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="0:0;2:23:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="15" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="353bb677b42be27312c9f093a30268be"/>
+ </lrm_resource>
+ <lrm_resource id="resource_dummyweb" type="Dummy" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_dummyweb_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="5:83:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;5:83:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="49" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ </lrm_resource>
+ <lrm_resource id="resource_dummy" type="Dummy" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_dummy_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="5:79:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;5:79:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="48" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ <lrm_rsc_op id="resource_dummy_start_0" operation="start" crm-debug-origin="do_update_resource" transition_key="34:0:5e45f285-3200-4d7f-966a-42c650d75a6c" transition_magic="0:0;34:0:5e45f285-3200-4d7f-966a-42c650d75a6c" call_id="51" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8" op_force_restart=" state " op_restart_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ </lrm_resource>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state uname="biggame.ds9" ha="active" crmd="online" shutdown="0" in_ccm="true" join="member" expected="member" id="de2a634c-e405-42bb-9df2-292e36ad5970" crm-debug-origin="do_lrm_query">
+ <transient_attributes id="de2a634c-e405-42bb-9df2-292e36ad5970">
+ <instance_attributes id="status-de2a634c-e405-42bb-9df2-292e36ad5970">
+ <attributes>
+ <nvpair id="status-de2a634c-e405-42bb-9df2-292e36ad5970-probe_complete" name="probe_complete" value="true"/>
+ </attributes>
+ </instance_attributes>
+ </transient_attributes>
+ <lrm id="de2a634c-e405-42bb-9df2-292e36ad5970">
+ <lrm_resources>
+ <lrm_resource id="resource_IP2" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_IP2_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="9:74:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;9:74:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="34" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="368d7680070c38f8f2f40ddf5a434d45"/>
+ </lrm_resource>
+ <lrm_resource id="Apache_IP" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="Apache_IP_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="8:26:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;8:26:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="4" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="a3558b7ea398267ef1ea56b21f5d840a"/>
+ </lrm_resource>
+ <lrm_resource id="resource_IP3" type="IPaddr" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_IP3_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="9:75:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;9:75:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="35" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="87f29a4a3d4a9a7ad6eadc46f37c1f64"/>
+ </lrm_resource>
+ <lrm_resource id="Apache" type="apache13" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="Apache_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="9:26:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:1;9:26:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="5" crm_feature_set="2.0" rc_code="1" op_status="4" interval="0" op_digest="353bb677b42be27312c9f093a30268be"/>
+ <lrm_rsc_op id="Apache_stop_0" operation="stop" crm-debug-origin="build_active_RAs" transition_key="1:27:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="0:0;1:27:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="6" crm_feature_set="2.0" rc_code="0" op_status="0" interval="0" op_digest="353bb677b42be27312c9f093a30268be"/>
+ </lrm_resource>
+ <lrm_resource id="resource_dummyweb" type="Dummy" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_dummyweb_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="9:83:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;9:83:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="37" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ </lrm_resource>
+ <lrm_resource id="resource_dummy" type="Dummy" class="ocf" provider="heartbeat">
+ <lrm_rsc_op id="resource_dummy_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" transition_key="9:79:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" transition_magic="4:7;9:79:33f424d2-dbce-4c8b-a19c-ce4da566c9d7" call_id="36" crm_feature_set="2.0" rc_code="7" op_status="4" interval="0" op_digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+ </lrm_resource>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ </status>
+ </cib>
+
diff --git a/crm/pengine/testcases/coloc-group.dot b/crm/pengine/testcases/coloc-group.dot
index f3562e2088..38648c3f56 100644
--- a/crm/pengine/testcases/coloc-group.dot
+++ b/crm/pengine/testcases/coloc-group.dot
@@ -1,42 +1,42 @@
digraph "g" {
-"group1_running_0" [ style=bold color="green" fontcolor="orange" ]
-"group1_start_0" -> "group1_running_0" [ style = bold]
+"group1_running_0" [ style=dashed color="red" fontcolor="orange" ]
+"group1_start_0" -> "group1_running_0" [ style = dashed]
"group1_start_0" -> "rsc2_start_0 node2" [ style = bold]
"group1_start_0" [ style=bold color="green" fontcolor="orange" ]
"probe_complete node1" -> "probe_complete" [ style = bold]
"probe_complete node1" [ style=bold color="green" fontcolor="black" ]
"probe_complete node2" -> "probe_complete" [ style = bold]
"probe_complete node2" [ style=bold color="green" fontcolor="black" ]
"probe_complete node3" -> "probe_complete" [ style = bold]
"probe_complete node3" [ style=bold color="green" fontcolor="black" ]
"probe_complete" -> "group1_start_0" [ style = bold]
"probe_complete" -> "rsc1_start_0 node2" [ style = bold]
"probe_complete" [ style=bold color="green" fontcolor="orange" ]
"rsc1_monitor_0 node1" -> "probe_complete node1" [ style = bold]
"rsc1_monitor_0 node1" [ style=bold color="green" fontcolor="black" ]
"rsc1_monitor_0 node2" -> "probe_complete node2" [ style = bold]
"rsc1_monitor_0 node2" [ style=bold color="green" fontcolor="black" ]
"rsc1_monitor_0 node3" -> "probe_complete node3" [ style = bold]
"rsc1_monitor_0 node3" [ style=bold color="green" fontcolor="black" ]
"rsc1_start_0 node2" [ style=bold color="green" fontcolor="black" ]
"rsc2_monitor_0 node2" -> "probe_complete node2" [ style = bold]
"rsc2_monitor_0 node2" [ style=bold color="green" fontcolor="black" ]
-"rsc2_start_0 node2" -> "group1_running_0" [ style = bold]
+"rsc2_start_0 node2" -> "group1_running_0" [ style = dashed]
"rsc2_start_0 node2" -> "rsc3_start_0 <none>" [ style = dashed]
"rsc2_start_0 node2" [ style=bold color="green" fontcolor="black" ]
"rsc3_monitor_0 node1" -> "probe_complete node1" [ style = bold]
"rsc3_monitor_0 node1" [ style=bold color="green" fontcolor="black" ]
"rsc3_monitor_0 node3" -> "probe_complete node3" [ style = bold]
"rsc3_monitor_0 node3" [ style=bold color="green" fontcolor="black" ]
"rsc3_start_0 <none>" -> "group1_running_0" [ style = dashed]
"rsc3_start_0 <none>" -> "rsc4_start_0 <none>" [ style = dashed]
"rsc3_start_0 <none>" [ style=dashed color="red" fontcolor="black" ]
"rsc4_monitor_0 node1" -> "probe_complete node1" [ style = bold]
"rsc4_monitor_0 node1" [ style=bold color="green" fontcolor="black" ]
"rsc4_monitor_0 node2" -> "probe_complete node2" [ style = bold]
"rsc4_monitor_0 node2" [ style=bold color="green" fontcolor="black" ]
"rsc4_monitor_0 node3" -> "probe_complete node3" [ style = bold]
"rsc4_monitor_0 node3" [ style=bold color="green" fontcolor="black" ]
"rsc4_start_0 <none>" -> "group1_running_0" [ style = dashed]
"rsc4_start_0 <none>" [ style=dashed color="red" fontcolor="black" ]
}
diff --git a/crm/pengine/testcases/coloc-group.exp b/crm/pengine/testcases/coloc-group.exp
index 276d16aa02..1c442e266e 100644
--- a/crm/pengine/testcases/coloc-group.exp
+++ b/crm/pengine/testcases/coloc-group.exp
@@ -1,209 +1,194 @@
<transition_graph cluster-delay="60s" transition_id="0">
<synapse id="0">
<action_set>
<rsc_op id="3" operation="monitor" operation_key="rsc1_monitor_0" on_node="node1" on_node_uuid="node1">
<primitive id="rsc1" long-id="rsc1" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="1">
<action_set>
<rsc_op id="7" operation="monitor" operation_key="rsc1_monitor_0" on_node="node2" on_node_uuid="node2">
<primitive id="rsc1" long-id="rsc1" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="2">
<action_set>
<rsc_op id="11" operation="monitor" operation_key="rsc1_monitor_0" on_node="node3" on_node_uuid="node3">
<primitive id="rsc1" long-id="rsc1" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="3">
<action_set>
<rsc_op id="15" operation="start" operation_key="rsc1_start_0" on_node="node2" on_node_uuid="node2">
<primitive id="rsc1" long-id="rsc1" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<pseudo_event id="1" operation="probe_complete" operation_key="probe_complete"/>
</trigger>
</inputs>
</synapse>
<synapse id="4">
<action_set>
<pseudo_event id="17" operation="start" operation_key="group1_start_0">
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000"/>
</pseudo_event>
</action_set>
<inputs>
<trigger>
<pseudo_event id="1" operation="probe_complete" operation_key="probe_complete"/>
</trigger>
</inputs>
</synapse>
<synapse id="5">
- <action_set>
- <pseudo_event id="18" operation="running" operation_key="group1_running_0">
- <attributes crm_feature_set="2.0" CRM_meta_timeout="20000"/>
- </pseudo_event>
- </action_set>
- <inputs>
- <trigger>
- <rsc_op id="16" operation="start" operation_key="rsc2_start_0" on_node="node2" on_node_uuid="node2"/>
- </trigger>
- <trigger>
- <pseudo_event id="17" operation="start" operation_key="group1_start_0"/>
- </trigger>
- </inputs>
- </synapse>
- <synapse id="6">
<action_set>
<rsc_op id="8" operation="monitor" operation_key="rsc2_monitor_0" on_node="node2" on_node_uuid="node2">
<primitive id="rsc2" long-id="group1:rsc2" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
- <synapse id="7">
+ <synapse id="6">
<action_set>
<rsc_op id="16" operation="start" operation_key="rsc2_start_0" on_node="node2" on_node_uuid="node2">
<primitive id="rsc2" long-id="group1:rsc2" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<pseudo_event id="17" operation="start" operation_key="group1_start_0"/>
</trigger>
</inputs>
</synapse>
- <synapse id="8">
+ <synapse id="7">
<action_set>
<rsc_op id="4" operation="monitor" operation_key="rsc3_monitor_0" on_node="node1" on_node_uuid="node1">
<primitive id="rsc3" long-id="group1:rsc3" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
- <synapse id="9">
+ <synapse id="8">
<action_set>
<rsc_op id="12" operation="monitor" operation_key="rsc3_monitor_0" on_node="node3" on_node_uuid="node3">
<primitive id="rsc3" long-id="group1:rsc3" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
- <synapse id="10">
+ <synapse id="9">
<action_set>
<rsc_op id="5" operation="monitor" operation_key="rsc4_monitor_0" on_node="node1" on_node_uuid="node1">
<primitive id="rsc4" long-id="group1:rsc4" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
- <synapse id="11">
+ <synapse id="10">
<action_set>
<rsc_op id="9" operation="monitor" operation_key="rsc4_monitor_0" on_node="node2" on_node_uuid="node2">
<primitive id="rsc4" long-id="group1:rsc4" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
- <synapse id="12">
+ <synapse id="11">
<action_set>
<rsc_op id="13" operation="monitor" operation_key="rsc4_monitor_0" on_node="node3" on_node_uuid="node3">
<primitive id="rsc4" long-id="group1:rsc4" class="heartbeat" type="apache"/>
<attributes crm_feature_set="2.0" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
- <synapse id="13">
+ <synapse id="12">
<action_set>
<pseudo_event id="1" operation="probe_complete" operation_key="probe_complete">
<attributes crm_feature_set="2.0"/>
</pseudo_event>
</action_set>
<inputs>
<trigger>
<rsc_op id="2" operation="probe_complete" operation_key="probe_complete" on_node="node1" on_node_uuid="node1"/>
</trigger>
<trigger>
<rsc_op id="6" operation="probe_complete" operation_key="probe_complete" on_node="node2" on_node_uuid="node2"/>
</trigger>
<trigger>
<rsc_op id="10" operation="probe_complete" operation_key="probe_complete" on_node="node3" on_node_uuid="node3"/>
</trigger>
</inputs>
</synapse>
- <synapse id="14" priority="1000000">
+ <synapse id="13" priority="1000000">
<action_set>
<rsc_op id="2" operation="probe_complete" operation_key="probe_complete" on_node="node1" on_node_uuid="node1">
<attributes crm_feature_set="2.0" CRM_meta_op_no_wait="true"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<rsc_op id="3" operation="monitor" operation_key="rsc1_monitor_0" on_node="node1" on_node_uuid="node1"/>
</trigger>
<trigger>
<rsc_op id="4" operation="monitor" operation_key="rsc3_monitor_0" on_node="node1" on_node_uuid="node1"/>
</trigger>
<trigger>
<rsc_op id="5" operation="monitor" operation_key="rsc4_monitor_0" on_node="node1" on_node_uuid="node1"/>
</trigger>
</inputs>
</synapse>
- <synapse id="15" priority="1000000">
+ <synapse id="14" priority="1000000">
<action_set>
<rsc_op id="6" operation="probe_complete" operation_key="probe_complete" on_node="node2" on_node_uuid="node2">
<attributes crm_feature_set="2.0" CRM_meta_op_no_wait="true"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<rsc_op id="7" operation="monitor" operation_key="rsc1_monitor_0" on_node="node2" on_node_uuid="node2"/>
</trigger>
<trigger>
<rsc_op id="8" operation="monitor" operation_key="rsc2_monitor_0" on_node="node2" on_node_uuid="node2"/>
</trigger>
<trigger>
<rsc_op id="9" operation="monitor" operation_key="rsc4_monitor_0" on_node="node2" on_node_uuid="node2"/>
</trigger>
</inputs>
</synapse>
- <synapse id="16" priority="1000000">
+ <synapse id="15" priority="1000000">
<action_set>
<rsc_op id="10" operation="probe_complete" operation_key="probe_complete" on_node="node3" on_node_uuid="node3">
<attributes crm_feature_set="2.0" CRM_meta_op_no_wait="true"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<rsc_op id="11" operation="monitor" operation_key="rsc1_monitor_0" on_node="node3" on_node_uuid="node3"/>
</trigger>
<trigger>
<rsc_op id="12" operation="monitor" operation_key="rsc3_monitor_0" on_node="node3" on_node_uuid="node3"/>
</trigger>
<trigger>
<rsc_op id="13" operation="monitor" operation_key="rsc4_monitor_0" on_node="node3" on_node_uuid="node3"/>
</trigger>
</inputs>
</synapse>
</transition_graph>
diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h
index afdb61a8a1..8dfe27e735 100644
--- a/include/crm/pengine/status.h
+++ b/include/crm/pengine/status.h
@@ -1,223 +1,224 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PENGINE_STATUS__H
#define PENGINE_STATUS__H
#include <glib.h>
#include <crm/common/iso8601.h>
#include <crm/pengine/common.h>
typedef struct node_s node_t;
typedef struct action_s action_t;
typedef struct resource_s resource_t;
typedef enum no_quorum_policy_e {
no_quorum_freeze,
no_quorum_stop,
no_quorum_ignore
} no_quorum_policy_t;
enum node_type {
node_ping,
node_member
};
enum pe_restart {
pe_restart_restart,
pe_restart_ignore
};
typedef struct pe_working_set_s
{
crm_data_t *input;
ha_time_t *now;
/* options extracted from the input */
char *transition_idle_timeout;
char *dc_uuid;
node_t *dc_node;
gboolean have_quorum;
gboolean stonith_enabled;
const char *stonith_action;
gboolean symmetric_cluster;
gboolean is_managed_default;
gboolean start_failure_fatal;
gboolean remove_after_stop;
gboolean stop_rsc_orphans;
gboolean stop_action_orphans;
int default_resource_stickiness;
int default_resource_fail_stickiness;
no_quorum_policy_t no_quorum_policy;
GHashTable *config_hash;
GListPtr nodes;
GListPtr resources;
GListPtr placement_constraints;
GListPtr ordering_constraints;
GListPtr colocation_constraints;
GListPtr actions;
crm_data_t *failed;
/* stats */
int num_synapse;
int max_valid_nodes;
int order_id;
int action_id;
/* final output */
crm_data_t *graph;
} pe_working_set_t;
struct node_shared_s {
const char *id;
const char *uname;
gboolean online;
gboolean standby;
gboolean unclean;
gboolean shutdown;
gboolean expected_up;
gboolean is_dc;
int num_resources;
GListPtr running_rsc; /* resource_t* */
GListPtr allocated_rsc; /* resource_t* */
GHashTable *attrs; /* char* => char* */
enum node_type type;
};
struct node_s {
int weight;
gboolean fixed;
int count;
struct node_shared_s *details;
};
#include <crm/pengine/complex.h>
struct resource_s {
char *id;
char *clone_name;
char *long_name;
crm_data_t *xml;
crm_data_t *ops_xml;
resource_t *parent;
void *variant_opaque;
enum pe_obj_types variant;
resource_object_functions_t *fns;
resource_alloc_functions_t *cmds;
enum rsc_recovery_type recovery_type;
enum pe_restart restart_type;
int priority;
int stickiness;
int sort_index;
int fail_stickiness;
int effective_priority;
gboolean notify;
gboolean is_managed;
gboolean can_migrate;
gboolean starting;
gboolean stopping;
gboolean runnable;
gboolean provisional;
gboolean globally_unique;
gboolean is_allocating;
gboolean is_merging;
gboolean failed;
gboolean start_pending;
+ gboolean shutdown;
gboolean orphan;
GListPtr rsc_cons_lhs; /* rsc_colocation_t* */
GListPtr rsc_cons; /* rsc_colocation_t* */
GListPtr rsc_location; /* rsc_to_node_t* */
GListPtr actions; /* action_t* */
node_t *allocated_to;
GListPtr running_on; /* node_t* */
GListPtr known_on; /* node_t* */
GListPtr allowed_nodes; /* node_t* */
enum rsc_role_e role;
enum rsc_role_e next_role;
GHashTable *meta;
GHashTable *parameters;
GListPtr children; /* resource_t* */
};
struct action_s
{
int id;
int priority;
resource_t *rsc;
void *rsc_opaque;
node_t *node;
char *task;
char *uuid;
crm_data_t *op_entry;
gboolean pseudo;
gboolean runnable;
gboolean optional;
gboolean failure_is_fatal;
gboolean implied_by_stonith;
gboolean allow_reload_conversion;
enum rsc_start_requirement needs;
enum action_fail_response on_fail;
enum rsc_role_e fail_role;
gboolean dumped;
gboolean processed;
action_t *pre_notify;
action_t *pre_notified;
action_t *post_notify;
action_t *post_notified;
int seen_count;
GHashTable *meta;
GHashTable *extra;
GHashTable *notify_keys; /* do NOT free */
GListPtr actions_before; /* action_warpper_t* */
GListPtr actions_after; /* action_warpper_t* */
};
gboolean cluster_status(pe_working_set_t *data_set);
extern void set_working_set_defaults(pe_working_set_t *data_set);
extern void cleanup_calculations(pe_working_set_t *data_set);
extern resource_t *pe_find_resource(GListPtr rsc_list, const char *id_rh);
extern node_t *pe_find_node(GListPtr node_list, const char *uname);
extern node_t *pe_find_node_id(GListPtr node_list, const char *id);
#endif

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:07 PM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002484
Default Alt Text
(122 KB)

Event Timeline