Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/crm/pengine/graph.c b/crm/pengine/graph.c
index 9c0684606f..2131b49ee4 100644
--- a/crm/pengine/graph.c
+++ b/crm/pengine/graph.c
@@ -1,533 +1,533 @@
/* $Id: graph.c,v 1.104 2006/07/18 06:19:33 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 <glib.h>
#include <allocate.h>
#include <lib/crm/pengine/utils.h>
#include <utils.h>
gboolean update_action(action_t *action);
gboolean
update_action_states(GListPtr actions)
{
crm_debug_2("Updating %d actions", g_list_length(actions));
slist_iter(
action, action_t, actions, lpc,
update_action(action);
);
return TRUE;
}
gboolean
update_action(action_t *action)
{
enum action_tasks task = no_action;
crm_debug_2("Processing action %s: %s",
action->uuid, action->optional?"optional":"required");
slist_iter(
other, action_wrapper_t, action->actions_before, lpc,
crm_debug_3("\tChecking action %s: %s/%s",
other->action->uuid, ordering_type2text(other->type),
other->action->optional?"optional":"required");
- if(other->type == pe_order_internal_restart
+ if(other->type & pe_order_internal_restart
&& action->rsc->role > RSC_ROLE_STOPPED) {
crm_debug_3("\t Upgrading %s constraint to %s",
ordering_type2text(other->type),
ordering_type2text(pe_order_implies_left));
other->type = pe_order_implies_left;
}
- if(other->type != pe_order_implies_left) {
+ if((other->type & pe_order_implies_left) == 0) {
crm_debug_3("\t Ignoring: %s",
ordering_type2text(other->type));
continue;
} else if(action->optional || other->action->optional == FALSE){
crm_debug_3("\t Ignoring: %s/%s",
other->action->optional?"-":"they are not optional",
action->optional?"we are optional":"-");
continue;
} else if(safe_str_eq(other->action->task, CRMD_ACTION_START)) {
const char *interval = g_hash_table_lookup(
action->meta, XML_LRM_ATTR_INTERVAL);
int interval_i = 0;
if(interval != NULL) {
interval_i = crm_parse_int(interval, NULL);
if(interval_i > 0) {
crm_debug_3("Ignoring: start + recurring");
continue;
}
}
}
other->action->optional = FALSE;
crm_debug_2("* Marking action %s mandatory because of %s",
other->action->uuid, action->uuid);
update_action(other->action);
);
slist_iter(
other, action_wrapper_t, action->actions_after, lpc,
if(action->pseudo == FALSE && action->runnable == FALSE) {
if(other->action->runnable == FALSE) {
crm_debug_2("Action %s already un-runnable",
other->action->uuid);
} else if(action->optional == FALSE) {
other->action->runnable = FALSE;
crm_debug_2("Marking action %s un-runnable"
" because of %s",
other->action->uuid, action->uuid);
update_action(other->action);
}
}
crm_debug_3("\t(Recover) Checking action %s: %s/%s",
other->action->uuid, ordering_type2text(other->type),
other->action->optional?"optional":"required");
if(other->action->rsc == NULL) {
continue;
- } else if(other->type == pe_order_implies_right) {
+ } else if(other->type & pe_order_internal_restart) {
+ } else if(other->type & pe_order_postnotify) {
+ CRM_CHECK(action->rsc == other->action->rsc, continue);
+
+ } else if(other->type & pe_order_implies_right) {
if(other->action->rsc->restart_type != pe_restart_restart) {
crm_debug_3("\t Ignoring: restart type %d",
other->action->rsc->restart_type);
continue;
}
- } else if(other->type == pe_order_internal_restart) {
- } else if(other->type == pe_order_postnotify) {
- CRM_CHECK(action->rsc == other->action->rsc, continue);
-
} else {
crm_debug_3("\t Ignoring: ordering %s",
ordering_type2text(other->type));
continue;
}
if(other->action->optional == FALSE || action->optional) {
crm_debug_3("\t Ignoring: %s/%s",
action->optional?"we are optional":"-",
other->action->optional?"-":"they are not optional");
continue;
}
task = text2task(action->task);
switch(task) {
case stop_rsc:
case stopped_rsc:
crm_debug_3("\t Ignoring: action %s",
action->uuid);
break;
case start_rsc:
case started_rsc:
crm_debug_2("* (Recover) Marking action %s"
" mandatory because of %s",
other->action->uuid, action->uuid);
other->action->optional = FALSE;
update_action(other->action);
break;
default:
crm_debug_3("\t Ignoring: action %s",
action->uuid);
break;
}
);
return FALSE;
}
gboolean
shutdown_constraints(
node_t *node, action_t *shutdown_op, pe_working_set_t *data_set)
{
/* add the stop to the before lists so it counts as a pre-req
* for the shutdown
*/
slist_iter(
rsc, resource_t, node->details->running_rsc, lpc,
if(rsc->is_managed == FALSE) {
continue;
}
custom_action_order(
rsc, stop_key(rsc), NULL,
NULL, crm_strdup(CRM_OP_SHUTDOWN), shutdown_op,
pe_order_implies_left, data_set);
);
return TRUE;
}
gboolean
stonith_constraints(
node_t *node, action_t *stonith_op, pe_working_set_t *data_set)
{
CRM_CHECK(stonith_op != NULL, return FALSE);
/*
* Make sure the stonith OP occurs before we start any shared resources
*/
if(stonith_op != NULL) {
slist_iter(
rsc, resource_t, data_set->resources, lpc,
rsc->cmds->stonith_ordering(rsc, stonith_op, data_set);
);
}
/* add the stonith OP as a stop pre-req and the mark the stop
* as a pseudo op - since its now redundant
*/
return TRUE;
}
static void dup_attr(gpointer key, gpointer value, gpointer user_data)
{
g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value));
}
crm_data_t *
action2xml(action_t *action, gboolean as_input)
{
gboolean needs_node_info = TRUE;
crm_data_t * action_xml = NULL;
crm_data_t * args_xml = NULL;
char *action_id_s = NULL;
if(action == NULL) {
return NULL;
}
crm_debug_4("Dumping action %d as XML", action->id);
if(safe_str_eq(action->task, CRM_OP_FENCE)) {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
/* needs_node_info = FALSE; */
} else if(safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
} else if(safe_str_eq(action->task, CRM_OP_LRM_REFRESH)) {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
/* } else if(safe_str_eq(action->task, CRMD_ACTION_PROBED)) { */
/* action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); */
} else if(action->pseudo) {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_PSEUDO_EVENT);
needs_node_info = FALSE;
} else {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
}
action_id_s = crm_itoa(action->id);
crm_xml_add(action_xml, XML_ATTR_ID, action_id_s);
crm_free(action_id_s);
crm_xml_add(action_xml, XML_LRM_ATTR_TASK, action->task);
if(action->rsc != NULL && action->rsc->clone_name != NULL) {
char *clone_key = NULL;
const char *interval_s = g_hash_table_lookup(action->meta, "interval");
int interval = crm_parse_int(interval_s, "0");
if(safe_str_eq(action->task, CRMD_ACTION_NOTIFY)) {
const char *n_type = g_hash_table_lookup(
action->extra, crm_meta_name("notify_type"));
const char *n_task = g_hash_table_lookup(
action->extra, crm_meta_name("notify_operation"));
CRM_CHECK(n_type != NULL, ;);
CRM_CHECK(n_task != NULL, ;);
clone_key = generate_notify_key(action->rsc->clone_name, n_type, n_task);
} else {
clone_key = generate_op_key(action->rsc->clone_name, action->task, interval);
}
crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, clone_key);
crm_xml_add(action_xml, "internal_"XML_LRM_ATTR_TASK_KEY, action->uuid);
crm_free(clone_key);
} else {
crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, action->uuid);
}
if(needs_node_info && action->node != NULL) {
crm_xml_add(action_xml, XML_LRM_ATTR_TARGET,
action->node->details->uname);
crm_xml_add(action_xml, XML_LRM_ATTR_TARGET_UUID,
action->node->details->id);
}
if(action->failure_is_fatal == FALSE) {
add_hash_param(action->meta,
XML_ATTR_TE_ALLOWFAIL, XML_BOOLEAN_TRUE);
}
if(as_input) {
return action_xml;
}
if(action->notify_keys != NULL) {
g_hash_table_foreach(
action->notify_keys, dup_attr, action->meta);
}
if(action->rsc != NULL && action->pseudo == FALSE) {
int lpc = 0;
crm_data_t *rsc_xml = create_xml_node(
action_xml, crm_element_name(action->rsc->xml));
const char *attr_list[] = {
XML_AGENT_ATTR_CLASS,
XML_AGENT_ATTR_PROVIDER,
XML_ATTR_TYPE
};
if(action->rsc->clone_name != NULL) {
crm_debug("Using clone name %s for %s", action->rsc->clone_name, action->rsc->id);
crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->clone_name);
crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
} else {
crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->id);
crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->long_name);
}
for(lpc = 0; lpc < DIMOF(attr_list); lpc++) {
crm_xml_add(rsc_xml, attr_list[lpc],
g_hash_table_lookup(action->rsc->meta, attr_list[lpc]));
}
}
args_xml = create_xml_node(action_xml, XML_TAG_ATTRS);
crm_xml_add(args_xml, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
g_hash_table_foreach(action->extra, hash2field, args_xml);
if(action->rsc != NULL && safe_str_neq(action->task, CRMD_ACTION_STOP)) {
g_hash_table_foreach(action->rsc->parameters, hash2field, args_xml);
}
g_hash_table_foreach(action->meta, hash2metafield, args_xml);
if(action->rsc != NULL) {
int lpc = 0;
const char *key = NULL;
const char *value = NULL;
const char *meta_list[] = {
XML_RSC_ATTR_UNIQUE,
XML_RSC_ATTR_INCARNATION,
XML_RSC_ATTR_INCARNATION_MAX,
XML_RSC_ATTR_INCARNATION_NODEMAX,
XML_RSC_ATTR_MASTER_MAX,
XML_RSC_ATTR_MASTER_NODEMAX,
};
for(lpc = 0; lpc < DIMOF(meta_list); lpc++) {
key = meta_list[lpc];
value = g_hash_table_lookup(action->rsc->meta, key);
if(value != NULL) {
char *crm_name = crm_concat(CRM_META, key, '_');
crm_xml_add(args_xml, crm_name, value);
crm_free(crm_name);
}
}
}
crm_log_xml_debug_4(action_xml, "dumped action");
return action_xml;
}
static gboolean
should_dump_action(action_t *action)
{
const char * interval = NULL;
CRM_CHECK(action != NULL, return FALSE);
interval = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL);
if(action->optional) {
crm_debug_5("action %d was optional", action->id);
return FALSE;
} else if(action->pseudo == FALSE && action->runnable == FALSE) {
crm_debug_5("action %d was not runnable", action->id);
return FALSE;
} else if(action->dumped) {
crm_debug_5("action %d was already dumped", action->id);
return FALSE;
} else if(action->rsc != NULL
&& action->rsc->is_managed == FALSE) {
/* make sure probes go through */
if(safe_str_neq(action->task, CRMD_ACTION_STATUS)) {
pe_warn("action %d (%s) was for an unmanaged resource (%s)",
action->id, action->uuid, action->rsc->id);
return FALSE;
}
if(interval != NULL && safe_str_neq(interval, "0")) {
pe_warn("action %d (%s) was for an unmanaged resource (%s)",
action->id, action->uuid, action->rsc->id);
return FALSE;
}
}
if(action->pseudo
|| safe_str_eq(action->task, CRM_OP_FENCE)
|| safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
/* skip the next checks */
return TRUE;
}
if(action->node == NULL) {
pe_err("action %d (%s) was not allocated",
action->id, action->uuid);
log_action(LOG_DEBUG, "Unallocated action", action, FALSE);
return FALSE;
} else if(action->node->details->online == FALSE) {
pe_err("action %d was (%s) scheduled for offline node",
action->id, action->uuid);
log_action(LOG_DEBUG, "Action for offline node", action, FALSE);
return FALSE;
#if 0
/* but this would also affect resources that can be safely
* migrated before a fencing op
*/
} else if(action->node->details->unclean == FALSE) {
pe_err("action %d was (%s) scheduled for unclean node",
action->id, action->uuid);
log_action(LOG_DEBUG, "Action for unclean node", action, FALSE);
return FALSE;
#endif
}
return TRUE;
}
/* lowest to highest */
static gint sort_action_id(gconstpointer a, gconstpointer b)
{
const action_wrapper_t *action_wrapper2 = (const action_wrapper_t*)a;
const action_wrapper_t *action_wrapper1 = (const action_wrapper_t*)b;
if(a == NULL) { return 1; }
if(b == NULL) { return -1; }
if(action_wrapper1->action->id > action_wrapper2->action->id) {
return -1;
}
if(action_wrapper1->action->id < action_wrapper2->action->id) {
return 1;
}
return 0;
}
void
graph_element_from_action(action_t *action, pe_working_set_t *data_set)
{
int last_action = -1;
int synapse_priority = 0;
crm_data_t * syn = NULL;
crm_data_t * set = NULL;
crm_data_t * in = NULL;
crm_data_t * input = NULL;
crm_data_t * xml_action = NULL;
if(should_dump_action(action) == FALSE) {
return;
}
action->dumped = TRUE;
syn = create_xml_node(data_set->graph, "synapse");
set = create_xml_node(syn, "action_set");
in = create_xml_node(syn, "inputs");
crm_xml_add_int(syn, XML_ATTR_ID, data_set->num_synapse);
data_set->num_synapse++;
if(action->rsc != NULL) {
synapse_priority = action->rsc->priority;
}
if(action->priority > synapse_priority) {
synapse_priority = action->priority;
}
if(synapse_priority > 0) {
crm_xml_add_int(syn, XML_CIB_ATTR_PRIORITY, synapse_priority);
}
xml_action = action2xml(action, FALSE);
add_node_copy(set, xml_action);
free_xml(xml_action);
action->actions_before = g_list_sort(
action->actions_before, sort_action_id);
slist_iter(wrapper,action_wrapper_t,action->actions_before,lpc,
if(last_action == wrapper->action->id) {
crm_debug_2("Input (%d) %s duplicated",
wrapper->action->id,
wrapper->action->uuid);
continue;
} else if(wrapper->action->optional == TRUE) {
crm_debug_2("Input (%d) %s optional",
wrapper->action->id,
wrapper->action->uuid);
continue;
}
CRM_CHECK(last_action < wrapper->action->id, ;);
last_action = wrapper->action->id;
input = create_xml_node(in, "trigger");
xml_action = action2xml(wrapper->action, TRUE);
add_node_copy(input, xml_action);
free_xml(xml_action);
);
}
diff --git a/crm/pengine/group.c b/crm/pengine/group.c
index 99e9a71166..6f6c2ce086 100644
--- a/crm/pengine/group.c
+++ b/crm/pengine/group.c
@@ -1,481 +1,456 @@
/* $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>
#define VARIANT_GROUP 1
#include <lib/crm/pengine/variant.h>
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)
{
resource_t *child = NULL;
node_t *group_node = NULL;
GListPtr child_iter = NULL;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
if(rsc->provisional == FALSE) {
return rsc->allocated_to;
}
/* combine the child weights */
crm_debug("Processing %s", rsc->id);
if(rsc->is_allocating) {
crm_debug("Dependancy loop detected involving %s", rsc->id);
return NULL;
}
rsc->is_allocating = TRUE;
group_data->self->role = group_data->first_child->role;
group_data->first_child->rsc_cons = g_list_concat(
group_data->first_child->rsc_cons, rsc->rsc_cons);
rsc->rsc_cons = NULL;
/* process in reverse so that all scores are merged before allocation */
child_iter = g_list_last(group_data->child_list);
for(; child_iter != NULL; ) {
child = child_iter->data;
child_iter = g_list_previous(child_iter);
group_node = child->cmds->color(child, data_set);
}
group_data->self->next_role = group_data->first_child->next_role;
rsc->is_allocating = FALSE;
rsc->provisional = FALSE;
if(group_data->colocated) {
return group_node;
}
return NULL;
}
void group_update_pseudo_status(resource_t *parent, resource_t *child);
void group_create_actions(resource_t *rsc, pe_working_set_t *data_set)
{
action_t *op = NULL;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_2("Creating actions for %s", rsc->id);
slist_iter(
child_rsc, resource_t, 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;
crm_debug_3("Based on %s the group is stopping", action->uuid);
} else if(safe_str_eq(CRMD_ACTION_START, action->task) && action->runnable) {
group_data->child_starting = TRUE;
crm_debug_3("Based on %s the group is starting", action->uuid);
}
);
}
void group_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
{
resource_t *this_rsc = NULL;
resource_t *last_rsc = NULL;
+ int ordering = pe_order_optional|pe_order_implies_right;
+
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
this_rsc = group_data->self;
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_order_internal_restart, data_set);
custom_action_order(
group_data->self, stop_key(group_data->self), NULL,
group_data->self, stopped_key(group_data->self), NULL,
pe_order_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_order_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 && last_rsc != NULL) {
rsc_colocation_new(
"group:internal_colocation", NULL, INFINITY,
child_rsc, last_rsc, NULL, NULL);
}
if(group_data->ordered == FALSE) {
order_start_start(
group_data->self, child_rsc, pe_order_optional);
custom_action_order(
child_rsc, start_key(child_rsc), NULL,
group_data->self, started_key(group_data->self), NULL,
pe_order_optional, data_set);
order_stop_stop(
group_data->self, child_rsc, pe_order_optional);
custom_action_order(
child_rsc, stop_key(child_rsc), NULL,
group_data->self, stopped_key(group_data->self), NULL,
pe_order_optional, data_set);
- /* recovery */
-
continue;
}
if(last_rsc != NULL) {
- order_start_start(
- last_rsc, child_rsc, pe_order_optional);
- order_stop_stop(
- child_rsc, last_rsc, pe_order_optional);
+ order_start_start(last_rsc, child_rsc, ordering);
+ order_stop_stop(child_rsc, last_rsc, ordering);
- /* recovery */
child_rsc->restart_type = pe_restart_restart;
- order_start_start(
- last_rsc, child_rsc, pe_order_implies_right);
- order_stop_stop(
- last_rsc, child_rsc, pe_order_implies_right);
} else {
custom_action_order(
child_rsc, stop_key(child_rsc), NULL,
this_rsc, stopped_key(this_rsc), NULL,
- pe_order_optional, data_set);
-
- order_start_start(
- this_rsc, child_rsc, pe_order_optional);
+ ordering, data_set);
- /* recovery */
- custom_action_order(
- child_rsc, stop_key(child_rsc), NULL,
- this_rsc, stopped_key(this_rsc), NULL,
- pe_order_implies_right, data_set);
- order_start_start(
- this_rsc, child_rsc, pe_order_implies_right);
+ order_start_start(this_rsc, child_rsc, ordering);
}
last_rsc = child_rsc;
);
if(group_data->ordered && last_rsc != NULL) {
- custom_action_order(
- last_rsc, start_key(last_rsc), NULL,
- this_rsc, started_key(this_rsc), NULL,
- pe_order_optional, data_set);
-
- order_stop_stop(this_rsc, last_rsc, pe_order_optional);
-
- /* recovery */
- custom_action_order(
- last_rsc, start_key(last_rsc), NULL,
- this_rsc, started_key(this_rsc), NULL,
- pe_order_implies_right, data_set);
+ custom_action_order(last_rsc, start_key(last_rsc), NULL,
+ this_rsc, started_key(this_rsc), NULL,
+ ordering, data_set);
- order_stop_stop(this_rsc, last_rsc, pe_order_implies_right);
+ order_stop_stop(this_rsc, last_rsc, ordering);
}
}
void group_rsc_colocation_lh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
group_variant_data_t *group_data = NULL;
if(rsc_lh == NULL) {
pe_err("rsc_lh was NULL for %s", constraint->id);
return;
} else if(rsc_rh == NULL) {
pe_err("rsc_rh was NULL for %s", constraint->id);
return;
}
crm_debug_4("Processing constraints from %s", rsc_lh->id);
get_group_variant_data(group_data, rsc_lh);
if(group_data->colocated) {
group_data->first_child->cmds->rsc_colocation_lh(
group_data->first_child, rsc_rh, constraint);
return;
} else if(constraint->score >= INFINITY) {
crm_config_err("%s: Cannot perform manditory colocation"
" between non-colocated group and %s",
rsc_lh->id, rsc_rh->id);
return;
}
slist_iter(
child_rsc, resource_t, 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(rsc_rh->provisional) {
return;
} else if(group_data->colocated) {
group_data->first_child->cmds->rsc_colocation_rh(
rsc_lh, group_data->first_child, constraint);
return;
} else if(constraint->score >= INFINITY) {
crm_config_err("%s: Cannot perform manditory colocation with"
" non-colocated group: %s", rsc_lh->id, rsc_rh->id);
return;
}
slist_iter(
child_rsc, resource_t, 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)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug("%s->%s", order->lh_action_task, order->rh_action_task);
if(group_data->self == NULL) {
return;
}
convert_non_atomic_task(rsc, order);
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_2("%s->%s", lh_action->uuid, order->rh_action_task);
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)
{
gboolean reset_scores = TRUE;
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug("Processing rsc_location %s for %s",
constraint->id, group_data->self->id);
slist_iter(
child_rsc, resource_t, group_data->child_list, lpc,
child_rsc->cmds->rsc_location(child_rsc, constraint);
if(group_data->colocated && reset_scores) {
reset_scores = FALSE;
slist_iter(node, node_t, constraint->node_list_rh, lpc2,
node->weight = 0;
);
}
);
}
void group_expand(resource_t *rsc, pe_working_set_t *data_set)
{
group_variant_data_t *group_data = NULL;
get_group_variant_data(group_data, rsc);
crm_debug_3("Processing actions from %s", rsc->id);
CRM_CHECK(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);
);
}
void
group_migrate_reload(resource_t *rsc, 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->migrate_reload(child_rsc, data_set);
);
}
diff --git a/crm/pengine/native.c b/crm/pengine/native.c
index 21b3c09ff8..93bac18c5d 100644
--- a/crm/pengine/native.c
+++ b/crm/pengine/native.c
@@ -1,1603 +1,1604 @@
/* $Id: native.c,v 1.161 2006/08/17 07:17:15 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 <crm/pengine/rules.h>
#include <lib/crm/pengine/utils.h>
#include <crm/msg_xml.h>
#include <allocate.h>
#include <utils.h>
#define DELETE_THEN_REFRESH 1
#define VARIANT_NATIVE 1
#include <lib/crm/pengine/variant.h>
resource_t *ultimate_parent(resource_t *rsc);
void node_list_update(GListPtr list1, GListPtr list2, int factor);
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 create_notifications(resource_t *rsc, pe_working_set_t *data_set);
void Recurring(resource_t *rsc, action_t *start, node_t *node,
pe_working_set_t *data_set);
void pe_pre_notify(
resource_t *rsc, node_t *node, action_t *op,
notify_data_t *n_data, pe_working_set_t *data_set);
void pe_post_notify(
resource_t *rsc, node_t *node, action_t *op,
notify_data_t *n_data, pe_working_set_t *data_set);
gboolean DeleteRsc(resource_t *rsc, node_t *node, pe_working_set_t *data_set);
void NoRoleChange(resource_t *rsc, node_t *current, node_t *next, pe_working_set_t *data_set);
gboolean StopRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set);
gboolean StartRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set);
extern gboolean DemoteRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set);
gboolean PromoteRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set);
gboolean RoleError(resource_t *rsc, node_t *next, pe_working_set_t *data_set);
gboolean NullOp(resource_t *rsc, node_t *next, pe_working_set_t *data_set);
enum rsc_role_e rsc_state_matrix[RSC_ROLE_MAX][RSC_ROLE_MAX] = {
/* Current State */
/* Next State: Unknown Stopped Started Slave Master */
/* Unknown */ { RSC_ROLE_UNKNOWN, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, },
/* Stopped */ { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE, RSC_ROLE_SLAVE, },
/* Started */ { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, },
/* Slave */ { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_UNKNOWN, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, },
/* Master */ { RSC_ROLE_STOPPED, RSC_ROLE_SLAVE, RSC_ROLE_UNKNOWN, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, },
};
gboolean (*rsc_action_matrix[RSC_ROLE_MAX][RSC_ROLE_MAX])(resource_t*,node_t*,pe_working_set_t*) = {
/* Current State */
/* Next State: Unknown Stopped Started Slave Master */
/* Unknown */ { RoleError, StopRsc, RoleError, RoleError, RoleError, },
/* Stopped */ { RoleError, NullOp, StartRsc, StartRsc, RoleError, },
/* Started */ { RoleError, StopRsc, NullOp, NullOp, PromoteRsc, },
/* Slave */ { RoleError, StopRsc, RoleError, NullOp, PromoteRsc, },
/* Master */ { RoleError, RoleError, RoleError, DemoteRsc, NullOp, },
};
static gboolean
native_choose_node(resource_t *rsc)
{
/*
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 = NULL;
node_t *chosen = NULL;
if(rsc->provisional == FALSE) {
return rsc->allocated_to?TRUE:FALSE;
}
crm_debug_3("Choosing node for %s from %d candidates",
rsc->id, g_list_length(rsc->allowed_nodes));
if(rsc->allowed_nodes) {
rsc->allowed_nodes = g_list_sort(
rsc->allowed_nodes, sort_node_weight);
nodes = rsc->allowed_nodes;
chosen = g_list_nth_data(nodes, 0);
}
return native_assign_node(rsc, nodes, chosen);
}
void native_set_cmds(resource_t *rsc)
{
}
int native_num_allowed_nodes(resource_t *rsc)
{
int num_nodes = 0;
if(rsc->next_role == RSC_ROLE_STOPPED) {
return 0;
}
crm_debug_4("Default case");
slist_iter(
this_node, node_t, rsc->allowed_nodes, lpc,
crm_debug_3("Rsc %s Checking %s: %d",
rsc->id, this_node->details->uname,
this_node->weight);
if(this_node->details->shutdown
|| this_node->details->online == FALSE) {
this_node->weight = -INFINITY;
}
if(this_node->weight < 0) {
continue;
/* } else if(this_node->details->unclean) { */
/* continue; */
}
num_nodes++;
);
crm_debug_2("Resource %s can run on %d nodes", rsc->id, num_nodes);
return num_nodes;
}
resource_t *
ultimate_parent(resource_t *rsc)
{
resource_t *parent = rsc;
while(parent->parent) {
parent = parent->parent;
}
return parent;
}
node_t *
native_color(resource_t *rsc, pe_working_set_t *data_set)
{
if(rsc->parent && rsc->parent->is_allocating == FALSE) {
/* never allocate children on their own */
crm_debug("Escalating allocation of %s to its parent: %s",
rsc->id, rsc->parent->id);
rsc->parent->cmds->color(rsc->parent, data_set);
}
print_resource(LOG_DEBUG_2, "Allocating: ", rsc, FALSE);
if(rsc->provisional == FALSE) {
return rsc->allocated_to;
}
if(rsc->is_allocating) {
crm_debug("Dependancy loop detected involving %s", rsc->id);
return NULL;
}
rsc->is_allocating = TRUE;
rsc->rsc_cons = g_list_sort(rsc->rsc_cons, sort_cons_strength);
slist_iter(
constraint, rsc_colocation_t, rsc->rsc_cons, lpc,
crm_debug_3("%s: Pre-Processing %s", rsc->id, constraint->id);
if(rsc->provisional && constraint->rsc_rh->provisional) {
crm_info("Combine scores from %s and %s",
rsc->id, constraint->rsc_rh->id);
node_list_update(constraint->rsc_rh->allowed_nodes,
rsc->allowed_nodes,
constraint->score/INFINITY);
}
constraint->rsc_rh->cmds->color(
constraint->rsc_rh, data_set);
rsc->cmds->rsc_colocation_lh(
rsc, constraint->rsc_rh, constraint);
);
print_resource(LOG_DEBUG, "Allocating: ", rsc, FALSE);
if(rsc->next_role == RSC_ROLE_STOPPED) {
crm_debug_2("Making sure %s doesn't get allocated", rsc->id);
/* make sure it doesnt come up again */
resource_location(
rsc, NULL, -INFINITY, "target_role", data_set);
}
if(rsc->provisional && native_choose_node(rsc) ) {
crm_debug_3("Allocated resource %s to %s",
rsc->id, rsc->allocated_to->details->uname);
} else if(rsc->allocated_to == NULL) {
if(rsc->orphan == FALSE) {
pe_warn("Resource %s cannot run anywhere", rsc->id);
} else {
crm_info("Stopping orphan resource %s", rsc->id);
}
} else {
crm_debug("Pre-Allocated resource %s to %s",
rsc->id, rsc->allocated_to->details->uname);
}
rsc->is_allocating = FALSE;
print_resource(LOG_DEBUG_3, "Allocated ", rsc, TRUE);
return rsc->allocated_to;
}
void
Recurring(resource_t *rsc, action_t *start, node_t *node,
pe_working_set_t *data_set)
{
char *key = NULL;
const char *name = NULL;
const char *value = NULL;
const char *interval = NULL;
const char *node_uname = NULL;
int interval_ms = 0;
action_t *mon = NULL;
gboolean is_optional = TRUE;
GListPtr possible_matches = NULL;
crm_debug_2("Creating recurring actions for %s", rsc->id);
if(node != NULL) {
node_uname = node->details->uname;
}
xml_child_iter_filter(
rsc->ops_xml, operation, "op",
is_optional = TRUE;
name = crm_element_value(operation, "name");
interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
interval_ms = crm_get_msec(interval);
if(interval_ms <= 0) {
continue;
}
value = crm_element_value(operation, "disabled");
if(crm_is_true(value)) {
continue;
}
key = generate_op_key(rsc->id, name, interval_ms);
if(start != NULL) {
crm_debug_3("Marking %s %s due to %s",
key, start->optional?"optional":"manditory",
start->uuid);
is_optional = start->optional;
} else {
crm_debug_2("Marking %s optional", key);
is_optional = TRUE;
}
/* start a monitor for an already active resource */
possible_matches = find_actions_exact(rsc->actions, key, node);
if(possible_matches == NULL) {
is_optional = FALSE;
crm_debug_3("Marking %s manditory: not active", key);
}
value = crm_element_value(operation, "role");
if((rsc->next_role == RSC_ROLE_MASTER && value == NULL)
|| (value != NULL && text2role(value) != rsc->next_role)) {
int log_level = LOG_DEBUG_2;
const char *foo = "Ignoring";
if(is_optional) {
log_level = LOG_INFO;
foo = "Cancelling";
/* its running : cancel it */
mon = custom_action(
rsc, crm_strdup(key), CRMD_ACTION_CANCEL, node,
FALSE, TRUE, data_set);
mon->task = CRMD_ACTION_CANCEL;
add_hash_param(mon->meta, XML_LRM_ATTR_INTERVAL, interval);
add_hash_param(mon->meta, XML_LRM_ATTR_TASK, name);
custom_action_order(
rsc, NULL, mon,
rsc, promote_key(rsc), NULL,
pe_order_optional, data_set);
mon = NULL;
}
do_crm_log(log_level, "%s action %s (%s vs. %s)",
foo , key, value?value:role2text(RSC_ROLE_SLAVE),
role2text(rsc->next_role));
crm_free(key);
key = NULL;
continue;
}
mon = custom_action(rsc, key, name, node,
is_optional, TRUE, data_set);
if(is_optional) {
crm_debug("%s\t %s (optional)",
crm_str(node_uname), mon->uuid);
}
if(start == NULL || start->runnable == FALSE) {
crm_debug("%s\t %s (cancelled : start un-runnable)",
crm_str(node_uname), mon->uuid);
mon->runnable = FALSE;
} else if(node == NULL
|| node->details->online == FALSE
|| node->details->unclean) {
crm_debug("%s\t %s (cancelled : no node available)",
crm_str(node_uname), mon->uuid);
mon->runnable = FALSE;
} else if(mon->optional == FALSE) {
crm_notice("%s\t %s", crm_str(node_uname),mon->uuid);
}
custom_action_order(rsc, start_key(rsc), NULL,
NULL, crm_strdup(key), mon,
pe_order_internal_restart, data_set);
if(rsc->next_role == RSC_ROLE_MASTER) {
char *running_master = crm_itoa(EXECRA_RUNNING_MASTER);
add_hash_param(mon->meta, XML_ATTR_TE_TARGET_RC, running_master);
custom_action_order(
rsc, promote_key(rsc), NULL,
rsc, NULL, mon,
pe_order_optional, data_set);
crm_free(running_master);
}
);
}
void native_create_actions(resource_t *rsc, pe_working_set_t *data_set)
{
action_t *start = NULL;
node_t *chosen = NULL;
enum rsc_role_e role = RSC_ROLE_UNKNOWN;
enum rsc_role_e next_role = RSC_ROLE_UNKNOWN;
crm_debug_2("Creating actions for %s", rsc->id);
chosen = rsc->allocated_to;
if(chosen != NULL) {
CRM_CHECK(rsc->next_role != RSC_ROLE_UNKNOWN, rsc->next_role = RSC_ROLE_STARTED);
}
unpack_instance_attributes(
rsc->xml, XML_TAG_ATTR_SETS,
chosen?chosen->details->attrs:NULL,
rsc->parameters, NULL, data_set->now);
crm_debug_2("%s: %s->%s", rsc->id,
role2text(rsc->role), role2text(rsc->next_role));
if(g_list_length(rsc->running_on) > 1) {
if(rsc->recovery_type == recovery_stop_start) {
pe_proc_err("Attempting recovery of resource %s", rsc->id);
StopRsc(rsc, NULL, data_set);
rsc->role = RSC_ROLE_STOPPED;
}
} else if(rsc->running_on != NULL) {
node_t *current = rsc->running_on->data;
NoRoleChange(rsc, current, chosen, data_set);
} else if(rsc->role == RSC_ROLE_STOPPED && rsc->next_role == RSC_ROLE_STOPPED) {
char *key = start_key(rsc);
GListPtr possible_matches = find_actions(rsc->actions, key, NULL);
slist_iter(
action, action_t, possible_matches, lpc,
action->optional = TRUE;
/* action->pseudo = TRUE; */
);
crm_debug_2("Stopping a stopped resource");
crm_free(key);
return;
}
role = rsc->role;
while(role != rsc->next_role) {
next_role = rsc_state_matrix[role][rsc->next_role];
crm_debug_2("Executing: %s->%s (%s)",
role2text(role), role2text(next_role), rsc->id);
if(rsc_action_matrix[role][next_role](
rsc, chosen, data_set) == FALSE) {
break;
}
role = next_role;
}
if(rsc->next_role != RSC_ROLE_STOPPED && rsc->is_managed) {
start = start_action(rsc, chosen, TRUE);
Recurring(rsc, start, chosen, data_set);
}
}
void native_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
{
order_restart(rsc);
custom_action_order(rsc, demote_key(rsc), NULL,
rsc, stop_key(rsc), NULL,
pe_order_implies_left, data_set);
custom_action_order(rsc, start_key(rsc), NULL,
rsc, promote_key(rsc), NULL,
pe_order_optional, data_set);
custom_action_order(
rsc, stop_key(rsc), NULL, rsc, delete_key(rsc), NULL,
pe_order_optional, data_set);
custom_action_order(
rsc, delete_key(rsc), NULL, rsc, start_key(rsc), NULL,
pe_order_implies_left, data_set);
if(rsc->notify) {
char *key1 = NULL;
char *key2 = NULL;
key1 = generate_op_key(rsc->id, "confirmed-post_notify_start", 0);
key2 = generate_op_key(rsc->id, "pre_notify_promote", 0);
custom_action_order(
rsc, key1, NULL, rsc, key2, NULL,
pe_order_optional, data_set);
key1 = generate_op_key(rsc->id, "confirmed-post_notify_demote", 0);
key2 = generate_op_key(rsc->id, "pre_notify_stop", 0);
custom_action_order(
rsc, key1, NULL, rsc, key2, NULL,
pe_order_optional, data_set);
}
}
void native_rsc_colocation_lh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
if(rsc_lh == NULL) {
pe_err("rsc_lh was NULL for %s", constraint->id);
return;
} else if(constraint->rsc_rh == NULL) {
pe_err("rsc_rh was NULL for %s", constraint->id);
return;
}
crm_debug_2("Processing colocation constraint between %s and %s",
rsc_lh->id, rsc_rh->id);
rsc_rh->cmds->rsc_colocation_rh(rsc_lh, rsc_rh, constraint);
}
static gboolean
filter_colocation_constraint(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
if(constraint->score == 0){
return FALSE;
}
if(constraint->role_lh != RSC_ROLE_UNKNOWN
&& constraint->role_lh != rsc_lh->next_role) {
crm_debug_4("RH: Skipping constraint: \"%s\" state filter",
role2text(constraint->role_rh));
return FALSE;
}
if(constraint->role_rh != RSC_ROLE_UNKNOWN
&& constraint->role_rh != rsc_rh->next_role) {
crm_debug_4("RH: Skipping constraint: \"%s\" state filter",
role2text(constraint->role_rh));
return FALSE;
}
return TRUE;
}
static void
colocation_match(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
const char *tmp = NULL;
const char *value = NULL;
gboolean do_check = FALSE;
const char *attribute = "#id";
if(constraint->node_attribute != NULL) {
attribute = constraint->node_attribute;
}
if(rsc_rh->allocated_to) {
value = g_hash_table_lookup(rsc_rh->allocated_to->details->attrs, attribute);
do_check = TRUE;
}
slist_iter(
node, node_t, rsc_lh->allowed_nodes, lpc,
tmp = g_hash_table_lookup(node->details->attrs, attribute);
if(do_check && safe_str_eq(tmp, value)) {
crm_debug_2("%s: %s.%s += %d", constraint->id, rsc_lh->id,
node->details->uname, constraint->score);
node->weight = merge_weights(
constraint->score, node->weight);
} else if(do_check == FALSE || constraint->score >= INFINITY) {
crm_debug_2("%s: %s.%s = -INFINITY (%s)", constraint->id, rsc_lh->id,
node->details->uname, do_check?"failed":"unallocated");
node->weight = -INFINITY;
}
);
}
void native_rsc_colocation_rh(
resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint)
{
crm_debug_2("%sColocating %s with %s (%s, weight=%d)",
constraint->score >= 0?"":"Anti-",
rsc_lh->id, rsc_rh->id, constraint->id, constraint->score);
if(filter_colocation_constraint(rsc_lh, rsc_rh, constraint) == FALSE) {
return;
}
if(rsc_rh->provisional) {
return;
} else if(rsc_lh->provisional == FALSE) {
/* error check */
struct node_shared_s *details_lh;
struct node_shared_s *details_rh;
if((constraint->score > -INFINITY) && (constraint->score < INFINITY)) {
return;
}
details_rh = rsc_rh->allocated_to?rsc_rh->allocated_to->details:NULL;
details_lh = rsc_lh->allocated_to?rsc_lh->allocated_to->details:NULL;
if(constraint->score == INFINITY && details_lh != details_rh) {
crm_err("%s and %s are both allocated"
" but to different nodes: %s vs. %s",
rsc_lh->id, rsc_rh->id,
details_lh?details_lh->uname:"n/a",
details_rh?details_rh->uname:"n/a");
} else if(constraint->score == -INFINITY && details_lh == details_rh) {
crm_err("%s and %s are both allocated"
" but to the SAME node: %s",
rsc_lh->id, rsc_rh->id,
details_rh?details_rh->uname:"n/a");
}
return;
} else {
colocation_match(rsc_lh, rsc_rh, constraint);
}
}
void
node_list_update(GListPtr list1, GListPtr list2, int factor)
{
node_t *other_node = NULL;
slist_iter(
node, node_t, list1, lpc,
if(node == NULL) {
continue;
}
other_node = (node_t*)pe_find_node_id(
list2, node->details->id);
if(other_node != NULL) {
crm_debug_2("%s: %d + %d",
node->details->uname,
node->weight, other_node->weight);
node->weight = merge_weights(
factor*other_node->weight, node->weight);
}
);
}
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_debug_3("Processing LH of ordering constraint %d", order->id);
if(lh_action != NULL) {
lh_actions = g_list_append(NULL, lh_action);
} else if(lh_action == NULL && lh_rsc != NULL) {
lh_actions = find_actions(
lh_rsc->actions, order->lh_action_task, NULL);
if(lh_actions == NULL) {
crm_debug_4("No LH-Side (%s/%s) found for constraint",
lh_rsc->id, order->lh_action_task);
if(lh_rsc->next_role == RSC_ROLE_STOPPED) {
resource_t *rh_rsc = order->rh_rsc;
- if(order->rh_action && order->type == pe_order_internal_restart) {
+ if(order->rh_action
+ && (order->type & pe_order_internal_restart)) {
crm_debug_3("No LH(%s/%s) found for RH(%s)...",
lh_rsc->id, order->lh_action_task,
order->rh_action->uuid);
order->rh_action->runnable = FALSE;
return;
} else if(rh_rsc != NULL) {
crm_debug_3("No LH(%s/%s) found for RH(%s/%s)...",
lh_rsc->id, order->lh_action_task,
rh_rsc->id, order->rh_action_task);
rh_rsc->cmds->rsc_order_rh(NULL, rh_rsc, order);
return;
}
}
return;
}
} else {
pe_warn("No LH-Side (%s) specified for constraint",
order->lh_action_task);
if(order->rh_rsc != NULL) {
crm_debug_4("RH-Side was: (%s/%s)",
order->rh_rsc->id,
order->rh_action_task);
} else if(order->rh_action != NULL
&& order->rh_action->rsc != NULL) {
crm_debug_4("RH-Side was: (%s/%s)",
order->rh_action->rsc->id,
order->rh_action_task);
} else if(order->rh_action != NULL) {
crm_debug_4("RH-Side was: %s",
order->rh_action_task);
} else {
crm_debug_4("RH-Side was NULL");
}
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->cmds->rsc_order_rh(
lh_action_iter, rh_rsc, order);
} else if(order->rh_action) {
order_actions(lh_action_iter, order->rh_action, order->type);
}
);
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_debug_3("Processing RH of ordering constraint %d", order->id);
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_debug_4("No RH-Side (%s/%s) found for constraint..."
" ignoring",
rsc->id, order->rh_action_task);
crm_debug_4("LH-Side was: (%s/%s)",
order->lh_rsc?order->lh_rsc->id:order->lh_action?order->lh_action->rsc->id:"<NULL>",
order->lh_action_task);
return;
}
} else if(rh_action == NULL) {
crm_debug_4("No RH-Side (%s) specified for constraint..."
" ignoring", order->rh_action_task);
crm_debug_4("LH-Side was: (%s/%s)",
order->lh_rsc?order->lh_rsc->id:order->lh_action?order->lh_action->rsc->id:"<NULL>",
order->lh_action_task);
return;
}
slist_iter(
rh_action_iter, action_t, rh_actions, lpc,
if(lh_action) {
order_actions(lh_action, rh_action_iter, order->type);
- } else if(order->type == pe_order_internal_restart) {
+ } else if(order->type & pe_order_internal_restart) {
rh_action_iter->runnable = FALSE;
}
);
pe_free_shallow_adv(rh_actions, FALSE);
}
void native_rsc_location(resource_t *rsc, rsc_to_node_t *constraint)
{
GListPtr or_list;
crm_debug_2("Applying %s (%s) to %s", constraint->id,
role2text(constraint->role_filter), rsc->id);
/* take "lifetime" into account */
if(constraint == NULL) {
pe_err("Constraint is NULL");
return;
} else if(rsc == NULL) {
pe_err("LHS of rsc_to_node (%s) is NULL", constraint->id);
return;
} else if(constraint->role_filter > 0
&& constraint->role_filter != rsc->next_role) {
crm_debug("Constraint (%s) is not active (role : %s)",
constraint->id, role2text(constraint->role_filter));
return;
} else if(is_active(constraint) == FALSE) {
crm_debug_2("Constraint (%s) is not active", constraint->id);
return;
}
if(constraint->node_list_rh == NULL) {
crm_debug_2("RHS of constraint %s is NULL", constraint->id);
return;
}
or_list = node_list_or(
rsc->allowed_nodes, constraint->node_list_rh, FALSE);
pe_free_shallow(rsc->allowed_nodes);
rsc->allowed_nodes = or_list;
slist_iter(node, node_t, or_list, lpc,
crm_debug_3("%s + %s : %d", rsc->id, node->details->uname, node->weight);
);
}
void native_expand(resource_t *rsc, pe_working_set_t *data_set)
{
slist_iter(
action, action_t, rsc->actions, lpc,
crm_debug_4("processing action %d for rsc=%s",
action->id, rsc->id);
graph_element_from_action(action, data_set);
);
}
void
native_agent_constraints(resource_t *rsc)
{
}
void
create_notifications(resource_t *rsc, pe_working_set_t *data_set)
{
if(rsc->notify == FALSE) {
return;
}
/* slist_iter( */
/* action, action_t, rsc->actions, lpc, */
/* ); */
}
static void
register_activity(resource_t *rsc, enum action_tasks task, node_t *node, notify_data_t *n_data)
{
notify_entry_t *entry = NULL;
crm_malloc0(entry, sizeof(notify_entry_t));
entry->rsc = rsc;
entry->node = node;
switch(task) {
case start_rsc:
n_data->start = g_list_append(n_data->start, entry);
break;
case stop_rsc:
n_data->stop = g_list_append(n_data->stop, entry);
break;
case action_promote:
n_data->promote = g_list_append(n_data->promote, entry);
break;
case action_demote:
n_data->demote = g_list_append(n_data->demote, entry);
break;
default:
crm_err("Unsupported notify action: %s", task2text(task));
break;
}
}
static void
register_state(resource_t *rsc, node_t *on_node, notify_data_t *n_data)
{
notify_entry_t *entry = NULL;
crm_malloc0(entry, sizeof(notify_entry_t));
entry->rsc = rsc;
entry->node = on_node;
crm_debug_2("%s state: %s", rsc->id, role2text(rsc->next_role));
switch(rsc->next_role) {
case RSC_ROLE_STOPPED:
/* n_data->inactive = g_list_append(n_data->inactive, entry); */
crm_free(entry);
break;
case RSC_ROLE_STARTED:
n_data->active = g_list_append(n_data->active, entry);
break;
case RSC_ROLE_SLAVE:
n_data->slave = g_list_append(n_data->slave, entry);
break;
case RSC_ROLE_MASTER:
n_data->master = g_list_append(n_data->master, entry);
break;
default:
crm_err("Unsupported notify role");
break;
}
}
void
native_create_notify_element(resource_t *rsc, action_t *op,
notify_data_t *n_data, pe_working_set_t *data_set)
{
node_t *next_node = NULL;
gboolean registered = FALSE;
char *op_key = NULL;
GListPtr possible_matches = NULL;
enum action_tasks task = text2task(op->task);
if(op->pre_notify == NULL || op->post_notify == NULL) {
/* no notifications required */
crm_debug_4("No notificaitons required for %s", op->task);
return;
}
next_node = rsc->allocated_to;
op_key = generate_op_key(rsc->id, op->task, 0);
possible_matches = find_actions(rsc->actions, op_key, NULL);
crm_debug_2("Creating notificaitons for: %s (%s->%s)",
op->uuid, role2text(rsc->role), role2text(rsc->next_role));
if(rsc->role == rsc->next_role) {
register_state(rsc, next_node, n_data);
}
slist_iter(
local_op, action_t, possible_matches, lpc,
local_op->notify_keys = n_data->keys;
if(local_op->optional == FALSE) {
registered = TRUE;
register_activity(rsc, task, local_op->node, n_data);
}
);
/* stop / demote */
if(rsc->role != RSC_ROLE_STOPPED) {
if(task == stop_rsc || task == action_demote) {
slist_iter(
current_node, node_t, rsc->running_on, lpc,
pe_pre_notify(rsc, current_node, op, n_data, data_set);
if(task == action_demote || registered == FALSE) {
pe_post_notify(rsc, current_node, op, n_data, data_set);
}
);
}
}
/* start / promote */
if(rsc->next_role != RSC_ROLE_STOPPED) {
CRM_CHECK(next_node != NULL,;);
if(next_node == NULL) {
pe_proc_err("next role: %s", role2text(rsc->next_role));
} else if(task == start_rsc || task == action_promote) {
if(task != start_rsc || registered == FALSE) {
pe_pre_notify(rsc, next_node, op, n_data, data_set);
}
pe_post_notify(rsc, next_node, op, n_data, data_set);
}
}
crm_free(op_key);
pe_free_shallow_adv(possible_matches, FALSE);
}
static void dup_attr(gpointer key, gpointer value, gpointer user_data)
{
char *meta_key = crm_concat(CRM_META, key, '_');
g_hash_table_replace(user_data, meta_key, crm_strdup(value));
}
static action_t *
pe_notify(resource_t *rsc, node_t *node, action_t *op, action_t *confirm,
notify_data_t *n_data, pe_working_set_t *data_set)
{
char *key = NULL;
action_t *trigger = NULL;
const char *value = NULL;
const char *task = NULL;
if(op == NULL || confirm == NULL) {
crm_debug_2("Op=%p confirm=%p", op, confirm);
return NULL;
}
CRM_CHECK(node != NULL, return NULL);
if(node->details->online == FALSE) {
crm_info("Skipping notification for %s", rsc->id);
return NULL;
}
value = g_hash_table_lookup(op->meta, "notify_type");
task = g_hash_table_lookup(op->meta, "notify_operation");
crm_debug_2("Creating actions for %s: %s (%s-%s)",
op->uuid, rsc->id, value, task);
key = generate_notify_key(rsc->id, value, task);
trigger = custom_action(rsc, key, op->task, node,
op->optional, TRUE, data_set);
g_hash_table_foreach(op->meta, dup_attr, trigger->extra);
trigger->notify_keys = n_data->keys;
/* pseudo_notify before notify */
crm_debug_3("Ordering %s before %s (%d->%d)",
op->uuid, trigger->uuid, trigger->id, op->id);
order_actions(op, trigger, pe_order_implies_left);
value = g_hash_table_lookup(op->meta, "notify_confirm");
if(crm_is_true(value)) {
/* notify before pseudo_notified */
crm_debug_3("Ordering %s before %s (%d->%d)",
trigger->uuid, confirm->uuid,
confirm->id, trigger->id);
order_actions(trigger, confirm, pe_order_implies_left);
}
return trigger;
}
void
pe_pre_notify(resource_t *rsc, node_t *node, action_t *op,
notify_data_t *n_data, pe_working_set_t *data_set)
{
crm_debug_2("%s: %s", rsc->id, op->uuid);
pe_notify(rsc, node, op->pre_notify, op->pre_notified,
n_data, data_set);
}
void
pe_post_notify(resource_t *rsc, node_t *node, action_t *op,
notify_data_t *n_data, pe_working_set_t *data_set)
{
action_t *notify = NULL;
CRM_CHECK(op != NULL, return);
CRM_CHECK(rsc != NULL, return);
crm_debug_2("%s: %s", rsc->id, op->uuid);
notify = pe_notify(rsc, node, op->post_notify, op->post_notified,
n_data, data_set);
if(notify != NULL) {
notify->priority = INFINITY;
}
notify = op->post_notified;
if(notify != NULL) {
notify->priority = INFINITY;
slist_iter(
mon, action_t, rsc->actions, lpc,
const char *interval = g_hash_table_lookup(mon->meta, "interval");
if(interval == NULL || safe_str_eq(interval, "0")) {
crm_debug_3("Skipping %s: interval", mon->uuid);
continue;
} else if(safe_str_eq(mon->task, "cancel")) {
crm_debug_3("Skipping %s: cancel", mon->uuid);
continue;
}
order_actions(notify, mon, pe_order_optional);
);
}
}
void
NoRoleChange(resource_t *rsc, node_t *current, node_t *next,
pe_working_set_t *data_set)
{
action_t *start = NULL;
action_t *stop = NULL;
GListPtr possible_matches = NULL;
crm_debug("Executing: %s (role=%s)",rsc->id, role2text(rsc->next_role));
if(current == NULL || next == NULL) {
return;
}
/* use StartRsc/StopRsc */
if(safe_str_neq(current->details->id, next->details->id)) {
crm_notice("Move resource %s\t(%s -> %s)", rsc->id,
current->details->uname, next->details->uname);
stop = stop_action(rsc, current, FALSE);
start = start_action(rsc, next, FALSE);
possible_matches = find_recurring_actions(rsc->actions, next);
slist_iter(match, action_t, possible_matches, lpc,
if(match->optional == FALSE) {
crm_err("Found bad recurring action: %s",
match->uuid);
match->optional = TRUE;
}
);
if(data_set->remove_after_stop) {
DeleteRsc(rsc, current, data_set);
}
} else {
if(rsc->failed) {
crm_notice("Recover resource %s\t(%s)",
rsc->id, next->details->uname);
stop = stop_action(rsc, current, FALSE);
start = start_action(rsc, next, FALSE);
/* /\* make the restart required *\/ */
/* order_stop_start(rsc, rsc, pe_order_implies_left); */
} else if(rsc->start_pending) {
start = start_action(rsc, next, TRUE);
if(start->runnable) {
/* wait for StartRsc() to be called */
rsc->role = RSC_ROLE_STOPPED;
} else {
/* wait for StopRsc() to be called */
rsc->next_role = RSC_ROLE_STOPPED;
}
} else {
stop = stop_action(rsc, current, TRUE);
start = start_action(rsc, next, TRUE);
stop->optional = start->optional;
if(start->runnable == FALSE) {
rsc->next_role = RSC_ROLE_STOPPED;
} else if(start->optional) {
crm_notice("Leave resource %s\t(%s)",
rsc->id, next->details->uname);
} else {
crm_notice("Restart resource %s\t(%s)",
rsc->id, next->details->uname);
}
}
}
}
gboolean
StopRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set)
{
action_t *stop = NULL;
crm_debug_2("Executing: %s", rsc->id);
slist_iter(
current, node_t, rsc->running_on, lpc,
crm_notice(" %s\tStop %s", current->details->uname, rsc->id);
stop = stop_action(rsc, current, FALSE);
if(data_set->remove_after_stop) {
DeleteRsc(rsc, current, data_set);
}
);
return TRUE;
}
gboolean
StartRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set)
{
action_t *start = NULL;
crm_debug_2("Executing: %s", rsc->id);
start = start_action(rsc, next, TRUE);
if(start->runnable) {
crm_notice(" %s\tStart %s", next->details->uname, rsc->id);
start->optional = FALSE;
}
return TRUE;
}
gboolean
PromoteRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set)
{
char *key = NULL;
gboolean runnable = TRUE;
GListPtr action_list = NULL;
crm_debug_2("Executing: %s", rsc->id);
CRM_CHECK(rsc->next_role == RSC_ROLE_MASTER, return FALSE);
key = start_key(rsc);
action_list = find_actions_exact(rsc->actions, key, next);
crm_free(key);
slist_iter(start, action_t, action_list, lpc,
if(start->runnable == FALSE) {
runnable = FALSE;
}
);
if(runnable) {
promote_action(rsc, next, FALSE);
crm_notice("%s\tPromote %s", next->details->uname, rsc->id);
return TRUE;
}
crm_debug("%s\tPromote %s (canceled)", next->details->uname, rsc->id);
key = promote_key(rsc);
action_list = find_actions_exact(rsc->actions, key, next);
crm_free(key);
slist_iter(promote, action_t, action_list, lpc,
promote->runnable = FALSE;
);
return TRUE;
}
gboolean
DemoteRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set)
{
crm_debug_2("Executing: %s", rsc->id);
/* CRM_CHECK(rsc->next_role == RSC_ROLE_SLAVE, return FALSE); */
slist_iter(
current, node_t, rsc->running_on, lpc,
crm_notice("%s\tDeomote %s", current->details->uname, rsc->id);
demote_action(rsc, current, FALSE);
);
return TRUE;
}
gboolean
RoleError(resource_t *rsc, node_t *next, pe_working_set_t *data_set)
{
crm_debug("Executing: %s", rsc->id);
CRM_CHECK(FALSE, return FALSE);
return FALSE;
}
gboolean
NullOp(resource_t *rsc, node_t *next, pe_working_set_t *data_set)
{
crm_debug("Executing: %s", rsc->id);
return FALSE;
}
gboolean
DeleteRsc(resource_t *rsc, node_t *node, pe_working_set_t *data_set)
{
action_t *delete = NULL;
action_t *refresh = NULL;
if(rsc->failed) {
crm_debug_2("Resource %s not deleted from %s: failed",
rsc->id, node->details->uname);
return FALSE;
} else if(node == NULL) {
crm_debug_2("Resource %s not deleted: NULL node", rsc->id);
return FALSE;
} else if(node->details->unclean || node->details->online == FALSE) {
crm_debug_2("Resource %s not deleted from %s: unrunnable",
rsc->id, node->details->uname);
return FALSE;
}
crm_notice("Removing %s from %s",
rsc->id, node->details->uname);
delete = delete_action(rsc, node);
#if DELETE_THEN_REFRESH
refresh = custom_action(
NULL, crm_strdup(CRM_OP_LRM_REFRESH), CRM_OP_LRM_REFRESH,
node, FALSE, TRUE, data_set);
add_hash_param(refresh->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE);
order_actions(delete, refresh, pe_order_optional);
#endif
return TRUE;
}
gboolean
native_create_probe(resource_t *rsc, node_t *node, action_t *complete,
gboolean force, pe_working_set_t *data_set)
{
char *key = NULL;
char *target_rc = NULL;
action_t *probe = NULL;
node_t *running = NULL;
CRM_CHECK(node != NULL, return FALSE);
if(rsc->orphan) {
crm_debug_2("Skipping orphan: %s", rsc->id);
return FALSE;
}
running = pe_find_node_id(rsc->known_on, node->details->id);
if(force == FALSE && running != NULL) {
/* we already know the status of the resource on this node */
crm_debug_3("Skipping active: %s", rsc->id);
return FALSE;
}
key = generate_op_key(rsc->id, CRMD_ACTION_STATUS, 0);
probe = custom_action(rsc, key, CRMD_ACTION_STATUS, node,
FALSE, TRUE, data_set);
probe->priority = INFINITY;
running = pe_find_node_id(rsc->running_on, node->details->id);
if(running == NULL) {
target_rc = crm_itoa(EXECRA_NOT_RUNNING);
add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, target_rc);
crm_free(target_rc);
}
crm_debug_2("%s: Created probe for %s", node->details->uname, rsc->id);
custom_action_order(rsc, NULL, probe, rsc, NULL, complete,
pe_order_implies_left, data_set);
return TRUE;
}
static void
native_start_constraints(
resource_t *rsc, action_t *stonith_op, gboolean is_stonith,
pe_working_set_t *data_set)
{
gboolean is_unprotected = FALSE;
gboolean run_unprotected = TRUE;
if(is_stonith) {
char *key = start_key(rsc);
crm_debug_2("Ordering %s action before stonith events", key);
custom_action_order(
rsc, key, NULL,
NULL, crm_strdup(CRM_OP_FENCE), stonith_op,
pe_order_optional, data_set);
} else {
slist_iter(action, action_t, rsc->actions, lpc2,
if(action->needs != rsc_req_stonith) {
crm_debug_3("%s doesnt need to wait for stonith events", action->uuid);
continue;
}
crm_debug_2("Ordering %s after stonith events", action->uuid);
if(stonith_op != NULL) {
custom_action_order(
NULL, crm_strdup(CRM_OP_FENCE), stonith_op,
rsc, NULL, action,
pe_order_implies_left, data_set);
} else if(run_unprotected == FALSE) {
/* mark the start unrunnable */
action->runnable = FALSE;
} else {
is_unprotected = TRUE;
}
);
}
if(is_unprotected) {
pe_err("SHARED RESOURCE %s IS NOT PROTECTED:"
" Stonith disabled", rsc->id);
}
}
static void
native_stop_constraints(
resource_t *rsc, action_t *stonith_op, gboolean is_stonith,
pe_working_set_t *data_set)
{
char *key = NULL;
GListPtr action_list = NULL;
node_t *node = stonith_op->node;
key = stop_key(rsc);
action_list = find_actions(rsc->actions, key, node);
crm_free(key);
/* add the stonith OP as a stop pre-req and the mark the stop
* as a pseudo op - since its now redundant
*/
slist_iter(
action, action_t, action_list, lpc2,
if(node->details->online == FALSE || rsc->failed) {
resource_t *parent = NULL;
crm_warn("Stop of failed resource %s is"
" implict after %s is fenced",
rsc->id, node->details->uname);
/* the stop would never complete and is
* now implied by the stonith operation
*/
action->pseudo = TRUE;
action->runnable = TRUE;
if(is_stonith) {
/* do nothing */
} else {
custom_action_order(
NULL, crm_strdup(CRM_OP_FENCE),stonith_op,
rsc, start_key(rsc), NULL,
pe_order_implies_left, data_set);
}
/* find the top-most resource */
parent = rsc->parent;
while(parent != NULL && parent->parent != NULL) {
parent = parent->parent;
}
if(parent) {
crm_info("Re-creating actions for %s",
parent->id);
parent->cmds->create_actions(parent, data_set);
}
} else if(is_stonith == FALSE) {
crm_info("Moving healthy resource %s"
" off %s before fencing",
rsc->id, node->details->uname);
/* stop healthy resources before the
* stonith op
*/
custom_action_order(
rsc, stop_key(rsc), NULL,
NULL,crm_strdup(CRM_OP_FENCE),stonith_op,
pe_order_implies_left, data_set);
}
);
key = demote_key(rsc);
action_list = find_actions(rsc->actions, key, node);
crm_free(key);
slist_iter(
action, action_t, action_list, lpc2,
if(node->details->online == FALSE || rsc->failed) {
crm_info("Demote of failed resource %s is"
" implict after %s is fenced",
rsc->id, node->details->uname);
/* the stop would never complete and is
* now implied by the stonith operation
*/
action->pseudo = TRUE;
action->runnable = TRUE;
if(is_stonith == FALSE) {
custom_action_order(
NULL, crm_strdup(CRM_OP_FENCE), stonith_op,
rsc, demote_key(rsc), NULL,
pe_order_implies_left, data_set);
}
}
);
}
void
native_stonith_ordering(
resource_t *rsc, action_t *stonith_op, pe_working_set_t *data_set)
{
gboolean is_stonith = FALSE;
const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
if(rsc->is_managed == FALSE) {
crm_debug_3("Skipping fencing constraints for unmanaged resource: %s", rsc->id);
return;
}
if(stonith_op != NULL && safe_str_eq(class, "stonith")) {
is_stonith = TRUE;
}
/* Start constraints */
native_start_constraints(rsc, stonith_op, is_stonith, data_set);
/* Stop constraints */
native_stop_constraints(rsc, stonith_op, is_stonith, data_set);
}
void
native_migrate_reload(resource_t *rsc, pe_working_set_t *data_set)
{
char *key = NULL;
GListPtr action_list = NULL;
const char *value = NULL;
action_t *stop = NULL;
action_t *start = NULL;
action_t *other = NULL;
action_t *action = NULL;
if(rsc->variant != pe_native) {
return;
}
if(rsc->is_managed == FALSE
|| rsc->failed
|| rsc->start_pending
|| rsc->next_role != RSC_ROLE_STARTED
|| g_list_length(rsc->running_on) != 1) {
crm_debug_3("%s: resource", rsc->id);
return;
}
key = start_key(rsc);
action_list = find_actions(rsc->actions, key, NULL);
crm_free(key);
if(action_list == NULL) {
crm_debug_3("%s: no start action", rsc->id);
return;
}
start = action_list->data;
value = g_hash_table_lookup(rsc->meta, "allow_migrate");
if(crm_is_true(value)) {
rsc->can_migrate = TRUE;
}
if(rsc->can_migrate == FALSE
&& start->allow_reload_conversion == FALSE) {
crm_debug_3("%s: no need to continue", rsc->id);
return;
}
key = stop_key(rsc);
action_list = find_actions(rsc->actions, key, NULL);
crm_free(key);
if(action_list == NULL) {
crm_debug_3("%s: no stop action", rsc->id);
return;
}
stop = action_list->data;
action = start;
if(action->pseudo
|| action->optional
|| action->node == NULL
|| action->runnable == FALSE) {
crm_debug_3("Skipping: %s", action->task);
return;
}
action = stop;
if(action->pseudo
|| action->optional
|| action->node == NULL
|| action->runnable == FALSE) {
crm_debug_3("Skipping: %s", action->task);
return;
}
slist_iter(
other_w, action_wrapper_t, start->actions_before, lpc,
other = other_w->action;
if(other->optional == FALSE
&& other->rsc != NULL
&& other->rsc != start->rsc) {
crm_debug_2("Skipping: start depends");
return;
}
);
slist_iter(
other_w, action_wrapper_t, stop->actions_after, lpc,
other = other_w->action;
if(other->optional == FALSE
&& other->rsc != NULL
&& other->rsc != stop->rsc) {
crm_debug_2("Skipping: stop depends");
return;
}
);
if(rsc->can_migrate && stop->node->details != start->node->details) {
crm_info("Migrating %s from %s to %s", rsc->id,
stop->node->details->uname,
start->node->details->uname);
crm_free(stop->uuid);
stop->task = CRMD_ACTION_MIGRATE;
stop->uuid = generate_op_key(rsc->id, stop->task, 0);
add_hash_param(stop->meta, "migrate_source",
stop->node->details->uname);
add_hash_param(stop->meta, "migrate_target",
start->node->details->uname);
crm_free(start->uuid);
start->task = CRMD_ACTION_MIGRATED;
start->uuid = generate_op_key(rsc->id, start->task, 0);
add_hash_param(start->meta, "migrate_source_uuid",
stop->node->details->id);
add_hash_param(start->meta, "migrate_source",
stop->node->details->uname);
add_hash_param(start->meta, "migrate_target",
start->node->details->uname);
} else if(start->allow_reload_conversion
&& stop->node->details == start->node->details) {
crm_info("Rewriting restart of %s on %s as a reload",
rsc->id, start->node->details->uname);
crm_free(start->uuid);
start->task = "reload";
start->uuid = generate_op_key(rsc->id, start->task, 0);
stop->pseudo = TRUE; /* easier than trying to delete it from the graph */
} else {
crm_debug_3("%s nothing to do", rsc->id);
}
}
diff --git a/crm/pengine/pengine.h b/crm/pengine/pengine.h
index 83573126b3..6fbdf9ea8a 100644
--- a/crm/pengine/pengine.h
+++ b/crm/pengine/pengine.h
@@ -1,166 +1,166 @@
/* $Id: pengine.h,v 1.115 2006/06/09 06:42:16 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 rsc_to_node_s rsc_to_node_t;
typedef struct rsc_colocation_s rsc_colocation_t;
typedef struct lrm_agent_s lrm_agent_t;
typedef struct order_constraint_s order_constraint_t;
#include <glib.h>
#include <crm/crm.h>
#include <crm/common/msg.h>
#include <crm/common/iso8601.h>
#include <crm/pengine/rules.h>
#include <crm/pengine/common.h>
#include <crm/pengine/status.h>
#include <linux-ha/config.h>
#include <crm/pengine/complex.h>
enum pe_stop_fail {
pesf_block,
pesf_stonith,
pesf_ignore
};
enum pe_ordering {
- pe_order_implies_left, /* was: _mandatory */
- pe_order_internal_restart, /* upgrades to: right_implies_left */
- pe_order_implies_right, /* was: _recover */
- pe_order_postnotify,
- pe_order_optional /* pure ordering, nothing implied */
+ pe_order_implies_left = 0x01, /* was: _mandatory */
+ pe_order_internal_restart = 0x02, /* upgrades to: right_implies_left */
+ pe_order_implies_right = 0x04, /* was: _recover */
+ pe_order_postnotify = 0x08,
+ pe_order_optional = 0x10 /* pure ordering, nothing implied */
};
struct rsc_colocation_s {
const char *id;
const char *node_attribute;
resource_t *rsc_lh;
resource_t *rsc_rh;
int role_lh;
int role_rh;
int score;
};
struct rsc_to_node_s {
const char *id;
resource_t *rsc_lh;
enum rsc_role_e role_filter;
GListPtr node_list_rh; /* node_t* */
};
struct order_constraint_s
{
int id;
enum pe_ordering type;
void *lh_opaque;
resource_t *lh_rsc;
action_t *lh_action;
char *lh_action_task;
void *rh_opaque;
resource_t *rh_rsc;
action_t *rh_action;
char *rh_action_task;
/* (soon to be) variant specific */
/* int lh_rsc_incarnation; */
/* int rh_rsc_incarnation; */
};
typedef struct action_wrapper_s action_wrapper_t;
struct action_wrapper_s
{
enum pe_ordering type;
action_t *action;
};
extern gboolean stage0(pe_working_set_t *data_set);
extern gboolean stage1(pe_working_set_t *data_set);
extern gboolean stage2(pe_working_set_t *data_set);
extern gboolean stage3(pe_working_set_t *data_set);
extern gboolean stage4(pe_working_set_t *data_set);
extern gboolean stage5(pe_working_set_t *data_set);
extern gboolean stage6(pe_working_set_t *data_set);
extern gboolean stage7(pe_working_set_t *data_set);
extern gboolean stage8(pe_working_set_t *data_set);
extern gboolean summary(GListPtr resources);
extern gboolean pe_msg_dispatch(IPC_Channel *sender, void *user_data);
extern gboolean process_pe_message(
HA_Message *msg, crm_data_t *xml_data, IPC_Channel *sender);
extern gboolean unpack_constraints(
crm_data_t *xml_constraints, pe_working_set_t *data_set);
extern gboolean update_action_states(GListPtr actions);
extern gboolean shutdown_constraints(
node_t *node, action_t *shutdown_op, pe_working_set_t *data_set);
extern gboolean stonith_constraints(
node_t *node, action_t *stonith_op, pe_working_set_t *data_set);
extern gboolean custom_action_order(
resource_t *lh_rsc, char *lh_task, action_t *lh_action,
resource_t *rh_rsc, char *rh_task, action_t *rh_action,
enum pe_ordering type, pe_working_set_t *data_set);
#define order_start_start(rsc1,rsc2, type) \
custom_action_order(rsc1, start_key(rsc1), NULL, \
rsc2, start_key(rsc2) ,NULL, \
type, data_set)
#define order_stop_stop(rsc1, rsc2, type) \
custom_action_order(rsc1, stop_key(rsc1), NULL, \
rsc2, stop_key(rsc2) ,NULL, \
type, data_set)
#define order_restart(rsc1) \
custom_action_order(rsc1, stop_key(rsc1), NULL, \
rsc1, start_key(rsc1), NULL, \
pe_order_internal_restart, data_set)
#define order_stop_start(rsc1, rsc2, type) \
custom_action_order(rsc1, stop_key(rsc1), NULL, \
rsc2, start_key(rsc2) ,NULL, \
type, data_set)
#define order_start_stop(rsc1, rsc2, type) \
custom_action_order(rsc1, start_key(rsc1), NULL, \
rsc2, stop_key(rsc2) ,NULL, \
type, data_set)
extern void graph_element_from_action(
action_t *action, pe_working_set_t *data_set);
extern const char* transition_idle_timeout;
#endif
diff --git a/crm/pengine/utils.c b/crm/pengine/utils.c
index ba0808f0b7..359e7c5c7a 100644
--- a/crm/pengine/utils.c
+++ b/crm/pengine/utils.c
@@ -1,528 +1,537 @@
/* $Id: utils.c,v 1.147 2006/07/05 14:20:02 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 <crm/msg_xml.h>
#include <allocate.h>
#include <utils.h>
#include <lib/crm/pengine/utils.h>
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->score > rsc_constraint2->score) {
return 1;
}
if(rsc_constraint1->score < rsc_constraint2->score) {
return -1;
}
return 0;
}
void
print_rsc_to_node(const char *pre_text, rsc_to_node_t *cons, gboolean details)
{
if(cons == NULL) {
crm_debug_4("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_debug_4("%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_debug_4("\t%s (node placement rule)",
safe_val3(NULL, cons, rsc_lh, id));
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_debug_4("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_debug_4("%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_debug_4("\t%s --> %s, %d",
safe_val3(NULL, cons, rsc_lh, id),
safe_val3(NULL, cons, rsc_rh, id),
cons->score);
}
}
void
pe_free_ordering(GListPtr constraints)
{
GListPtr iterator = constraints;
while(iterator != NULL) {
order_constraint_t *order = iterator->data;
iterator = iterator->next;
crm_free(order->lh_action_task);
crm_free(order->rh_action_task);
crm_free(order);
}
if(constraints != NULL) {
g_list_free(constraints);
}
}
void
pe_free_rsc_to_node(GListPtr constraints)
{
GListPtr iterator = constraints;
while(iterator != NULL) {
rsc_to_node_t *cons = iterator->data;
iterator = iterator->next;
pe_free_shallow(cons->node_list_rh);
crm_free(cons);
}
if(constraints != NULL) {
g_list_free(constraints);
}
}
rsc_to_node_t *
rsc2node_new(const char *id, resource_t *rsc,
int node_weight, node_t *foo_node, pe_working_set_t *data_set)
{
rsc_to_node_t *new_con = NULL;
if(rsc == NULL || id == NULL) {
pe_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc);
return NULL;
}
crm_malloc0(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->role_filter = RSC_ROLE_UNKNOWN;
if(foo_node != NULL) {
node_t *copy = node_copy(foo_node);
copy->weight = node_weight;
new_con->node_list_rh = g_list_append(NULL, copy);
} else {
CRM_CHECK(node_weight == 0, return NULL);
}
data_set->placement_constraints = g_list_append(
data_set->placement_constraints, new_con);
rsc->rsc_location = g_list_append(
rsc->rsc_location, new_con);
}
return new_con;
}
const char *
ordering_type2text(enum pe_ordering type)
{
const char *result = "<unknown>";
- switch(type)
- {
- case pe_order_implies_left:
- result = "right_implies_left"; /* was: mandatory */
- break;
- case pe_order_internal_restart:
- result = "internal_restart"; /* upgrades to: right_implies_left */
- break;
- case pe_order_implies_right:
- result = "left_implies_right"; /* was: recover */
- break;
- case pe_order_optional: /* pure ordering, nothing implied */
- result = "optional";
- break;
- case pe_order_postnotify:
- result = "post_notify";
- break;
+ if(type & pe_order_implies_left) {
+ /* was: mandatory */
+ result = "right_implies_left";
+
+ } else if(type & pe_order_internal_restart) {
+ /* upgrades to: right_implies_left */
+ result = "internal_restart";
+
+ } else if(type & pe_order_implies_right) {
+ /* was: recover */
+ result = "left_implies_right";
+
+ } else if(type & pe_order_optional) {
+ /* pure ordering, nothing implied */
+ result = "optional";
+
+ } else if(type & pe_order_postnotify) {
+ result = "post_notify";
+
+ } else {
+ crm_err("Unknown ordering type: %.3x", type);
}
+
return result;
}
gboolean
can_run_resources(const node_t *node)
{
if(node == NULL) {
crm_err("No node supplied");
return FALSE;
} else if(node->details->online == FALSE
|| node->details->shutdown
|| node->details->unclean
|| node->details->standby) {
crm_debug_2("%s: online=%d, unclean=%d, standby=%d",
node->details->uname, node->details->online,
node->details->unclean, node->details->standby);
return FALSE;
}
return TRUE;
}
/* 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;
int node1_weight = 0;
int node2_weight = 0;
if(a == NULL) { return 1; }
if(b == NULL) { return -1; }
node1_weight = node1->weight;
node2_weight = node2->weight;
if(can_run_resources(node1) == FALSE) {
node1_weight = -INFINITY;
}
if(can_run_resources(node2) == FALSE) {
node2_weight = -INFINITY;
}
if(node1_weight > node2_weight) {
crm_debug_3("%s (%d) > %s (%d) : weight",
node1->details->uname, node1_weight,
node2->details->uname, node2_weight);
return -1;
}
if(node1_weight < node2_weight) {
crm_debug_3("%s (%d) < %s (%d) : weight",
node1->details->uname, node1_weight,
node2->details->uname, node2_weight);
return 1;
}
crm_debug_3("%s (%d) == %s (%d) : weight",
node1->details->uname, node1_weight,
node2->details->uname, node2_weight);
/* now try to balance resources across the cluster */
if(node1->details->num_resources
< node2->details->num_resources) {
crm_debug_3("%s (%d) < %s (%d) : resources",
node1->details->uname, node1->details->num_resources,
node2->details->uname, node2->details->num_resources);
return -1;
} else if(node1->details->num_resources
> node2->details->num_resources) {
crm_debug_3("%s (%d) > %s (%d) : resources",
node1->details->uname, node1->details->num_resources,
node2->details->uname, node2->details->num_resources);
return 1;
}
crm_debug_4("%s = %s", node1->details->uname, node2->details->uname);
return 0;
}
gboolean
native_assign_node(resource_t *rsc, GListPtr nodes, node_t *chosen)
{
int multiple = 0;
CRM_ASSERT(rsc->variant == pe_native);
rsc->provisional = FALSE;
if(chosen == NULL) {
crm_debug("Could not allocate a node for %s", rsc->id);
rsc->next_role = RSC_ROLE_STOPPED;
return FALSE;
} else if(can_run_resources(chosen) == FALSE) {
crm_debug("All nodes for resource %s are unavailable"
", unclean or shutting down", rsc->id);
rsc->next_role = RSC_ROLE_STOPPED;
return FALSE;
} else if(chosen->weight < 0) {
crm_debug("Even highest ranked node for %s, had weight %d",
rsc->id, chosen->weight);
rsc->next_role = RSC_ROLE_STOPPED;
return FALSE;
}
if(rsc->next_role == RSC_ROLE_UNKNOWN) {
rsc->next_role = RSC_ROLE_STARTED;
}
slist_iter(candidate, node_t, nodes, lpc,
crm_debug("Color %s, Node[%d] %s: %d", rsc->id, lpc,
candidate->details->uname, candidate->weight);
if(chosen->weight > 0
&& candidate->details->unclean == FALSE
&& candidate->weight == chosen->weight) {
multiple++;
}
);
if(multiple > 1) {
int log_level = LOG_INFO;
char *score = score2char(chosen->weight);
if(chosen->weight >= INFINITY) {
log_level = LOG_WARNING;
}
do_crm_log(log_level, "%d nodes with equal score (%s) for"
" running the listed resources (chose %s):",
multiple, score, chosen->details->uname);
crm_free(score);
}
/* todo: update the old node for each resource to reflect its
* new resource count
*/
if(rsc->allocated_to) {
node_t *old = rsc->allocated_to;
old->details->allocated_rsc = g_list_remove(
old->details->allocated_rsc, rsc);
old->details->num_resources--;
old->count--;
}
crm_debug("Assigning %s to %s", chosen->details->uname, rsc->id);
crm_free(rsc->allocated_to);
rsc->allocated_to = node_copy(chosen);
chosen->details->allocated_rsc = g_list_append(chosen->details->allocated_rsc, rsc);
chosen->details->num_resources++;
chosen->count++;
return TRUE;
}
void
convert_non_atomic_task(resource_t *rsc, order_constraint_t *order)
{
int interval = 0;
char *rid = NULL;
char *raw_task = NULL;
int task = no_action;
char *old_uuid = order->lh_action_task;
crm_debug("Processing %s", old_uuid);
if(order->lh_action_task == NULL
|| strstr(order->lh_action_task, "notify") != NULL) {
/* no conversion */
return;
}
CRM_ASSERT(parse_op_key(old_uuid, &rid, &raw_task, &interval));
task = text2task(raw_task);
switch(task) {
case stop_rsc:
case start_rsc:
case action_notify:
case action_promote:
case action_demote:
break;
case stopped_rsc:
case started_rsc:
case action_notified:
case action_promoted:
case action_demoted:
task--;
break;
case monitor_rsc:
case shutdown_crm:
case stonith_node:
task = no_action;
break;
default:
crm_err("Unknown action: %s", raw_task);
task = no_action;
break;
}
if(task != no_action) {
if(rsc->notify) {
order->lh_action_task = generate_notify_key(
rsc->id, "confirmed-post",
task2text(task));
} else {
order->lh_action_task = generate_op_key(
rsc->id, task2text(task+1), 0);
}
crm_debug("Converted %s -> %s",
old_uuid, order->lh_action_task);
crm_free(old_uuid);
}
crm_free(raw_task);
crm_free(rid);
}
void
order_actions(
action_t *lh_action, action_t *rh_action, enum pe_ordering order)
{
action_wrapper_t *wrapper = NULL;
GListPtr list = NULL;
crm_debug_2("Ordering Action %s before %s",
lh_action->uuid, rh_action->uuid);
log_action(LOG_DEBUG_4, "LH (order_actions)", lh_action, FALSE);
log_action(LOG_DEBUG_4, "RH (order_actions)", rh_action, FALSE);
crm_malloc0(wrapper, sizeof(action_wrapper_t));
if(wrapper != NULL) {
wrapper->action = rh_action;
wrapper->type = order;
list = lh_action->actions_after;
list = g_list_append(list, wrapper);
lh_action->actions_after = list;
wrapper = NULL;
}
- if(order != pe_order_implies_right) {
+
+ order |= pe_order_implies_right;
+ order ^= pe_order_implies_right;
+
+ if(order) {
crm_malloc0(wrapper, sizeof(action_wrapper_t));
if(wrapper != NULL) {
wrapper->action = lh_action;
wrapper->type = order;
list = rh_action->actions_before;
list = g_list_append(list, wrapper);
rh_action->actions_before = list;
}
}
}
void
log_action(unsigned int log_level, const char *pre_text, action_t *action, gboolean details)
{
const char *node_uname = NULL;
const char *node_uuid = NULL;
if(action == NULL) {
do_crm_log(log_level, "%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
if(action->pseudo) {
node_uname = NULL;
node_uuid = NULL;
} else if(action->node != NULL) {
node_uname = action->node->details->uname;
node_uuid = action->node->details->id;
} else {
node_uname = "<none>";
node_uuid = NULL;
}
switch(text2task(action->task)) {
case stonith_node:
case shutdown_crm:
do_crm_log(log_level,
"%s%s%sAction %d: %s%s%s%s%s%s",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
action->pseudo?"Pseduo ":action->optional?"Optional ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
action->id, action->uuid,
node_uname?"\ton ":"",
node_uname?node_uname:"",
node_uuid?"\t\t(":"",
node_uuid?node_uuid:"",
node_uuid?")":"");
break;
default:
do_crm_log(log_level,
"%s%s%sAction %d: %s %s%s%s%s%s%s",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
action->optional?"Optional ":action->pseudo?"Pseduo ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
action->id, action->uuid,
safe_val3("<none>", action, rsc, id),
node_uname?"\ton ":"",
node_uname?node_uname:"",
node_uuid?"\t\t(":"",
node_uuid?node_uuid:"",
node_uuid?")":"");
break;
}
if(details) {
do_crm_log(log_level+1, "\t\t====== Preceeding Actions");
slist_iter(
other, action_wrapper_t, action->actions_before, lpc,
log_action(log_level+1, "\t\t", other->action, FALSE);
);
do_crm_log(log_level+1, "\t\t====== Subsequent Actions");
slist_iter(
other, action_wrapper_t, action->actions_after, lpc,
log_action(log_level+1, "\t\t", other->action, FALSE);
);
do_crm_log(log_level+1, "\t\t====== End");
} else {
do_crm_log(log_level, "\t\t(seen=%d, before=%d, after=%d)",
action->seen_count,
g_list_length(action->actions_before),
g_list_length(action->actions_after));
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 8, 5:38 PM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002376
Default Alt Text
(92 KB)

Event Timeline