Page MenuHomeClusterLabs Projects

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/crm/pengine/complex.c b/crm/pengine/complex.c
index 613f2d7b3c..2806a92ef8 100644
--- a/crm/pengine/complex.c
+++ b/crm/pengine/complex.c
@@ -1,418 +1,438 @@
-/* $Id: complex.c,v 1.18 2005/04/11 10:55:00 andrew Exp $ */
+/* $Id: complex.c,v 1.19 2005/04/13 08:13:26 andrew Exp $ */
/*
* 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 <pengine.h>
#include <pe_utils.h>
#include <crm/msg_xml.h>
gboolean update_node_weight(rsc_to_node_t *cons,const char *id,GListPtr nodes);
gboolean is_active(rsc_to_node_t *cons);
gboolean constraint_violated(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint);
void order_actions(action_t *lh, action_t *rh, order_constraint_t *order);
gboolean has_agent(node_t *a_node, lrm_agent_t *an_agent);
resource_object_functions_t resource_class_functions[] = {
{
native_unpack,
native_find_child,
native_num_allowed_nodes,
native_color,
native_create_actions,
native_internal_constraints,
native_agent_constraints,
native_rsc_colocation_lh,
native_rsc_colocation_rh,
native_rsc_order_lh,
native_rsc_order_rh,
native_rsc_location,
native_expand,
native_dump,
native_free
},
{
group_unpack,
group_find_child,
group_num_allowed_nodes,
group_color,
group_create_actions,
group_internal_constraints,
group_agent_constraints,
group_rsc_colocation_lh,
group_rsc_colocation_rh,
group_rsc_order_lh,
group_rsc_order_rh,
group_rsc_location,
group_expand,
group_dump,
group_free
},
{
incarnation_unpack,
incarnation_find_child,
incarnation_num_allowed_nodes,
incarnation_color,
incarnation_create_actions,
incarnation_internal_constraints,
incarnation_agent_constraints,
incarnation_rsc_colocation_lh,
incarnation_rsc_colocation_rh,
incarnation_rsc_order_lh,
incarnation_rsc_order_rh,
incarnation_rsc_location,
incarnation_expand,
incarnation_dump,
incarnation_free
}
};
/* resource_object_functions_t resource_variants[] = resource_class_functions; */
int get_resource_type(const char *name)
{
if(safe_str_eq(name, "resource")) {
return pe_native;
} else if(safe_str_eq(name, "resource_group")) {
return pe_group;
} else if(safe_str_eq(name, XML_RSC_ATTR_INCARNATION)) {
return pe_incarnation;
}
return pe_unknown;
}
gboolean
is_active(rsc_to_node_t *cons)
{
/* todo: check constraint lifetime */
return TRUE;
}
gboolean
common_unpack(crm_data_t * xml_obj, resource_t **rsc)
{
- const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
- const char *stopfail = crm_element_value(xml_obj, XML_RSC_ATTR_STOPFAIL);
- const char *restart = crm_element_value(xml_obj, XML_RSC_ATTR_RESTART);
- const char *priority = NULL;
+ const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
+ const char *stopfail = crm_element_value(xml_obj, XML_RSC_ATTR_STOPFAIL);
+ const char *restart = crm_element_value(xml_obj, XML_RSC_ATTR_RESTART);
+ const char *multiple = crm_element_value(xml_obj, "multi_active");
+ const char *priority = NULL;
crm_xml_verbose(xml_obj, "Processing resource input...");
if(id == NULL) {
crm_err("Must specify id tag in <resource>");
return FALSE;
} else if(rsc == NULL) {
crm_err("Nowhere to unpack resource into");
return FALSE;
}
crm_malloc(*rsc, sizeof(resource_t));
if(*rsc == NULL) {
return FALSE;
}
(*rsc)->id = id;
(*rsc)->xml = xml_obj;
(*rsc)->ops_xml = find_xml_node(xml_obj, "operations", FALSE);
(*rsc)->variant = get_resource_type(crm_element_name(xml_obj));
if((*rsc)->variant == pe_unknown) {
crm_err("Unknown resource type: %s", crm_element_name(xml_obj));
crm_free(*rsc);
return FALSE;
}
(*rsc)->fns = &resource_class_functions[(*rsc)->variant];
crm_verbose("Unpacking resource...");
(*rsc)->parameters = g_hash_table_new_full(
g_str_hash,g_str_equal, g_hash_destroy_str,g_hash_destroy_str);
unpack_instance_attributes(xml_obj, (*rsc)->parameters);
priority = get_rsc_param(*rsc, XML_CIB_ATTR_PRIORITY);
(*rsc)->priority = atoi(priority?priority:"0");
(*rsc)->effective_priority = (*rsc)->priority;
(*rsc)->recovery_type = recovery_stop_start;
(*rsc)->runnable = TRUE;
(*rsc)->provisional = TRUE;
+ (*rsc)->start_pending = FALSE;
(*rsc)->starting = FALSE;
(*rsc)->stopping = FALSE;
(*rsc)->candidate_colors = NULL;
(*rsc)->rsc_cons = NULL;
(*rsc)->actions = NULL;
+ crm_debug("Options for %s", id);
if(stopfail == NULL && stonith_enabled) {
(*rsc)->stopfail_type = pesf_stonith;
+ crm_debug("\tFailed stop handling handling: fence (default)");
} else if(stopfail == NULL) {
(*rsc)->stopfail_type = pesf_block;
+ crm_debug("\tFailed stop handling handling: block (default)");
} else if(safe_str_eq(stopfail, "ignore")) {
(*rsc)->stopfail_type = pesf_ignore;
+ crm_debug("\tFailed stop handling handling: ignore");
- } else if(safe_str_eq(stopfail, XML_CIB_ATTR_STONITH)) {
+ } else if(safe_str_eq(stopfail, "fence")) {
(*rsc)->stopfail_type = pesf_stonith;
+ crm_debug("\tFailed stop handling handling: fence");
} else {
(*rsc)->stopfail_type = pesf_block;
+ crm_debug("\tFailed stop handling handling: block");
}
if(safe_str_eq(restart, "restart")) {
(*rsc)->restart_type = pe_restart_restart;
-
- } else if(safe_str_eq(restart, "recover")) {
- (*rsc)->restart_type = pe_restart_recover;
+ crm_debug("\tDependancy restart handling: restart");
} else {
(*rsc)->restart_type = pe_restart_ignore;
+ crm_debug("\tDependancy restart handling: ignore");
}
+ if(multiple == NULL || safe_str_eq(multiple, "stop_start")) {
+ (*rsc)->recovery_type = recovery_stop_start;
+ crm_debug("\tMultiple running resource recovery: stop/start");
+
+ } else if(safe_str_eq(multiple, "stop_only")) {
+ (*rsc)->recovery_type = recovery_stop_only;
+ crm_debug("\tMultiple running resource recovery: stop only");
+
+ } else {
+ (*rsc)->recovery_type = recovery_block;
+ crm_debug("\tMultiple running resource recovery: block");
+ }
+
(*rsc)->fns->unpack(*rsc);
return TRUE;
}
void
order_actions(action_t *lh_action, action_t *rh_action, order_constraint_t *order)
{
action_wrapper_t *wrapper = NULL;
GListPtr list = NULL;
- crm_verbose("%d Processing %d -> %d",
- order->id, lh_action->id, rh_action->id);
+ crm_debug("Ordering %d: Action %d before %d",
+ order?order->id:-1, lh_action->id, rh_action->id);
crm_devel_action(
print_action("LH (order_actions)", lh_action, FALSE));
crm_devel_action(
print_action("RH (order_actions)", rh_action, FALSE));
crm_malloc(wrapper, sizeof(action_wrapper_t));
if(wrapper != NULL) {
wrapper->action = rh_action;
wrapper->strength = order->strength;
list = lh_action->actions_after;
list = g_list_append(list, wrapper);
lh_action->actions_after = list;
}
crm_malloc(wrapper, sizeof(action_wrapper_t));
if(wrapper != NULL) {
wrapper->action = lh_action;
wrapper->strength = order->strength;
list = rh_action->actions_before;
list = g_list_append(list, wrapper);
rh_action->actions_before = list;
}
}
void common_dump(resource_t *rsc, const char *pre_text, gboolean details)
{
crm_devel("%s%s%s%sResource %s: (variant=%s, priority=%f)",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
rsc->provisional?"Provisional ":"",
rsc->runnable?"":"(Non-Startable) ",
rsc->id,
crm_element_name(rsc->xml),
(double)rsc->priority);
}
void common_free(resource_t *rsc)
{
if(rsc == NULL) {
return;
}
crm_trace("Freeing %s", rsc->id);
while(rsc->rsc_cons) {
pe_free_rsc_colocation(
(rsc_colocation_t*)rsc->rsc_cons->data);
rsc->rsc_cons = rsc->rsc_cons->next;
}
crm_trace("Freeing constraint list");
if(rsc->rsc_cons != NULL) {
g_list_free(rsc->rsc_cons);
}
crm_trace("Freeing opaque data");
crm_free(rsc->variant_opaque);
crm_trace("Freeing resource");
crm_free(rsc);
crm_trace("Resource freed");
}
void
common_agent_constraints(
GListPtr node_list, lrm_agent_t *agent, const char *id)
{
#if 0
slist_iter(
node, node_t, node_list, lpc,
crm_trace("Checking if %s supports %s/%s (%s)",
node->details->uname,
agent->class, agent->type, agent->version);
if(has_agent(node, agent) == FALSE) {
/* remove node from contention */
crm_trace("Marking node %s unavailable for %s",
node->details->uname, id);
node->weight = -1.0;
node->fixed = TRUE;
}
);
#endif
}
gboolean
has_agent(node_t *a_node, lrm_agent_t *an_agent)
{
if(a_node == NULL || an_agent == NULL || an_agent->type == NULL) {
crm_warn("Invalid inputs");
return FALSE;
}
crm_devel("Checking %d agents on %s",
g_list_length(a_node->details->agents),
a_node->details->uname);
slist_iter(
agent, lrm_agent_t, a_node->details->agents, lpc,
crm_trace("Checking against %s/%s (%s)",
agent->class, agent->type, agent->version);
if(safe_str_eq(an_agent->type, agent->type)){
if(an_agent->class == NULL) {
return TRUE;
} else if(safe_str_eq(an_agent->class, agent->class)) {
if(compare_version(
an_agent->version, agent->version)
<= 0) {
return TRUE;
}
}
}
);
crm_verbose("%s doesnt support version %s of %s/%s",
a_node->details->uname, an_agent->version,
an_agent->class, an_agent->type);
return FALSE;
}
void
unpack_instance_attributes(crm_data_t *xml_obj, GHashTable *hash)
{
const char *name = NULL;
const char *value = NULL;
if(xml_obj == NULL) {
crm_devel("No instance attributes");
return;
}
xml_child_iter(
xml_obj, attr_set, XML_TAG_ATTR_SETS,
xml_child_iter(
attr_set, attrs, XML_TAG_ATTRS,
/* todo: check any rules */
xml_child_iter(
attrs, an_attr, XML_CIB_TAG_NVPAIR,
name = crm_element_value(
an_attr, XML_NVPAIR_ATTR_NAME);
value = crm_element_value(
an_attr, XML_NVPAIR_ATTR_VALUE);
add_hash_param(hash, name, value);
);
);
);
}
void
add_rsc_param(resource_t *rsc, const char *name, const char *value)
{
CRM_DEV_ASSERT(rsc != NULL);
if(crm_assert_failed) {
return;
}
add_hash_param(rsc->parameters, name, value);
}
void
add_hash_param(GHashTable *hash, const char *name, const char *value)
{
CRM_DEV_ASSERT(hash != NULL);
if(crm_assert_failed) {
return;
}
if(g_hash_table_lookup(hash, name) == NULL) {
crm_debug("adding: name=%s value=%s", name, value);
g_hash_table_insert(hash, crm_strdup(name), crm_strdup(value));
}
}
const char *
get_rsc_param(resource_t *rsc, const char *name)
{
CRM_DEV_ASSERT(rsc != NULL);
if(crm_assert_failed) {
return NULL;
}
return g_hash_table_lookup(rsc->parameters, name);
}
void
hash2nvpair(gpointer key, gpointer value, gpointer user_data)
{
const char *name = key;
const char *s_value = value;
crm_data_t *xml_node = user_data;
crm_data_t *xml_child = create_xml_node(xml_node, XML_CIB_TAG_NVPAIR);
set_xml_property_copy(xml_child, XML_NVPAIR_ATTR_NAME, name);
set_xml_property_copy(xml_child, XML_NVPAIR_ATTR_VALUE, s_value);
crm_debug("dumped: name=%s value=%s", name, s_value);
}
diff --git a/crm/pengine/graph.c b/crm/pengine/graph.c
index a71f7a914e..0b99e9e380 100644
--- a/crm/pengine/graph.c
+++ b/crm/pengine/graph.c
@@ -1,371 +1,356 @@
-/* $Id: graph.c,v 1.35 2005/04/11 15:31:58 andrew Exp $ */
+/* $Id: graph.c,v 1.36 2005/04/13 08:13:26 andrew Exp $ */
/*
* 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 <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 <pengine.h>
#include <pe_utils.h>
gboolean update_action(action_t *action);
gboolean
update_action_states(GListPtr actions)
{
+ crm_debug("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)
{
gboolean change = FALSE;
+ crm_debug("Processing action %d", action->id);
if(action->optional && action->runnable) {
return FALSE;
}
slist_iter(
other, action_wrapper_t, action->actions_after, lpc,
if(action->runnable == FALSE && action->optional == FALSE) {
if(other->action->runnable == FALSE) {
+ crm_debug("Action %d already un-runnable",
+ other->action->id);
continue;
- } else if (other->strength == pecs_must) {
+ } else {
change = TRUE;
other->action->runnable =FALSE;
- crm_devel_action(
- print_action("Marking unrunnable",
- other->action, FALSE);
- print_action("Reason",
- action, FALSE);
- );
+ crm_debug("Marking action %d un-runnable"
+ " because of %d",
+ other->action->id, action->id);
}
}
if(action->optional == FALSE && other->action->optional) {
switch(action->rsc->restart_type) {
case pe_restart_ignore:
break;
- case pe_restart_recover:
- crm_err("Recover after dependancy "
- "restart not supported... "
- "forcing a restart");
- /* keep going */
case pe_restart_restart:
change = TRUE;
other->action->optional = FALSE;
- crm_devel_action(
- print_action("Marking manditory",
- other->action, FALSE));
+ crm_debug("Marking action %d manditory because of %d",
+ other->action->id, action->id);
}
}
if(change) {
update_action(other->action);
}
);
return change;
}
gboolean
shutdown_constraints(
node_t *node, action_t *shutdown_op, GListPtr *ordering_constraints)
{
/* 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,
order_new(rsc, stop_rsc, NULL,
NULL, shutdown_crm, shutdown_op,
pecs_must, ordering_constraints);
);
return TRUE;
}
gboolean
stonith_constraints(node_t *node,
action_t *stonith_op, action_t *shutdown_op,
GListPtr *ordering_constraints)
{
GListPtr stop_actions = NULL;
if(shutdown_op != NULL) {
/* stop everything we can via shutdown_constraints() and then
* shoot the node... the shutdown has been superceeded
*/
shutdown_op->pseudo = TRUE;
+ shutdown_op->runnable = TRUE;
/* shutdown before stonith */
/* Give any resources a chance to shutdown normally */
crm_devel("Adding shutdown (%d) as an input to stonith (%d)",
shutdown_op->id, stonith_op->id);
order_new(NULL, shutdown_crm, shutdown_op,
NULL, stonith_node, stonith_op,
pecs_must, ordering_constraints);
}
/* add the stonith OP to the before lists so it counts as a pre-req */
slist_iter(
rsc, resource_t, node->details->running_rsc, lpc,
if(stonith_op != NULL) {
stop_actions = find_actions(rsc->actions,stop_rsc,node);
slist_iter(
action, action_t, stop_actions, lpc2,
- if(node->details->unclean || rsc->unclean) {
+ if(node->details->online == FALSE
+ || rsc->unclean) {
/* the stop would never complete and is
* now implied by the stonith operation
*/
action->pseudo = TRUE;
+ action->runnable = TRUE;
order_new(NULL,stonith_node,stonith_op,
rsc, stop_rsc, NULL,
pecs_must, ordering_constraints);
} else {
/* stop healthy resources before the
* stonith op
*/
order_new(rsc, stop_rsc, NULL,
NULL,stonith_node,stonith_op,
pecs_must, ordering_constraints);
}
);
crm_devel("Adding stonith (%d) as an input to stop",
stonith_op->id);
} else if((rsc->unclean || node->details->unclean)
&& rsc->stopfail_type == pesf_block) {
/* depend on the stop action which will fail */
crm_err("SHARED RESOURCE %s WILL REMAIN BLOCKED"
- " UNTIL CLEANED UP MANUALLY ON NODE %s",
- rsc->id, node->details->uname);
+ " ON NODE %s UNTIL %s",
+ rsc->id, node->details->uname,
+ stonith_enabled?"QUORUM RETURNS":"CLEANED UP MANUALLY");
continue;
} else if((rsc->unclean || node->details->unclean)
&& rsc->stopfail_type == pesf_ignore) {
/* nothing to do here */
crm_err("SHARED RESOURCE %s IS NOT PROTECTED",
rsc->id);
continue;
}
);
return TRUE;
}
crm_data_t *
action2xml(action_t *action, gboolean as_input)
{
crm_data_t * action_xml = NULL;
crm_data_t * args_xml = NULL;
if(action == NULL) {
return NULL;
}
crm_devel("Dumping action %d as XML", action->id);
switch(action->task) {
case stonith_node:
case shutdown_crm:
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
set_xml_property_copy(
action_xml, XML_ATTR_ID, crm_itoa(action->id));
set_xml_property_copy(action_xml, XML_LRM_ATTR_TASK,
task2text(action->task));
break;
default:
if(action->pseudo) {
action_xml = create_xml_node(NULL,XML_GRAPH_TAG_PSEUDO_EVENT);
} else {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
}
if(!as_input && action->rsc != NULL) {
crm_data_t *rsc_xml = create_xml_node(
action_xml, crm_element_name(action->rsc->xml));
copy_in_properties(rsc_xml, action->rsc->xml);
}
set_xml_property_copy(
action_xml, XML_ATTR_ID, crm_itoa(action->id));
if(safe_val3(NULL, action, rsc, id) != NULL) {
set_xml_property_copy(
action_xml, XML_LRM_ATTR_RSCID,
safe_val3(NULL, action, rsc, id));
}
set_xml_property_copy(action_xml, XML_LRM_ATTR_TASK,
task2text(action->task));
break;
}
if(action->task != stonith_node
&& (action->pseudo == FALSE || action->node != NULL)) {
const char *default_value = NULL;
if(as_input) {
default_value = "__none__";
}
set_xml_property_copy(
action_xml, XML_LRM_ATTR_TARGET,
safe_val4(default_value, action, node, details,uname));
set_xml_property_copy(
action_xml, XML_LRM_ATTR_TARGET_UUID,
safe_val4(default_value, action, node, details, id));
CRM_DEV_ASSERT(NULL != crm_element_value(
action_xml, XML_LRM_ATTR_TARGET));
CRM_DEV_ASSERT(NULL != crm_element_value(
action_xml, XML_LRM_ATTR_TARGET_UUID));
}
set_xml_property_copy(
action_xml, "allow_fail",
action->failure_is_fatal?XML_BOOLEAN_FALSE:XML_BOOLEAN_TRUE);
if(as_input) {
return action_xml;
}
args_xml = create_xml_node(action_xml, XML_TAG_ATTRS);
g_hash_table_foreach(action->extra, hash2nvpair, args_xml);
if(action->rsc != NULL) {
g_hash_table_foreach(
action->rsc->parameters, hash2nvpair, args_xml);
}
crm_xml_debug(args_xml, "copied in extra attributes");
return action_xml;
}
void
graph_element_from_action(action_t *action, crm_data_t * *graph)
{
char *syn_id = NULL;
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(action == NULL) {
crm_err("Cannot dump NULL action");
return;
} else if(action->optional) {
crm_trace("action %d was optional", action->id);
return;
- } else if(action->runnable == FALSE) {
+ } else if(action->pseudo == FALSE && action->runnable == FALSE) {
crm_trace("action %d was not runnable", action->id);
return;
} else if(action->dumped) {
crm_trace("action %d was already dumped", action->id);
return;
- } else if(action->discard) {
- crm_trace("action %d was discarded", action->id);
- return;
-
- } else if(action->pseudo == FALSE && action->node == NULL) {
- crm_err("action %d was not allocated", action->id);
- return;
-
- } else if(action->pseudo == FALSE
- && action->node->details->online == FALSE) {
- crm_err("action %d was scheduled for offline node", action->id);
- return;
+ } else if(action->pseudo
+ || action->task == stonith_node
+ || action->task == shutdown_crm) {
+ /* skip the next check */
+
+ } else {
+ if(action->node == NULL) {
+ crm_err("action %d was not allocated", action->id);
+ return;
+
+ } else if(action->node->details->online == FALSE) {
+ crm_err("action %d was scheduled for offline node", action->id);
+ return;
+ }
}
action->dumped = TRUE;
syn = create_xml_node(*graph, "synapse");
set = create_xml_node(syn, "action_set");
in = create_xml_node(syn, "inputs");
syn_id = crm_itoa(num_synapse++);
set_xml_property_copy(syn, XML_ATTR_ID, syn_id);
crm_free(syn_id);
xml_action = action2xml(action, FALSE);
add_node_copy(set, xml_action);
slist_iter(wrapper,action_wrapper_t,action->actions_before,lpc,
if(wrapper->action->optional == TRUE) {
- continue;
-
- } else if(wrapper->action->discard == TRUE) {
+ crm_debug("Input %d optional", wrapper->action->id);
continue;
}
- switch(wrapper->strength) {
- case pecs_must_not:
- case pecs_ignore:
- /* ignore both */
- break;
- case pecs_startstop:
- if(wrapper->action->runnable == FALSE){
- break;
- }
- /* keep going */
- case pecs_must:
- input = create_xml_node(in, "trigger");
-
- xml_action = action2xml(
- wrapper->action, TRUE);
- add_node_copy(input, xml_action);
- break;
- }
+ input = create_xml_node(in, "trigger");
+
+ xml_action = action2xml(wrapper->action, TRUE);
+ add_node_copy(input, xml_action);
);
free_xml(xml_action);
}
diff --git a/crm/pengine/native.c b/crm/pengine/native.c
index 3c787d2077..49ec7b4dbb 100644
--- a/crm/pengine/native.c
+++ b/crm/pengine/native.c
@@ -1,1144 +1,1153 @@
-/* $Id: native.c,v 1.25 2005/04/11 15:34:12 andrew Exp $ */
+/* $Id: native.c,v 1.26 2005/04/13 08:13:26 andrew Exp $ */
/*
* 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 <pengine.h>
#include <pe_utils.h>
#include <crm/msg_xml.h>
extern color_t *add_color(resource_t *rh_resource, color_t *color);
gboolean native_choose_color(resource_t *lh_resource);
void native_assign_color(resource_t *rsc, color_t *color);
void native_update_node_weight(resource_t *rsc, rsc_to_node_t *cons,
const char *id, GListPtr nodes);
void native_rsc_colocation_rh_must(resource_t *rsc_lh, gboolean update_lh,
resource_t *rsc_rh, gboolean update_rh);
void native_rsc_colocation_rh_mustnot(resource_t *rsc_lh, gboolean update_lh,
resource_t *rsc_rh, gboolean update_rh);
void filter_nodes(resource_t *rsc);
int num_allowed_nodes4color(color_t *color);
void create_monitor_actions(resource_t *rsc, action_t *start, node_t *node,
GListPtr *ordering_constraints);
typedef struct native_variant_data_s
{
lrm_agent_t *agent;
GListPtr running_on; /* node_t* */
color_t *color;
GListPtr node_cons; /* rsc_to_node_t* */
GListPtr allowed_nodes; /* node_t* */
} native_variant_data_t;
#define get_native_variant_data(data, rsc) \
CRM_ASSERT(rsc->variant == pe_native); \
CRM_ASSERT(rsc->variant_opaque != NULL); \
data = (native_variant_data_t *)rsc->variant_opaque;
void
native_add_running(resource_t *rsc, node_t *node)
{
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
native_data->running_on = g_list_append(native_data->running_on, node);
if(g_list_length(native_data->running_on) > 1) {
crm_warn("Resource %s is (potentially) active on %d nodes."
" Latest: %s", rsc->id,
g_list_length(native_data->running_on),
node->details->id);
}
}
void native_unpack(resource_t *rsc)
{
crm_data_t * xml_obj = rsc->xml;
native_variant_data_t *native_data = NULL;
const char *version = crm_element_value(xml_obj, XML_ATTR_VERSION);
crm_verbose("Processing resource %s...", rsc->id);
crm_malloc(native_data, sizeof(native_variant_data_t));
crm_malloc(native_data->agent, sizeof(lrm_agent_t));
native_data->agent->class = crm_element_value(xml_obj, "class");
native_data->agent->type = crm_element_value(xml_obj, "type");
native_data->agent->version = version?version:"0.0";
native_data->color = NULL;
native_data->allowed_nodes = NULL;
native_data->node_cons = NULL;
native_data->running_on = NULL;
rsc->variant_opaque = native_data;
}
resource_t *
native_find_child(resource_t *rsc, const char *id)
{
return NULL;
}
int native_num_allowed_nodes(resource_t *rsc)
{
int num_nodes = 0;
native_variant_data_t *native_data = NULL;
if(rsc->variant == pe_native) {
native_data = (native_variant_data_t *)rsc->variant_opaque;
} else {
crm_err("Resource %s was not a \"native\" variant",
rsc->id);
return 0;
}
if(native_data->color) {
return num_allowed_nodes4color(native_data->color);
} else if(rsc->candidate_colors) {
/* TODO: sort colors first */
color_t *color = g_list_nth_data(rsc->candidate_colors, 0);
return num_allowed_nodes4color(color);
} else {
slist_iter(
this_node, node_t, native_data->allowed_nodes, lpc,
if(this_node->weight < 0) {
continue;
}
num_nodes++;
);
}
return num_nodes;
}
int num_allowed_nodes4color(color_t *color)
{
int num_nodes = 0;
if(color->details->pending == FALSE) {
if(color->details->chosen_node) {
return 1;
}
return 0;
}
slist_iter(
this_node, node_t, color->details->candidate_nodes, lpc,
if(this_node->weight < 0) {
continue;
}
num_nodes++;
);
return num_nodes;
}
void native_color(resource_t *rsc, GListPtr *colors)
{
color_t *new_color = NULL;
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
if( native_choose_color(rsc) ) {
crm_verbose("Colored resource %s with color %d",
rsc->id, native_data->color->id);
} else {
if(native_data->allowed_nodes != NULL) {
/* filter out nodes with a negative weight */
filter_nodes(rsc);
new_color = create_color(
colors, rsc, native_data->allowed_nodes);
native_assign_color(rsc, new_color);
}
if(new_color == NULL) {
crm_warn("Resource %s cannot run anywhere", rsc->id);
print_resource("ERROR: No color", rsc, FALSE);
native_assign_color(rsc, no_color);
}
}
rsc->provisional = FALSE;
-
}
void
create_monitor_actions(resource_t *rsc, action_t *start, node_t *node,
GListPtr *ordering_constraints)
{
action_t *mon = NULL;
xml_child_iter(
rsc->ops_xml, operation, "op",
if(safe_str_neq(
crm_element_value(operation, "name"), CRMD_RSCSTATE_MON)) {
continue;
}
mon = action_new(rsc, monitor_rsc,
crm_element_value(operation, "timeout"), node);
add_hash_param(mon->extra, "interval",
crm_element_value(operation, "interval"));
unpack_instance_attributes(operation, mon->extra);
- order_new(NULL, start_rsc, start, NULL, monitor_rsc, mon,
- pecs_must, ordering_constraints);
+ if(start != NULL) {
+ order_new(NULL, start_rsc, start,
+ NULL, monitor_rsc, mon,
+ pecs_must, ordering_constraints);
+ }
);
}
void native_create_actions(resource_t *rsc, GListPtr *ordering_constraints)
{
action_t *op = NULL;
node_t *chosen = NULL;
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
if(native_data->color != NULL) {
chosen = native_data->color->details->chosen_node;
}
if(chosen != NULL && g_list_length(native_data->running_on) == 0) {
/* create start action */
op = action_new(rsc, start_rsc, NULL, chosen);
if( !have_quorum && no_quorum_policy != no_quorum_ignore) {
op->runnable = FALSE;
} else {
crm_info("Start resource %s (%s)",
rsc->id, safe_val3(
NULL, chosen, details, uname));
}
} else if(g_list_length(native_data->running_on) > 1) {
crm_info("Attempting recovery of resource %s",
rsc->id);
if(rsc->recovery_type == recovery_stop_start
|| rsc->recovery_type == recovery_stop_only) {
slist_iter(
node, node_t,
native_data->running_on, lpc,
crm_info("Stop resource %s (%s) (recovery)",
rsc->id,
safe_val3(NULL, node, details, uname));
action_new(rsc, stop_rsc, NULL, node);
);
}
if(rsc->recovery_type == recovery_stop_start && chosen) {
/* if one of the "stops" is for a node outside
* our partition, then this will block anyway
*/
crm_info("Start resource %s (%s) (recovery)",
rsc->id,
safe_val3(NULL, chosen, details, uname));
op = action_new(rsc, start_rsc, NULL, chosen);
}
} else if(g_list_length(native_data->running_on) == 1) {
node_t *node = native_data->running_on->data;
crm_debug("Stop%s of %s",
chosen != NULL?" and restart":"",rsc->id);
CRM_DEV_ASSERT(node != NULL);
if(chosen != NULL && safe_str_eq(
node->details->id, chosen->details->id)) {
/* restart */
crm_info("Leave resource %s on (%s)",rsc->id,
safe_val3(NULL,chosen,details,uname));
+
+ if(rsc->start_pending) {
+ op = action_new(rsc, start_rsc, NULL, chosen);
+ }
/* in case the actions already exist */
slist_iter(
action, action_t, rsc->actions, lpc2,
if(action->task == start_rsc
- || action->task == stop_rsc){
+ && rsc->start_pending == FALSE) {
+ action->optional = TRUE;
+
+ } else if(action->task == stop_rsc){
action->optional = TRUE;
- }
+ }
);
} else if(chosen != NULL) {
/* move */
crm_info("Move resource %s (%s -> %s)", rsc->id,
safe_val3(NULL, node, details, uname),
safe_val3(NULL, chosen, details, uname));
action_new(rsc, stop_rsc, NULL, node);
op = action_new(rsc, start_rsc, NULL, chosen);
} else {
crm_info("Stop resource %s (%s)", rsc->id,
safe_val3(NULL, node, details, uname));
action_new(rsc, stop_rsc, NULL, node);
}
}
if(op != NULL && op->runnable) {
create_monitor_actions(
rsc, op, chosen, ordering_constraints);
}
}
void native_internal_constraints(resource_t *rsc, GListPtr *ordering_constraints)
{
order_new(rsc, stop_rsc, NULL, rsc, start_rsc, NULL,
pecs_startstop, ordering_constraints);
}
void native_rsc_colocation_lh(rsc_colocation_t *constraint)
{
resource_t *rsc = constraint->rsc_lh;
if(rsc == NULL) {
crm_err("rsc_lh was NULL for %s", constraint->id);
return;
} else if(constraint->rsc_rh == NULL) {
crm_err("rsc_rh was NULL for %s", constraint->id);
return;
} else {
crm_devel("Processing constraints from %s", rsc->id);
}
constraint->rsc_rh->fns->rsc_colocation_rh(rsc, constraint);
}
void native_rsc_colocation_rh(resource_t *rsc, rsc_colocation_t *constraint)
{
gboolean do_check = FALSE;
gboolean update_lh = FALSE;
gboolean update_rh = FALSE;
resource_t *rsc_lh = rsc;
resource_t *rsc_rh = constraint->rsc_rh;
native_variant_data_t *native_data_lh = NULL;
native_variant_data_t *native_data_rh = NULL;
get_native_variant_data(native_data_lh, rsc_lh);
get_native_variant_data(native_data_rh, rsc_rh);
crm_verbose("Processing RH of constraint %s", constraint->id);
crm_devel_action(print_resource("LHS", rsc_lh, TRUE));
crm_devel_action(print_resource("RHS", rsc_rh, TRUE));
if(constraint->strength == pecs_ignore
|| constraint->strength == pecs_startstop){
crm_devel("Skipping constraint type %d", constraint->strength);
return;
}
if(rsc_lh->provisional && rsc_rh->provisional) {
if(constraint->strength == pecs_must) {
/* update effective_priorities */
native_rsc_colocation_rh_must(
rsc_lh, update_lh, rsc_rh, update_rh);
} else {
/* nothing */
crm_devel(
"Skipping constraint, both sides provisional");
}
return;
} else if( (!rsc_lh->provisional) && (!rsc_rh->provisional)
&& (!native_data_lh->color->details->pending)
&& (!native_data_rh->color->details->pending) ) {
/* error check */
do_check = TRUE;
if(rsc_lh->effective_priority < rsc_rh->effective_priority) {
update_lh = TRUE;
} else if(rsc_lh->effective_priority
> rsc_rh->effective_priority) {
update_rh = TRUE;
} else {
update_lh = TRUE;
update_rh = TRUE;
}
} else if(rsc_lh->provisional == FALSE
&& native_data_lh->color->details->pending == FALSE) {
/* update _them_ : postproc color version */
update_rh = TRUE;
} else if(rsc_rh->provisional == FALSE
&& native_data_rh->color->details->pending == FALSE) {
/* update _us_ : postproc color alt version */
update_lh = TRUE;
} else if(rsc_lh->provisional == FALSE) {
/* update _them_ : preproc version */
update_rh = TRUE;
} else if(rsc_rh->provisional == FALSE) {
/* update _us_ : postproc version */
update_lh = TRUE;
} else {
crm_warn("Un-expected combination of inputs");
return;
}
if(update_lh) {
crm_devel("Updating LHS");
}
if(update_rh) {
crm_devel("Updating RHS");
}
if(do_check) {
if(native_constraint_violated(
rsc_lh, rsc_rh, constraint) == FALSE) {
crm_devel("Constraint satisfied");
return;
}
/* else constraint cant be satisified */
crm_warn("Constraint %s could not be satisfied",
constraint->id);
if(update_lh) {
crm_warn("Marking resource %s unrunnable as a result",
rsc_lh->id);
rsc_lh->runnable = FALSE;
}
if(update_rh) {
crm_warn("Marking resource %s unrunnable as a result",
rsc_rh->id);
rsc_rh->runnable = FALSE;
}
}
if(constraint->strength == pecs_must) {
native_rsc_colocation_rh_must(
rsc_lh, update_lh, rsc_rh, update_rh);
return;
} else if(constraint->strength != pecs_must_not) {
/* unknown type */
crm_err("Unknown constraint type %d", constraint->strength);
return;
}
native_rsc_colocation_rh_mustnot(rsc_lh, update_lh,rsc_rh, update_rh);
}
void native_rsc_order_lh(resource_t *lh_rsc, order_constraint_t *order)
{
GListPtr lh_actions = NULL;
action_t *lh_action = order->lh_action;
crm_verbose("Processing LH of ordering constraint %d", order->id);
switch(order->lh_action_task) {
case start_rsc:
case started_rsc:
case stop_rsc:
case stopped_rsc:
break;
default:
crm_err("Task \"%s\" from ordering %d isnt a resource action",
task2text(order->lh_action_task), order->id);
return;
}
if(lh_action != NULL) {
lh_actions = g_list_append(NULL, lh_action);
} else if(lh_action == NULL && lh_rsc != NULL) {
if(order->strength == pecs_must) {
crm_devel("No LH-Side (%s/%s) found for constraint..."
" creating",
lh_rsc->id, task2text(order->lh_action_task));
action_new(lh_rsc, order->lh_action_task, NULL, NULL);
}
lh_actions = find_actions(
lh_rsc->actions, order->lh_action_task, NULL);
if(lh_actions == NULL) {
crm_devel("No LH-Side (%s/%s) found for constraint",
lh_rsc->id, task2text(order->lh_action_task));
crm_devel("RH-Side was: (%s/%s)",
order->rh_rsc?order->rh_rsc->id:order->rh_action?order->rh_action->rsc->id:"<NULL>",
task2text(order->rh_action_task));
return;
}
} else {
crm_warn("No LH-Side (%s) specified for constraint",
task2text(order->lh_action_task));
crm_devel("RH-Side was: (%s/%s)",
order->rh_rsc?order->rh_rsc->id:order->rh_action?order->rh_action->rsc->id:"<NULL>",
task2text(order->rh_action_task));
return;
}
slist_iter(
lh_action_iter, action_t, lh_actions, lpc,
resource_t *rh_rsc = order->rh_rsc;
if(rh_rsc == NULL && order->rh_action) {
rh_rsc = order->rh_action->rsc;
}
if(rh_rsc) {
rh_rsc->fns->rsc_order_rh(
lh_action_iter, rh_rsc, order);
} else if(order->rh_action) {
order_actions(lh_action_iter, order->rh_action, order);
}
);
pe_free_shallow_adv(lh_actions, FALSE);
}
void native_rsc_order_rh(
action_t *lh_action, resource_t *rsc, order_constraint_t *order)
{
GListPtr rh_actions = NULL;
action_t *rh_action = order->rh_action;
crm_verbose("Processing RH of ordering constraint %d", order->id);
switch(order->rh_action_task) {
case start_rsc:
case started_rsc:
case stop_rsc:
case stopped_rsc:
case monitor_rsc:
break;
default:
crm_err("Task \"%s\" from ordering %d isnt a resource action",
task2text(order->rh_action_task), order->id);
return;
}
if(rh_action != NULL) {
rh_actions = g_list_append(NULL, rh_action);
} else if(rh_action == NULL && rsc != NULL) {
rh_actions = find_actions(
rsc->actions, order->rh_action_task, NULL);
if(rh_actions == NULL) {
crm_devel("No RH-Side (%s/%s) found for constraint..."
" ignoring",
rsc->id, task2text(order->rh_action_task));
crm_devel("LH-Side was: (%s/%s)",
order->lh_rsc?order->lh_rsc->id:order->lh_action?order->lh_action->rsc->id:"<NULL>",
task2text(order->lh_action_task));
return;
}
} else if(rh_action == NULL) {
crm_devel("No RH-Side (%s) specified for constraint..."
" ignoring", task2text(order->rh_action_task));
crm_devel("LH-Side was: (%s/%s)",
order->lh_rsc?order->lh_rsc->id:order->lh_action?order->lh_action->rsc->id:"<NULL>",
task2text(order->lh_action_task));
return;
}
slist_iter(
rh_action_iter, action_t, rh_actions, lpc,
order_actions(lh_action, rh_action_iter, order);
);
pe_free_shallow_adv(rh_actions, FALSE);
}
void native_rsc_location(resource_t *rsc, rsc_to_node_t *constraint)
{
GListPtr or_list;
native_variant_data_t *native_data = NULL;
crm_devel_action(print_rsc_to_node("Applying", constraint, FALSE));
/* take "lifetime" into account */
if(constraint == NULL) {
crm_err("Constraint is NULL");
return;
} else if(is_active(constraint) == FALSE) {
crm_debug("Constraint (%s) is not active", constraint->id);
return;
} else if(rsc == NULL) {
crm_err("LHS of rsc_to_node (%s) is NULL", constraint->id);
return;
}
get_native_variant_data(native_data, rsc);
native_data->node_cons =
g_list_append(native_data->node_cons, constraint);
if(constraint->node_list_rh == NULL) {
crm_debug("RHS of constraint %s is NULL", constraint->id);
return;
}
crm_devel_action(print_resource("before update", rsc,TRUE));
or_list = node_list_or(
native_data->allowed_nodes, constraint->node_list_rh, FALSE);
pe_free_shallow(native_data->allowed_nodes);
native_data->allowed_nodes = or_list;
slist_iter(node_rh, node_t, constraint->node_list_rh, lpc,
native_update_node_weight(
rsc, constraint, node_rh->details->uname,
native_data->allowed_nodes));
crm_devel_action(print_resource("after update", rsc, TRUE));
}
void native_expand(resource_t *rsc, crm_data_t * *graph)
{
slist_iter(
action, action_t, rsc->actions, lpc,
crm_devel("processing action %d for rsc=%s",
action->id, rsc->id);
graph_element_from_action(action, graph);
);
}
void native_dump(resource_t *rsc, const char *pre_text, gboolean details)
{
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
common_dump(rsc, pre_text, details);
crm_devel("\t%d candidate colors, %d allowed nodes,"
" %d rsc_cons and %d node_cons",
g_list_length(rsc->candidate_colors),
g_list_length(native_data->allowed_nodes),
g_list_length(rsc->rsc_cons),
g_list_length(native_data->node_cons));
if(details) {
crm_devel("\t=== Actions");
slist_iter(
action, action_t, rsc->actions, lpc,
print_action("\trsc action: ", action, FALSE);
);
crm_devel("\t=== Colors");
slist_iter(
color, color_t, rsc->candidate_colors, lpc,
print_color("\t", color, FALSE)
);
crm_devel("\t=== Allowed Nodes");
slist_iter(
node, node_t, native_data->allowed_nodes, lpc,
print_node("\t", node, FALSE);
);
}
}
void native_free(resource_t *rsc)
{
native_variant_data_t *native_data =
(native_variant_data_t *)rsc->variant_opaque;
crm_devel("Freeing Allowed Nodes");
pe_free_shallow(native_data->allowed_nodes);
common_free(rsc);
}
void native_rsc_colocation_rh_must(resource_t *rsc_lh, gboolean update_lh,
resource_t *rsc_rh, gboolean update_rh)
{
native_variant_data_t *native_data_lh = NULL;
native_variant_data_t *native_data_rh = NULL;
gboolean do_merge = FALSE;
GListPtr old_list = NULL;
GListPtr merged_node_list = NULL;
float max_pri = rsc_lh->effective_priority;
if(max_pri < rsc_rh->effective_priority) {
max_pri = rsc_rh->effective_priority;
}
rsc_lh->effective_priority = max_pri;
rsc_rh->effective_priority = max_pri;
get_native_variant_data(native_data_lh, rsc_lh);
get_native_variant_data(native_data_rh, rsc_rh);
if(native_data_lh->color && native_data_rh->color) {
do_merge = TRUE;
merged_node_list = node_list_and(
native_data_lh->color->details->candidate_nodes,
native_data_rh->color->details->candidate_nodes, TRUE);
} else if(native_data_lh->color) {
do_merge = TRUE;
merged_node_list = node_list_and(
native_data_lh->color->details->candidate_nodes,
native_data_rh->allowed_nodes, TRUE);
} else if(native_data_rh->color) {
do_merge = TRUE;
merged_node_list = node_list_and(
native_data_lh->allowed_nodes,
native_data_rh->color->details->candidate_nodes, TRUE);
}
if(update_lh) {
crm_free(native_data_lh->color);
rsc_lh->runnable = rsc_rh->runnable;
rsc_lh->provisional = rsc_rh->provisional;
native_data_lh->color = copy_color(native_data_rh->color);
}
if(update_rh) {
crm_free(native_data_rh->color);
rsc_rh->runnable = rsc_lh->runnable;
rsc_rh->provisional = rsc_lh->provisional;
native_data_rh->color = copy_color(native_data_lh->color);
}
if((update_rh || update_lh) && do_merge) {
crm_devel("Merging candidate nodes");
old_list = native_data_rh->color->details->candidate_nodes;
native_data_rh->color->details->candidate_nodes = merged_node_list;
pe_free_shallow(old_list);
}
crm_devel("Finished processing pecs_must constraint");
}
void native_rsc_colocation_rh_mustnot(resource_t *rsc_lh, gboolean update_lh,
resource_t *rsc_rh, gboolean update_rh)
{
color_t *color_lh = NULL;
color_t *color_rh = NULL;
native_variant_data_t *native_data_lh = NULL;
native_variant_data_t *native_data_rh = NULL;
get_native_variant_data(native_data_lh, rsc_lh);
get_native_variant_data(native_data_rh, rsc_rh);
crm_devel("Processing pecs_must_not constraint");
/* pecs_must_not */
if(update_lh) {
color_rh = native_data_rh->color;
if(rsc_lh->provisional) {
color_lh = find_color(
rsc_lh->candidate_colors, color_rh);
rsc_lh->candidate_colors = g_list_remove(
rsc_lh->candidate_colors, color_lh);
crm_devel_action(
print_color("Removed LH", color_lh, FALSE));
crm_devel_action(
print_resource("Modified LH", rsc_lh, TRUE));
crm_free(color_lh);
} else if(native_data_lh->color
&& native_data_lh->color->details->pending) {
node_t *node_lh = NULL;
color_lh = native_data_lh->color;
node_lh = pe_find_node(
color_lh->details->candidate_nodes,
safe_val5(NULL, color_rh, details,
chosen_node, details, uname));
color_lh->details->candidate_nodes =
g_list_remove(
color_lh->details->candidate_nodes,
node_lh);
crm_devel_action(
print_node("Removed LH", node_lh, FALSE));
crm_devel_action(
print_color("Modified LH", color_lh, FALSE));
crm_free(node_lh);
} else {
/* error, rsc marked as unrunnable above */
crm_warn("lh else");
}
}
if(update_rh) {
color_lh = native_data_lh->color;
if(rsc_rh->provisional) {
color_rh = find_color(
rsc_rh->candidate_colors, color_lh);
rsc_rh->candidate_colors = g_list_remove(
rsc_rh->candidate_colors, color_rh);
crm_devel_action(
print_color("Removed RH", color_rh, FALSE));
crm_devel_action(
print_resource("Modified RH", rsc_rh, TRUE));
crm_free(color_rh);
} else if(native_data_rh->color
&& native_data_rh->color->details->pending) {
node_t *node_rh = NULL;
color_rh = native_data_rh->color;
node_rh = pe_find_node(
color_rh->details->candidate_nodes,
safe_val5(NULL, color_lh, details,
chosen_node, details, uname));
color_rh->details->candidate_nodes =
g_list_remove(
color_rh->details->candidate_nodes,
node_rh);
crm_devel_action(
print_node("Removed RH", node_rh, FALSE));
crm_devel_action(
print_color("Modified RH", color_rh, FALSE));
crm_free(node_rh);
} else {
/* error, rsc marked as unrunnable above */
crm_warn("rh else");
}
}
}
void
native_agent_constraints(resource_t *rsc)
{
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
crm_trace("Applying RA restrictions to %s", rsc->id);
common_agent_constraints(
native_data->allowed_nodes, native_data->agent, rsc->id);
}
gboolean
native_choose_color(resource_t *rsc)
{
GListPtr sorted_colors = NULL;
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
if(rsc->runnable == FALSE) {
native_assign_color(rsc, no_color);
}
if(rsc->provisional == FALSE) {
return !rsc->provisional;
}
sorted_colors = g_list_sort(
rsc->candidate_colors, sort_color_weight);
rsc->candidate_colors = sorted_colors;
crm_verbose("Choose a color from %d possibilities",
g_list_length(sorted_colors));
slist_iter(
this_color, color_t, rsc->candidate_colors, lpc,
GListPtr intersection = NULL;
GListPtr minus = NULL;
int len = 0;
if(this_color == NULL) {
crm_err("color was NULL");
continue;
} else if(rsc->effective_priority
< this_color->details->highest_priority) {
minus = node_list_minus(
this_color->details->candidate_nodes,
native_data->allowed_nodes, TRUE);
len = g_list_length(minus);
pe_free_shallow(minus);
if(len > 0) {
native_assign_color(rsc, this_color);
break;
}
} else {
intersection = node_list_and(
this_color->details->candidate_nodes,
native_data->allowed_nodes, TRUE);
len = g_list_length(intersection);
pe_free_shallow(intersection);
if(len != 0) {
native_assign_color(rsc, this_color);
break;
}
}
);
return !rsc->provisional;
}
void
native_assign_color(resource_t *rsc, color_t *color)
{
color_t *local_color = add_color(rsc, color);
GListPtr intersection = NULL;
GListPtr old_list = NULL;
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
native_data->color = local_color;
rsc->provisional = FALSE;
if(local_color != NULL) {
(local_color->details->num_resources)++;
local_color->details->allocated_resources =
g_list_append(
local_color->details->allocated_resources,rsc);
intersection = node_list_and(
local_color->details->candidate_nodes,
native_data->allowed_nodes, TRUE);
old_list = local_color->details->candidate_nodes;
pe_free_shallow(old_list);
local_color->details->candidate_nodes = intersection;
crm_verbose("Colored resource %s with new color %d",
rsc->id, native_data->color->id);
crm_devel_action(
print_resource("Colored Resource", rsc, TRUE));
} else {
crm_err("local color was NULL");
}
return;
}
void
native_update_node_weight(resource_t *rsc, rsc_to_node_t *cons,
const char *id, GListPtr nodes)
{
node_t *node_rh = NULL;
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
node_rh = pe_find_node(native_data->allowed_nodes, id);
if(node_rh == NULL) {
crm_err("Node not found - cant update");
return;
}
if(node_rh->weight >= INFINITY && cons->weight == -INFINITY) {
crm_err("Constraint %s mixes +/- INFINITY", cons->id);
} else if(node_rh->weight <= -INFINITY && cons->weight == INFINITY) {
crm_err("Constraint %s mixes +/- INFINITY", cons->id);
}
if(node_rh->fixed) {
/* warning */
crm_debug("Constraint %s is irrelevant as the"
" weight of node %s is fixed as %f.",
cons->id,
node_rh->details->uname,
node_rh->weight);
return;
}
if(cons->weight != INFINITY && cons->weight != -INFINITY) {
crm_verbose("Constraint %s (%f): node %s weight %f.",
cons->id,
cons->weight,
node_rh->details->uname,
node_rh->weight);
} else if(cons->weight == -INFINITY) {
crm_verbose("Constraint %s (-INFINITY): node %s weight %f.",
cons->id,
node_rh->details->uname,
node_rh->weight);
} else {
crm_verbose("Constraint %s (+INFINITY): node %s weight %f.",
cons->id,
node_rh->details->uname,
node_rh->weight);
}
node_rh->weight = merge_weights(node_rh->weight, cons->weight);
if(node_rh->weight < 0) {
node_rh->fixed = TRUE;
}
crm_devel_action(print_node("Updated", node_rh, FALSE));
return;
}
gboolean
native_constraint_violated(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
native_variant_data_t *native_data_lh = NULL;
native_variant_data_t *native_data_rh = NULL;
GListPtr result = NULL;
color_t *color_lh = NULL;
color_t *color_rh = NULL;
GListPtr candidate_nodes_lh = NULL;
GListPtr candidate_nodes_rh = NULL;
gboolean matched = FALSE;
get_native_variant_data(native_data_lh, rsc_lh);
get_native_variant_data(native_data_rh, rsc_rh);
color_lh = native_data_lh->color;
color_rh = native_data_rh->color;
if(constraint->strength == pecs_must_not) {
matched = TRUE;
}
if(rsc_lh->provisional || rsc_rh->provisional) {
return FALSE;
}
if(color_lh->details->pending
&& color_rh->details->pending) {
candidate_nodes_lh = color_lh->details->candidate_nodes;
candidate_nodes_rh = color_rh->details->candidate_nodes;
} else if(color_lh->details->pending == FALSE
&& color_rh->details->pending == FALSE) {
if(color_lh == NULL && color_rh == NULL) {
return matched;
} else if(color_lh == NULL || color_rh == NULL) {
return !matched;
} else if(color_lh->details->chosen_node == NULL
&& color_rh->details->chosen_node == NULL) {
return matched;
} else if(color_lh->details->chosen_node == NULL
|| color_rh->details->chosen_node == NULL) {
return !matched;
} else if(safe_str_eq(
color_lh->details->chosen_node->details->id,
color_rh->details->chosen_node->details->id)) {
return matched;
}
return !matched;
} else if(color_lh->details->pending) {
candidate_nodes_lh = color_lh->details->candidate_nodes;
candidate_nodes_rh = g_list_append(
NULL, color_rh->details->chosen_node);
} else if(color_rh->details->pending) {
candidate_nodes_rh = color_rh->details->candidate_nodes;
candidate_nodes_lh = g_list_append(
NULL, color_lh->details->chosen_node);
}
result = node_list_and(candidate_nodes_lh, candidate_nodes_rh, TRUE);
if(g_list_length(result) == 0 && constraint->strength == pecs_must) {
/* free result */
return TRUE;
}
return FALSE;
}
/*
* Remove any nodes with a -ve weight
*/
void
filter_nodes(resource_t *rsc)
{
native_variant_data_t *native_data = NULL;
get_native_variant_data(native_data, rsc);
crm_devel_action(print_resource("Filtering nodes for", rsc, FALSE));
slist_iter(
node, node_t, native_data->allowed_nodes, lpc,
if(node == NULL) {
crm_err("Invalid NULL node");
} else if(node->weight < 0.0
|| node->details->online == FALSE
|| node->details->type == node_ping) {
crm_devel_action(print_node("Removing", node, FALSE));
native_data->allowed_nodes =
g_list_remove(native_data->allowed_nodes, node);
crm_free(node);
lpc = -1; /* restart the loop */
}
);
}
diff --git a/crm/pengine/pengine.h b/crm/pengine/pengine.h
index 26dce97507..a58075e22a 100644
--- a/crm/pengine/pengine.h
+++ b/crm/pengine/pengine.h
@@ -1,348 +1,347 @@
-/* $Id: pengine.h,v 1.58 2005/04/11 15:34:12 andrew Exp $ */
+/* $Id: pengine.h,v 1.59 2005/04/13 08:13:26 andrew Exp $ */
/*
* 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 node_s node_t;
typedef struct color_s color_t;
typedef struct rsc_to_node_s rsc_to_node_t;
typedef struct rsc_colocation_s rsc_colocation_t;
typedef struct resource_s resource_t;
typedef struct lrm_agent_s lrm_agent_t;
typedef struct order_constraint_s order_constraint_t;
typedef struct action_s action_t;
typedef struct action_wrapper_s action_wrapper_t;
#include <glib.h>
#include <crm/crm.h>
#include <crm/common/msg.h>
#include <complex.h>
typedef enum no_quorum_policy_e {
no_quorum_freeze,
no_quorum_stop,
no_quorum_ignore
} no_quorum_policy_t;
enum con_type {
type_none,
rsc_colocation,
rsc_to_node,
rsc_to_attr,
base_weight
};
enum node_type {
node_ping,
node_member
};
enum con_strength {
pecs_ignore,
pecs_must,
pecs_must_not,
pecs_startstop
};
enum action_tasks {
no_action,
monitor_rsc,
stop_rsc,
stopped_rsc,
start_rsc,
started_rsc,
shutdown_crm,
stonith_node
};
enum rsc_recovery_type {
recovery_stop_start,
recovery_stop_only,
recovery_block
};
enum pe_stop_fail {
pesf_block,
pesf_stonith,
pesf_ignore
};
enum pe_restart {
pe_restart_restart,
- pe_restart_recover,
pe_restart_ignore
};
struct node_shared_s {
const char *id;
const char *uname;
gboolean online;
gboolean unclean;
gboolean shutdown;
gboolean expected_up;
gboolean is_dc;
int num_resources;
GListPtr running_rsc; /* resource_t* */
GListPtr agents; /* lrm_agent_t* */
GHashTable *attrs; /* char* => char* */
enum node_type type;
};
struct node_s {
float weight;
gboolean fixed;
struct node_shared_s *details;
};
struct color_shared_s {
int id;
float highest_priority;
GListPtr candidate_nodes; /* node_t* */
GListPtr allocated_resources; /* resources_t* */
node_t *chosen_node;
gboolean pending;
int num_resources;
};
struct color_s {
int id;
struct color_shared_s *details;
float local_weight;
};
struct rsc_colocation_s {
const char *id;
resource_t *rsc_lh;
resource_t *rsc_rh;
enum con_strength strength;
};
struct rsc_to_node_s {
const char *id;
resource_t *rsc_lh;
float weight;
GListPtr node_list_rh; /* node_t* */
};
struct lrm_agent_s {
const char *class;
const char *type;
const char *version;
};
struct resource_s {
const char *id;
crm_data_t * xml;
crm_data_t * ops_xml;
void *variant_opaque;
enum pe_obj_types variant;
resource_object_functions_t *fns;
- float priority;
- float effective_priority;
-
- gboolean starting;
- gboolean stopping;
- gboolean is_stonith;
- gboolean runnable;
- gboolean provisional;
- gboolean unclean;
-
enum rsc_recovery_type recovery_type;
enum pe_stop_fail stopfail_type;
enum pe_restart restart_type;
+ float priority;
+ float effective_priority;
+
+ gboolean start_pending;
+ gboolean starting;
+ gboolean stopping;
+ gboolean is_stonith;
+ gboolean runnable;
+ gboolean provisional;
+ gboolean unclean;
+
GListPtr candidate_colors; /* color_t* */
GListPtr rsc_cons; /* rsc_colocation_t* */
GListPtr actions; /* action_t* */
GHashTable * parameters;
};
struct action_wrapper_s
{
enum con_strength strength;
action_t *action;
};
struct action_s
{
int id;
resource_t *rsc;
void *rsc_opaque;
node_t *node;
enum action_tasks task;
gboolean pseudo;
gboolean runnable;
gboolean dumped;
gboolean processed;
gboolean optional;
- gboolean discard;
gboolean failure_is_fatal;
int seen_count;
const char *timeout;
/* crm_data_t *args; */
GHashTable *extra;
GListPtr actions_before; /* action_warpper_t* */
GListPtr actions_after; /* action_warpper_t* */
};
struct order_constraint_s
{
int id;
enum con_strength strength;
void *lh_opaque;
resource_t *lh_rsc;
action_t *lh_action;
enum action_tasks lh_action_task;
void *rh_opaque;
resource_t *rh_rsc;
action_t *rh_action;
enum action_tasks rh_action_task;
/* (soon to be) variant specific */
/* int lh_rsc_incarnation; */
/* int rh_rsc_incarnation; */
};
extern gboolean stage0(crm_data_t *cib,
GListPtr *nodes,
GListPtr *rscs,
GListPtr *cons,
GListPtr *actions, GListPtr *ordering_constraints,
GListPtr *stonith_list, GListPtr *shutdown_list);
extern gboolean stage1(GListPtr placement_constraints,
GListPtr nodes,
GListPtr resources);
extern gboolean stage2(GListPtr sorted_rscs,
GListPtr sorted_nodes,
GListPtr *colors);
extern gboolean stage3(GListPtr colors);
extern gboolean stage4(GListPtr colors);
extern gboolean stage5(GListPtr resources, GListPtr *ordering_constraints);
extern gboolean stage6(
GListPtr *actions, GListPtr *ordering_constraints,
GListPtr nodes, GListPtr resources);
extern gboolean stage7(
GListPtr resources, GListPtr actions, GListPtr ordering_constraints);
extern gboolean stage8(
GListPtr resources, GListPtr action_sets, crm_data_t **graph);
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,
GListPtr nodes, GListPtr resources,
GListPtr *placement_constraints,
GListPtr *ordering_constraints);
extern gboolean unpack_resources(crm_data_t *xml_resources,
GListPtr *resources,
GListPtr *actions,
GListPtr *ordering_constraints,
GListPtr *placement_constraints,
GListPtr all_nodes);
extern gboolean unpack_config(crm_data_t *config);
extern gboolean unpack_config(crm_data_t *config);
extern gboolean unpack_global_defaults(crm_data_t *defaults);
extern gboolean unpack_nodes(crm_data_t *xml_nodes, GListPtr *nodes);
extern gboolean unpack_status(crm_data_t *status,
GListPtr nodes,
GListPtr rsc_list,
GListPtr *actions,
GListPtr *placement_constraints);
extern gboolean apply_placement_constraints(GListPtr constraints, GListPtr nodes);
extern gboolean apply_agent_constraints(GListPtr resources);
extern void color_resource(resource_t *lh_resource,
GListPtr *colors,
GListPtr resources);
extern gboolean choose_node_from_list(color_t *color);
extern gboolean update_action_states(GListPtr actions);
extern gboolean shutdown_constraints(
node_t *node, action_t *shutdown_op, GListPtr *ordering_constraints);
extern gboolean stonith_constraints(
node_t *node, action_t *stonith_op, action_t *shutdown_op,
GListPtr *ordering_constraints);
extern gboolean order_new(
resource_t *lh_rsc, enum action_tasks lh_task, action_t *lh_action,
resource_t *rh_rsc, enum action_tasks rh_task, action_t *rh_action,
enum con_strength strength, GListPtr *ordering_constraints);
extern gboolean process_colored_constraints(resource_t *rsc);
extern void graph_element_from_action(action_t *action, crm_data_t **graph);
extern color_t *no_color;
extern int max_valid_nodes;
extern int order_id;
extern int action_id;
extern gboolean stonith_enabled;
extern gboolean have_quorum;
extern no_quorum_policy_t no_quorum_policy;
extern gboolean symmetric_cluster;
extern GListPtr agent_defaults;
extern const char* transition_timeout;
extern int num_synapse;
extern int color_id;
extern char *dc_uuid;
#endif
diff --git a/crm/pengine/regression.core.sh b/crm/pengine/regression.core.sh
index 58ca181d43..2b8206ab73 100755
--- a/crm/pengine/regression.core.sh
+++ b/crm/pengine/regression.core.sh
@@ -1,140 +1,139 @@
#!/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
#
verbose=$1
io_dir=testcases
diff_opts="--ignore-all-space -U 1 -u"
failed=.regression.failed
# zero out the error log
> $failed
function do_test {
base=$1;
name=$2;
input=$io_dir/${base}.xml
output=$io_dir/${base}.pe.out
te_output=$io_dir/${base}.te.out
expected=$io_dir/${base}.exp
te_expected=$io_dir/${base}.te.exp
if [ ! -f $input ]; then
echo "Test $name ($base)... Error ($input)";
return;
fi
if [ "$create_mode" != "true" -a ! -f $expected ]; then
echo "Test $name ($base)... Error ($expected)";
# return;
fi
./ptest -X $input 2>/dev/null > $output
if [ -s core ]; then
echo "Test $name ($base)... Moved core to core.${base}";
rm -f core.$base
mv core core.$base
return;
fi
if [ ! -s $output ]; then
echo "Test $name ($base)... Error ($output)";
rm $output
return;
fi
if [ ! -s $output ]; then
echo "Test $name ($base)... Error (fixed $output)";
rm $output
return;
fi
-# if [ "$create_mode" = "true" ]; then
- if [ "$create_mode" = "true" -a ! -f $expected ]; then
+ if [ "$create_mode" = "true" ]; then
cp "$output" "$expected"
fi
if [ -f $expected ]; then
diff $diff_opts -q $expected $output >/dev/null
rc=$?
fi
if [ "$create_mode" = "true" ]; then
echo "Test $name ($base)... Created expected output (PE)"
elif [ ! -f $expected ]; then
echo "==== Raw results for PE test ($base) ====" >> $failed
cat $output 2>/dev/null >> $failed
elif [ "$rc" = 0 ]; then
echo "Test $name ($base)... Passed (PE)";
elif [ "$rc" = 1 ]; then
echo "Test $name ($base)... * Failed (PE)";
diff $diff_opts $expected $output 2>/dev/null >> $failed
else
echo "Test $name ($base)... Error PE (diff: $rc)";
echo "==== Raw results for test ($base) ====" >> $failed
cat $output 2>/dev/null >> $failed
fi
if [ "$test_te" = "true" ]; then
../tengine/ttest -X $expected 2> $te_output
# if [ "$create_mode" = "true" ]; then
if [ "$create_mode" = "true" -a ! -f $te_expected ]; then
cp "$te_output" "$te_expected"
fi
if [ -f $te_expected ]; then
diff $diff_opts -q $te_expected $te_output >/dev/null
rc=$?
fi
if [ "$create_mode" = "true" ]; then
echo "Test $name ($base)... Created expected output (PE)"
elif [ ! -f $te_expected ]; then
echo "==== Raw results for TE test ($base) ====" >> $failed
cat $te_output 2>/dev/null >> $failed
elif [ "$rc" = 0 ]; then
echo "Test $name ($base)... Passed (TE)";
elif [ "$rc" = 1 ]; then
echo "Test $name ($base)... * Failed (TE)";
diff $diff_opts $te_expected $te_output 2>/dev/null >> $failed
else
echo "Test $name ($base)... Error TE (diff: $rc)";
echo "==== Raw results for test ($base) TE ====" >> $failed
cat $te_output 2>/dev/null >> $failed
fi
fi
rm -f $output $te_output
}
function test_results {
if [ -s $failed ]; then
if [ "$verbose" = "-v" ]; then
echo "Results of failed tests...."
less $failed
else
echo "Results of failed tests are in $failed...."
echo "Use $0 -v to display them automatically."
fi
else
rm $failed
fi
}
diff --git a/crm/pengine/regression.sh b/crm/pengine/regression.sh
index c3f4b919be..70203f82b0 100755
--- a/crm/pengine/regression.sh
+++ b/crm/pengine/regression.sh
@@ -1,129 +1,145 @@
#!/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
#
. regression.core.sh
create_mode="true"
echo Generating test outputs for these tests...
#do_test bad7
echo ""
echo Done.
echo ""
echo Performing the following tests...
create_mode="false"
-do_test simple1 "Offline "
-do_test simple2 "Start "
-do_test simple3 "Start 2 "
+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 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)"
echo ""
-do_test rsc_dep1 "Must not "
+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 (cant)"
#do_test rsc_dep2 "Should not "
-do_test rsc_dep3 "Must "
#do_test rsc_dep4 "Should "
-do_test rsc_dep5 "Must not 3 "
#do_test rsc_dep6 "Should not 3"
-do_test rsc_dep7 "Must 3 "
#do_test rsc_dep8 "Should 3 "
-do_test rsc_dep10 "Must (cant)"
#do_test rsc_dep9 "2*MustNot 1*ShouldNot"
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 order1 "Order start 1 "
+do_test order2 "Order start 2 "
+do_test order3 "Order stop "
+do_test order4 "Order (multiple) *"
#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 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 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 "
+
+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 "
echo ""
-do_test nodefail1 "Node Fail - Fence "
-do_test nodefail5 "Node Fail - Fence2Block"
-do_test nodefail4 "Node Fail - Block&Fence"
-do_test nodefail2 "Node Fail - Block "
-do_test nodefail3 "Node Fail - Ignore "
+do_test quorum-1 "No quorum - ignore"
+do_test quorum-2 "No quorum - freeze"
+do_test quorum-3 "No quorum - stop "
echo ""
-do_test stopfail1 "Stop Fail - Disabled "
-do_test stopfail9 "Stop Fail - Enabled, 1 node"
-do_test stopfail2 "Stop Fail - Enabled, 2 node"
-do_test stopfail3 "Stop Fail - Ignore (1 node)"
-do_test stopfail4 "Stop Fail - Ignore (2 node)"
-#do_test stopfail5 "Stop Fail - STONITH (pass2) "
-#do_test stopfail6 "Stop Fail - STONITH (pass3) "
-#do_test stopfail7 "Stop Fail - STONITH (should fail)"
+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"
echo ""
do_test rsc_location1 "Score (not running) "
do_test rsc_location2 "Score (running) "
do_test rsc_location3 "Score (not running/no swap)"
do_test rsc_location4 "Score (running/swap) "
do_test rsc_location5 "Score (running/swap 2) "
echo ""
do_test multi1 "Multiple Active (stop/start)"
#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 group5 "Group + Native (move) "
+do_test group6 "Group + Group (move) "
echo ""
do_test inc1 "Incarnation start "
do_test inc2 "Incarnation silent restart, stop, move "
do_test inc3 "Inter-incarnation ordering, silent restart, stop, move"
echo ""
do_test bad1 "Bad node "
do_test bad2 "Bad rsc "
do_test bad3 "No rsc class "
do_test bad4 "Bad data "
do_test bad5 "Bad data "
do_test bad6 "Bad lrm_rsc "
echo ""
test_results
diff --git a/crm/pengine/stages.c b/crm/pengine/stages.c
index 156dfef50f..1a11f9141e 100644
--- a/crm/pengine/stages.c
+++ b/crm/pengine/stages.c
@@ -1,483 +1,497 @@
-/* $Id: stages.c,v 1.52 2005/04/11 15:34:12 andrew Exp $ */
+/* $Id: stages.c,v 1.53 2005/04/13 08:13:26 andrew Exp $ */
/*
* 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 <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 <pengine.h>
#include <pe_utils.h>
node_t *choose_fencer(action_t *stonith, node_t *node, GListPtr resources);
void order_actions(action_t *lh, action_t *rh, order_constraint_t *order);
int order_id = 1;
int max_valid_nodes = 0;
GListPtr agent_defaults = NULL;
+GListPtr global_action_list = NULL;
gboolean have_quorum = FALSE;
gboolean stonith_enabled = FALSE;
gboolean symmetric_cluster = TRUE;
no_quorum_policy_t no_quorum_policy = no_quorum_freeze;
char *dc_uuid = NULL;
const char* transition_timeout = "60000"; /* 1 minute */
/*
* Unpack everything
* At the end you'll have:
* - A list of nodes
* - A list of resources (each with any dependancies on other resources)
* - A list of constraints between resources and nodes
* - A list of constraints between start/stop actions
* - A list of nodes that need to be stonith'd
* - A list of nodes that need to be shutdown
* - A list of the possible stop/start actions (without dependancies)
*/
gboolean
stage0(crm_data_t * cib,
GListPtr *resources,
GListPtr *nodes, GListPtr *placement_constraints,
GListPtr *actions, GListPtr *ordering_constraints,
GListPtr *stonith_list, GListPtr *shutdown_list)
{
/* int lpc; */
crm_data_t * cib_nodes = get_object_root(
XML_CIB_TAG_NODES, cib);
crm_data_t * cib_status = get_object_root(
XML_CIB_TAG_STATUS, cib);
crm_data_t * cib_resources = get_object_root(
XML_CIB_TAG_RESOURCES, cib);
crm_data_t * cib_constraints = get_object_root(
XML_CIB_TAG_CONSTRAINTS, cib);
crm_data_t * config = get_object_root(
XML_CIB_TAG_CRMCONFIG, cib);
crm_data_t * agent_defaults = NULL;
/*get_object_root(XML_CIB_TAG_RA_DEFAULTS, cib); */
/* reset remaining global variables */
num_synapse = 0;
max_valid_nodes = 0;
order_id = 1;
action_id = 1;
color_id = 0;
have_quorum = TRUE;
stonith_enabled = FALSE;
+ if(global_action_list != NULL) {
+ crm_verbose("deleting actions");
+ pe_free_actions(global_action_list);
+ global_action_list = NULL;
+ }
+
+
crm_free(dc_uuid); dc_uuid = NULL;
if(cib == NULL) {
return FALSE;
}
if(cib != NULL && crm_element_value(cib, XML_ATTR_DC_UUID) != NULL) {
/* this should always be present */
dc_uuid = crm_element_value_copy(cib, XML_ATTR_DC_UUID);
}
unpack_config(config);
if(no_quorum_policy != no_quorum_ignore) {
const char *value = crm_element_value(
cib, XML_ATTR_HAVE_QUORUM);
+
+ have_quorum = FALSE;
if(value != NULL) {
crm_str_to_boolean(value, &have_quorum);
}
+
if(have_quorum == FALSE) {
crm_warn("We do not have quorum"
" - fencing and resource management disabled");
}
}
unpack_global_defaults(agent_defaults);
unpack_nodes(cib_nodes, nodes);
unpack_resources(cib_resources, resources, actions,
ordering_constraints, placement_constraints, *nodes);
unpack_status(cib_status, *nodes, *resources, actions,
placement_constraints);
unpack_constraints(cib_constraints, *nodes, *resources,
placement_constraints, ordering_constraints);
return TRUE;
}
/*
* Count how many valid nodes we have (so we know the maximum number of
* colors we can resolve).
*
* Apply node constraints (ie. filter the "allowed_nodes" part of resources
*/
gboolean
stage1(GListPtr placement_constraints, GListPtr nodes, GListPtr resources)
{
crm_devel("Processing stage 1");
slist_iter(
node, node_t, nodes, lpc,
if(node == NULL) {
/* error */
} else if(node->weight >= 0.0 /* global weight */
&& node->details->online
&& node->details->type == node_member) {
max_valid_nodes++;
}
);
apply_placement_constraints(placement_constraints, nodes);
/* will also filter -ve "final" weighted nodes from resources'
* allowed lists while we are there
*/
apply_agent_constraints(resources);
return TRUE;
}
/*
* Choose a color for all resources from highest priority and XML_STRENGTH_VAL_MUST
* dependancies to lowest, creating new colors as necessary (returned
* as "colors").
*
* Some nodes may be colored as a "no_color" meaning that it was unresolvable
* given the current node stati and constraints.
*/
gboolean
stage2(GListPtr sorted_rscs, GListPtr sorted_nodes, GListPtr *colors)
{
crm_devel("Processing stage 2");
if(no_color != NULL) {
crm_free(no_color->details);
crm_free(no_color);
}
crm_trace("create \"no color\"");
no_color = create_color(NULL, NULL, NULL);
/* Take (next) highest resource */
slist_iter(
lh_resource, resource_t, sorted_rscs, lpc,
/* if resource.provisional == FALSE, repeat */
if(lh_resource->provisional == FALSE) {
/* already processed this resource */
continue;
}
color_resource(lh_resource, colors, sorted_rscs);
/* next resource */
);
return TRUE;
}
/*
* not sure if this is a good idea or not, but eventually we might like
* to utilize as many nodes as possible... and this might be a convienient
* hook
*/
gboolean
stage3(GListPtr colors)
{
crm_devel("Processing stage 3");
/* not sure if this is a good idea or not */
if((ssize_t)g_list_length(colors) > max_valid_nodes) {
/* we need to consolidate some */
} else if((ssize_t)g_list_length(colors) < max_valid_nodes) {
/* we can create a few more */
}
return TRUE;
}
/*
* Choose a node for each (if possible) color
*/
gboolean
stage4(GListPtr colors)
{
crm_devel("Processing stage 4");
slist_iter(
color, color_t, colors, lpc,
crm_devel("assigning node to color %d", color->id);
if(color == NULL) {
crm_err("NULL color detected");
continue;
} else if(color->details->pending == FALSE) {
continue;
}
choose_node_from_list(color);
crm_devel("assigned %s to color %d",
safe_val5(NULL, color, details, chosen_node, details, uname),
color->id);
slist_iter(
rsc, resource_t, color->details->allocated_resources, lpc2,
slist_iter(
constraint, rsc_colocation_t, rsc->rsc_cons, lpc,
rsc->fns->rsc_colocation_lh(constraint);
);
);
);
crm_verbose("done");
return TRUE;
}
/*
* Attach nodes to the actions that need to be taken
*
* Mark actions XML_LRM_ATTR_OPTIONAL if possible (Ie. if the start and stop are
* for the same node)
*
* Mark unrunnable actions
*/
gboolean
stage5(GListPtr resources, GListPtr *ordering_constraints)
{
slist_iter(
rsc, resource_t, resources, lpc,
rsc->fns->create_actions(rsc, ordering_constraints);
rsc->fns->internal_constraints(rsc, ordering_constraints);
);
return TRUE;
}
/*
* Create dependacies for stonith and shutdown operations
*/
gboolean
stage6(GListPtr *actions, GListPtr *ordering_constraints,
GListPtr nodes, GListPtr resources)
{
action_t *down_op = NULL;
action_t *stonith_op = NULL;
crm_devel("Processing stage 6");
slist_iter(
node, node_t, nodes, lpc,
if(node->details->online && node->details->shutdown) {
crm_info("Scheduling Node %s for shutdown",
node->details->uname);
down_op = action_new(NULL, shutdown_crm, NULL, node);
down_op->runnable = TRUE;
*actions = g_list_append(*actions, down_op);
shutdown_constraints(
node, down_op, ordering_constraints);
}
- if(node->details->unclean && stonith_enabled) {
+ if(node->details->unclean && stonith_enabled == FALSE) {
+ crm_err("Node %s is unclean!", node->details->uname);
+ crm_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
+ crm_warn("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
+
+ } else if(node->details->unclean && stonith_enabled
+ && (have_quorum || no_quorum_policy == no_quorum_ignore)) {
crm_warn("Scheduling Node %s for STONITH",
node->details->uname);
stonith_op = action_new(NULL, stonith_node,NULL,NULL);
stonith_op->runnable = TRUE;
add_hash_param(
stonith_op->extra, XML_LRM_ATTR_TARGET,
node->details->uname);
add_hash_param(
stonith_op->extra, XML_LRM_ATTR_TARGET_UUID,
node->details->id);
if(down_op != NULL) {
down_op->failure_is_fatal = FALSE;
}
- *actions = g_list_append(*actions, stonith_op);
-
- } else if(node->details->unclean) {
- crm_err("Node %s is unclean!", node->details->uname);
- crm_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
- crm_warn("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
+ *actions = g_list_append(*actions, stonith_op);
}
if(node->details->unclean) {
stonith_constraints(
node, stonith_op, down_op, ordering_constraints);
}
);
return TRUE;
}
/*
* Determin the sets of independant actions and the correct order for the
* actions in each set.
*
* Mark dependancies of un-runnable actions un-runnable
*
*/
gboolean
stage7(GListPtr resources, GListPtr actions, GListPtr ordering_constraints)
{
crm_devel("Processing stage 7");
slist_iter(
order, order_constraint_t, ordering_constraints, lpc,
/* try rsc_action-to-rsc_action */
resource_t *rsc = order->lh_rsc;
if(rsc == NULL && order->lh_action) {
rsc = order->lh_action->rsc;
}
if(rsc != NULL) {
rsc->fns->rsc_order_lh(rsc, order);
continue;
}
/* try action-to-rsc_action */
/* que off the rh resource */
rsc = order->rh_rsc;
if(rsc == NULL && order->rh_action) {
rsc = order->rh_action->rsc;
}
if(rsc != NULL) {
rsc->fns->rsc_order_rh(order->lh_action, rsc, order);
} else {
/* fall back to action-to-action */
order_actions(
order->lh_action, order->rh_action, order);
}
);
- update_action_states(actions);
+ update_action_states(global_action_list);
return TRUE;
}
/*
* Create a dependancy graph to send to the transitioner (via the CRMd)
*/
gboolean
stage8(GListPtr resources, GListPtr actions, crm_data_t * *graph)
{
crm_devel("Processing stage 8");
*graph = create_xml_node(NULL, XML_TAG_GRAPH);
set_xml_property_copy(
*graph, "global_timeout", transition_timeout);
/* errors...
slist_iter(action, action_t, action_list, lpc,
if(action->optional == FALSE && action->runnable == FALSE) {
print_action("Ignoring", action, TRUE);
}
);
*/
crm_verbose("========= Action List =========");
- slist_iter(action, action_t, actions, lpc,
+ crm_debug("%d actions created", g_list_length(global_action_list));
+
+ slist_iter(action, action_t, global_action_list, lpc,
print_action(NULL, action, FALSE));
slist_iter(
rsc, resource_t, resources, lpc,
crm_devel("processing actions for rsc=%s", rsc->id);
rsc->fns->expand(rsc, graph);
);
crm_xml_devel(*graph, "created resource-driven action list");
/* catch any non-resource specific actions */
crm_devel("processing non-resource actions");
slist_iter(
- action, action_t, actions, lpc,
+ action, action_t, global_action_list, lpc,
graph_element_from_action(action, graph);
);
crm_xml_devel(*graph, "created generic action list");
return TRUE;
}
gboolean
choose_node_from_list(color_t *color)
{
/*
1. Sort by weight
2. color.chosen_node = the node (of those with the highest wieght)
with the fewest resources
3. remove color.chosen_node from all other colors
*/
GListPtr nodes = color->details->candidate_nodes;
node_t *chosen = NULL;
crm_devel("Choosing node for color %d", color->id);
nodes = g_list_sort(nodes, sort_node_weight);
chosen = g_list_nth_data(nodes, 0);
color->details->chosen_node = NULL;
color->details->pending = FALSE;
if(chosen == NULL) {
crm_debug("Could not allocate a node for color %d", color->id);
return FALSE;
} else if(chosen->details->unclean || chosen->details->shutdown) {
crm_debug("Even highest ranked node for color %d"
" is unclean or shutting down",
color->id);
return FALSE;
} else if(chosen->weight < 0) {
crm_debug("Even highest ranked node for color %d, had weight %f",
color->id, chosen->weight);
return FALSE;
}
/* todo: update the old node for each resource to reflect its
* new resource count
*/
chosen->details->num_resources += color->details->num_resources;
color->details->chosen_node = node_copy(chosen);
return TRUE;
}
diff --git a/crm/pengine/testcases/attrs1.xml b/crm/pengine/testcases/attrs1.xml
index bf8519c13e..076a315548 100644
--- a/crm/pengine/testcases/attrs1.xml
+++ b/crm/pengine/testcases/attrs1.xml
@@ -1,42 +1,43 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1">
<expression attribute="id" operation="eq" value="uuid2"/>
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/attrs2.xml b/crm/pengine/testcases/attrs2.xml
index fdc4d29777..c420c8a318 100644
--- a/crm/pengine/testcases/attrs2.xml
+++ b/crm/pengine/testcases/attrs2.xml
@@ -1,42 +1,43 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1">
<expression attribute="id" operation="lt" value="uuid3"/>
<expression attribute="uname" operation="gt" value="node1"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/attrs3.xml b/crm/pengine/testcases/attrs3.xml
index ef0c52ec91..5d3a868099 100644
--- a/crm/pengine/testcases/attrs3.xml
+++ b/crm/pengine/testcases/attrs3.xml
@@ -1,36 +1,37 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1" boolean_op="or">
<expression attribute="id" operation="ne" value="uuid1"/>
<expression attribute="uname" operation="ne" value="node2"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/attrs4.xml b/crm/pengine/testcases/attrs4.xml
index ed5ff6ac26..7b231f4d3c 100644
--- a/crm/pengine/testcases/attrs4.xml
+++ b/crm/pengine/testcases/attrs4.xml
@@ -1,41 +1,42 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1" boolean_op="and">
<expression attribute="id" operation="defined"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/attrs5.xml b/crm/pengine/testcases/attrs5.xml
index 69c28e319b..e07f76ba56 100644
--- a/crm/pengine/testcases/attrs5.xml
+++ b/crm/pengine/testcases/attrs5.xml
@@ -1,27 +1,28 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1">
<expression attribute="id" operation="not_defined"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/attrs6.xml b/crm/pengine/testcases/attrs6.xml
index 76cac4e38f..a7bcbd389d 100644
--- a/crm/pengine/testcases/attrs6.xml
+++ b/crm/pengine/testcases/attrs6.xml
@@ -1,41 +1,28 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib dc_uuid="uuid1">
- <crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
- </crm_config>
<configuration>
+ <crm_config>
+ <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1">
<expression attribute="is_dc" operation="eq" value="true"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
- <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
- <lrm>
- <lrm_agents>
- <lrm_agent class="heartbeat" type="apache"/>
- </lrm_agents>
- <lrm_resources/>
- </lrm>
- </node_state>
- <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
- <lrm>
- <lrm_agents>
- <lrm_agent class="heartbeat" type="apache"/>
- </lrm_agents>
- <lrm_resources/>
- </lrm>
- </node_state>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/attrs7.xml b/crm/pengine/testcases/attrs7.xml
index 55b0844213..f5c76165b2 100644
--- a/crm/pengine/testcases/attrs7.xml
+++ b/crm/pengine/testcases/attrs7.xml
@@ -1,41 +1,42 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib dc_uuid="uuid1">
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1">
<expression attribute="is_dc" operation="eq" value="false"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/bad1.xml b/crm/pengine/testcases/bad1.xml
index 80965c0abe..c627d243eb 100644
--- a/crm/pengine/testcases/bad1.xml
+++ b/crm/pengine/testcases/bad1.xml
@@ -1,40 +1,42 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- bad node -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="cannot1" score="-INFINITY" boolean_op="or">
<expression id="exp1" attribute="uname" operation="eq" value="node2"/>
<expression id="exp2" attribute="uname" operation="eq" value="node3"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/bad2.xml b/crm/pengine/testcases/bad2.xml
index c9b0485307..007ead1f9b 100644
--- a/crm/pengine/testcases/bad2.xml
+++ b/crm/pengine/testcases/bad2.xml
@@ -1,39 +1,41 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- bad resource -->
<cib>
- <crm_config/>
<configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc3">
<rule id="can1" score="-INFINITY">
<expression attribute="uname" op="eq" value="node1"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/bad3.xml b/crm/pengine/testcases/bad3.xml
index 9d7266fa89..b270e85c45 100644
--- a/crm/pengine/testcases/bad3.xml
+++ b/crm/pengine/testcases/bad3.xml
@@ -1,28 +1,30 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- no rsc class -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" type="apache" priority="1.0"/>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="stop" rsc_state="stopped" op_status="0" rc_code="0" on_node="hadev"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/bad4.xml b/crm/pengine/testcases/bad4.xml
index bae58b80d0..ab8f8e7365 100644
--- a/crm/pengine/testcases/bad4.xml
+++ b/crm/pengine/testcases/bad4.xml
@@ -1,28 +1,30 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- no rsc type -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" priority="1.0"/>
</resources>
<constraints>
<constraints/>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="stop" rsc_state="stopped" op_status="0" rc_code="0" on_node="hadev"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/bad5.xml b/crm/pengine/testcases/bad5.xml
index a2e6e69ab4..06292ece0f 100644
--- a/crm/pengine/testcases/bad5.xml
+++ b/crm/pengine/testcases/bad5.xml
@@ -1,28 +1,30 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- lrm status -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc2" last_op="stop" rsc_state="stopped" op_status="0" rc_code="0" on_node="hadev"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/bad6.xml b/crm/pengine/testcases/bad6.xml
index a8eb4427e7..ac52d26103 100644
--- a/crm/pengine/testcases/bad6.xml
+++ b/crm/pengine/testcases/bad6.xml
@@ -1,28 +1,30 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- lrm status -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/bad7.xml b/crm/pengine/testcases/bad7.xml
index 2a24010388..ef2e2154ac 100644
--- a/crm/pengine/testcases/bad7.xml
+++ b/crm/pengine/testcases/bad7.xml
@@ -1,19 +1,21 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- lrm status -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints/>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/group1.xml b/crm/pengine/testcases/group1.xml
index 8217ec6d22..a3c72f835d 100644
--- a/crm/pengine/testcases/group1.xml
+++ b/crm/pengine/testcases/group1.xml
@@ -1,38 +1,40 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource_group id="rsc1" priority="1.0">
<resource id="child_rsc1" class="heartbeat" type="apache"/>
<resource id="child_rsc2" class="heartbeat" type="apache"/>
<resource id="child_rsc3" class="heartbeat" type="apache"/>
</resource_group>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="uuid1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/group2.xml b/crm/pengine/testcases/group2.xml
index 8cb04ed72e..e8cfe3067a 100644
--- a/crm/pengine/testcases/group2.xml
+++ b/crm/pengine/testcases/group2.xml
@@ -1,42 +1,44 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
<resource_group id="rsc2">
<resource id="child_rsc1" class="heartbeat" type="apache"/>
<resource id="child_rsc2" class="heartbeat" type="apache"/>
<resource id="child_rsc3" class="heartbeat" type="apache"/>
</resource_group>
<resource id="rsc3" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
<rsc_order id="order2" from="rsc2" type="before" to="rsc3"/>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/group3.xml b/crm/pengine/testcases/group3.xml
index 009d49c7bf..a80db436f8 100644
--- a/crm/pengine/testcases/group3.xml
+++ b/crm/pengine/testcases/group3.xml
@@ -1,44 +1,46 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource_group id="rsc1">
<resource id="child_rsc1" class="heartbeat" type="apache"/>
<resource id="child_rsc2" class="heartbeat" type="apache"/>
<resource id="child_rsc3" class="heartbeat" type="apache"/>
</resource_group>
<resource_group id="rsc2">
<resource id="child_rsc4" class="heartbeat" type="apache"/>
<resource id="child_rsc5" class="heartbeat" type="apache"/>
<resource id="child_rsc6" class="heartbeat" type="apache"/>
</resource_group>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/group4.xml b/crm/pengine/testcases/group4.xml
index 5a101c30d1..d4ef50360b 100644
--- a/crm/pengine/testcases/group4.xml
+++ b/crm/pengine/testcases/group4.xml
@@ -1,65 +1,66 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
<resource_group id="rsc2">
<resource id="child_rsc1" class="heartbeat" type="apache"/>
<resource id="child_rsc2" class="heartbeat" type="apache"/>
<resource id="child_rsc3" class="heartbeat" type="apache"/>
</resource_group>
<resource id="rsc3" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
<rsc_order id="order2" from="rsc2" type="before" to="rsc3"/>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="can2-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc3" rsc="rsc3">
<rule id="can3-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc2" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/group5.xml b/crm/pengine/testcases/group5.xml
index a9acfe8e38..bf44e10467 100644
--- a/crm/pengine/testcases/group5.xml
+++ b/crm/pengine/testcases/group5.xml
@@ -1,63 +1,65 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
<resource_group id="rsc2" priority="1.0">
<resource id="child_rsc1" class="heartbeat" type="apache"/>
<resource id="child_rsc2" class="heartbeat" type="apache"/>
<resource id="child_rsc3" class="heartbeat" type="apache"/>
</resource_group>
<resource id="rsc3" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
<rsc_order id="order2" from="rsc2" type="before" to="rsc3"/>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="can2-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc3" rsc="rsc3">
<rule id="can3-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc2" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
</lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/group6.xml b/crm/pengine/testcases/group6.xml
index b9b6042874..f986ae9a89 100644
--- a/crm/pengine/testcases/group6.xml
+++ b/crm/pengine/testcases/group6.xml
@@ -1,61 +1,63 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource_group id="rsc1">
<resource id="child_rsc1" class="heartbeat" type="apache"/>
<resource id="child_rsc2" class="heartbeat" type="apache"/>
<resource id="child_rsc3" class="heartbeat" type="apache"/>
</resource_group>
<resource_group id="rsc2">
<resource id="child_rsc4" class="heartbeat" type="apache"/>
<resource id="child_rsc5" class="heartbeat" type="apache"/>
<resource id="child_rsc6" class="heartbeat" type="apache"/>
</resource_group>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="can2-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1:child_rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc1:child_rsc2" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc1:child_rsc3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc2:child_rsc4" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc2:child_rsc5" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc2:child_rsc6" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
</lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/inc1.xml b/crm/pengine/testcases/inc1.xml
index 8526fd824a..3e7225a8b0 100644
--- a/crm/pengine/testcases/inc1.xml
+++ b/crm/pengine/testcases/inc1.xml
@@ -1,42 +1,44 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<incarnation id="rsc1">
<instance_attributes>
<attributes>
<nvpair name="incarnation_max" value="5"/>
<nvpair name="incarnation_node_max" value="2"/>
</attributes>
</instance_attributes>
<resource id="child_rsc1" class="heartbeat" type="apache"/>
</incarnation>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/inc2.xml b/crm/pengine/testcases/inc2.xml
index e3047ae042..dbc9bee727 100644
--- a/crm/pengine/testcases/inc2.xml
+++ b/crm/pengine/testcases/inc2.xml
@@ -1,37 +1,39 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<incarnation id="rsc1">
<instance_attributes>
<attributes>
<nvpair name="incarnation_max" value="5"/>
<nvpair name="incarnation_node_max" value="2"/>
</attributes>
</instance_attributes>
<resource id="child_rsc1" class="heartbeat" type="apache"/>
</incarnation>
</resources>
<constraints/>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_resources>
<lrm_resource id="rsc1:child_rsc1:0" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc1:child_rsc1:1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc1:child_rsc1:2" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc1:child_rsc1:3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc1:child_rsc1:4" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
</lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/inc3.xml b/crm/pengine/testcases/inc3.xml
index 79a952fab6..98bd18285b 100644
--- a/crm/pengine/testcases/inc3.xml
+++ b/crm/pengine/testcases/inc3.xml
@@ -1,64 +1,66 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<incarnation id="rsc1">
<instance_attributes>
<attributes>
<nvpair name="incarnation_max" value="5"/>
<nvpair name="incarnation_node_max" value="2"/>
</attributes>
</instance_attributes>
<resource id="child_rsc1" class="heartbeat" type="apache" priority="1.0"/>
</incarnation>
<incarnation id="rsc2">
<instance_attributes>
<attributes>
<nvpair name="incarnation_max" value="5"/>
<nvpair name="incarnation_node_max" value="3"/>
</attributes>
</instance_attributes>
<resource id="child_rsc2" class="heartbeat" type="apache" priority="1.0"/>
</incarnation>
</resources>
<constraints>
<rsc_order id="order1" from="rsc1" type="before" to="rsc2"/>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1:child_rsc1:0" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc1:child_rsc1:1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc1:child_rsc1:2" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc1:child_rsc1:3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
<lrm_resource id="rsc1:child_rsc1:4" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
</lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc2:child_rsc2:0" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc2:1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc2:2" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc2:3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
<lrm_resource id="rsc2:child_rsc2:4" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/mon-rsc-1.exp b/crm/pengine/testcases/mon-rsc-1.exp
new file mode 100644
index 0000000000..819ccc5933
--- /dev/null
+++ b/crm/pengine/testcases/mon-rsc-1.exp
@@ -0,0 +1,28 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="monitor" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes>
+ <nvpair name="timeout" value="3s"/>
+ <nvpair name="interval" value="5s"/>
+ </attributes>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/mon-rsc-1.xml b/crm/pengine/testcases/mon-rsc-1.xml
new file mode 100644
index 0000000000..a0e3110629
--- /dev/null
+++ b/crm/pengine/testcases/mon-rsc-1.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache">
+ <operations>
+ <op id="1" name="monitor" interval="5s" timeout="3s"/>
+ </operations>
+ </resource>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid2" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/mon-rsc-2.exp b/crm/pengine/testcases/mon-rsc-2.exp
new file mode 100644
index 0000000000..233883799d
--- /dev/null
+++ b/crm/pengine/testcases/mon-rsc-2.exp
@@ -0,0 +1,41 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <rsc_op id="3" rsc_id="rsc1" operation="monitor" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes>
+ <nvpair name="timeout" value="3s"/>
+ <nvpair name="interval" value="5s"/>
+ </attributes>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="2" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/mon-rsc-2.xml b/crm/pengine/testcases/mon-rsc-2.xml
new file mode 100644
index 0000000000..e51317426c
--- /dev/null
+++ b/crm/pengine/testcases/mon-rsc-2.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache">
+ <operations>
+ <op id="1" name="monitor" interval="5s" timeout="3s"/>
+ </operations>
+ </resource>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/mon-rsc-3.exp b/crm/pengine/testcases/mon-rsc-3.exp
new file mode 100644
index 0000000000..ca70c516ed
--- /dev/null
+++ b/crm/pengine/testcases/mon-rsc-3.exp
@@ -0,0 +1,28 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="monitor" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes>
+ <nvpair name="timeout" value="3s"/>
+ <nvpair name="interval" value="5s"/>
+ </attributes>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/mon-rsc-3.xml b/crm/pengine/testcases/mon-rsc-3.xml
new file mode 100644
index 0000000000..cd2e95d5c6
--- /dev/null
+++ b/crm/pengine/testcases/mon-rsc-3.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache">
+ <operations>
+ <op id="1" name="monitor" interval="5s" timeout="3s"/>
+ </operations>
+ </resource>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="starting" op_status="-1" rc_code="-1" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/mon-rsc-4.exp b/crm/pengine/testcases/mon-rsc-4.exp
new file mode 100644
index 0000000000..a66b6f8ffc
--- /dev/null
+++ b/crm/pengine/testcases/mon-rsc-4.exp
@@ -0,0 +1,41 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="2" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <rsc_op id="3" rsc_id="rsc1" operation="monitor" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes>
+ <nvpair name="timeout" value="3s"/>
+ <nvpair name="interval" value="5s"/>
+ </attributes>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/mon-rsc-4.xml b/crm/pengine/testcases/mon-rsc-4.xml
new file mode 100644
index 0000000000..5f66e4f162
--- /dev/null
+++ b/crm/pengine/testcases/mon-rsc-4.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache">
+ <operations>
+ <op id="1" name="monitor" interval="5s" timeout="3s"/>
+ </operations>
+ </resource>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="starting" op_status="-1" rc_code="-1" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/order1.exp b/crm/pengine/testcases/order1.exp
index af40741ea7..c77589b5e7 100644
--- a/crm/pengine/testcases/order1.exp
+++ b/crm/pengine/testcases/order1.exp
@@ -1,38 +1,38 @@
<transition_graph global_timeout="60000">
<synapse id="0">
<action_set>
<rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
- <resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
+ <resource id="rsc1" class="heartbeat" type="apache"/>
<attributes/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="1">
<action_set>
- <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
- <resource id="rsc2" class="heartbeat" type="apache" priority="1.0"/>
+ <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache"/>
<attributes/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
</trigger>
</inputs>
</synapse>
<synapse id="2">
<action_set>
<rsc_op id="3" rsc_id="rsc3" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
- <resource id="rsc3" class="heartbeat" type="apache" priority="1.0"/>
+ <resource id="rsc3" class="heartbeat" type="apache"/>
<attributes/>
</rsc_op>
</action_set>
<inputs>
<trigger>
- <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false"/>
</trigger>
</inputs>
</synapse>
</transition_graph>
diff --git a/crm/pengine/testcases/order1.xml b/crm/pengine/testcases/order1.xml
index 6a321b34e1..c4b62cd301 100644
--- a/crm/pengine/testcases/order1.xml
+++ b/crm/pengine/testcases/order1.xml
@@ -1,38 +1,26 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
- <resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
- <resource id="rsc2" class="heartbeat" type="apache" priority="1.0"/>
- <resource id="rsc3" class="heartbeat" type="apache" priority="1.0"/>
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <resource id="rsc2" class="heartbeat" type="apache"/>
+ <resource id="rsc3" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
<rsc_order id="order2" from="rsc2" type="before" to="rsc3"/>
</constraints>
</configuration>
<status>
- <node_state id="uuid1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
- <lrm>
- <lrm_agents>
- <lrm_agent class="heartbeat" type="apache"/>
- </lrm_agents>
- <lrm_resources/>
- </lrm>
- </node_state>
- <node_state id="uuid2" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
- <lrm>
- <lrm_agents>
- <lrm_agent class="heartbeat" type="apache"/>
- </lrm_agents>
- <lrm_resources/>
- </lrm>
- </node_state>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/order2.xml b/crm/pengine/testcases/order2.xml
index 813e41ab8c..99a761285c 100644
--- a/crm/pengine/testcases/order2.xml
+++ b/crm/pengine/testcases/order2.xml
@@ -1,40 +1,42 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
<resource id="rsc2" class="heartbeat" type="apache" priority="1.0"/>
<resource id="rsc3" class="heartbeat" type="apache" priority="1.0"/>
<resource id="rsc4" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
<rsc_order id="order2" from="rsc2" type="before" to="rsc3"/>
<rsc_order id="order3" from="rsc2" type="after" to="rsc4"/>
</constraints>
</configuration>
<status>
<node_state id="uuid1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/order3.xml b/crm/pengine/testcases/order3.xml
index c75b0edee1..ddd5efb617 100644
--- a/crm/pengine/testcases/order3.xml
+++ b/crm/pengine/testcases/order3.xml
@@ -1,67 +1,68 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
<resource id="rsc2" class="heartbeat" type="apache" priority="1.0"/>
<resource id="rsc3" class="heartbeat" type="apache" priority="1.0"/>
<resource id="rsc4" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
<rsc_order id="order2" from="rsc2" type="before" to="rsc3"/>
<rsc_order id="order3" from="rsc2" type="after" to="rsc4"/>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="can2-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc3" rsc="rsc3">
<rule id="can3-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc4" rsc="rsc4">
<rule id="can4-1" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="hadev"/>
<lrm_resource id="rsc2" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="hadev"/>
<lrm_resource id="rsc3" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="hadev"/>
<lrm_resource id="rsc4" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="hadev"/>
</lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/order4.xml b/crm/pengine/testcases/order4.xml
index b6ce5cf7ea..d8bbc0aba7 100644
--- a/crm/pengine/testcases/order4.xml
+++ b/crm/pengine/testcases/order4.xml
@@ -1,40 +1,42 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
<resource id="rsc2" class="heartbeat" type="apache" priority="1.0"/>
<resource id="rsc3" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
<rsc_order id="order1" from="rsc2" type="after" to="rsc1"/>
<rsc_order id="order2" from="rsc2" type="after" to="rsc1"/>
<rsc_order id="order3" from="rsc2" type="before" to="rsc3"/>
<rsc_order id="order4" from="rsc2" type="before" to="rsc3"/>
</constraints>
</configuration>
<status>
<node_state id="uuid1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/quorum-1.exp b/crm/pengine/testcases/quorum-1.exp
new file mode 100644
index 0000000000..8bc1fbce58
--- /dev/null
+++ b/crm/pengine/testcases/quorum-1.exp
@@ -0,0 +1,34 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <rsc_op id="3" rsc_id="rsc3" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc3" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/quorum-1.xml b/crm/pengine/testcases/quorum-1.xml
new file mode 100644
index 0000000000..24dcc684c0
--- /dev/null
+++ b/crm/pengine/testcases/quorum-1.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc3" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/quorum-2.exp b/crm/pengine/testcases/quorum-2.exp
new file mode 100644
index 0000000000..07ac5b7864
--- /dev/null
+++ b/crm/pengine/testcases/quorum-2.exp
@@ -0,0 +1,25 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/quorum-2.xml b/crm/pengine/testcases/quorum-2.xml
new file mode 100644
index 0000000000..dd6ab3c035
--- /dev/null
+++ b/crm/pengine/testcases/quorum-2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="freeze"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc3" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/quorum-3.exp b/crm/pengine/testcases/quorum-3.exp
new file mode 100644
index 0000000000..bd82e567a6
--- /dev/null
+++ b/crm/pengine/testcases/quorum-3.exp
@@ -0,0 +1,21 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/quorum-3.xml b/crm/pengine/testcases/quorum-3.xml
new file mode 100644
index 0000000000..6bd1d30208
--- /dev/null
+++ b/crm/pengine/testcases/quorum-3.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="stop"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc3" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-1.exp b/crm/pengine/testcases/rec-node-1.exp
new file mode 100644
index 0000000000..c8ed90fef0
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-1.exp
@@ -0,0 +1,21 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/rec-node-1.xml b/crm/pengine/testcases/rec-node-1.xml
new file mode 100644
index 0000000000..0f655499db
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-10.exp b/crm/pengine/testcases/rec-node-10.exp
new file mode 100644
index 0000000000..795b48357e
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-10.exp
@@ -0,0 +1,2 @@
+ <transition_graph global_timeout="60000"/>
+
diff --git a/crm/pengine/testcases/rec-node-10.xml b/crm/pengine/testcases/rec-node-10.xml
new file mode 100644
index 0000000000..479a39cafd
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-10.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="true"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="stop"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" join="member" expected="member" timestamp="1086187789" in_ccm="false">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-2.exp b/crm/pengine/testcases/rec-node-2.exp
new file mode 100644
index 0000000000..04a239fedb
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-2.exp
@@ -0,0 +1,40 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="3" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="3" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <crm_event id="3" operation="stonith" allow_fail="false">
+ <attributes>
+ <nvpair name="on_node" value="node1"/>
+ <nvpair name="on_node_uuid" value="uuid1"/>
+ </attributes>
+ </crm_event>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/rec-node-2.xml b/crm/pengine/testcases/rec-node-2.xml
new file mode 100644
index 0000000000..1e6bc1952b
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="true"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-3.exp b/crm/pengine/testcases/rec-node-3.exp
new file mode 100644
index 0000000000..c8ed90fef0
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-3.exp
@@ -0,0 +1,21 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/rec-node-3.xml b/crm/pengine/testcases/rec-node-3.xml
new file mode 100644
index 0000000000..a256f05e73
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-3.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" join="member" expected="member" timestamp="1086187789" in_ccm="false">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-4.exp b/crm/pengine/testcases/rec-node-4.exp
new file mode 100644
index 0000000000..4fc37560c0
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-4.exp
@@ -0,0 +1,66 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <pseudo_event id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </pseudo_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="5" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <pseudo_event id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <pseudo_event id="3" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </pseudo_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="5" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="3">
+ <action_set>
+ <rsc_op id="4" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <pseudo_event id="3" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="4">
+ <action_set>
+ <crm_event id="5" operation="stonith" allow_fail="false">
+ <attributes>
+ <nvpair name="on_node" value="node1"/>
+ <nvpair name="on_node_uuid" value="uuid1"/>
+ </attributes>
+ </crm_event>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/rec-node-4.xml b/crm/pengine/testcases/rec-node-4.xml
new file mode 100644
index 0000000000..0b05aad5f6
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-4.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="true"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" join="member" expected="member" timestamp="1086187789" in_ccm="false">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-5.exp b/crm/pengine/testcases/rec-node-5.exp
new file mode 100644
index 0000000000..c8ed90fef0
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-5.exp
@@ -0,0 +1,21 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/rec-node-5.xml b/crm/pengine/testcases/rec-node-5.xml
new file mode 100644
index 0000000000..c3667b7719
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-5.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-6.exp b/crm/pengine/testcases/rec-node-6.exp
new file mode 100644
index 0000000000..4fc37560c0
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-6.exp
@@ -0,0 +1,66 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <pseudo_event id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </pseudo_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="5" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <pseudo_event id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <pseudo_event id="3" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </pseudo_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="5" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="3">
+ <action_set>
+ <rsc_op id="4" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <pseudo_event id="3" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="4">
+ <action_set>
+ <crm_event id="5" operation="stonith" allow_fail="false">
+ <attributes>
+ <nvpair name="on_node" value="node1"/>
+ <nvpair name="on_node_uuid" value="uuid1"/>
+ </attributes>
+ </crm_event>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/rec-node-6.xml b/crm/pengine/testcases/rec-node-6.xml
new file mode 100644
index 0000000000..b108c00d83
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-6.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="true"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-7.exp b/crm/pengine/testcases/rec-node-7.exp
new file mode 100644
index 0000000000..4fc37560c0
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-7.exp
@@ -0,0 +1,66 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <pseudo_event id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </pseudo_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="5" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <pseudo_event id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <pseudo_event id="3" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </pseudo_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="5" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="3">
+ <action_set>
+ <rsc_op id="4" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <pseudo_event id="3" rsc_id="rsc2" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="4">
+ <action_set>
+ <crm_event id="5" operation="stonith" allow_fail="false">
+ <attributes>
+ <nvpair name="on_node" value="node1"/>
+ <nvpair name="on_node_uuid" value="uuid1"/>
+ </attributes>
+ </crm_event>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/rec-node-7.xml b/crm/pengine/testcases/rec-node-7.xml
new file mode 100644
index 0000000000..0b05aad5f6
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-7.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="true"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" join="member" expected="member" timestamp="1086187789" in_ccm="false">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-8.exp b/crm/pengine/testcases/rec-node-8.exp
new file mode 100644
index 0000000000..795b48357e
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-8.exp
@@ -0,0 +1,2 @@
+ <transition_graph global_timeout="60000"/>
+
diff --git a/crm/pengine/testcases/rec-node-8.xml b/crm/pengine/testcases/rec-node-8.xml
new file mode 100644
index 0000000000..5cfb883027
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-8.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="true"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="freeze"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc3" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" join="member" expected="member" timestamp="1086187789" in_ccm="false">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-node-9.exp b/crm/pengine/testcases/rec-node-9.exp
new file mode 100644
index 0000000000..795b48357e
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-9.exp
@@ -0,0 +1,2 @@
+ <transition_graph global_timeout="60000"/>
+
diff --git a/crm/pengine/testcases/rec-node-9.xml b/crm/pengine/testcases/rec-node-9.xml
new file mode 100644
index 0000000000..c2cb41238f
--- /dev/null
+++ b/crm/pengine/testcases/rec-node-9.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="stop"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="block"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" join="member" expected="member" timestamp="1086187789" in_ccm="false">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-rsc-0.exp b/crm/pengine/testcases/rec-rsc-0.exp
new file mode 100644
index 0000000000..795b48357e
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-0.exp
@@ -0,0 +1,2 @@
+ <transition_graph global_timeout="60000"/>
+
diff --git a/crm/pengine/testcases/attrs3.xml b/crm/pengine/testcases/rec-rsc-0.xml
similarity index 62%
copy from crm/pengine/testcases/attrs3.xml
copy to crm/pengine/testcases/rec-rsc-0.xml
index ef0c52ec91..18f25dcdc2 100644
--- a/crm/pengine/testcases/attrs3.xml
+++ b/crm/pengine/testcases/rec-rsc-0.xml
@@ -1,36 +1,33 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
- <constraints>
- <rsc_location id="run_rsc1" rsc="rsc1">
- <rule id="can1" score="1" boolean_op="or">
- <expression attribute="id" operation="ne" value="uuid1"/>
- <expression attribute="uname" operation="ne" value="node2"/>
- </rule>
- </rsc_location>
- </constraints>
+ <constraints/>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
- <lrm_resources/>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="start_failed" op_status="4" rc_code="152" on_node="node1"/>
+ </lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
- <lrm_resources/>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="start_failed" op_status="4" rc_code="152" on_node="node2"/>
+ </lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rec-rsc-1.exp b/crm/pengine/testcases/rec-rsc-1.exp
new file mode 100644
index 0000000000..11b2f107a1
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-1.exp
@@ -0,0 +1,12 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/attrs5.xml b/crm/pengine/testcases/rec-rsc-1.xml
similarity index 61%
copy from crm/pengine/testcases/attrs5.xml
copy to crm/pengine/testcases/rec-rsc-1.xml
index 69c28e319b..6c7b3c8d62 100644
--- a/crm/pengine/testcases/attrs5.xml
+++ b/crm/pengine/testcases/rec-rsc-1.xml
@@ -1,27 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
- <constraints>
- <rsc_location id="run_rsc1" rsc="rsc1">
- <rule id="can1" score="1">
- <expression attribute="id" operation="not_defined"/>
- </rule>
- </rsc_location>
- </constraints>
+ <constraints/>
</configuration>
<status>
- <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="start_failed" op_status="4" rc_code="152" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/rec-rsc-2.exp b/crm/pengine/testcases/rec-rsc-2.exp
new file mode 100644
index 0000000000..8471973bc9
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-2.exp
@@ -0,0 +1,25 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="start" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/attrs5.xml b/crm/pengine/testcases/rec-rsc-2.xml
similarity index 60%
copy from crm/pengine/testcases/attrs5.xml
copy to crm/pengine/testcases/rec-rsc-2.xml
index 69c28e319b..9b82caea12 100644
--- a/crm/pengine/testcases/attrs5.xml
+++ b/crm/pengine/testcases/rec-rsc-2.xml
@@ -1,27 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
- <constraints>
- <rsc_location id="run_rsc1" rsc="rsc1">
- <rule id="can1" score="1">
- <expression attribute="id" operation="not_defined"/>
- </rule>
- </rsc_location>
- </constraints>
+ <constraints/>
</configuration>
<status>
- <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="monitor" rsc_state="monitor_failed" op_status="4" rc_code="7" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/rec-rsc-3.exp b/crm/pengine/testcases/rec-rsc-3.exp
new file mode 100644
index 0000000000..29f21b2aa0
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-3.exp
@@ -0,0 +1,12 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="ignore"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/attrs5.xml b/crm/pengine/testcases/rec-rsc-3.xml
similarity index 53%
copy from crm/pengine/testcases/attrs5.xml
copy to crm/pengine/testcases/rec-rsc-3.xml
index 69c28e319b..f9c82901d1 100644
--- a/crm/pengine/testcases/attrs5.xml
+++ b/crm/pengine/testcases/rec-rsc-3.xml
@@ -1,27 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
- <resource id="rsc1" class="heartbeat" type="apache"/>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="ignore"/>
</resources>
- <constraints>
- <rsc_location id="run_rsc1" rsc="rsc1">
- <rule id="can1" score="1">
- <expression attribute="id" operation="not_defined"/>
- </rule>
- </rsc_location>
- </constraints>
+ <constraints/>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
- <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rec-rsc-4.exp b/crm/pengine/testcases/rec-rsc-4.exp
new file mode 100644
index 0000000000..20b3766d24
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-4.exp
@@ -0,0 +1,25 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/attrs5.xml b/crm/pengine/testcases/rec-rsc-4.xml
similarity index 53%
copy from crm/pengine/testcases/attrs5.xml
copy to crm/pengine/testcases/rec-rsc-4.xml
index 69c28e319b..68a8dd676f 100644
--- a/crm/pengine/testcases/attrs5.xml
+++ b/crm/pengine/testcases/rec-rsc-4.xml
@@ -1,27 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
- <resource id="rsc1" class="heartbeat" type="apache"/>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="block"/>
</resources>
- <constraints>
- <rsc_location id="run_rsc1" rsc="rsc1">
- <rule id="can1" score="1">
- <expression attribute="id" operation="not_defined"/>
- </rule>
- </rsc_location>
- </constraints>
+ <constraints/>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
- <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node1"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rec-rsc-5.exp b/crm/pengine/testcases/rec-rsc-5.exp
new file mode 100644
index 0000000000..65a9c8c3c1
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-5.exp
@@ -0,0 +1,66 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <pseudo_event id="1" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="fence"/>
+ <attributes/>
+ </pseudo_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <crm_event id="5" operation="stonith" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="fence"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <pseudo_event id="1" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <rsc_op id="3" rsc_id="rsc2" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="fence"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="3">
+ <action_set>
+ <rsc_op id="4" rsc_id="rsc2" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="fence"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="3" rsc_id="rsc2" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ <synapse id="4">
+ <action_set>
+ <crm_event id="5" operation="stonith" allow_fail="false">
+ <attributes>
+ <nvpair name="on_node" value="node2"/>
+ <nvpair name="on_node_uuid" value="uuid2"/>
+ </attributes>
+ </crm_event>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="3" rsc_id="rsc2" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/rec-rsc-5.xml b/crm/pengine/testcases/rec-rsc-5.xml
new file mode 100644
index 0000000000..9cde276d7d
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-5.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
+<cib>
+ <configuration>
+ <crm_config>
+ <nvpair id="stonith_enabled" name="stonith_enabled" value="true"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
+ <nodes>
+ <node id="uuid1" uname="node1" type="member"/>
+ <node id="uuid2" uname="node2" type="member"/>
+ </nodes>
+ <resources>
+ <resource id="rsc1" class="heartbeat" type="apache" on_stopfail="fence"/>
+ <resource id="rsc2" class="heartbeat" type="apache" on_stopfail="fence"/>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status>
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
+ <node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <lrm>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="stop" rsc_state="stop_failed" op_status="4" rc_code="7" on_node="node2"/>
+ <lrm_resource id="rsc2" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
+ </lrm>
+ </node_state>
+ </status>
+</cib>
diff --git a/crm/pengine/testcases/rec-rsc-6.exp b/crm/pengine/testcases/rec-rsc-6.exp
new file mode 100644
index 0000000000..df22bc0e71
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-6.exp
@@ -0,0 +1,37 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" multi_active="stop_start"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" multi_active="stop_start"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="2">
+ <action_set>
+ <rsc_op id="3" rsc_id="rsc1" operation="start" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" multi_active="stop_start"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs>
+ <trigger>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false"/>
+ </trigger>
+ <trigger>
+ <rsc_op id="2" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false"/>
+ </trigger>
+ </inputs>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/attrs3.xml b/crm/pengine/testcases/rec-rsc-6.xml
similarity index 56%
copy from crm/pengine/testcases/attrs3.xml
copy to crm/pengine/testcases/rec-rsc-6.xml
index ef0c52ec91..718c49d786 100644
--- a/crm/pengine/testcases/attrs3.xml
+++ b/crm/pengine/testcases/rec-rsc-6.xml
@@ -1,36 +1,33 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
- <resource id="rsc1" class="heartbeat" type="apache"/>
+ <resource id="rsc1" class="heartbeat" type="apache" multi_active="stop_start"/>
</resources>
- <constraints>
- <rsc_location id="run_rsc1" rsc="rsc1">
- <rule id="can1" score="1" boolean_op="or">
- <expression attribute="id" operation="ne" value="uuid1"/>
- <expression attribute="uname" operation="ne" value="node2"/>
- </rule>
- </rsc_location>
- </constraints>
+ <constraints/>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
- <lrm_resources/>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ </lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
- <lrm_resources/>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rec-rsc-7.exp b/crm/pengine/testcases/rec-rsc-7.exp
new file mode 100644
index 0000000000..d349bc2274
--- /dev/null
+++ b/crm/pengine/testcases/rec-rsc-7.exp
@@ -0,0 +1,21 @@
+ <transition_graph global_timeout="60000">
+ <synapse id="0">
+ <action_set>
+ <rsc_op id="1" rsc_id="rsc1" operation="stop" on_node="node1" on_node_uuid="uuid1" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" multi_active="stop_only"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ <synapse id="1">
+ <action_set>
+ <rsc_op id="2" rsc_id="rsc1" operation="stop" on_node="node2" on_node_uuid="uuid2" allow_fail="false">
+ <resource id="rsc1" class="heartbeat" type="apache" multi_active="stop_only"/>
+ <attributes/>
+ </rsc_op>
+ </action_set>
+ <inputs/>
+ </synapse>
+ </transition_graph>
+
diff --git a/crm/pengine/testcases/attrs3.xml b/crm/pengine/testcases/rec-rsc-7.xml
similarity index 56%
copy from crm/pengine/testcases/attrs3.xml
copy to crm/pengine/testcases/rec-rsc-7.xml
index ef0c52ec91..d6f4857481 100644
--- a/crm/pengine/testcases/attrs3.xml
+++ b/crm/pengine/testcases/rec-rsc-7.xml
@@ -1,36 +1,33 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
- <resource id="rsc1" class="heartbeat" type="apache"/>
+ <resource id="rsc1" class="heartbeat" type="apache" multi_active="stop_only"/>
</resources>
- <constraints>
- <rsc_location id="run_rsc1" rsc="rsc1">
- <rule id="can1" score="1" boolean_op="or">
- <expression attribute="id" operation="ne" value="uuid1"/>
- <expression attribute="uname" operation="ne" value="node2"/>
- </rule>
- </rsc_location>
- </constraints>
+ <constraints/>
</configuration>
<status>
<node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
- <lrm_resources/>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ </lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
- <lrm_resources/>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/attrs3.xml b/crm/pengine/testcases/rec-rsc-8.xml
similarity index 51%
copy from crm/pengine/testcases/attrs3.xml
copy to crm/pengine/testcases/rec-rsc-8.xml
index ef0c52ec91..fd5214d0d4 100644
--- a/crm/pengine/testcases/attrs3.xml
+++ b/crm/pengine/testcases/rec-rsc-8.xml
@@ -1,36 +1,33 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
- <nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
- <resource id="rsc1" class="heartbeat" type="apache"/>
+ <resource id="rsc1" class="heartbeat" type="apache" multi_active="block"/>
</resources>
- <constraints>
- <rsc_location id="run_rsc1" rsc="rsc1">
- <rule id="can1" score="1" boolean_op="or">
- <expression attribute="id" operation="ne" value="uuid1"/>
- <expression attribute="uname" operation="ne" value="node2"/>
- </rule>
- </rsc_location>
- </constraints>
+ <constraints/>
</configuration>
<status>
- <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
+ <node_state id="uuid1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
<lrm>
- <lrm_resources/>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node1"/>
+ </lrm_resources>
</lrm>
</node_state>
<node_state id="uuid2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
- <lrm_resources/>
+ <lrm_resources>
+ <lrm_resource id="rsc1" last_op="start" rsc_state="running" op_status="0" rc_code="0" on_node="node2"/>
+ </lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_dep1.xml b/crm/pengine/testcases/rsc_dep1.xml
index 9b73af196e..c7b619f0dd 100644
--- a/crm/pengine/testcases/rsc_dep1.xml
+++ b/crm/pengine/testcases/rsc_dep1.xml
@@ -1,35 +1,37 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must not -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_colocation id="not_same_1" from="rsc1" to="rsc2" type="must_not"/>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_dep10.xml b/crm/pengine/testcases/rsc_dep10.xml
index 062a99994c..3dfe0fd388 100644
--- a/crm/pengine/testcases/rsc_dep10.xml
+++ b/crm/pengine/testcases/rsc_dep10.xml
@@ -1,43 +1,44 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must but cant -->
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
<resource id="rsc2" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_colocation id="same_1" from="rsc1" to="rsc2" type="must"/>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can2" score="1">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="can3" score="1">
<expression attribute="uname" operation="eq" value="node1"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_dep3.xml b/crm/pengine/testcases/rsc_dep3.xml
index 3a174e47a4..bc0a5fb62d 100644
--- a/crm/pengine/testcases/rsc_dep3.xml
+++ b/crm/pengine/testcases/rsc_dep3.xml
@@ -1,49 +1,51 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_colocation id="same_1" from="rsc1" to="rsc2" type="must"/>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_dep5.xml b/crm/pengine/testcases/rsc_dep5.xml
index cd0ad9f010..8b8df7fd42 100644
--- a/crm/pengine/testcases/rsc_dep5.xml
+++ b/crm/pengine/testcases/rsc_dep5.xml
@@ -1,58 +1,60 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must not -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc3" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="3.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_colocation id="not_same_1" from="rsc1" to="rsc2" type="must_not"/>
<rsc_colocation id="not_same_2" from="rsc1" to="rsc3" type="must_not"/>
<rsc_colocation id="not_same_3" from="rsc3" to="rsc2" type="must_not"/>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_dep7.xml b/crm/pengine/testcases/rsc_dep7.xml
index f69037a06b..eb63b01325 100644
--- a/crm/pengine/testcases/rsc_dep7.xml
+++ b/crm/pengine/testcases/rsc_dep7.xml
@@ -1,58 +1,60 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc3" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="3.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_colocation id="not_same_1" from="rsc1" to="rsc2" type="must"/>
<rsc_colocation id="not_same_2" from="rsc1" to="rsc3" type="must"/>
<rsc_colocation id="not_same_3" from="rsc3" to="rsc2" type="must"/>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_location1.exp b/crm/pengine/testcases/rsc_location1.exp
index eee51203c8..0503c1956a 100644
--- a/crm/pengine/testcases/rsc_location1.exp
+++ b/crm/pengine/testcases/rsc_location1.exp
@@ -1,14 +1,14 @@
<transition_graph global_timeout="60000">
<synapse id="0">
<action_set>
- <rsc_op id="1" rsc_id="rsc2" operation="start" on_node="node2" on_node_uuid="node2" allow_fail="false">
+ <rsc_op id="1" rsc_id="rsc2" operation="start" on_node="node1" on_node_uuid="node1" allow_fail="false">
<resource id="rsc2" class="heartbeat" type="apache"/>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</rsc_op>
</action_set>
<inputs/>
</synapse>
</transition_graph>
diff --git a/crm/pengine/testcases/rsc_location1.xml b/crm/pengine/testcases/rsc_location1.xml
index 78421b77ba..79f762aa8c 100644
--- a/crm/pengine/testcases/rsc_location1.xml
+++ b/crm/pengine/testcases/rsc_location1.xml
@@ -1,45 +1,47 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must not -->
<cib>
<configuration>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
- <crm_config/>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="score1" score="10">
<expression id="exp1" attribute="rsc1" operation="colocated"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
</lrm_resources>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true"/>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_location2.xml b/crm/pengine/testcases/rsc_location2.xml
index 1cf777f0f4..a6d959d671 100644
--- a/crm/pengine/testcases/rsc_location2.xml
+++ b/crm/pengine/testcases/rsc_location2.xml
@@ -1,60 +1,62 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must not -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="score1" score="10">
<expression id="exp1" attribute="rsc2" operation="colocated"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="score1" score="10">
<expression id="exp1" attribute="rsc2" operation="colocated"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc2" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node2"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_location3.xml b/crm/pengine/testcases/rsc_location3.xml
index cc346ce5a1..a55d40faed 100644
--- a/crm/pengine/testcases/rsc_location3.xml
+++ b/crm/pengine/testcases/rsc_location3.xml
@@ -1,51 +1,53 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must not -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_colocation id="not_same_1" from="rsc1" to="rsc2" type="must_not"/>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_location4.xml b/crm/pengine/testcases/rsc_location4.xml
index af8b0db31a..bab13ea7c7 100644
--- a/crm/pengine/testcases/rsc_location4.xml
+++ b/crm/pengine/testcases/rsc_location4.xml
@@ -1,56 +1,58 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must not -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_colocation id="not_same_1" from="rsc1" to="rsc2" type="must_not"/>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="score1" score="10">
<expression id="exp1" attribute="rsc1" operation="colocated"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/rsc_location5.xml b/crm/pengine/testcases/rsc_location5.xml
index e373544b62..218133eb66 100644
--- a/crm/pengine/testcases/rsc_location5.xml
+++ b/crm/pengine/testcases/rsc_location5.xml
@@ -1,42 +1,44 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- must not -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="score1" score="1000">
<expression id="exp1" attribute="rsc1" operation="not_colocated"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="node1"/>
</lrm_resources>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/simple1.xml b/crm/pengine/testcases/simple1.xml
index 8a7a32eb2d..8a1376f149 100644
--- a/crm/pengine/testcases/simple1.xml
+++ b/crm/pengine/testcases/simple1.xml
@@ -1,25 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="node1" crmd="offline" join="down" expected="down" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/simple11.xml b/crm/pengine/testcases/simple11.xml
index a5fd7326df..d240b84261 100644
--- a/crm/pengine/testcases/simple11.xml
+++ b/crm/pengine/testcases/simple11.xml
@@ -1,59 +1,60 @@
<?xml version="1.0"?>
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="3.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1"/>
<rule id="score1" score="10.0">
<expression attribute="uname" operation="eq" value="node1"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="can2" score="1">
<expression attribute="uname" operation="eq" value="node1"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/simple12.xml b/crm/pengine/testcases/simple12.xml
index 4ea533cf24..ba692ec21d 100644
--- a/crm/pengine/testcases/simple12.xml
+++ b/crm/pengine/testcases/simple12.xml
@@ -1,48 +1,49 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
<crm_config>
<nvpair id="symmetric_cluster" name="symetric_cluster" value="false"/>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
</crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
<node id="node2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache"/>
<resource id="rsc2" class="heartbeat" type="apache"/>
</resources>
<constraints>
<rsc_location id="run_rsc1" rsc="rsc1">
<rule id="can1" score="1"/>
<rule id="score1" score="10.0">
<expression attribute="uname" operation="eq" value="node2"/>
</rule>
</rsc_location>
<rsc_location id="run_rsc2" rsc="rsc2">
<rule id="can2" score="1">
<expression attribute="uname" operation="eq" value="node1"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="node2" uname="node2" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/simple2.xml b/crm/pengine/testcases/simple2.xml
index 65f4df575b..a5a55eb5fa 100644
--- a/crm/pengine/testcases/simple2.xml
+++ b/crm/pengine/testcases/simple2.xml
@@ -1,34 +1,36 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="uuid1" uname="node1" type="member"/>
<node id="uuid2" uname="node2" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="uuid1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
<node_state id="uuid2" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources/>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/simple3.xml b/crm/pengine/testcases/simple3.xml
index c164c5dc69..5e12f4acf0 100644
--- a/crm/pengine/testcases/simple3.xml
+++ b/crm/pengine/testcases/simple3.xml
@@ -1,27 +1,29 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="stop" rsc_state="stopped" op_status="0" rc_code="0" on_node="hadev"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/simple4.xml b/crm/pengine/testcases/simple4.xml
index 4ea3a878af..953fad0855 100644
--- a/crm/pengine/testcases/simple4.xml
+++ b/crm/pengine/testcases/simple4.xml
@@ -1,27 +1,29 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="failed" op_status="4" rc_code="4" on_node="hadev"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/simple6.xml b/crm/pengine/testcases/simple6.xml
index 56c2906f5e..a7e3689f2e 100644
--- a/crm/pengine/testcases/simple6.xml
+++ b/crm/pengine/testcases/simple6.xml
@@ -1,42 +1,44 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- stop rsc1 start rsc2 -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="1.0"/>
</attributes>
</instance_attributes>
</resource>
<resource id="rsc2" class="heartbeat" type="apache">
<instance_attributes>
<attributes>
<nvpair name="priority" value="2.0"/>
</attributes>
</instance_attributes>
</resource>
</resources>
<constraints>
<rsc_colocation id="not_same_1" from="rsc1" to="rsc2" type="must_not"/>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="hadev"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/testcases/simple7.xml b/crm/pengine/testcases/simple7.xml
index 445b55a60f..5709de1de9 100644
--- a/crm/pengine/testcases/simple7.xml
+++ b/crm/pengine/testcases/simple7.xml
@@ -1,28 +1,30 @@
<?xml version="1.0"?>
<!DOCTYPE cib SYSTEM "crm-1.0.dtd">
<!-- shutdown -->
<cib>
<configuration>
- <crm_config/>
+ <crm_config>
+ <nvpair id="no_quorum_policy" name="no_quorum_policy" value="ignore"/>
+ </crm_config>
<nodes>
<node id="node1" uname="node1" type="member"/>
</nodes>
<resources>
<resource id="rsc1" class="heartbeat" type="apache" priority="1.0"/>
</resources>
<constraints>
</constraints>
</configuration>
<status>
<node_state id="node1" uname="node1" crmd="online" join="member" expected="member" timestamp="1086187789" in_ccm="true" shutdown="1086187789">
<lrm>
<lrm_agents>
<lrm_agent class="heartbeat" type="apache"/>
</lrm_agents>
<lrm_resources>
<lrm_resource id="rsc1" last_op="start" rsc_state="started" op_status="0" rc_code="0" on_node="hadev"/>
</lrm_resources>
</lrm>
</node_state>
</status>
</cib>
diff --git a/crm/pengine/unpack.c b/crm/pengine/unpack.c
index b9c2b0a8e7..83a3aeed60 100644
--- a/crm/pengine/unpack.c
+++ b/crm/pengine/unpack.c
@@ -1,1220 +1,1221 @@
-/* $Id: unpack.c,v 1.73 2005/04/11 15:34:12 andrew Exp $ */
+/* $Id: unpack.c,v 1.74 2005/04/13 08:13:26 andrew Exp $ */
/*
* 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 <portability.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 <lrm/lrm_api.h>
#include <glib.h>
#include <heartbeat.h> /* for ONLINESTATUS */
#include <pengine.h>
#include <pe_utils.h>
#include <pe_rules.h>
gboolean unpack_rsc_to_attr(crm_data_t * xml_obj,
GListPtr rsc_list,
GListPtr node_list,
GListPtr *placement_constraints);
gboolean unpack_rsc_to_node(crm_data_t * xml_obj,
GListPtr rsc_list,
GListPtr node_list,
GListPtr *placement_constraints);
gboolean unpack_rsc_order(
crm_data_t * xml_obj, GListPtr rsc_list, GListPtr *ordering_constraints);
gboolean unpack_rsc_colocation(
crm_data_t * xml_obj, GListPtr rsc_list, GListPtr *ordering_constraints);
gboolean unpack_rsc_location(
crm_data_t * xml_obj, GListPtr rsc_list, GListPtr node_list,
GListPtr *ordering_constraints);
gboolean unpack_lrm_rsc_state(
node_t *node, crm_data_t * lrm_state,
GListPtr rsc_list, GListPtr nodes,
GListPtr *actions, GListPtr *placement_constraints);
gboolean add_node_attrs(crm_data_t * attrs, node_t *node);
gboolean unpack_healthy_resource(GListPtr *placement_constraints, GListPtr *actions,
crm_data_t * rsc_entry, resource_t *rsc_lh, node_t *node);
gboolean unpack_failed_resource(GListPtr *placement_constraints,
crm_data_t * rsc_entry, resource_t *rsc_lh, node_t *node);
gboolean determine_online_status(crm_data_t * node_state, node_t *this_node);
gboolean unpack_lrm_agents(node_t *node, crm_data_t * agent_list);
gboolean rsc_colocation_new(
const char *id, enum con_strength strength,
resource_t *rsc_lh, resource_t *rsc_rh);
gboolean create_ordering(
const char *id, enum con_strength strength,
resource_t *rsc_lh, resource_t *rsc_rh, GListPtr *ordering_constraints);
rsc_to_node_t *rsc2node_new(
const char *id, resource_t *rsc,
double weight, gboolean can_run, node_t *node,
GListPtr *placement_constraints);
const char *get_agent_param(resource_t *rsc, const char *param);
const char *get_agent_param_rsc(resource_t *rsc, const char *param);
const void *get_agent_param_metadata(resource_t *rsc, const char *param);
const char *get_agent_param_global(resource_t *rsc, const char *param);
const char *param_value(crm_data_t * parent, const char *name);
gboolean
unpack_config(crm_data_t * config)
{
const char *value = NULL;
value = param_value(config, "transition_timeout");
if(value != NULL) {
int tmp = atoi(value);
if(tmp > 0) {
transition_timeout = value;
} else {
crm_warn("Invalid value for %s: %s",
"transition_timeout", value);
}
}
crm_devel("%s set to: %s",
"transition_timeout", transition_timeout);
value = param_value(config, "stonith_enabled");
if(value != NULL) {
crm_str_to_boolean(value, &stonith_enabled);
}
crm_info("STONITH of failed nodes is %s", stonith_enabled?"enabled":"disabled");
value = param_value(config, "symmetric_cluster");
if(value != NULL) {
crm_str_to_boolean(value, &symmetric_cluster);
}
if(symmetric_cluster) {
crm_info("Cluster is symmetric"
" - resources can run anywhere by default");
}
value = param_value(config, "no_quorum_policy");
if(safe_str_eq(value, "ignore")) {
no_quorum_policy = no_quorum_ignore;
} else if(safe_str_eq(value, "stop")) {
no_quorum_policy = no_quorum_stop;
} else {
no_quorum_policy = no_quorum_freeze;
}
switch (no_quorum_policy) {
case no_quorum_freeze:
crm_info("On loss of CCM Quorum: Freeze resources");
break;
case no_quorum_stop:
crm_info("On loss of CCM Quorum: Stop ALL resources");
break;
case no_quorum_ignore:
crm_warn("On loss of CCM Quorum: Ignore");
break;
}
return TRUE;
}
const char *
param_value(crm_data_t * parent, const char *name)
{
crm_data_t * a_default = NULL;
if(parent != NULL) {
a_default = find_entity(
parent, XML_CIB_TAG_NVPAIR, name, FALSE);
}
if(a_default == NULL) {
crm_warn("Option %s not set", name);
return NULL;
}
return crm_element_value(a_default, XML_NVPAIR_ATTR_VALUE);
}
const char *
get_agent_param(resource_t *rsc, const char *param)
{
const char *value = NULL;
if(param == NULL) {
return NULL;
}
value = get_agent_param_rsc(rsc, param);
if(value == NULL) {
value = get_agent_param_metadata(rsc, param);
}
if(value == NULL) {
value = get_agent_param_global(rsc, param);
}
return value;
}
const char *
get_agent_param_rsc(resource_t *rsc, const char *param)
{
crm_data_t * xml_rsc = rsc->xml;
return crm_element_value(xml_rsc, param);
}
const void *
get_agent_param_metadata(resource_t *rsc, const char *param)
{
return NULL;
}
const char *
get_agent_param_global(resource_t *rsc, const char *param)
{
const char * value = NULL;/*g_hashtable_lookup(agent_global_defaults, param); */
if(value == NULL) {
crm_err("No global value default for %s", param);
}
return value;
}
gboolean
unpack_global_defaults(crm_data_t * defaults)
{
return TRUE;
}
gboolean
unpack_nodes(crm_data_t * xml_nodes, GListPtr *nodes)
{
node_t *new_node = NULL;
crm_data_t * attrs = NULL;
const char *id = NULL;
const char *uname = NULL;
const char *type = NULL;
crm_verbose("Begining unpack...");
xml_child_iter(
xml_nodes, xml_obj, XML_CIB_TAG_NODE,
id = crm_element_value(xml_obj, XML_ATTR_ID);
uname = crm_element_value(xml_obj, XML_ATTR_UNAME);
type = crm_element_value(xml_obj, XML_ATTR_TYPE);
crm_verbose("Processing node %s/%s", uname, id);
attrs = find_xml_node(xml_obj, "attributes", FALSE);
if(id == NULL) {
crm_err("Must specify id tag in <node>");
continue;
}
if(type == NULL) {
crm_err("Must specify type tag in <node>");
continue;
}
crm_malloc(new_node, sizeof(node_t));
if(new_node == NULL) {
return FALSE;
}
new_node->weight = 0;
new_node->fixed = FALSE;
crm_malloc(new_node->details,
sizeof(struct node_shared_s));
if(new_node->details == NULL) {
crm_free(new_node);
return FALSE;
}
crm_verbose("Creaing node for entry %s/%s", uname, id);
new_node->details->id = id;
new_node->details->uname = uname;
new_node->details->type = node_ping;
new_node->details->online = FALSE;
new_node->details->shutdown = FALSE;
new_node->details->running_rsc = NULL;
new_node->details->agents = NULL;
new_node->details->attrs = g_hash_table_new(
g_str_hash, g_str_equal);
if(have_quorum == FALSE && no_quorum_policy == no_quorum_stop) {
/* start shutting resources down */
new_node->weight = -INFINITY;
}
if(stonith_enabled) {
/* all nodes are unclean until we've seen their
* status entry
*/
new_node->details->unclean = TRUE;
} else {
/* blind faith... */
new_node->details->unclean = FALSE;
}
if(safe_str_eq(type, "member")) {
new_node->details->type = node_member;
}
add_node_attrs(xml_obj, new_node);
if(crm_is_true(g_hash_table_lookup(
new_node->details->attrs, "standby"))) {
crm_info("Node %s is in standby-mode",
new_node->details->uname);
new_node->weight = -INFINITY;
}
*nodes = g_list_append(*nodes, new_node);
crm_verbose("Done with node %s",
crm_element_value(xml_obj, XML_ATTR_UNAME));
crm_devel_action(print_node("Added", new_node, FALSE));
);
*nodes = g_list_sort(*nodes, sort_node_weight);
return TRUE;
}
gboolean
unpack_resources(crm_data_t * xml_resources,
GListPtr *resources,
GListPtr *actions,
GListPtr *ordering_constraints,
GListPtr *placement_constraints,
GListPtr all_nodes)
{
crm_verbose("Begining unpack...");
xml_child_iter(
xml_resources, xml_obj, NULL,
resource_t *new_rsc = NULL;
if(common_unpack(xml_obj, &new_rsc)) {
*resources = g_list_append(*resources, new_rsc);
crm_devel_action(
print_resource("Added", new_rsc, FALSE));
if(symmetric_cluster) {
rsc_to_node_t *new_con = rsc2node_new(
"symmetric_default", new_rsc, 0,
TRUE, NULL, placement_constraints);
new_con->node_list_rh = node_list_dup(all_nodes, FALSE);
}
} else {
crm_err("Failed unpacking resource %s",
crm_element_value(xml_obj, XML_ATTR_ID));
}
);
*resources = g_list_sort(*resources, sort_rsc_priority);
return TRUE;
}
gboolean
unpack_constraints(crm_data_t * xml_constraints,
GListPtr nodes, GListPtr resources,
GListPtr *placement_constraints,
GListPtr *ordering_constraints)
{
crm_verbose("Begining unpack...");
xml_child_iter(
xml_constraints, xml_obj, NULL,
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
if(id == NULL) {
crm_err("Constraint <%s...> must have an id",
crm_element_name(xml_obj));
continue;
}
crm_verbose("Processing constraint %s %s", crm_element_name(xml_obj),id);
if(safe_str_eq(XML_CONS_TAG_RSC_ORDER, crm_element_name(xml_obj))) {
unpack_rsc_order(
xml_obj, resources, ordering_constraints);
} else if(safe_str_eq(XML_CONS_TAG_RSC_DEPEND, crm_element_name(xml_obj))) {
unpack_rsc_colocation(
xml_obj, resources, ordering_constraints);
} else if(safe_str_eq(XML_CONS_TAG_RSC_LOCATION, crm_element_name(xml_obj))) {
unpack_rsc_location(
xml_obj, resources, nodes, placement_constraints);
} else {
crm_err("Unsupported constraint type: %s", crm_element_name(xml_obj));
}
);
return TRUE;
}
rsc_to_node_t *
rsc2node_new(const char *id, resource_t *rsc,
double weight, gboolean can, node_t *node,
GListPtr *placement_constraints)
{
rsc_to_node_t *new_con = NULL;
if(rsc == NULL || id == NULL) {
crm_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc);
return NULL;
}
crm_malloc(new_con, sizeof(rsc_to_node_t));
if(new_con != NULL) {
new_con->id = id;
new_con->rsc_lh = rsc;
new_con->node_list_rh = NULL;
new_con->weight = weight;
if(node != NULL) {
new_con->node_list_rh = g_list_append(NULL, node);
}
*placement_constraints = g_list_append(*placement_constraints, new_con);
}
return new_con;
}
/* remove nodes that are down, stopping */
/* create +ve rsc_to_node constraints between resources and the nodes they are running on */
/* anything else? */
gboolean
unpack_status(crm_data_t * status,
GListPtr nodes, GListPtr rsc_list,
GListPtr *actions, GListPtr *placement_constraints)
{
const char *uname = NULL;
crm_data_t * lrm_rsc = NULL;
crm_data_t * lrm_agents = NULL;
crm_data_t * attrs = NULL;
node_t *this_node = NULL;
crm_verbose("Begining unpack");
xml_child_iter(
status, node_state, XML_CIB_TAG_STATE,
/* id = crm_element_value(node_state, XML_ATTR_ID); */
uname = crm_element_value(node_state, XML_ATTR_UNAME);
attrs = find_xml_node(node_state, XML_LRM_TAG_ATTRIBUTES,FALSE);
lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
lrm_agents = find_xml_node(lrm_rsc, XML_LRM_TAG_AGENTS, FALSE);
lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE);
crm_verbose("Processing node %s", uname);
this_node = pe_find_node(nodes, uname);
if(uname == NULL) {
/* error */
continue;
} else if(this_node == NULL) {
crm_warn("Node %s in status section no longer exists",
uname);
continue;
}
/* Mark the node as provisionally clean
* - at least we have seen it in the current cluster's lifetime
*/
this_node->details->unclean = FALSE;
crm_verbose("Adding runtime node attrs");
add_node_attrs(node_state, this_node);
crm_verbose("determining node state");
determine_online_status(node_state, this_node);
if(this_node->details->online || stonith_enabled) {
/* offline nodes run no resources...
* unless stonith is enabled in which case we need to
* make sure rsc start events happen after the stonith
*/
crm_verbose("Processing lrm resource entries");
unpack_lrm_rsc_state(
this_node, lrm_rsc, rsc_list, nodes,
actions, placement_constraints);
}
);
return TRUE;
}
gboolean
determine_online_status(crm_data_t * node_state, node_t *this_node)
{
gboolean online = FALSE;
const char *uname = crm_element_value(node_state,XML_ATTR_UNAME);
const char *exp_state =
crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE);
const char *join_state =
crm_element_value(node_state, XML_CIB_ATTR_JOINSTATE);
const char *crm_state =
crm_element_value(node_state, XML_CIB_ATTR_CRMDSTATE);
const char *ccm_state =
crm_element_value(node_state, XML_CIB_ATTR_INCCM);
const char *ha_state =
crm_element_value(node_state, XML_CIB_ATTR_HASTATE);
const char *shutdown =
crm_element_value(node_state, XML_CIB_ATTR_SHUTDOWN);
if(this_node == NULL) {
return online;
}
if(shutdown != NULL) {
this_node->details->shutdown = TRUE;
}
if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) {
this_node->details->expected_up = TRUE;
}
if(stonith_enabled == FALSE) {
if(!crm_is_true(ccm_state) || safe_str_eq(ha_state,DEADSTATUS)){
crm_debug("Node is down: ha_state=%s, ccm_state=%s",
crm_str(ha_state), crm_str(ccm_state));
} else if(!crm_is_true(ccm_state)
|| safe_str_eq(ha_state, DEADSTATUS)) {
} else if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)
&& safe_str_eq(crm_state, ONLINESTATUS)) {
online = TRUE;
} else if(this_node->details->expected_up == FALSE) {
crm_debug("CRMd is down: ha_state=%s, ccm_state=%s",
crm_str(ha_state), crm_str(ccm_state));
crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
crm_str(crm_state), crm_str(join_state),
crm_str(exp_state));
} else {
/* mark it unclean */
this_node->details->unclean = TRUE;
crm_err("Node %s is partially & un-expectedly down",
uname);
crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
crm_str(crm_state), crm_str(join_state),
crm_str(exp_state));
}
} else {
if(crm_is_true(ccm_state)
&& (ha_state == NULL || safe_str_eq(ha_state, ACTIVESTATUS))
+ && safe_str_eq(crm_state, ONLINESTATUS)
&& safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) {
online = TRUE;
} else if(this_node->details->expected_up == FALSE) {
crm_debug("CRMd on %s is down: ha_state=%s, ccm_state=%s",
uname, crm_str(ha_state), crm_str(ccm_state));
crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
crm_str(crm_state), crm_str(join_state),
crm_str(exp_state));
} else {
/* mark it unclean */
this_node->details->unclean = TRUE;
crm_err("Node %s is un-expectedly down", uname);
crm_debug("\tha_state=%s, ccm_state=%s",
crm_str(ha_state), crm_str(ccm_state));
crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
crm_str(crm_state), crm_str(join_state),
crm_str(exp_state));
}
}
if(online) {
crm_debug("Node %s is online", uname);
this_node->details->online = TRUE;
} else {
/* remove node from contention */
crm_debug("Node %s is down", uname);
this_node->weight = -INFINITY;
this_node->fixed = TRUE;
}
if(this_node->details->unclean) {
crm_warn("Node %s is unclean", uname);
}
if(this_node->details->shutdown) {
/* dont run resources here */
this_node->weight = -INFINITY;
this_node->fixed = TRUE;
crm_debug("Node %s is due for shutdown", uname);
}
return online;
}
gboolean
unpack_lrm_agents(node_t *node, crm_data_t * agent_list)
{
/* if the agent is not listed, remove the node from
* the resource's list of allowed_nodes
*/
lrm_agent_t *agent = NULL;
const char *version = NULL;
if(agent_list == NULL) {
return FALSE;
}
xml_child_iter(
agent_list, xml_agent, XML_LRM_TAG_AGENT,
crm_malloc(agent, sizeof(lrm_agent_t));
if(agent == NULL) {
continue;
}
agent->class = crm_element_value(xml_agent, XML_AGENT_ATTR_CLASS);
agent->type = crm_element_value(xml_agent, XML_ATTR_TYPE);
version = crm_element_value(xml_agent, XML_ATTR_VERSION);
agent->version = version?version:"0.0";
crm_trace("Adding agent %s/%s %s to node %s",
agent->class,
agent->type,
agent->version,
node->details->uname);
node->details->agents = g_list_append(
node->details->agents, agent);
);
return TRUE;
}
gboolean
unpack_lrm_rsc_state(node_t *node, crm_data_t * lrm_rsc,
GListPtr rsc_list, GListPtr nodes,
GListPtr *actions, GListPtr *placement_constraints)
{
const char *rsc_id = NULL;
const char *node_id = NULL;
const char *rsc_state = NULL;
const char *op_status = NULL;
const char *last_rc = NULL;
const char *last_op = NULL;
resource_t *rsc_lh = NULL;
op_status_t action_status_i = LRM_OP_ERROR;
xml_child_iter(
lrm_rsc, rsc_entry, XML_LRM_TAG_RESOURCE,
rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID);
node_id = crm_element_value(rsc_entry, XML_LRM_ATTR_TARGET);
rsc_state = crm_element_value(rsc_entry, XML_LRM_ATTR_RSCSTATE);
op_status = crm_element_value(rsc_entry, XML_LRM_ATTR_OPSTATUS);
last_rc = crm_element_value(rsc_entry, XML_LRM_ATTR_RC);
last_op = crm_element_value(rsc_entry, XML_LRM_ATTR_LASTOP);
rsc_lh = pe_find_resource(rsc_list, rsc_id);
crm_verbose("[%s] Processing %s on %s (%s)",
crm_element_name(rsc_entry), rsc_id, node_id, rsc_state);
if(rsc_lh == NULL) {
crm_err("Could not find a match for resource"
" %s in %s's status section",
rsc_id, node_id);
continue;
} else if(op_status == NULL) {
crm_err("Invalid resource status entry for %s in %s",
rsc_id, node_id);
continue;
}
action_status_i = atoi(op_status);
if(node->details->unclean) {
crm_debug("Node %s (where %s is running) is unclean."
" Further action depends on the value of %s",
node->details->uname, rsc_lh->id,
XML_RSC_ATTR_STOPFAIL);
/* map the status to an error and then handle as a
* failed resource.
*/
- action_status_i = LRM_OP_ERROR;
+/* action_status_i = LRM_OP_ERROR; */
} else if(action_status_i == (op_status_t)-1) {
/*
* TODO: this may need some more thought
* Some cases:
* - PE reinvoked with pending action that will succeed
* - PE reinvoked with pending action that will fail
* - After DC election
* - After startup
*
* pending start - required start
* pending stop - required stop
* pending <any> on unavailable node - stonith
*
* For now this should do
*/
if(safe_str_eq(last_op, "stop")) {
/* map this to a timeout so it is re-issued */
action_status_i = LRM_OP_TIMEOUT;
} else {
/* map this to a "done" so it is not marked
* as failed, then make sure it is re-issued
*/
- action_new(rsc_lh, start_rsc, NULL, node);
+ action_new(rsc_lh, start_rsc, NULL, NULL);
action_status_i = LRM_OP_DONE;
+ rsc_lh->start_pending = TRUE;
}
}
switch(action_status_i) {
case LRM_OP_DONE:
unpack_healthy_resource(
placement_constraints, actions,
rsc_entry, rsc_lh,node);
break;
case LRM_OP_ERROR:
case LRM_OP_TIMEOUT:
case LRM_OP_NOTSUPPORTED:
unpack_failed_resource(placement_constraints,
rsc_entry, rsc_lh,node);
break;
case LRM_OP_CANCELLED:
/* do nothing?? */
crm_warn("Dont know what to do for cancelled ops yet");
break;
}
);
return TRUE;
}
gboolean
unpack_failed_resource(GListPtr *placement_constraints,
crm_data_t * rsc_entry, resource_t *rsc_lh, node_t *node)
{
const char *last_op = crm_element_value(rsc_entry, XML_LRM_ATTR_LASTOP);
- crm_devel("Unpacking failed action %s on %s", last_op, rsc_lh->id);
+ crm_warn("Unpacking failed action %s for %s on %s",
+ last_op, rsc_lh->id, node->details->uname);
CRM_DEV_ASSERT(node != NULL);
if(crm_assert_failed) {
return FALSE;
}
/* make sure we dont allocate the resource here again*/
rsc2node_new("dont_run__generated",
rsc_lh, -INFINITY, FALSE, node, placement_constraints);
if(safe_str_eq(last_op, "start")) {
/* the resource is not actually running... nothing more to do*/
return TRUE;
} else if(stonith_enabled == FALSE
&& rsc_lh->stopfail_type == pesf_stonith) {
crm_err("Cannot fence node %s after %s on %s"
" as STONITH is disabled",
node->details->uname, last_op, rsc_lh->id);
return FALSE;
}
switch(rsc_lh->stopfail_type) {
case pesf_stonith:
/* treat it as if it is still running
* but also mark the node as unclean
*/
native_add_running(rsc_lh, node);
node->details->running_rsc = g_list_append(
node->details->running_rsc, rsc_lh);
rsc_lh->unclean = TRUE;
node->details->unclean = TRUE;
break;
case pesf_block:
/* let this depend on the stop action which will fail
* but make sure the transition continues...
*/
native_add_running(rsc_lh, node);
- (node->details->num_resources)++;
node->details->running_rsc = g_list_append(
node->details->running_rsc, rsc_lh);
/* rsc_lh->stop->timeout = NULL; /\* wait forever *\/ */
rsc_lh->unclean = TRUE;
break;
case pesf_ignore:
/* pretend nothing happened */
break;
}
return TRUE;
}
gboolean
unpack_healthy_resource(GListPtr *placement_constraints, GListPtr *actions,
crm_data_t * rsc_entry, resource_t *rsc_lh, node_t *node)
{
const char *last_op = crm_element_value(rsc_entry, XML_LRM_ATTR_LASTOP);
crm_devel("Unpacking healthy action %s on %s", last_op, rsc_lh->id);
if(safe_str_neq(last_op, "stop")) {
/* create the link between this node and the rsc */
crm_verbose("Setting cur_node = %s for rsc = %s",
node->details->uname, rsc_lh->id);
native_add_running(rsc_lh, node);
- (node->details->num_resources)++;
node->details->running_rsc = g_list_append(
node->details->running_rsc, rsc_lh);
}
return TRUE;
}
gboolean
rsc_colocation_new(const char *id, enum con_strength strength,
resource_t *rsc_lh, resource_t *rsc_rh)
{
rsc_colocation_t *new_con = NULL;
rsc_colocation_t *inverted_con = NULL;
if(rsc_lh == NULL || rsc_rh == NULL){
/* error */
return FALSE;
}
crm_malloc(new_con, sizeof(rsc_colocation_t));
if(new_con == NULL) {
return FALSE;
}
new_con->id = id;
new_con->rsc_lh = rsc_lh;
new_con->rsc_rh = rsc_rh;
new_con->strength = strength;
inverted_con = invert_constraint(new_con);
crm_devel("Adding constraint %s (%p) to %s",
new_con->id, new_con, rsc_lh->id);
rsc_lh->rsc_cons = g_list_insert_sorted(
rsc_lh->rsc_cons, new_con, sort_cons_strength);
crm_devel("Adding constraint %s (%p) to %s",
inverted_con->id, inverted_con, rsc_rh->id);
rsc_rh->rsc_cons = g_list_insert_sorted(
rsc_rh->rsc_cons, inverted_con, sort_cons_strength);
return TRUE;
}
gboolean
order_new(resource_t *lh_rsc, enum action_tasks lh_action_task, action_t *lh_action,
resource_t *rh_rsc, enum action_tasks rh_action_task, action_t *rh_action,
enum con_strength strength, GListPtr *ordering_constraints)
{
order_constraint_t *order = NULL;
if((lh_action == NULL && lh_rsc == NULL)
|| (rh_action == NULL && rh_rsc == NULL)
|| ordering_constraints == NULL){
crm_err("Invalid inputs lh_rsc=%p, lh_a=%p,"
" rh_rsc=%p, rh_a=%p, l=%p",
lh_rsc, lh_action, rh_rsc, rh_action,
ordering_constraints);
return FALSE;
}
crm_malloc(order, sizeof(order_constraint_t));
if(order == NULL) {
return FALSE;
}
order->id = order_id++;
order->strength = strength;
order->lh_rsc = lh_rsc;
order->rh_rsc = rh_rsc;
order->lh_action = lh_action;
order->rh_action = rh_action;
order->lh_action_task = lh_action_task;
order->rh_action_task = rh_action_task;
*ordering_constraints = g_list_append(
*ordering_constraints, order);
if(lh_rsc != NULL && rh_rsc != NULL) {
crm_devel("Created ordering constraint %d (%s):"
" %s/%s before %s/%s",
order->id, strength2text(order->strength),
lh_rsc->id, task2text(lh_action_task),
rh_rsc->id, task2text(rh_action_task));
} else if(lh_rsc != NULL) {
crm_devel("Created ordering constraint %d (%s):"
" %s/%s before action %d (%s)",
order->id, strength2text(order->strength),
lh_rsc->id, task2text(lh_action_task),
rh_action->id, task2text(rh_action_task));
} else if(rh_rsc != NULL) {
crm_devel("Created ordering constraint %d (%s):"
" action %d (%s) before %s/%s",
order->id, strength2text(order->strength),
lh_action->id, task2text(lh_action_task),
rh_rsc->id, task2text(rh_action_task));
} else {
crm_devel("Created ordering constraint %d (%s):"
" action %d (%s) before action %d (%s)",
order->id, strength2text(order->strength),
lh_action->id, task2text(lh_action_task),
rh_action->id, task2text(rh_action_task));
}
return TRUE;
}
gboolean
unpack_rsc_colocation(crm_data_t * xml_obj,
GListPtr rsc_list,
GListPtr *ordering_constraints)
{
enum con_strength strength_e = pecs_ignore;
const char *id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM);
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
const char *id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TO);
const char *type = crm_element_value(xml_obj, XML_ATTR_TYPE);
resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);
resource_t *rsc_rh = pe_find_resource(rsc_list, id_rh);
if(rsc_lh == NULL) {
crm_err("No resource (con=%s, rsc=%s)", id, id_lh);
return FALSE;
} else if(rsc_rh == NULL) {
crm_err("No resource (con=%s, rsc=%s)", id, id_rh);
return FALSE;
}
if(safe_str_eq(type, XML_STRENGTH_VAL_MUST)) {
strength_e = pecs_must;
} else if(safe_str_eq(type, XML_STRENGTH_VAL_SHOULD)) {
crm_err("Type %s is no longer supported", type);
strength_e = pecs_must;
} else if(safe_str_eq(type, XML_STRENGTH_VAL_SHOULDNOT)) {
crm_err("Type %s is no longer supported", type);
strength_e = pecs_must_not;
} else if(safe_str_eq(type, XML_STRENGTH_VAL_MUSTNOT)) {
strength_e = pecs_must_not;
} else {
crm_err("Unknown value for %s: %s", XML_ATTR_TYPE, type);
return FALSE;
}
return rsc_colocation_new(id, strength_e, rsc_lh, rsc_rh);
}
gboolean
unpack_rsc_order(
crm_data_t * xml_obj, GListPtr rsc_list, GListPtr *ordering_constraints)
{
gboolean symmetrical_bool = TRUE;
gboolean action_is_start = TRUE;
gboolean type_is_after = TRUE;
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
const char *id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM);
const char *id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TO);
const char *action = crm_element_value(xml_obj, XML_CONS_ATTR_ACTION);
const char *symmetrical = crm_element_value(xml_obj, XML_CONS_ATTR_SYMMETRICAL);
const char *type = crm_element_value(xml_obj, XML_ATTR_TYPE);
resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);
resource_t *rsc_rh = pe_find_resource(rsc_list, id_rh);
if(xml_obj == NULL) {
crm_err("No constraint object to process.");
return FALSE;
} else if(id == NULL) {
crm_err("%s constraint must have an id", crm_element_name(xml_obj));
return FALSE;
} else if(rsc_lh == NULL || rsc_rh == NULL) {
crm_err("Constraint %s needs two sides lh: %p rh: %p"
" (NULL indicates missing side)",
id, rsc_lh, rsc_rh);
return FALSE;
}
crm_str_to_boolean(symmetrical, &symmetrical_bool);
if(safe_str_eq(type, "before")) {
type_is_after = FALSE;
}
if(safe_str_eq(action, CRMD_RSCSTATE_STOP)) {
action_is_start = FALSE;
}
#if 1
if((type_is_after && action_is_start)
|| (type_is_after == FALSE && action_is_start == FALSE)){
if(symmetrical_bool || action_is_start == FALSE) {
order_new(rsc_lh, stop_rsc, NULL, rsc_rh, stop_rsc, NULL,
pecs_startstop, ordering_constraints);
}
if(symmetrical_bool || action_is_start) {
order_new(rsc_rh, start_rsc, NULL, rsc_lh, start_rsc, NULL,
pecs_startstop, ordering_constraints);
}
} else {
if(symmetrical_bool || action_is_start == FALSE) {
order_new(rsc_rh, stop_rsc, NULL, rsc_lh, stop_rsc, NULL,
pecs_startstop, ordering_constraints);
}
if(symmetrical_bool || action_is_start) {
order_new(rsc_lh, start_rsc, NULL, rsc_rh, start_rsc, NULL,
pecs_startstop, ordering_constraints);
}
}
#else
if(type_is_after) {
order_new(rsc_lh, stop_rsc, NULL, rsc_rh, stop_rsc, NULL,
pecs_startstop, ordering_constraints);
order_new(rsc_rh, start_rsc, NULL, rsc_lh, start_rsc, NULL,
pecs_startstop, ordering_constraints);
} else {
order_new(rsc_rh, stop_rsc, NULL, rsc_lh, stop_rsc, NULL,
pecs_startstop, ordering_constraints);
order_new(rsc_lh, start_rsc, NULL, rsc_rh, start_rsc, NULL,
pecs_startstop, ordering_constraints);
}
#endif
return TRUE;
}
gboolean
add_node_attrs(crm_data_t *xml_obj, node_t *node)
{
g_hash_table_insert(node->details->attrs,
crm_strdup(XML_ATTR_UNAME),
crm_strdup(node->details->uname));
g_hash_table_insert(node->details->attrs,
crm_strdup(XML_ATTR_ID),
crm_strdup(node->details->id));
if(safe_str_eq(node->details->id, dc_uuid)) {
node->details->is_dc = TRUE;
g_hash_table_insert(node->details->attrs,
crm_strdup(XML_ATTR_DC),
crm_strdup(XML_BOOLEAN_TRUE));
} else {
g_hash_table_insert(node->details->attrs,
crm_strdup(XML_ATTR_DC),
crm_strdup(XML_BOOLEAN_FALSE));
}
unpack_instance_attributes(xml_obj, node->details->attrs);
return TRUE;
}
gboolean
unpack_rsc_location(
crm_data_t * xml_obj,
GListPtr rsc_list, GListPtr node_list, GListPtr *placement_constraints)
{
gboolean were_rules = FALSE;
const char *id_lh = crm_element_value(xml_obj, "rsc");
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);
if(rsc_lh == NULL) {
crm_warn("No resource (con=%s, rsc=%s)", id, id_lh);
return FALSE;
}
xml_child_iter(
xml_obj, rule, XML_TAG_RULE,
gboolean first_expr = TRUE;
gboolean can_run = FALSE;
gboolean do_and = TRUE;
gboolean rule_has_expressions;
const char *rule_id = crm_element_value(rule, XML_ATTR_ID);
const char *score = crm_element_value(rule, XML_RULE_ATTR_SCORE);
const char *boolean = crm_element_value(rule, XML_RULE_ATTR_BOOLEAN_OP);
GListPtr match_L = NULL;
GListPtr old_list = NULL;
float score_f = 0.0;
rsc_to_node_t *new_con = NULL;
were_rules = TRUE;
if(score == NULL) {
score_f = 0.0;
} else if(safe_str_eq(score, MINUS_INFINITY_S)) {
score_f = -INFINITY;
} else if(safe_str_eq(score, INFINITY_S)) {
score_f = INFINITY;
} else {
score_f = atof(score);
}
if(safe_str_eq(boolean, "or")) {
do_and = FALSE;
}
if(score_f >= 0.0) {
can_run = TRUE;
}
new_con = rsc2node_new(rule_id, rsc_lh, score_f,
can_run, NULL, placement_constraints);
if(new_con == NULL) {
continue;
}
crm_trace("processing rule: %s",
crm_element_value(rule, XML_ATTR_ID));
rule_has_expressions = FALSE;
xml_child_iter(
rule, expr, XML_TAG_EXPRESSION,
const char *attr = crm_element_value(
expr, XML_EXPR_ATTR_ATTRIBUTE);
const char *op = crm_element_value(
expr, XML_EXPR_ATTR_OPERATION);
const char *value = crm_element_value(
expr, XML_EXPR_ATTR_VALUE);
const char *type = crm_element_value(
expr, XML_EXPR_ATTR_TYPE);
rule_has_expressions = TRUE;
crm_trace("processing expression: %s",
crm_element_value(expr, XML_ATTR_ID));
match_L = apply_node_expression(
attr, op, value, type, node_list);
if(first_expr) {
new_con->node_list_rh = node_list_dup(
match_L, FALSE);
first_expr = FALSE;
continue;
}
old_list = new_con->node_list_rh;
if(do_and) {
crm_trace("do_and");
new_con->node_list_rh = node_list_and(
old_list, match_L, FALSE);
} else {
crm_trace("do_or");
new_con->node_list_rh = node_list_or(
old_list, match_L, FALSE);
}
pe_free_shallow_adv(match_L, FALSE);
pe_free_shallow_adv(old_list, TRUE);
);
if(rule_has_expressions == FALSE && symmetric_cluster == FALSE) {
/* feels like a hack */
crm_devel("Rule %s had no expressions,"
" adding all nodes", crm_element_value(rule, XML_ATTR_ID));
new_con->node_list_rh = node_list_dup(node_list,FALSE);
}
if(new_con->node_list_rh == NULL) {
crm_debug("No matching nodes for constraint/rule %s/%s",
id, crm_element_value(rule, XML_ATTR_ID));
}
crm_devel_action(print_rsc_to_node("Added", new_con, FALSE));
);
if(were_rules == FALSE) {
crm_debug("no rules for constraint %s", id);
}
return TRUE;
}
diff --git a/crm/pengine/utils.c b/crm/pengine/utils.c
index 8bed1bed95..4c458d5669 100644
--- a/crm/pengine/utils.c
+++ b/crm/pengine/utils.c
@@ -1,1253 +1,1252 @@
-/* $Id: utils.c,v 1.65 2005/04/11 10:40:10 andrew Exp $ */
+/* $Id: utils.c,v 1.66 2005/04/13 08:13:26 andrew Exp $ */
/*
* 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 <portability.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/util.h>
#include <glib.h>
#include <pengine.h>
#include <pe_utils.h>
int action_id = 1;
int color_id = 0;
+extern GListPtr global_action_list;
void print_str_str(gpointer key, gpointer value, gpointer user_data);
gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
const char *find_action_timeout(resource_t *rsc, enum action_tasks task);
/* only for rsc_colocation constraints */
rsc_colocation_t *
invert_constraint(rsc_colocation_t *constraint)
{
rsc_colocation_t *inverted_con = NULL;
crm_verbose("Inverting constraint");
if(constraint == NULL) {
crm_err("Cannot invert NULL constraint");
return NULL;
}
crm_malloc(inverted_con, sizeof(rsc_colocation_t));
if(inverted_con == NULL) {
return NULL;
}
inverted_con->id = crm_strdup(constraint->id);
inverted_con->strength = constraint->strength;
/* swap the direction */
inverted_con->rsc_lh = constraint->rsc_rh;
inverted_con->rsc_rh = constraint->rsc_lh;
crm_devel_action(
print_rsc_colocation("Inverted constraint", inverted_con, FALSE));
return inverted_con;
}
/* are the contents of list1 and list2 equal
* nodes with weight < 0 are ignored if filter == TRUE
*
* slow but linear
*
*/
gboolean
node_list_eq(GListPtr list1, GListPtr list2, gboolean filter)
{
node_t *other_node;
GListPtr lhs = list1;
GListPtr rhs = list2;
slist_iter(
node, node_t, lhs, lpc,
if(node == NULL || (filter && node->weight < 0)) {
continue;
}
other_node = (node_t*)
pe_find_node(rhs, node->details->uname);
if(other_node == NULL || other_node->weight < 0) {
return FALSE;
}
);
lhs = list2;
rhs = list1;
slist_iter(
node, node_t, lhs, lpc,
if(node == NULL || (filter && node->weight < 0)) {
continue;
}
other_node = (node_t*)
pe_find_node(rhs, node->details->uname);
if(other_node == NULL || other_node->weight < 0) {
return FALSE;
}
);
return TRUE;
}
/* the intersection of list1 and list2
*/
GListPtr
node_list_and(GListPtr list1, GListPtr list2, gboolean filter)
{
GListPtr result = NULL;
unsigned lpc = 0;
for(lpc = 0; lpc < g_list_length(list1); lpc++) {
node_t *node = (node_t*)g_list_nth_data(list1, lpc);
node_t *other_node = pe_find_node(list2, node->details->uname);
node_t *new_node = NULL;
if(other_node != NULL) {
new_node = node_copy(node);
}
if(new_node != NULL) {
new_node->weight = merge_weights(
new_node->weight, other_node->weight);
if(filter && new_node->weight < 0) {
crm_free(new_node);
new_node = NULL;
}
}
if(new_node != NULL) {
result = g_list_append(result, new_node);
}
}
return result;
}
/* list1 - list2 */
GListPtr
node_list_minus(GListPtr list1, GListPtr list2, gboolean filter)
{
GListPtr result = NULL;
slist_iter(
node, node_t, list1, lpc,
node_t *other_node = pe_find_node(list2, node->details->uname);
node_t *new_node = NULL;
if(node == NULL || other_node != NULL
|| (filter && node->weight < 0)) {
continue;
}
new_node = node_copy(node);
result = g_list_append(result, new_node);
);
crm_verbose("Minus result len: %d", g_list_length(result));
return result;
}
/* list1 + list2 - (intersection of list1 and list2) */
GListPtr
node_list_xor(GListPtr list1, GListPtr list2, gboolean filter)
{
GListPtr result = NULL;
slist_iter(
node, node_t, list1, lpc,
node_t *new_node = NULL;
node_t *other_node = (node_t*)
pe_find_node(list2, node->details->uname);
if(node == NULL || other_node != NULL
|| (filter && node->weight < 0)) {
continue;
}
new_node = node_copy(node);
result = g_list_append(result, new_node);
);
slist_iter(
node, node_t, list2, lpc,
node_t *new_node = NULL;
node_t *other_node = (node_t*)
pe_find_node(list1, node->details->uname);
if(node == NULL || other_node != NULL
|| (filter && node->weight < 0)) {
continue;
}
new_node = node_copy(node);
result = g_list_append(result, new_node);
);
crm_verbose("Xor result len: %d", g_list_length(result));
return result;
}
GListPtr
node_list_or(GListPtr list1, GListPtr list2, gboolean filter)
{
node_t *other_node = NULL;
GListPtr result = NULL;
gboolean needs_filter = FALSE;
result = node_list_dup(list1, filter);
slist_iter(
node, node_t, list2, lpc,
if(node == NULL) {
continue;
}
other_node = (node_t*)pe_find_node(
result, node->details->uname);
if(other_node != NULL) {
other_node->weight = merge_weights(
other_node->weight, node->weight);
if(filter && node->weight < 0) {
needs_filter = TRUE;
}
} else {
node_t *new_node = node_copy(node);
result = g_list_append(result, new_node);
}
);
/* not the neatest way, but the most expedient for now */
if(filter && needs_filter) {
GListPtr old_result = result;
result = node_list_dup(old_result, filter);
pe_free_shallow_adv(old_result, TRUE);
}
return result;
}
GListPtr
node_list_dup(GListPtr list1, gboolean filter)
{
GListPtr result = NULL;
slist_iter(
this_node, node_t, list1, lpc,
node_t *new_node = NULL;
if(filter && this_node->weight < 0) {
continue;
}
new_node = node_copy(this_node);
if(new_node != NULL) {
result = g_list_append(result, new_node);
}
);
return result;
}
node_t *
node_copy(node_t *this_node)
{
node_t *new_node = NULL;
CRM_DEV_ASSERT(this_node != NULL);
if(this_node == NULL) {
crm_err("Failed copy of <null> node.");
return NULL;
}
crm_malloc(new_node, sizeof(node_t));
CRM_DEV_ASSERT(new_node != NULL);
if(new_node == NULL) {
return NULL;
}
crm_trace("Copying %p (%s) to %p",
this_node, this_node->details->uname, new_node);
new_node->weight = this_node->weight;
new_node->fixed = this_node->fixed;
new_node->details = this_node->details;
return new_node;
}
/*
* Create a new color with the contents of "nodes" as the list of
* possible nodes that resources with this color can be run on.
*
* Typically, when creating a color you will provide the node list from
* the resource you will first assign the color to.
*
* If "colors" != NULL, it will be added to that list
* If "resources" != NULL, it will be added to every provisional resource
* in that list
*/
color_t *
create_color(GListPtr *colors, resource_t *resource, GListPtr node_list)
{
color_t *new_color = NULL;
crm_trace("Creating color");
crm_malloc(new_color, sizeof(color_t));
if(new_color == NULL) {
return NULL;
}
new_color->id = color_id++;
new_color->local_weight = 1.0;
crm_trace("Creating color details");
crm_malloc(new_color->details, sizeof(struct color_shared_s));
if(new_color->details == NULL) {
crm_free(new_color);
return NULL;
}
new_color->details->id = new_color->id;
new_color->details->highest_priority = -1;
new_color->details->chosen_node = NULL;
new_color->details->candidate_nodes = NULL;
new_color->details->allocated_resources = NULL;
new_color->details->pending = TRUE;
if(resource != NULL) {
crm_trace("populating node list");
new_color->details->highest_priority = resource->priority;
new_color->details->candidate_nodes =
node_list_dup(node_list, TRUE);
}
crm_devel_action(print_color("Created color", new_color, TRUE));
if(colors != NULL) {
*colors = g_list_append(*colors, new_color);
}
return new_color;
}
color_t *
copy_color(color_t *a_color)
{
color_t *color_copy = NULL;
if(a_color == NULL) {
crm_err("Cannot copy NULL");
return NULL;
}
crm_malloc(color_copy, sizeof(color_t));
if(color_copy != NULL) {
color_copy->id = a_color->id;
color_copy->details = a_color->details;
color_copy->local_weight = 1.0;
}
return color_copy;
}
resource_t *
pe_find_resource(GListPtr rsc_list, const char *id)
{
unsigned lpc = 0;
resource_t *rsc = NULL;
resource_t *child_rsc = NULL;
crm_devel("Looking for %s in %d objects", id, g_list_length(rsc_list));
for(lpc = 0; lpc < g_list_length(rsc_list); lpc++) {
rsc = g_list_nth_data(rsc_list, lpc);
if(rsc != NULL && safe_str_eq(rsc->id, id)){
crm_devel("Found a match for %s", id);
return rsc;
}
}
for(lpc = 0; lpc < g_list_length(rsc_list); lpc++) {
rsc = g_list_nth_data(rsc_list, lpc);
child_rsc = rsc->fns->find_child(rsc, id);
if(child_rsc != NULL) {
crm_devel("Found a match for %s in %s",
id, rsc->id);
return child_rsc;
}
}
/* error */
return NULL;
}
node_t *
pe_find_node(GListPtr nodes, const char *uname)
{
unsigned lpc = 0;
node_t *node = NULL;
for(lpc = 0; lpc < g_list_length(nodes); lpc++) {
node = g_list_nth_data(nodes, lpc);
if(node != NULL && safe_str_eq(node->details->uname, uname)) {
return node;
}
}
/* error */
return NULL;
}
node_t *
pe_find_node_id(GListPtr nodes, const char *id)
{
unsigned lpc = 0;
node_t *node = NULL;
for(lpc = 0; lpc < g_list_length(nodes); lpc++) {
node = g_list_nth_data(nodes, lpc);
if(safe_str_eq(node->details->id, id)) {
return node;
}
}
/* error */
return NULL;
}
gint gslist_color_compare(gconstpointer a, gconstpointer b);
color_t *
find_color(GListPtr candidate_colors, color_t *other_color)
{
GListPtr tmp = g_list_find_custom(candidate_colors, other_color,
gslist_color_compare);
if(tmp != NULL) {
return (color_t *)tmp->data;
}
return NULL;
}
gint gslist_color_compare(gconstpointer a, gconstpointer b)
{
const color_t *color_a = (const color_t*)a;
const color_t *color_b = (const color_t*)b;
/* crm_trace("%d vs. %d", a?color_a->id:-2, b?color_b->id:-2); */
if(a == b) {
return 0;
} else if(a == NULL || b == NULL) {
return 1;
} else if(color_a->id == color_b->id) {
return 0;
}
return 1;
}
gint sort_rsc_priority(gconstpointer a, gconstpointer b)
{
const resource_t *resource1 = (const resource_t*)a;
const resource_t *resource2 = (const resource_t*)b;
if(a == NULL) { return 1; }
if(b == NULL) { return -1; }
if(resource1->priority > resource2->priority) {
return -1;
}
if(resource1->priority < resource2->priority) {
return 1;
}
return 0;
}
gint sort_cons_strength(gconstpointer a, gconstpointer b)
{
const rsc_colocation_t *rsc_constraint1 = (const rsc_colocation_t*)a;
const rsc_colocation_t *rsc_constraint2 = (const rsc_colocation_t*)b;
if(a == NULL) { return 1; }
if(b == NULL) { return -1; }
if(rsc_constraint1->strength > rsc_constraint2->strength) {
return 1;
}
if(rsc_constraint1->strength < rsc_constraint2->strength) {
return -1;
}
return 0;
}
gint sort_color_weight(gconstpointer a, gconstpointer b)
{
const color_t *color1 = (const color_t*)a;
const color_t *color2 = (const color_t*)b;
if(a == NULL) { return 1; }
if(b == NULL) { return -1; }
if(color1->local_weight > color2->local_weight) {
return -1;
}
if(color1->local_weight < color2->local_weight) {
return 1;
}
return 0;
}
/* return -1 if 'a' is more preferred
* return 1 if 'b' is more preferred
*/
gint sort_node_weight(gconstpointer a, gconstpointer b)
{
const node_t *node1 = (const node_t*)a;
const node_t *node2 = (const node_t*)b;
float node1_weight = 0;
float node2_weight = 0;
if(a == NULL) { return 1; }
if(b == NULL) { return -1; }
node1_weight = node1->weight;
node2_weight = node2->weight;
if(node1->details->unclean || node1->details->shutdown) {
node1_weight = -INFINITY;
}
if(node2->details->unclean || node2->details->shutdown) {
node2_weight = -INFINITY;
}
if(node1_weight > node2_weight) {
crm_devel("%s (%f) > %s (%f) : weight",
node1->details->id, node1_weight,
node2->details->id, node2_weight);
return -1;
}
if(node1_weight < node2_weight) {
crm_devel("%s (%f) < %s (%f) : weight",
node1->details->id, node1_weight,
node2->details->id, node2_weight);
return 1;
}
/* now try to balance resources across the cluster */
if(node1->details->num_resources
< node2->details->num_resources) {
crm_devel("%s (%d) < %s (%d) : resources",
node1->details->id, node1->details->num_resources,
node2->details->id, node2->details->num_resources);
return -1;
} else if(node1->details->num_resources
> node2->details->num_resources) {
crm_devel("%s (%d) > %s (%d) : resources",
node1->details->id, node1->details->num_resources,
node2->details->id, node2->details->num_resources);
return 1;
}
crm_devel("%s = %s", node1->details->id, node2->details->id);
return 0;
}
action_t *
action_new(resource_t *rsc, enum action_tasks task,
const char *timeout, node_t *on_node)
{
action_t *action = NULL;
GListPtr possible_matches = NULL;
if(rsc != NULL && task != monitor_rsc) {
possible_matches =
find_actions(rsc->actions, task, on_node);
}
- if(on_node != NULL && on_node->details->unclean) {
- crm_warn("Not creating action %s for %s because %s is unclean",
- task2text(task), rsc?rsc->id:"<NULL>",
- on_node->details->id);
- }
-
- if(on_node != NULL && on_node->details->unclean) {
- crm_warn("Not creating action %s for %s because %s is unclean",
- task2text(task), rsc?rsc->id:"<NULL>",
- on_node->details->id);
- }
-
if(possible_matches != NULL) {
if(g_list_length(possible_matches) > 1) {
crm_warn("Action %s for %s on %s exists %d times",
task2text(task), rsc?rsc->id:"<NULL>",
on_node?on_node->details->id:"<NULL>",
g_list_length(possible_matches));
}
action = g_list_nth_data(possible_matches, 0);
crm_devel("Returning existing action (%d) %s for %s on %s",
action->id,
task2text(task), rsc?rsc->id:"<NULL>",
on_node?on_node->details->id:"<NULL>");
/* todo: free possible_matches */
return action;
}
if(timeout == NULL && rsc != NULL) {
timeout = find_action_timeout(rsc, task);
}
crm_devel("Creating action %s for %s on %s",
task2text(task), rsc?rsc->id:"<NULL>",
on_node?on_node->details->id:"<NULL>");
crm_malloc(action, sizeof(action_t));
if(action != NULL) {
action->id = action_id++;
action->rsc = rsc;
action->task = task;
action->node = on_node;
+
action->actions_before = NULL;
action->actions_after = NULL;
action->failure_is_fatal = TRUE;
- action->pseudo = FALSE;
+
+ action->pseudo = FALSE;
action->dumped = FALSE;
- action->discard = FALSE;
action->runnable = TRUE;
action->processed = FALSE;
action->optional = FALSE;
action->seen_count = 0;
action->extra = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
if(timeout != NULL) {
add_hash_param(action->extra, "timeout", timeout);
}
+
if(rsc != NULL) {
+ if(on_node != NULL && !(on_node->details->online)) {
+ crm_warn("Action %s for %s is unrunnable:"
+ " %s is offline",
+ task2text(task), rsc?rsc->id:"<NULL>",
+ on_node->details->id);
+ action->runnable = FALSE;
+ }
+
crm_devel("Adding created action to its resource");
rsc->actions = g_list_append(rsc->actions, action);
if(task == start_rsc) {
rsc->starting = TRUE;
} else if(task == stop_rsc) {
rsc->stopping = TRUE;
- }
-
+ }
}
}
crm_devel("Action %d created", action->id);
+ global_action_list = g_list_append(global_action_list, action);
return action;
}
const char *
find_action_timeout(resource_t *rsc, enum action_tasks task)
{
crm_data_t *op = NULL;
if(rsc != NULL && rsc->ops_xml != NULL) {
xml_child_iter(
rsc->ops_xml, a_child, "op",
if(safe_str_eq(task2text(task),
crm_element_value(a_child,"name"))) {
op = a_child;
break;
}
);
}
if(op == NULL) {
return NULL;
}
return crm_element_value(op, "timeout");
}
const char *
strength2text(enum con_strength strength)
{
const char *result = "<unknown>";
switch(strength)
{
case pecs_ignore:
result = "ignore";
break;
case pecs_must:
result = XML_STRENGTH_VAL_MUST;
break;
case pecs_must_not:
result = XML_STRENGTH_VAL_MUSTNOT;
break;
case pecs_startstop:
result = "start/stop";
break;
}
return result;
}
const char *
task2text(enum action_tasks task)
{
const char *result = "<unknown>";
switch(task)
{
case no_action:
result = "no_action";
break;
case stop_rsc:
result = CRMD_RSCSTATE_STOP;
break;
case stopped_rsc:
result = CRMD_RSCSTATE_STOP_OK;
break;
case start_rsc:
result = CRMD_RSCSTATE_START;
break;
case started_rsc:
result = CRMD_RSCSTATE_START_OK;
break;
case shutdown_crm:
result = CRM_OP_SHUTDOWN;
break;
case stonith_node:
result = XML_CIB_ATTR_STONITH;
break;
case monitor_rsc:
result = CRMD_RSCSTATE_MON;
break;
}
return result;
}
void
print_node(const char *pre_text, node_t *node, gboolean details)
{
if(node == NULL) {
crm_devel("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_devel("%s%s%sNode %s: (weight=%f, fixed=%s)",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
node->details==NULL?"error ":node->details->online?"":"Unavailable/Unclean ",
node->details->uname,
node->weight,
node->fixed?"True":"False");
if(details && node->details != NULL) {
char *pe_mutable = crm_strdup("\t\t");
crm_devel("\t\t===Node Attributes");
g_hash_table_foreach(node->details->attrs,
print_str_str, pe_mutable);
crm_free(pe_mutable);
}
if(details) {
crm_devel("\t\t===Node Attributes");
slist_iter(
rsc, resource_t, node->details->running_rsc, lpc,
print_resource("\t\t", rsc, FALSE);
);
}
}
/*
* Used by the HashTable for-loop
*/
void print_str_str(gpointer key, gpointer value, gpointer user_data)
{
crm_devel("%s%s %s ==> %s",
user_data==NULL?"":(char*)user_data,
user_data==NULL?"":": ",
(char*)key,
(char*)value);
}
void
print_color_details(const char *pre_text,
struct color_shared_s *color,
gboolean details)
{
if(color == NULL) {
crm_devel("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_devel("%s%sColor %d: node=%s (from %d candidates)",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
color->id,
color->chosen_node==NULL?"<unset>":color->chosen_node->details->uname,
g_list_length(color->candidate_nodes));
if(details) {
slist_iter(node, node_t, color->candidate_nodes, lpc,
print_node("\t", node, FALSE));
}
}
void
print_color(const char *pre_text, color_t *color, gboolean details)
{
if(color == NULL) {
crm_devel("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_devel("%s%sColor %d: (weight=%f, node=%s, possible=%d)",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
color->id,
color->local_weight,
safe_val5("<unset>",color,details,chosen_node,details,uname),
g_list_length(color->details->candidate_nodes));
if(details) {
print_color_details("\t", color->details, details);
}
}
void
print_rsc_to_node(const char *pre_text, rsc_to_node_t *cons, gboolean details)
{
if(cons == NULL) {
crm_devel("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_devel("%s%s%s Constraint %s (%p) - %d nodes:",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
"rsc_to_node",
cons->id, cons,
g_list_length(cons->node_list_rh));
if(details == FALSE) {
crm_devel("\t%s (score=%f : node placement rule)",
safe_val3(NULL, cons, rsc_lh, id),
cons->weight);
slist_iter(
node, node_t, cons->node_list_rh, lpc,
print_node("\t\t-->", node, FALSE)
);
}
}
void
print_rsc_colocation(const char *pre_text, rsc_colocation_t *cons, gboolean details)
{
if(cons == NULL) {
crm_devel("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_devel("%s%s%s Constraint %s (%p):",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
XML_CONS_TAG_RSC_DEPEND, cons->id, cons);
if(details == FALSE) {
crm_devel("\t%s --> %s, %s",
safe_val3(NULL, cons, rsc_lh, id),
safe_val3(NULL, cons, rsc_rh, id),
strength2text(cons->strength));
}
}
void
print_resource(const char *pre_text, resource_t *rsc, gboolean details)
{
if(rsc == NULL) {
crm_devel("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
rsc->fns->dump(rsc, pre_text, details);
}
void
print_action(const char *pre_text, action_t *action, gboolean details)
{
if(action == NULL) {
crm_devel("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
switch(action->task) {
case stonith_node:
case shutdown_crm:
crm_devel("%s%s%sAction %d: %s @ %s",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
- action->discard?"Discarded ":action->optional?"Optional ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
+ action->pseudo?"Pseduo ":action->optional?"Optional ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
action->id,
task2text(action->task),
safe_val4(NULL, action, node, details, uname));
break;
default:
crm_devel("%s%s%sAction %d: %s %s @ %s",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
action->optional?"Optional ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
action->id,
task2text(action->task),
safe_val3(NULL, action, rsc, id),
safe_val4(NULL, action, node, details, uname));
break;
}
if(details) {
#if 1
crm_devel("\t\t====== Preceeding Actions");
slist_iter(
other, action_wrapper_t, action->actions_before, lpc,
print_action("\t\t", other->action, FALSE);
);
crm_devel("\t\t====== Subsequent Actions");
slist_iter(
other, action_wrapper_t, action->actions_after, lpc,
print_action("\t\t", other->action, FALSE);
);
#else
crm_devel("\t\t====== Subsequent Actions");
slist_iter(
other, action_wrapper_t, action->actions_after, lpc,
print_action("\t\t", other->action, FALSE);
);
#endif
crm_devel("\t\t====== End");
} else {
crm_devel("\t\t(seen=%d, before=%d, after=%d)",
action->seen_count,
g_list_length(action->actions_before),
g_list_length(action->actions_after));
}
}
void
pe_free_nodes(GListPtr nodes)
{
while(nodes != NULL) {
GListPtr list_item = nodes;
node_t *node = (node_t*)list_item->data;
struct node_shared_s *details = node->details;
nodes = nodes->next;
crm_trace("deleting node");
crm_trace("%s is being deleted", details->uname);
print_node("delete", node, FALSE);
if(details != NULL) {
if(details->attrs != NULL) {
g_hash_table_foreach_remove(details->attrs,
ghash_free_str_str,
NULL);
g_hash_table_destroy(details->attrs);
}
}
}
if(nodes != NULL) {
g_list_free(nodes);
}
}
gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data)
{
crm_free(key);
crm_free(value);
return TRUE;
}
void
pe_free_colors(GListPtr colors)
{
while(colors != NULL) {
GListPtr list_item = colors;
color_t *color = (color_t *)list_item->data;
struct color_shared_s *details = color->details;
colors = colors->next;
if(details != NULL) {
pe_free_shallow(details->candidate_nodes);
pe_free_shallow_adv(details->allocated_resources, FALSE);
crm_free(details->chosen_node);
crm_free(details);
}
crm_free(color);
}
if(colors != NULL) {
g_list_free(colors);
}
}
void
pe_free_shallow(GListPtr alist)
{
pe_free_shallow_adv(alist, TRUE);
}
void
pe_free_shallow_adv(GListPtr alist, gboolean with_data)
{
GListPtr item;
GListPtr item_next = alist;
while(item_next != NULL) {
item = item_next;
item_next = item_next->next;
if(with_data) {
/* crm_trace("freeing %p", item->data); */
crm_free(item->data);
}
item->data = NULL;
item->next = NULL;
g_list_free(item);
}
}
void
pe_free_resources(GListPtr resources)
{
volatile GListPtr list_item = NULL;
resource_t *rsc = NULL;
while(resources != NULL) {
list_item = resources;
rsc = (resource_t *)list_item->data;
resources = resources->next;
pe_free_shallow_adv(rsc->candidate_colors, TRUE);
g_hash_table_destroy(rsc->parameters);
rsc->fns->free(rsc);
}
if(resources != NULL) {
g_list_free(resources);
}
}
void
pe_free_actions(GListPtr actions)
{
while(actions != NULL) {
GListPtr list_item = actions;
action_t *action = (action_t *)list_item->data;
actions = actions->next;
pe_free_shallow(action->actions_before);/* action_warpper_t* */
pe_free_shallow(action->actions_after); /* action_warpper_t* */
action->actions_before = NULL;
action->actions_after = NULL;
g_hash_table_destroy(action->extra);
crm_free(action);
}
if(actions != NULL) {
g_list_free(actions);
}
}
void
pe_free_rsc_colocation(rsc_colocation_t *cons)
{
if(cons != NULL) {
crm_devel("Freeing constraint %s (%p)", cons->id, cons);
crm_free(cons);
}
}
void
pe_free_rsc_to_node(rsc_to_node_t *cons)
{
if(cons != NULL) {
/* right now we dont make copies so this isnt required */
/* pe_free_shallow(cons->node_list_rh); */ /* node_t* */
crm_free(cons);
}
}
GListPtr
find_actions(GListPtr input, enum action_tasks task, node_t *on_node)
{
GListPtr result = NULL;
slist_iter(
action, action_t, input, lpc,
if(action->task == task) {
if(on_node == NULL) {
result = g_list_append(result, action);
} else if(action->node == NULL) {
/* skip */
crm_warn("While looking for %s action on %s, "
"found an unallocated one. Assigning"
" it to the requested node...",
task2text(task),
on_node->details->uname);
action->node = on_node;
result = g_list_append(result, action);
} else if(safe_str_eq(on_node->details->id,
action->node->details->id)) {
result = g_list_append(result, action);
}
}
);
return result;
}
void
set_id(crm_data_t * xml_obj, const char *prefix, int child)
{
int id_len = 0;
gboolean use_prefix = TRUE;
gboolean use_child = TRUE;
char *new_id = NULL;
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
id_len = 1 + strlen(id);
if(child > 999) {
crm_err("Are you insane?!?"
" The CRM does not support > 1000 children per resource");
return;
} else if(child < 0) {
use_child = FALSE;
} else {
id_len += 4; /* child */
}
if(prefix == NULL || safe_str_eq(id, prefix)) {
use_prefix = FALSE;
} else {
id_len += (1 + strlen(prefix));
}
crm_malloc(new_id, id_len);
if(use_child) {
snprintf(new_id, id_len, "%s%s%s:%d",
use_prefix?prefix:"", use_prefix?":":"", id, child);
} else {
snprintf(new_id, id_len, "%s%s%s",
use_prefix?prefix:"", use_prefix?":":"", id);
}
set_xml_property_copy(xml_obj, XML_ATTR_ID, new_id);
crm_free(new_id);
}
float
merge_weights(float w1, float w2)
{
float result = w1 + w2;
if(w1 <= -INFINITY || w2 <= -INFINITY) {
if(w1 == INFINITY || w2 == INFINITY) {
crm_warn("-INFINITY + INFINITY == -INFINITY");
}
return -INFINITY;
} else if(w1 >= INFINITY || w2 >= INFINITY) {
return INFINITY;
}
/* detect wrap-around */
if(result > 0) {
if(w1 <= 0 && w2 < 0) {
result = -INFINITY;
}
} else if(w1 > 0 && w2 > 0) {
result = INFINITY;
}
/* detect +/- INFINITY */
if(result >= INFINITY) {
result = INFINITY;
} else if(result <= -INFINITY) {
result = -INFINITY;
}
return result;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 10, 1:33 AM (16 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2009504
Default Alt Text
(299 KB)

Event Timeline