Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F7609992
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
65 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crm/pengine/allocate.c b/crm/pengine/allocate.c
index dd4040cb42..0a4c715ab1 100644
--- a/crm/pengine/allocate.c
+++ b/crm/pengine/allocate.c
@@ -1,1318 +1,1339 @@
/* $Id: allocate.c,v 1.12 2006/08/14 09:06:31 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 <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 <clplumbing/cl_misc.h>
#include <glib.h>
#include <crm/pengine/status.h>
#include <pengine.h>
#include <allocate.h>
#include <utils.h>
#include <lib/crm/pengine/utils.h>
void set_alloc_actions(pe_working_set_t *data_set);
resource_alloc_functions_t resource_class_alloc_functions[] = {
{
native_set_cmds,
native_num_allowed_nodes,
native_color,
native_create_actions,
native_create_probe,
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_stonith_ordering,
native_create_notify_element,
},
{
group_set_cmds,
group_num_allowed_nodes,
group_color,
group_create_actions,
group_create_probe,
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_stonith_ordering,
group_create_notify_element,
},
{
clone_set_cmds,
clone_num_allowed_nodes,
clone_color,
clone_create_actions,
clone_create_probe,
clone_internal_constraints,
clone_agent_constraints,
clone_rsc_colocation_lh,
clone_rsc_colocation_rh,
clone_rsc_order_lh,
clone_rsc_order_rh,
clone_rsc_location,
clone_expand,
clone_stonith_ordering,
clone_create_notify_element,
},
{
clone_set_cmds,
clone_num_allowed_nodes,
clone_color,
master_create_actions,
clone_create_probe,
master_internal_constraints,
clone_agent_constraints,
clone_rsc_colocation_lh,
clone_rsc_colocation_rh,
clone_rsc_order_lh,
clone_rsc_order_rh,
clone_rsc_location,
clone_expand,
clone_stonith_ordering,
clone_create_notify_element,
}
};
static gboolean
check_rsc_parameters(resource_t *rsc, node_t *node, crm_data_t *rsc_entry,
pe_working_set_t *data_set)
{
int attr_lpc = 0;
gboolean force_restart = FALSE;
gboolean delete_resource = FALSE;
const char *value = NULL;
const char *old_value = NULL;
const char *attr_list[] = {
XML_ATTR_TYPE,
XML_AGENT_ATTR_CLASS,
XML_AGENT_ATTR_PROVIDER
};
for(; attr_lpc < DIMOF(attr_list); attr_lpc++) {
value = crm_element_value(rsc->xml, attr_list[attr_lpc]);
old_value = crm_element_value(rsc_entry, attr_list[attr_lpc]);
if(safe_str_eq(value, old_value)) {
continue;
}
force_restart = TRUE;
crm_notice("Forcing restart of %s on %s, %s changed: %s -> %s",
rsc->id, node->details->uname, attr_list[attr_lpc],
crm_str(old_value), crm_str(value));
}
if(force_restart) {
/* make sure the restart happens */
stop_action(rsc, node, FALSE);
rsc->start_pending = TRUE;
delete_resource = TRUE;
}
return delete_resource;
}
static gboolean
check_action_definition(resource_t *rsc, node_t *active_node, crm_data_t *xml_op,
pe_working_set_t *data_set)
{
char *key = NULL;
int interval = 0;
const char *interval_s = NULL;
gboolean did_change = FALSE;
crm_data_t *pnow = NULL;
GHashTable *local_rsc_params = NULL;
char *pnow_digest = NULL;
const char *param_digest = NULL;
char *local_param_digest = NULL;
#if CRM_DEPRECATED_SINCE_2_0_4
crm_data_t *params = NULL;
#endif
action_t *action = NULL;
const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
const char *op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
CRM_CHECK(active_node != NULL, return FALSE);
interval_s = get_interval(xml_op);
interval = crm_parse_int(interval_s, "0");
key = generate_op_key(rsc->id, task, interval);
if(interval > 0) {
crm_data_t *op_match = NULL;
crm_debug_2("Checking parameters for %s %s", key, task);
op_match = find_rsc_op_entry(rsc, key);
if(op_match == NULL && data_set->stop_action_orphans) {
/* create a cancel action */
action_t *cancel = NULL;
char *cancel_key = NULL;
crm_info("Orphan action will be stopped: %s on %s",
key, active_node->details->uname);
cancel_key = generate_op_key(rsc->id, CRMD_ACTION_CANCEL, interval);
cancel = custom_action(
rsc, cancel_key, CRMD_ACTION_CANCEL,
active_node, FALSE, TRUE, data_set);
add_hash_param(cancel->meta, XML_LRM_ATTR_TASK, task);
add_hash_param(cancel->meta,
XML_LRM_ATTR_INTERVAL, interval_s);
custom_action_order(
rsc, NULL, cancel,
rsc, stop_key(rsc), NULL,
pe_ordering_optional, data_set);
}
if(op_match == NULL) {
crm_debug("Orphan action detected: %s on %s",
key, active_node->details->uname);
crm_free(key); key = NULL;
return TRUE;
}
}
action = custom_action(rsc, key, task, active_node, TRUE, FALSE, data_set);
local_rsc_params = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
unpack_instance_attributes(
rsc->xml, XML_TAG_ATTR_SETS, active_node->details->attrs,
local_rsc_params, NULL, data_set->now);
pnow = create_xml_node(NULL, XML_TAG_PARAMS);
g_hash_table_foreach(action->extra, hash2field, pnow);
g_hash_table_foreach(rsc->parameters, hash2field, pnow);
g_hash_table_foreach(local_rsc_params, hash2field, pnow);
filter_action_parameters(pnow, op_version);
pnow_digest = calculate_xml_digest(pnow, TRUE);
param_digest = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST);
#if CRM_DEPRECATED_SINCE_2_0_4
if(param_digest == NULL) {
params = find_xml_node(xml_op, XML_TAG_PARAMS, TRUE);
}
if(params != NULL) {
crm_data_t *local_params = copy_xml(params);
crm_warn("Faking parameter digest creation for %s", ID(xml_op));
filter_action_parameters(local_params, op_version);
xml_remove_prop(local_params, "interval");
xml_remove_prop(local_params, "timeout");
crm_log_xml_warn(local_params, "params:used");
local_param_digest = calculate_xml_digest(local_params, TRUE);
param_digest = local_param_digest;
free_xml(local_params);
}
#endif
if(safe_str_neq(pnow_digest, param_digest)) {
did_change = TRUE;
crm_log_xml_info(pnow, "params:calc");
crm_warn("Parameters to %s on %s changed: recorded %s vs. calculated %s",
ID(xml_op), active_node->details->uname,
crm_str(param_digest), pnow_digest);
key = generate_op_key(rsc->id, task, interval);
custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
}
free_xml(pnow);
crm_free(pnow_digest);
crm_free(local_param_digest);
g_hash_table_destroy(local_rsc_params);
pe_free_action(action);
return did_change;
}
extern gboolean DeleteRsc(resource_t *rsc, node_t *node, pe_working_set_t *data_set);
static void
check_actions_for(crm_data_t *rsc_entry, node_t *node, pe_working_set_t *data_set)
{
const char *id = NULL;
const char *task = NULL;
int interval = 0;
const char *interval_s = NULL;
GListPtr op_list = NULL;
GListPtr sorted_op_list = NULL;
const char *rsc_id = ID(rsc_entry);
gboolean is_probe = FALSE;
resource_t *rsc = pe_find_resource(data_set->resources, rsc_id);
CRM_CHECK(rsc_id != NULL, return);
if(rsc == NULL) {
crm_warn("Skipping param check for resource with no actions");
return;
} else if(rsc->orphan) {
crm_debug_2("Skipping param check for orphan: %s %s",
rsc->id, task);
return;
}
crm_debug_2("Processing %s on %s", rsc->id, node->details->uname);
if(check_rsc_parameters(rsc, node, rsc_entry, data_set)) {
DeleteRsc(rsc, node, data_set);
}
xml_child_iter_filter(
rsc_entry, rsc_op, XML_LRM_TAG_RSC_OP,
op_list = g_list_append(op_list, rsc_op);
);
sorted_op_list = g_list_sort(op_list, sort_op_by_callid);
slist_iter(
rsc_op, crm_data_t, sorted_op_list, lpc,
id = ID(rsc_op);
is_probe = FALSE;
task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
interval_s = get_interval(rsc_op);
interval = crm_parse_int(interval_s, "0");
if(interval == 0 && safe_str_eq(task, CRMD_ACTION_STATUS)) {
is_probe = TRUE;
}
if(is_probe || safe_str_eq(task, CRMD_ACTION_START) || interval > 0) {
crm_debug_2("Checking resource definition: %s", rsc->id);
check_action_definition(rsc, node, rsc_op, data_set);
}
crm_debug_3("Ignoring %s params: %s", task, id);
);
g_list_free(sorted_op_list);
}
static void
check_actions(pe_working_set_t *data_set)
{
const char *id = NULL;
node_t *node = NULL;
crm_data_t *lrm_rscs = NULL;
crm_data_t *status = get_object_root(XML_CIB_TAG_STATUS, data_set->input);
xml_child_iter_filter(
status, node_state, XML_CIB_TAG_STATE,
id = crm_element_value(node_state, XML_ATTR_ID);
lrm_rscs = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
lrm_rscs = find_xml_node(lrm_rscs, XML_LRM_TAG_RESOURCES, FALSE);
node = pe_find_node_id(data_set->nodes, id);
if(node == NULL) {
continue;
}
crm_debug("Processing node %s", node->details->uname);
if(node->details->online || data_set->stonith_enabled) {
xml_child_iter_filter(
lrm_rscs, rsc_entry, XML_LRM_TAG_RESOURCE,
check_actions_for(rsc_entry, node, data_set);
);
}
);
}
static gboolean
apply_placement_constraints(pe_working_set_t *data_set)
{
crm_debug_3("Applying constraints...");
slist_iter(
cons, rsc_to_node_t, data_set->placement_constraints, lpc,
cons->rsc_lh->cmds->rsc_location(cons->rsc_lh, cons);
);
return TRUE;
}
void
set_alloc_actions(pe_working_set_t *data_set)
{
slist_iter(
rsc, resource_t, data_set->resources, lpc,
rsc->cmds = &resource_class_alloc_functions[rsc->variant];
rsc->cmds->set_cmds(rsc);
);
}
gboolean
stage0(pe_working_set_t *data_set)
{
crm_data_t * cib_constraints = get_object_root(
XML_CIB_TAG_CONSTRAINTS, data_set->input);
if(data_set->input == NULL) {
return FALSE;
}
cluster_status(data_set);
set_alloc_actions(data_set);
unpack_constraints(cib_constraints, data_set);
return TRUE;
}
/*
* Check nodes for resources started outside of the LRM
*/
gboolean
stage1(pe_working_set_t *data_set)
{
action_t *probe_complete = NULL;
action_t *probe_node_complete = NULL;
slist_iter(
node, node_t, data_set->nodes, lpc,
gboolean force_probe = FALSE;
const char *probed = g_hash_table_lookup(
node->details->attrs, CRM_OP_PROBED);
crm_debug_2("%s probed: %s", node->details->uname, probed);
if(node->details->online == FALSE) {
continue;
} else if(node->details->unclean) {
continue;
} else if(probe_complete == NULL) {
probe_complete = custom_action(
NULL, crm_strdup(CRM_OP_PROBED),
CRM_OP_PROBED, NULL, FALSE, TRUE,
data_set);
probe_complete->pseudo = TRUE;
probe_complete->optional = TRUE;
}
if(probed != NULL && crm_is_true(probed) == FALSE) {
force_probe = TRUE;
}
probe_node_complete = custom_action(
NULL, crm_strdup(CRM_OP_PROBED),
CRM_OP_PROBED, node, FALSE, TRUE, data_set);
probe_node_complete->optional = crm_is_true(probed);
probe_node_complete->priority = INFINITY;
add_hash_param(probe_node_complete->meta,
XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE);
custom_action_order(NULL, NULL, probe_node_complete,
NULL, NULL, probe_complete,
pe_ordering_optional, data_set);
slist_iter(
rsc, resource_t, data_set->resources, lpc2,
if(rsc->cmds->create_probe(
rsc, node, probe_node_complete,
force_probe, data_set)) {
probe_complete->optional = FALSE;
probe_node_complete->optional = FALSE;
custom_action_order(
NULL, NULL, probe_complete,
rsc, start_key(rsc), NULL,
pe_ordering_manditory, data_set);
}
);
);
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
stage2(pe_working_set_t *data_set)
{
crm_debug_3("Applying placement constraints");
slist_iter(
node, node_t, data_set->nodes, lpc,
if(node == NULL) {
/* error */
} else if(node->weight >= 0.0 /* global weight */
&& node->details->online
&& node->details->type == node_member) {
data_set->max_valid_nodes++;
}
);
apply_placement_constraints(data_set);
return TRUE;
}
/*
* Choose a color for all resources from highest priority and XML_STRENGTH_VAL_MUST
* dependencies 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
stage3(pe_working_set_t *data_set)
{
/* Take (next) highest resource */
slist_iter(
rsc, resource_t, data_set->resources, lpc,
rsc->cmds->internal_constraints(rsc, data_set);
rsc->cmds->color(rsc, data_set);
);
return TRUE;
}
/*
* Choose a node for each (if possible) color
*/
gboolean
stage4(pe_working_set_t *data_set)
{
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(pe_working_set_t *data_set)
{
crm_debug_3("Creating actions and internal ording constraints");
check_actions(data_set);
slist_iter(
rsc, resource_t, data_set->resources, lpc,
rsc->cmds->create_actions(rsc, data_set);
);
return TRUE;
}
/*
* Create dependacies for stonith and shutdown operations
*/
gboolean
stage6(pe_working_set_t *data_set)
{
action_t *dc_down = NULL;
action_t *stonith_op = NULL;
action_t *last_stonith = NULL;
gboolean integrity_lost = FALSE;
crm_debug_3("Processing fencing and shutdown cases");
slist_iter(
node, node_t, data_set->nodes, lpc,
stonith_op = NULL;
if(node->details->unclean && data_set->stonith_enabled
&& (data_set->have_quorum
|| data_set->no_quorum_policy == no_quorum_ignore)) {
pe_warn("Scheduling Node %s for STONITH",
node->details->uname);
stonith_op = custom_action(
NULL, crm_strdup(CRM_OP_FENCE),
CRM_OP_FENCE, node, FALSE, TRUE, data_set);
add_hash_param(
stonith_op->meta, XML_LRM_ATTR_TARGET,
node->details->uname);
add_hash_param(
stonith_op->meta, XML_LRM_ATTR_TARGET_UUID,
node->details->id);
add_hash_param(
stonith_op->meta, "stonith_action",
data_set->stonith_action);
stonith_constraints(node, stonith_op, data_set);
if(node->details->is_dc) {
dc_down = stonith_op;
} else {
if(last_stonith) {
order_actions(last_stonith, stonith_op, pe_ordering_manditory);
}
last_stonith = stonith_op;
}
} else if(node->details->online && node->details->shutdown) {
action_t *down_op = NULL;
crm_info("Scheduling Node %s for shutdown",
node->details->uname);
down_op = custom_action(
NULL, crm_strdup(CRM_OP_SHUTDOWN),
CRM_OP_SHUTDOWN, node, FALSE, TRUE, data_set);
shutdown_constraints(node, down_op, data_set);
if(node->details->is_dc) {
dc_down = down_op;
}
}
if(node->details->unclean && stonith_op == NULL) {
integrity_lost = TRUE;
pe_warn("Node %s is unclean!", node->details->uname);
}
);
if(integrity_lost) {
if(data_set->have_quorum == FALSE) {
crm_notice("Cannot fence unclean nodes until quorum is"
" attained (or no_quorum_policy is set to ignore)");
} else if(data_set->stonith_enabled == FALSE) {
pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
pe_err("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
}
}
if(dc_down != NULL) {
GListPtr shutdown_matches = find_actions(
data_set->actions, CRM_OP_SHUTDOWN, NULL);
crm_debug_2("Ordering shutdowns before %s on %s (DC)",
dc_down->task, dc_down->node->details->uname);
add_hash_param(dc_down->meta, XML_ATTR_TE_NOWAIT,
XML_BOOLEAN_TRUE);
slist_iter(
node_stop, action_t, shutdown_matches, lpc,
if(node_stop->node->details->is_dc) {
continue;
}
crm_debug("Ordering shutdown on %s before %s on %s",
node_stop->node->details->uname,
dc_down->task, dc_down->node->details->uname);
order_actions(node_stop, dc_down, pe_ordering_manditory);
);
if(last_stonith && dc_down != last_stonith) {
order_actions(last_stonith, dc_down, pe_ordering_manditory);
}
}
return TRUE;
}
/*
* Determin the sets of independant actions and the correct order for the
* actions in each set.
*
* Mark dependencies of un-runnable actions un-runnable
*
*/
gboolean
stage7(pe_working_set_t *data_set)
{
crm_debug_3("Applying ordering constraints");
slist_iter(
order, order_constraint_t, data_set->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->cmds->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->cmds->rsc_order_rh(order->lh_action, rsc, order);
} else {
/* fall back to action-to-action */
order_actions(
order->lh_action, order->rh_action, order->type);
}
);
update_action_states(data_set->actions);
return TRUE;
}
int transition_id = -1;
/*
* Create a dependency graph to send to the transitioner (via the CRMd)
*/
gboolean
stage8(pe_working_set_t *data_set)
{
const char *value = NULL;
char *transition_id_s = NULL;
transition_id++;
transition_id_s = crm_itoa(transition_id);
value = pe_pref(data_set->config_hash, "network-delay");
crm_debug("Creating transition graph %d.", transition_id);
data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH);
crm_xml_add(data_set->graph, "network-delay", value);
crm_xml_add(data_set->graph, "transition_id", transition_id_s);
crm_free(transition_id_s);
/* errors...
slist_iter(action, action_t, action_list, lpc,
if(action->optional == FALSE && action->runnable == FALSE) {
print_action("Ignoring", action, TRUE);
}
);
*/
slist_iter(
rsc, resource_t, data_set->resources, lpc,
crm_debug_4("processing actions for rsc=%s", rsc->id);
rsc->cmds->expand(rsc, data_set);
);
crm_log_xml_debug_3(
data_set->graph, "created resource-driven action list");
/* catch any non-resource specific actions */
crm_debug_4("processing non-resource actions");
slist_iter(
action, action_t, data_set->actions, lpc,
graph_element_from_action(action, data_set);
);
crm_log_xml_debug_3(data_set->graph, "created generic action list");
crm_notice("Created transition graph %d.", transition_id);
return TRUE;
}
void
cleanup_alloc_calculations(pe_working_set_t *data_set)
{
if(data_set == NULL) {
return;
}
crm_debug_3("deleting order cons: %p", data_set->ordering_constraints);
pe_free_ordering(data_set->ordering_constraints);
data_set->ordering_constraints = NULL;
crm_debug_3("deleting node cons: %p", data_set->placement_constraints);
pe_free_rsc_to_node(data_set->placement_constraints);
data_set->placement_constraints = NULL;
cleanup_calculations(data_set);
}
gboolean
unpack_constraints(crm_data_t * xml_constraints, pe_working_set_t *data_set)
{
crm_data_t *lifetime = NULL;
crm_debug_2("Begining unpack... %s",
xml_constraints?crm_element_name(xml_constraints):"<none>");
xml_child_iter(
xml_constraints, xml_obj,
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
if(id == NULL) {
crm_config_err("Constraint <%s...> must have an id",
crm_element_name(xml_obj));
continue;
}
crm_debug_3("Processing constraint %s %s",
crm_element_name(xml_obj),id);
lifetime = cl_get_struct(xml_obj, "lifetime");
if(test_ruleset(lifetime, NULL, data_set->now) == FALSE) {
crm_info("Constraint %s %s is not active",
crm_element_name(xml_obj), id);
} else if(safe_str_eq(XML_CONS_TAG_RSC_ORDER,
crm_element_name(xml_obj))) {
unpack_rsc_order(xml_obj, data_set);
} else if(safe_str_eq(XML_CONS_TAG_RSC_DEPEND,
crm_element_name(xml_obj))) {
unpack_rsc_colocation(xml_obj, data_set);
} else if(safe_str_eq(XML_CONS_TAG_RSC_LOCATION,
crm_element_name(xml_obj))) {
unpack_rsc_location(xml_obj, data_set);
} else {
pe_err("Unsupported constraint type: %s",
crm_element_name(xml_obj));
}
);
return TRUE;
}
static const char *
invert_action(const char *action)
{
if(safe_str_eq(action, CRMD_ACTION_START)) {
return CRMD_ACTION_STOP;
} else if(safe_str_eq(action, CRMD_ACTION_STOP)) {
return CRMD_ACTION_START;
} else if(safe_str_eq(action, CRMD_ACTION_PROMOTE)) {
return CRMD_ACTION_DEMOTE;
} else if(safe_str_eq(action, CRMD_ACTION_DEMOTE)) {
return CRMD_ACTION_PROMOTE;
} else if(safe_str_eq(action, CRMD_ACTION_STARTED)) {
return CRMD_ACTION_STOPPED;
} else if(safe_str_eq(action, CRMD_ACTION_STOPPED)) {
return CRMD_ACTION_STARTED;
}
pe_err("Unknown action: %s", action);
return NULL;
}
gboolean
unpack_rsc_order(crm_data_t * xml_obj, pe_working_set_t *data_set)
{
gboolean symmetrical_bool = TRUE;
enum pe_ordering cons_weight = pe_ordering_optional;
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
const char *type = crm_element_value(xml_obj, XML_ATTR_TYPE);
const char *id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TO);
const char *id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM);
const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE);
const char *action = crm_element_value(xml_obj, XML_CONS_ATTR_ACTION);
const char *action_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TOACTION);
const char *symmetrical = crm_element_value(
xml_obj, XML_CONS_ATTR_SYMMETRICAL);
resource_t *rsc_lh = NULL;
resource_t *rsc_rh = NULL;
if(xml_obj == NULL) {
crm_config_err("No constraint object to process.");
return FALSE;
} else if(id == NULL) {
crm_config_err("%s constraint must have an id",
crm_element_name(xml_obj));
return FALSE;
} else if(id_lh == NULL || id_rh == NULL) {
crm_config_err("Constraint %s needs two sides lh: %s rh: %s",
id, crm_str(id_lh), crm_str(id_rh));
return FALSE;
}
if(action == NULL) {
action = CRMD_ACTION_START;
}
if(action_rh == NULL) {
action_rh = action;
}
CRM_CHECK(action != NULL, return FALSE);
CRM_CHECK(action_rh != NULL, return FALSE);
if(safe_str_eq(type, "before")) {
id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_TO);
id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM);
action = crm_element_value(xml_obj, XML_CONS_ATTR_TOACTION);
action_rh = crm_element_value(xml_obj, XML_CONS_ATTR_ACTION);
if(action_rh == NULL) {
action_rh = CRMD_ACTION_START;
}
if(action == NULL) {
action = action_rh;
}
}
CRM_CHECK(action != NULL, return FALSE);
CRM_CHECK(action_rh != NULL, return FALSE);
rsc_lh = pe_find_resource(data_set->resources, id_rh);
rsc_rh = pe_find_resource(data_set->resources, id_lh);
if(rsc_lh == NULL) {
crm_config_err("Constraint %s: no resource found for LHS of %s", id, id_lh);
return FALSE;
} else if(rsc_rh == NULL) {
crm_config_err("Constraint %s: no resource found for RHS of %s", id, id_rh);
return FALSE;
}
if(crm_atoi(score, "0") > 0) {
/* the name seems weird but the effect is correct */
cons_weight = pe_ordering_restart;
}
custom_action_order(
rsc_lh, generate_op_key(rsc_lh->id, action, 0), NULL,
rsc_rh, generate_op_key(rsc_rh->id, action_rh, 0), NULL,
cons_weight, data_set);
if(rsc_rh->restart_type == pe_restart_restart
&& safe_str_eq(action, action_rh)) {
if(safe_str_eq(action, CRMD_ACTION_START)) {
crm_debug_2("Recover start-start: %s-%s",
rsc_lh->id, rsc_rh->id);
order_start_start(rsc_lh, rsc_rh, pe_ordering_recover);
} else if(safe_str_eq(action, CRMD_ACTION_STOP)) {
crm_debug_2("Recover stop-stop: %s-%s",
rsc_rh->id, rsc_lh->id);
order_stop_stop(rsc_rh, rsc_lh, pe_ordering_recover);
}
}
cl_str_to_boolean(symmetrical, &symmetrical_bool);
if(symmetrical_bool == FALSE) {
return TRUE;
}
action = invert_action(action);
action_rh = invert_action(action_rh);
custom_action_order(
rsc_rh, generate_op_key(rsc_rh->id, action_rh, 0), NULL,
rsc_lh, generate_op_key(rsc_lh->id, action, 0), NULL,
cons_weight, data_set);
if(rsc_lh->restart_type == pe_restart_restart
&& safe_str_eq(action, action_rh)) {
if(safe_str_eq(action, CRMD_ACTION_START)) {
crm_debug_2("Recover start-start (2): %s-%s",
rsc_lh->id, rsc_rh->id);
order_start_start(rsc_lh, rsc_rh, pe_ordering_recover);
} else if(safe_str_eq(action, CRMD_ACTION_STOP)) {
crm_debug_2("Recover stop-stop (2): %s-%s",
rsc_rh->id, rsc_lh->id);
order_stop_stop(rsc_rh, rsc_lh, pe_ordering_recover);
}
}
return TRUE;
}
gboolean
unpack_rsc_location(crm_data_t * xml_obj, pe_working_set_t *data_set)
{
gboolean empty = TRUE;
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(data_set->resources, id_lh);
if(rsc_lh == NULL) {
/* only a warn as BSC adds the constraint then the resource */
crm_config_warn("No resource (con=%s, rsc=%s)", id, id_lh);
return FALSE;
} else if(rsc_lh->is_managed == FALSE) {
crm_debug_2("Ignoring constraint %s: resource %s not managed",
id, id_lh);
return FALSE;
}
xml_child_iter_filter(
xml_obj, rule_xml, XML_TAG_RULE,
empty = FALSE;
crm_debug_2("Unpacking %s/%s", id, ID(rule_xml));
generate_location_rule(rsc_lh, rule_xml, data_set);
);
if(empty) {
crm_config_err("Invalid location constraint %s:"
" rsc_location must contain at least one rule",
ID(xml_obj));
}
return TRUE;
}
+static int
+get_node_score(const char *rule, const char *score, gboolean raw, node_t *node)
+{
+ int score_f = 0;
+ if(score == NULL) {
+ pe_err("Rule %s: no score specified. Assuming 0.", rule);
+
+ } else if(raw) {
+ score_f = char2score(score);
+
+ } else {
+ const char *attr_score = g_hash_table_lookup(
+ node->details->attrs, score);
+ if(attr_score == NULL) {
+ crm_debug("Rule %s: node %s did not have a value for %s",
+ rule, node->details->uname, score);
+ score_f = -INFINITY;
+
+ } else {
+ crm_debug("Rule %s: node %s had value %s for %s",
+ rule, node->details->uname, attr_score, score);
+ score_f = char2score(attr_score);
+ }
+ }
+ return score_f;
+}
+
+
rsc_to_node_t *
generate_location_rule(
resource_t *rsc, crm_data_t *rule_xml, pe_working_set_t *data_set)
{
const char *rule_id = NULL;
const char *score = NULL;
const char *boolean = NULL;
const char *role = NULL;
- const char *attr_score = NULL;
GListPtr match_L = NULL;
int score_f = 0;
gboolean do_and = TRUE;
gboolean accept = TRUE;
gboolean raw_score = TRUE;
rsc_to_node_t *location_rule = NULL;
rule_id = crm_element_value(rule_xml, XML_ATTR_ID);
boolean = crm_element_value(rule_xml, XML_RULE_ATTR_BOOLEAN_OP);
role = crm_element_value(rule_xml, XML_RULE_ATTR_ROLE);
crm_debug_2("Processing rule: %s", rule_id);
if(role != NULL && text2role(role) == RSC_ROLE_UNKNOWN) {
pe_err("Bad role specified for %s: %s", rule_id, role);
return NULL;
}
score = crm_element_value(rule_xml, XML_RULE_ATTR_SCORE);
if(score != NULL) {
score_f = char2score(score);
} else {
score = crm_element_value(
rule_xml, XML_RULE_ATTR_SCORE_ATTRIBUTE);
if(score == NULL) {
score = crm_element_value(
rule_xml, XML_RULE_ATTR_SCORE_MANGLED);
}
if(score != NULL) {
raw_score = FALSE;
}
}
if(safe_str_eq(boolean, "or")) {
do_and = FALSE;
}
location_rule = rsc2node_new(rule_id, rsc, 0, NULL, data_set);
if(location_rule == NULL) {
return NULL;
}
if(role != NULL) {
crm_debug_2("Setting role filter: %s", role);
location_rule->role_filter = text2role(role);
}
if(do_and) {
match_L = node_list_dup(data_set->nodes, TRUE, FALSE);
slist_iter(
node, node_t, match_L, lpc,
- node->weight = score_f;
+ node->weight = get_node_score(rule_id, score, raw_score, node);
);
}
xml_child_iter(
rule_xml, expr,
enum expression_type type = find_expression_type(expr);
+ crm_debug_2("Processing expression: %s", ID(expr));
+
if(type == not_expr) {
pe_err("Expression <%s id=%s...> is not valid",
crm_element_name(expr), crm_str(ID(expr)));
continue;
}
slist_iter(
node, node_t, data_set->nodes, lpc,
if(type == nested_rule) {
accept = test_rule(
expr, node->details->attrs,
RSC_ROLE_UNKNOWN, data_set->now);
} else {
accept = test_expression(
expr, node->details->attrs,
RSC_ROLE_UNKNOWN, data_set->now);
}
-
- if(raw_score == FALSE) {
- attr_score = g_hash_table_lookup(
- node->details->attrs, score);
- if(attr_score == NULL) {
- accept = FALSE;
- crm_debug("node %s did not have a value"
- " for %s",
- node->details->uname, score);
- } else {
- crm_debug("Rule %s: node %s had value %s for %s",
- rule_id, node->details->uname, attr_score, score);
- score_f = char2score(attr_score);
- }
- }
+
+ score_f = get_node_score(rule_id, score, raw_score, node);
+/* if(accept && score_f == -INFINITY) { */
+/* accept = FALSE; */
+/* } */
if(accept) {
node_t *local = pe_find_node_id(
match_L, node->details->id);
if(local == NULL && do_and) {
continue;
} else if(local == NULL) {
local = node_copy(node);
match_L = g_list_append(match_L, local);
}
-
- local->weight = merge_weights(
- local->weight, score_f);
- crm_debug_3("node %s now has weight %d",
- node->details->uname,local->weight);
+
+ if(do_and == FALSE) {
+ local->weight = merge_weights(
+ local->weight, score_f);
+ }
+ crm_debug_2("node %s now has weight %d",
+ node->details->uname, local->weight);
} else if(do_and && !accept) {
/* remove it */
node_t *delete = pe_find_node_id(
match_L, node->details->id);
if(delete != NULL) {
match_L = g_list_remove(match_L,delete);
crm_debug_5("node %s did not match",
node->details->uname);
}
crm_free(delete);
}
);
);
location_rule->node_list_rh = match_L;
if(location_rule->node_list_rh == NULL) {
crm_debug_2("No matching nodes for rule %s", rule_id);
return NULL;
}
crm_debug_3("%s: %d nodes matched",
rule_id, g_list_length(location_rule->node_list_rh));
crm_action_debug_3(print_rsc_to_node("Added", location_rule, FALSE));
return location_rule;
}
gboolean
rsc_colocation_new(const char *id, int score,
resource_t *rsc_lh, resource_t *rsc_rh,
const char *state_lh, const char *state_rh)
{
rsc_colocation_t *new_con = NULL;
if(rsc_lh == NULL){
crm_config_err("No resource found for LHS %s", id);
return FALSE;
} else if(rsc_rh == NULL){
crm_config_err("No resource found for RHS of %s", id);
return FALSE;
}
crm_malloc0(new_con, sizeof(rsc_colocation_t));
if(new_con == NULL) {
return FALSE;
}
if(safe_str_eq(state_lh, CRMD_ACTION_STARTED)) {
state_lh = NULL;
}
if(safe_str_eq(state_rh, CRMD_ACTION_STARTED)) {
state_rh = NULL;
}
new_con->id = id;
new_con->rsc_lh = rsc_lh;
new_con->rsc_rh = rsc_rh;
new_con->score = score;
new_con->state_lh = state_lh;
new_con->state_rh = state_rh;
crm_debug_4("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);
return TRUE;
}
/* LHS before RHS */
gboolean
custom_action_order(
resource_t *lh_rsc, char *lh_action_task, action_t *lh_action,
resource_t *rh_rsc, char *rh_action_task, action_t *rh_action,
enum pe_ordering type, pe_working_set_t *data_set)
{
order_constraint_t *order = NULL;
if((lh_action == NULL && lh_rsc == NULL)
|| (rh_action == NULL && rh_rsc == NULL)){
crm_config_err("Invalid inputs lh_rsc=%p, lh_a=%p,"
" rh_rsc=%p, rh_a=%p",
lh_rsc, lh_action, rh_rsc, rh_action);
crm_free(lh_action_task);
crm_free(rh_action_task);
return FALSE;
}
crm_malloc0(order, sizeof(order_constraint_t));
if(order == NULL) { return FALSE; }
order->id = data_set->order_id++;
order->type = type;
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;
data_set->ordering_constraints = g_list_append(
data_set->ordering_constraints, order);
if(lh_rsc != NULL && rh_rsc != NULL) {
crm_debug_4("Created ordering constraint %d (%s):"
" %s/%s before %s/%s",
order->id, ordering_type2text(order->type),
lh_rsc->id, lh_action_task,
rh_rsc->id, rh_action_task);
} else if(lh_rsc != NULL) {
crm_debug_4("Created ordering constraint %d (%s):"
" %s/%s before action %d (%s)",
order->id, ordering_type2text(order->type),
lh_rsc->id, lh_action_task,
rh_action->id, rh_action_task);
} else if(rh_rsc != NULL) {
crm_debug_4("Created ordering constraint %d (%s):"
" action %d (%s) before %s/%s",
order->id, ordering_type2text(order->type),
lh_action->id, lh_action_task,
rh_rsc->id, rh_action_task);
} else {
crm_debug_4("Created ordering constraint %d (%s):"
" action %d (%s) before action %d (%s)",
order->id, ordering_type2text(order->type),
lh_action->id, lh_action_task,
rh_action->id, rh_action_task);
}
return TRUE;
}
gboolean
unpack_rsc_colocation(crm_data_t * xml_obj, pe_working_set_t *data_set)
{
int score_i = 0;
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 *id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM);
const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE);
const char *state_lh = crm_element_value(xml_obj, XML_RULE_ATTR_FROMSTATE);
const char *state_rh = crm_element_value(xml_obj, XML_RULE_ATTR_TOSTATE);
resource_t *rsc_lh = pe_find_resource(data_set->resources, id_lh);
resource_t *rsc_rh = pe_find_resource(data_set->resources, id_rh);
if(rsc_lh == NULL) {
crm_config_err("No resource (con=%s, rsc=%s)", id, id_lh);
return FALSE;
} else if(rsc_rh == NULL) {
crm_config_err("No resource (con=%s, rsc=%s)", id, id_rh);
return FALSE;
}
/* the docs indicate that only +/- INFINITY are allowed,
* but no-one ever reads the docs so all positive values will
* count as "must" and negative values as "must not"
*/
if(score) {
score_i = char2score(score);
}
return rsc_colocation_new(
id, score_i, rsc_lh, rsc_rh, state_lh, state_rh);
}
gboolean is_active(rsc_to_node_t *cons)
{
return TRUE;
}
diff --git a/crm/pengine/group.c b/crm/pengine/group.c
index a0cd4960dd..5fa34ac840 100644
--- a/crm/pengine/group.c
+++ b/crm/pengine/group.c
@@ -1,481 +1,482 @@
/* $Id: group.c,v 1.69 2006/08/14 09:06:31 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 <pengine.h>
#include <lib/crm/pengine/utils.h>
#include <crm/msg_xml.h>
#include <clplumbing/cl_misc.h>
#include <allocate.h>
#include <utils.h>
typedef struct group_variant_data_s
{
int num_children;
GListPtr child_list; /* resource_t* */
resource_t *self;
resource_t *first_child;
resource_t *last_child;
gboolean colocated;
gboolean ordered;
gboolean child_starting;
gboolean child_stopping;
} group_variant_data_t;
#define get_group_variant_data(data, rsc) \
CRM_ASSERT(rsc != NULL); \
CRM_ASSERT(rsc->variant == pe_group); \
CRM_ASSERT(rsc->variant_opaque != NULL); \
data = (group_variant_data_t *)rsc->variant_opaque; \
void group_set_cmds(resource_t *rsc)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
group_data->self->cmds = &resource_class_alloc_functions[group_data->self->variant];
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds = &resource_class_alloc_functions[child_rsc->variant];
child_rsc->cmds->set_cmds(child_rsc);
);
}
int group_num_allowed_nodes(resource_t *rsc)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
if(group_data->colocated == FALSE) {
crm_config_err("Cannot clone non-colocated group: %s", rsc->id);
return 0;
}
return group_data->self->cmds->num_allowed_nodes(group_data->self);
}
node_t *
group_color(resource_t *rsc, pe_working_set_t *data_set)
{
gboolean first = TRUE;
node_t *group_node = NULL;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
if(rsc->provisional == FALSE) {
return rsc->allocated_to;
}
if(rsc->is_allocating) {
crm_err("Dependancy loop detected involving %s", rsc->id);
return NULL;
}
rsc->is_allocating = TRUE;
crm_debug_3("Coloring children of: %s", rsc->id);
slist_iter(
coloc, rsc_colocation_t, rsc->rsc_cons, lpc,
crm_debug("Pre-Processing %s for %s", coloc->id, rsc->id);
coloc->rsc_rh->cmds->color(coloc->rsc_rh, data_set);
group_data->first_child->cmds->rsc_colocation_lh(
group_data->first_child, coloc->rsc_rh, coloc);
);
/* combine the child weights */
crm_debug("Processing %s", rsc->id);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
if(first) {
crm_debug("Color %s", child_rsc->id);
group_node = child_rsc->cmds->color(child_rsc, data_set);
first = FALSE;
+
} else if(child_rsc->provisional) {
native_assign_node(child_rsc, NULL, group_node);
} else {
crm_debug_2("Skip %s", child_rsc->id);
break;
}
);
rsc->provisional = FALSE;
rsc->is_allocating = FALSE;
return group_node;
}
void group_update_pseudo_status(resource_t *parent, resource_t *child);
void group_create_actions(resource_t *rsc, pe_working_set_t *data_set)
{
action_t *op = NULL;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->create_actions(child_rsc, data_set);
group_update_pseudo_status(rsc, child_rsc);
);
op = start_action(group_data->self, NULL, !group_data->child_starting);
op->pseudo = TRUE;
op = custom_action(group_data->self, started_key(group_data->self),
CRMD_ACTION_STARTED, NULL,
!group_data->child_starting, TRUE, data_set);
op->pseudo = TRUE;
op = stop_action(group_data->self, NULL, !group_data->child_stopping);
op->pseudo = TRUE;
op = custom_action(group_data->self, stopped_key(group_data->self),
CRMD_ACTION_STOPPED, NULL,
!group_data->child_stopping, TRUE, data_set);
op->pseudo = TRUE;
rsc->actions = group_data->self->actions;
}
void
group_update_pseudo_status(resource_t *parent, resource_t *child)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, parent);
if(group_data->child_stopping && group_data->child_starting) {
return;
}
slist_iter(
action, action_t, child->actions, lpc,
if(action->optional) {
continue;
}
if(safe_str_eq(CRMD_ACTION_STOP, action->task) && action->runnable) {
group_data->child_stopping = TRUE;
} else if(safe_str_eq(CRMD_ACTION_START, action->task) && action->runnable) {
group_data->child_starting = TRUE;
}
);
}
void group_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
{
resource_t *last_rsc = NULL;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
group_data->self->cmds->internal_constraints(group_data->self, data_set);
custom_action_order(
group_data->self, stopped_key(group_data->self), NULL,
group_data->self, start_key(group_data->self), NULL,
pe_ordering_optional, data_set);
custom_action_order(
group_data->self, stop_key(group_data->self), NULL,
group_data->self, stopped_key(group_data->self), NULL,
pe_ordering_optional, data_set);
custom_action_order(
group_data->self, start_key(group_data->self), NULL,
group_data->self, started_key(group_data->self), NULL,
pe_ordering_optional, data_set);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->internal_constraints(child_rsc, data_set);
if(group_data->colocated && child_rsc != group_data->first_child) {
rsc_colocation_new(
"group:internal_colocation", INFINITY,
child_rsc, group_data->first_child,
NULL, NULL);
}
if(group_data->ordered == FALSE) {
order_start_start(
group_data->self, child_rsc, pe_ordering_optional);
custom_action_order(
child_rsc, start_key(child_rsc), NULL,
group_data->self, started_key(group_data->self), NULL,
pe_ordering_optional, data_set);
order_stop_stop(
group_data->self, child_rsc, pe_ordering_optional);
custom_action_order(
child_rsc, stop_key(child_rsc), NULL,
group_data->self, stopped_key(group_data->self), NULL,
pe_ordering_optional, data_set);
continue;
}
if(last_rsc != NULL) {
order_start_start(
last_rsc, child_rsc, pe_ordering_optional);
order_stop_stop(
child_rsc, last_rsc, pe_ordering_optional);
/* recovery */
child_rsc->restart_type = pe_restart_restart;
order_start_start(
last_rsc, child_rsc, pe_ordering_recover);
order_stop_stop(
child_rsc, last_rsc, pe_ordering_recover);
} else {
custom_action_order(
child_rsc, stop_key(child_rsc), NULL,
group_data->self, stopped_key(group_data->self), NULL,
pe_ordering_optional, data_set);
order_start_start(group_data->self, child_rsc,
pe_ordering_optional);
}
last_rsc = child_rsc;
);
if(group_data->ordered && last_rsc != NULL) {
custom_action_order(
last_rsc, start_key(last_rsc), NULL,
group_data->self, started_key(group_data->self), NULL,
pe_ordering_optional, data_set);
order_stop_stop(
group_data->self, last_rsc, pe_ordering_optional);
}
}
void group_rsc_colocation_lh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
group_variant_data_t *group_data = NULL;
if(rsc_lh == NULL) {
pe_err("rsc_lh was NULL for %s", constraint->id);
return;
} else if(rsc_rh == NULL) {
pe_err("rsc_rh was NULL for %s", constraint->id);
return;
}
crm_debug_4("Processing constraints from %s", rsc_lh->id);
get_group_variant_data(group_data, rsc_lh);
if(group_data->colocated) {
group_data->first_child->cmds->rsc_colocation_lh(
group_data->first_child, rsc_rh, constraint);
return;
}
if(constraint->score > 0) {
crm_config_err("Cannot colocate resources with"
" non-colocated group: %s", rsc_lh->id);
return;
}
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->rsc_colocation_lh(
child_rsc, rsc_rh, constraint);
);
}
void group_rsc_colocation_rh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc_rh);
CRM_CHECK(rsc_lh->variant == pe_native, return);
crm_debug_3("Processing RH of constraint %s", constraint->id);
print_resource(LOG_DEBUG_3, "LHS", rsc_lh, TRUE);
if(group_data->colocated) {
group_data->first_child->cmds->rsc_colocation_rh(
rsc_lh, group_data->first_child, constraint);
return;
}
if(constraint->score > 0) {
crm_config_err("Cannot colocate resources with"
" non-colocated group: %s", rsc_rh->id);
return;
}
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->rsc_colocation_rh(
rsc_lh, child_rsc, constraint);
);
}
void group_rsc_order_lh(resource_t *rsc, order_constraint_t *order)
{
char *stop_id = NULL;
char *start_id = NULL;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_3("Processing LH of ordering constraint %d", order->id);
if(group_data->self == NULL) {
return;
}
stop_id = stop_key(group_data->self);
start_id = start_key(group_data->self);
if(safe_str_eq(order->lh_action_task, start_id)) {
crm_free(order->lh_action_task);
order->lh_action_task = started_key(group_data->self);
} else if(safe_str_eq(order->lh_action_task, stop_id)) {
crm_free(order->lh_action_task);
order->lh_action_task = stopped_key(group_data->self);
}
crm_free(start_id);
crm_free(stop_id);
group_data->self->cmds->rsc_order_lh(group_data->self, order);
}
void group_rsc_order_rh(
action_t *lh_action, resource_t *rsc, order_constraint_t *order)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_3("Processing RH of ordering constraint %d", order->id);
if(group_data->self == NULL) {
return;
}
group_data->self->cmds->rsc_order_rh(lh_action, group_data->self, order);
}
void group_rsc_location(resource_t *rsc, rsc_to_node_t *constraint)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_3("Processing actions from %s", group_data->self->id);
group_data->self->cmds->rsc_location(group_data->self, constraint);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->rsc_location(child_rsc, constraint);
);
}
void group_expand(resource_t *rsc, pe_working_set_t *data_set)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_3("Processing actions from %s", rsc->id);
CRM_CHECK(group_data->self != NULL, return);
group_data->self->cmds->expand(group_data->self, data_set);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->expand(child_rsc, data_set);
);
}
void
group_agent_constraints(resource_t *rsc)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->agent_constraints(child_rsc);
);
}
void
group_create_notify_element(resource_t *rsc, action_t *op,
notify_data_t *n_data, pe_working_set_t *data_set)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->create_notify_element(
child_rsc, op, n_data, data_set);
);
}
gboolean
group_create_probe(resource_t *rsc, node_t *node, action_t *complete,
gboolean force, pe_working_set_t *data_set)
{
gboolean any_created = FALSE;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
any_created = child_rsc->cmds->create_probe(
child_rsc, node, complete, force, data_set) || any_created;
);
return any_created;
}
void
group_stonith_ordering(
resource_t *rsc, action_t *stonith_op, pe_working_set_t *data_set)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->stonith_ordering(
child_rsc, stonith_op, data_set);
);
}
diff --git a/crm/pengine/testcases/master-3.exp b/crm/pengine/testcases/master-3.exp
index fe617dd96d..2baa172fb2 100644
--- a/crm/pengine/testcases/master-3.exp
+++ b/crm/pengine/testcases/master-3.exp
@@ -1,287 +1,287 @@
<transition_graph network-delay="60s" transition_id="0">
<synapse id="0" priority="1000000">
<action_set>
<rsc_op id="5" operation="monitor" operation_key="child_rsc1:2_monitor_0" on_node="node1" on_node_uuid="uuid1">
<primitive id="child_rsc1:2" long-id="rsc1:child_rsc1:2" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Master" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="2" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="1" priority="1000000">
<action_set>
<rsc_op id="11" operation="monitor" operation_key="child_rsc1:2_monitor_0" on_node="node2" on_node_uuid="uuid2">
<primitive id="child_rsc1:2" long-id="rsc1:child_rsc1:2" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Master" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="2" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
- <synapse id="2" priority="600">
+ <synapse id="2" priority="500">
<action_set>
<rsc_op id="14" operation="start" operation_key="child_rsc1:2_start_0" on_node="node2" on_node_uuid="uuid2">
<primitive id="child_rsc1:2" long-id="rsc1:child_rsc1:2" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Master" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_clone="2" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<pseudo_event id="19" operation="start" operation_key="rsc1_start_0"/>
</trigger>
</inputs>
</synapse>
- <synapse id="3" priority="600">
+ <synapse id="3" priority="500">
<action_set>
<rsc_op id="15" operation="promote" operation_key="child_rsc1:2_promote_0" on_node="node2" on_node_uuid="uuid2">
<primitive id="child_rsc1:2" long-id="rsc1:child_rsc1:2" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Master" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_clone="2" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<rsc_op id="14" operation="start" operation_key="child_rsc1:2_start_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
<trigger>
<pseudo_event id="23" operation="promote" operation_key="rsc1_promote_0"/>
</trigger>
</inputs>
</synapse>
<synapse id="4" priority="1000000">
<action_set>
<rsc_op id="6" operation="monitor" operation_key="child_rsc1:3_monitor_0" on_node="node1" on_node_uuid="uuid1">
<primitive id="child_rsc1:3" long-id="rsc1:child_rsc1:3" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="3" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="5" priority="1000000">
<action_set>
<rsc_op id="12" operation="monitor" operation_key="child_rsc1:3_monitor_0" on_node="node2" on_node_uuid="uuid2">
<primitive id="child_rsc1:3" long-id="rsc1:child_rsc1:3" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="3" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
- <synapse id="6" priority="240">
+ <synapse id="6" priority="140">
<action_set>
<rsc_op id="16" operation="start" operation_key="child_rsc1:3_start_0" on_node="node2" on_node_uuid="uuid2">
<primitive id="child_rsc1:3" long-id="rsc1:child_rsc1:3" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_clone="3" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<pseudo_event id="19" operation="start" operation_key="rsc1_start_0"/>
</trigger>
</inputs>
</synapse>
<synapse id="7" priority="1000000">
<action_set>
<rsc_op id="7" operation="monitor" operation_key="child_rsc1:4_monitor_0" on_node="node1" on_node_uuid="uuid1">
<primitive id="child_rsc1:4" long-id="rsc1:child_rsc1:4" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="4" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="8" priority="1000000">
<action_set>
<rsc_op id="13" operation="monitor" operation_key="child_rsc1:4_monitor_0" on_node="node2" on_node_uuid="uuid2">
<primitive id="child_rsc1:4" long-id="rsc1:child_rsc1:4" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="4" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="9" priority="1000000">
<action_set>
<rsc_op id="3" operation="monitor" operation_key="child_rsc1:0_monitor_0" on_node="node1" on_node_uuid="uuid1">
<primitive id="child_rsc1:0" long-id="rsc1:child_rsc1:0" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="0" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="10" priority="1000000">
<action_set>
<rsc_op id="9" operation="monitor" operation_key="child_rsc1:0_monitor_0" on_node="node2" on_node_uuid="uuid2">
<primitive id="child_rsc1:0" long-id="rsc1:child_rsc1:0" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="0" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="11">
<action_set>
<rsc_op id="17" operation="start" operation_key="child_rsc1:0_start_0" on_node="node1" on_node_uuid="uuid1">
<primitive id="child_rsc1:0" long-id="rsc1:child_rsc1:0" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_clone="0" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<pseudo_event id="19" operation="start" operation_key="rsc1_start_0"/>
</trigger>
</inputs>
</synapse>
<synapse id="12" priority="1000000">
<action_set>
<rsc_op id="4" operation="monitor" operation_key="child_rsc1:1_monitor_0" on_node="node1" on_node_uuid="uuid1">
<primitive id="child_rsc1:1" long-id="rsc1:child_rsc1:1" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="1" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="13" priority="1000000">
<action_set>
<rsc_op id="10" operation="monitor" operation_key="child_rsc1:1_monitor_0" on_node="node2" on_node_uuid="uuid2">
<primitive id="child_rsc1:1" long-id="rsc1:child_rsc1:1" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_op_target_rc="7" CRM_meta_clone="1" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs/>
</synapse>
<synapse id="14">
<action_set>
<rsc_op id="18" operation="start" operation_key="child_rsc1:1_start_0" on_node="node1" on_node_uuid="uuid1">
<primitive id="child_rsc1:1" long-id="rsc1:child_rsc1:1" class="heartbeat" type="apache"/>
<attributes crm_feature_set="1.0.6" CRM_meta_role="Slave" CRM_meta_stateful="true" CRM_meta_timeout="20000" CRM_meta_clone="1" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<pseudo_event id="19" operation="start" operation_key="rsc1_start_0"/>
</trigger>
</inputs>
</synapse>
<synapse id="15">
<action_set>
<pseudo_event id="19" operation="start" operation_key="rsc1_start_0">
<attributes crm_feature_set="1.0.6" CRM_meta_timeout="20000" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</pseudo_event>
</action_set>
<inputs>
<trigger>
<pseudo_event id="1" operation="probe_complete" operation_key="probe_complete"/>
</trigger>
</inputs>
</synapse>
<synapse id="16" priority="1000000">
<action_set>
<pseudo_event id="20" operation="running" operation_key="rsc1_running_0">
<attributes crm_feature_set="1.0.6" CRM_meta_timeout="20000" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</pseudo_event>
</action_set>
<inputs>
<trigger>
<rsc_op id="14" operation="start" operation_key="child_rsc1:2_start_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
<trigger>
<rsc_op id="16" operation="start" operation_key="child_rsc1:3_start_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
<trigger>
<rsc_op id="17" operation="start" operation_key="child_rsc1:0_start_0" on_node="node1" on_node_uuid="uuid1"/>
</trigger>
<trigger>
<rsc_op id="18" operation="start" operation_key="child_rsc1:1_start_0" on_node="node1" on_node_uuid="uuid1"/>
</trigger>
<trigger>
<pseudo_event id="19" operation="start" operation_key="rsc1_start_0"/>
</trigger>
</inputs>
</synapse>
<synapse id="17">
<action_set>
<pseudo_event id="23" operation="promote" operation_key="rsc1_promote_0">
<attributes crm_feature_set="1.0.6" CRM_meta_timeout="20000" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</pseudo_event>
</action_set>
<inputs>
<trigger>
<pseudo_event id="19" operation="start" operation_key="rsc1_start_0"/>
</trigger>
<trigger>
<pseudo_event id="20" operation="running" operation_key="rsc1_running_0"/>
</trigger>
</inputs>
</synapse>
<synapse id="18" priority="1000000">
<action_set>
<pseudo_event id="24" operation="promoted" operation_key="rsc1_promoted_0">
<attributes crm_feature_set="1.0.6" CRM_meta_timeout="20000" CRM_meta_clone_max="5" CRM_meta_clone_node_max="2" CRM_meta_master_max="2" CRM_meta_master_node_max="1"/>
</pseudo_event>
</action_set>
<inputs>
<trigger>
<rsc_op id="15" operation="promote" operation_key="child_rsc1:2_promote_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
</inputs>
</synapse>
<synapse id="19">
<action_set>
<pseudo_event id="1" operation="probe_complete" operation_key="probe_complete">
<attributes crm_feature_set="1.0.6"/>
</pseudo_event>
</action_set>
<inputs>
<trigger>
<rsc_op id="2" operation="probe_complete" operation_key="probe_complete" on_node="node1" on_node_uuid="uuid1"/>
</trigger>
<trigger>
<rsc_op id="8" operation="probe_complete" operation_key="probe_complete" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
</inputs>
</synapse>
<synapse id="20" priority="1000000">
<action_set>
<rsc_op id="2" operation="probe_complete" operation_key="probe_complete" on_node="node1" on_node_uuid="uuid1">
<attributes crm_feature_set="1.0.6" CRM_meta_op_no_wait="true"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<rsc_op id="3" operation="monitor" operation_key="child_rsc1:0_monitor_0" on_node="node1" on_node_uuid="uuid1"/>
</trigger>
<trigger>
<rsc_op id="4" operation="monitor" operation_key="child_rsc1:1_monitor_0" on_node="node1" on_node_uuid="uuid1"/>
</trigger>
<trigger>
<rsc_op id="5" operation="monitor" operation_key="child_rsc1:2_monitor_0" on_node="node1" on_node_uuid="uuid1"/>
</trigger>
<trigger>
<rsc_op id="6" operation="monitor" operation_key="child_rsc1:3_monitor_0" on_node="node1" on_node_uuid="uuid1"/>
</trigger>
<trigger>
<rsc_op id="7" operation="monitor" operation_key="child_rsc1:4_monitor_0" on_node="node1" on_node_uuid="uuid1"/>
</trigger>
</inputs>
</synapse>
<synapse id="21" priority="1000000">
<action_set>
<rsc_op id="8" operation="probe_complete" operation_key="probe_complete" on_node="node2" on_node_uuid="uuid2">
<attributes crm_feature_set="1.0.6" CRM_meta_op_no_wait="true"/>
</rsc_op>
</action_set>
<inputs>
<trigger>
<rsc_op id="9" operation="monitor" operation_key="child_rsc1:0_monitor_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
<trigger>
<rsc_op id="10" operation="monitor" operation_key="child_rsc1:1_monitor_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
<trigger>
<rsc_op id="11" operation="monitor" operation_key="child_rsc1:2_monitor_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
<trigger>
<rsc_op id="12" operation="monitor" operation_key="child_rsc1:3_monitor_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
<trigger>
<rsc_op id="13" operation="monitor" operation_key="child_rsc1:4_monitor_0" on_node="node2" on_node_uuid="uuid2"/>
</trigger>
</inputs>
</synapse>
</transition_graph>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Oct 16, 12:30 AM (12 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2530884
Default Alt Text
(65 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment