Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F7631652
graph.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
graph.c
View Options
/* $Id: graph.c,v 1.74 2006/02/14 11:59:36 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 <pengine.h>
#include <pe_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;
}
#define UPDATE_THEM 1
gboolean
update_action(action_t *action)
{
gboolean change = FALSE;
enum action_tasks task = no_action;
crm_debug_3("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_ordering_restart
&& action->rsc->role > RSC_ROLE_STOPPED) {
crm_debug_3("Upgrading %s constraint to %s",
ordering_type2text(other->type),
ordering_type2text(pe_ordering_manditory));
other->type = pe_ordering_manditory;
}
if(other->type != pe_ordering_manditory) {
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->extra, "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 manditory 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_ordering_recover) {
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_ordering_restart) {
} else if(other->type == pe_ordering_postnotify) {
CRM_DEV_ASSERT(action->rsc == other->action->rsc);
if(crm_assert_failed) {
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"
" manditory 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;
}
);
if(change) {
update_action(action);
}
crm_debug_3("Action %s: %s", action->uuid, change?"update":"untouched");
return change;
}
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_ordering_manditory, data_set);
);
return TRUE;
}
gboolean
stonith_constraints(node_t *node,
action_t *stonith_op, action_t *shutdown_op,
pe_working_set_t *data_set)
{
GListPtr stop_actions = NULL;
gboolean run_unprotected = TRUE;
if(shutdown_op != NULL && stonith_op != NULL) {
/* stop everything we can via shutdown_constraints() and then
* shoot the node... the shutdown has been superceeded
*/
shutdown_op->pseudo = TRUE;
shutdown_op->runnable = TRUE;
/* shutdown before stonith */
/* Give any resources a chance to shutdown normally */
crm_debug_4("Adding shutdown (%d) as an input to stonith (%d)",
shutdown_op->id, stonith_op->id);
custom_action_order(
NULL, crm_strdup(CRM_OP_SHUTDOWN), shutdown_op,
NULL, crm_strdup(CRM_OP_FENCE), stonith_op,
pe_ordering_manditory, data_set);
}
/*
* Make sure the stonith OP occurs before we start any shared resources
*/
slist_iter(
rsc, resource_t, data_set->resources, lpc,
slist_iter(action, action_t, rsc->actions, lpc2,
if(action->needs != rsc_req_stonith) {
continue;
}
if(stonith_op != NULL) {
custom_action_order(
NULL, crm_strdup(CRM_OP_FENCE), stonith_op,
rsc, NULL, action,
pe_ordering_manditory, data_set);
} else if(run_unprotected == FALSE) {
/* mark the start unrunnable */
action->runnable = FALSE;
} else {
pe_err("SHARED RESOURCE %s IS NOT PROTECTED:"
" Stonith disabled", rsc->id);
}
);
);
/* add the stonith OP as a stop pre-req and the mark the stop
* as a pseudo op - since its now redundant
*/
slist_iter(
rsc, resource_t, node->details->running_rsc, lpc,
if(rsc->is_managed == FALSE) {
crm_debug_2("Skipping fencing constraints for unmanaged resource: %s", rsc->id);
} else if(stonith_op != NULL) {
char *key = stop_key(rsc);
stop_actions = find_actions(rsc->actions, key, node);
crm_free(key);
slist_iter(
action, action_t, stop_actions, lpc2,
if(node->details->online == FALSE
|| rsc->failed) {
crm_info("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;
custom_action_order(
NULL, crm_strdup(CRM_OP_FENCE),stonith_op,
rsc, start_key(rsc), NULL,
pe_ordering_manditory, data_set);
} else {
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_ordering_manditory, data_set);
}
);
crm_debug_4("Adding stonith (%d) as an input to stop",
stonith_op->id);
/* } else if((rsc->unclean || node->details->unclean) */
/* && rsc->stopfail_type == pesf_block) { */
/* /\* depend on the stop action which will fail *\/ */
/* pe_err("SHARED RESOURCE %s WILL REMAIN BLOCKED" */
/* " ON NODE %s UNTIL %s", */
/* rsc->id, node->details->uname, */
/* data_set->stonith_enabled?"QUORUM RETURNS":"CLEANED UP MANUALLY"); */
/* continue; */
/* } else if((rsc->unclean || node->details->unclean) */
/* && rsc->stopfail_type == pesf_ignore) { */
/* /\* nothing to do here *\/ */
/* pe_err("SHARED RESOURCE %s IS NOT PROTECTED", rsc->id); */
/* continue; */
}
);
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);
if(action->rsc != NULL) {
crm_xml_add(
action_xml, XML_LRM_ATTR_RSCID, action->rsc->name);
}
crm_xml_add(action_xml, XML_LRM_ATTR_TASK, action->task);
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);
CRM_DEV_ASSERT(NULL != crm_element_value(
action_xml, XML_LRM_ATTR_TARGET));
CRM_DEV_ASSERT(NULL != crm_element_value(
action_xml, XML_LRM_ATTR_TARGET_UUID));
}
if(action->failure_is_fatal == FALSE) {
g_hash_table_insert(
action->extra, crm_strdup(XML_ATTR_TE_ALLOWFAIL),
crm_strdup(XML_BOOLEAN_TRUE));
}
if(as_input) {
return action_xml;
}
if(action->notify_keys != NULL) {
g_hash_table_foreach(
action->notify_keys, dup_attr, action->extra);
}
if(action->rsc != NULL && action->pseudo == FALSE) {
crm_data_t *rsc_xml = create_xml_node(
action_xml, crm_element_name(action->rsc->xml));
copy_in_properties(rsc_xml, action->rsc->xml);
args_xml = create_xml_node(action_xml, XML_TAG_ATTRS);
g_hash_table_foreach(action->extra, hash2field, args_xml);
g_hash_table_foreach(
action->rsc->parameters, hash2field, args_xml);
} else {
args_xml = create_xml_node(action_xml, XML_TAG_ATTRS);
g_hash_table_foreach(action->extra, hash2field, args_xml);
}
crm_log_xml_debug_2(action_xml, "dumped action");
return action_xml;
}
static gboolean
should_dump_action(action_t *action)
{
const char * interval = g_hash_table_lookup(action->extra, "interval");
if(action == NULL) {
pe_err("Cannot dump NULL action");
return FALSE;
} else 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 two 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;
}
return TRUE;
}
void
graph_element_from_action(action_t *action, pe_working_set_t *data_set)
{
int last_action = -1;
char *syn_id = NULL;
crm_data_t * syn = NULL;
crm_data_t * set = NULL;
crm_data_t * in = NULL;
crm_data_t * input = NULL;
crm_data_t * xml_action = NULL;
if(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");
syn_id = crm_itoa(data_set->num_synapse);
crm_xml_add(syn, XML_ATTR_ID, syn_id);
crm_free(syn_id);
data_set->num_synapse++;
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_DEV_ASSERT(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);
);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Thu, Oct 16, 3:05 PM (14 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2536441
Default Alt Text
graph.c (14 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment