Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/crm/pengine/graph.c b/crm/pengine/graph.c
index 07ef3b7dec..4e52fbb93a 100644
--- a/crm/pengine/graph.c
+++ b/crm/pengine/graph.c
@@ -1,376 +1,370 @@
-/* $Id: graph.c,v 1.33 2005/04/08 17:04:12 andrew Exp $ */
+/* $Id: graph.c,v 1.34 2005/04/11 10:51:05 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/param.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/msg.h>
#include <glib.h>
#include <pengine.h>
#include <pe_utils.h>
gboolean update_action(action_t *action);
gboolean
update_action_states(GListPtr actions)
{
slist_iter(
action, action_t, actions, lpc,
update_action(action);
);
return TRUE;
}
gboolean
update_action(action_t *action)
{
gboolean change = FALSE;
if(action->optional && action->runnable) {
return FALSE;
}
slist_iter(
other, action_wrapper_t, action->actions_after, lpc,
if(action->runnable == FALSE && action->optional == FALSE) {
if(other->action->runnable == FALSE) {
continue;
} else if (other->strength == pecs_must) {
change = TRUE;
other->action->runnable =FALSE;
crm_devel_action(
print_action("Marking unrunnable",
other->action, FALSE);
print_action("Reason",
action, FALSE);
);
}
}
if(action->optional == FALSE && other->action->optional) {
switch(action->rsc->restart_type) {
case pe_restart_ignore:
break;
case pe_restart_recover:
crm_err("Recover after dependancy "
"restart not supported... "
"forcing a restart");
/* keep going */
case pe_restart_restart:
change = TRUE;
other->action->optional = FALSE;
crm_devel_action(
print_action("Marking manditory",
other->action, FALSE));
}
}
if(change) {
update_action(other->action);
}
);
return change;
}
gboolean
shutdown_constraints(
node_t *node, action_t *shutdown_op, GListPtr *ordering_constraints)
{
/* add the stop to the before lists so it counts as a pre-req
* for the shutdown
*/
slist_iter(
rsc, resource_t, node->details->running_rsc, lpc,
order_new(rsc, stop_rsc, NULL,
NULL, shutdown_crm, shutdown_op,
pecs_must, ordering_constraints);
);
return TRUE;
}
gboolean
stonith_constraints(node_t *node,
action_t *stonith_op, action_t *shutdown_op,
GListPtr *ordering_constraints)
{
GListPtr stop_actions = NULL;
-
+
if(shutdown_op != NULL) {
+ /* stop everything we can via shutdown_constraints() and then
+ * shoot the node... the shutdown has been superceeded
+ */
+ shutdown_op->pseudo = TRUE;
+
/* shutdown before stonith */
- /* add the shutdown OP to the before lists so it counts as a pre-req */
+ /* Give any resources a chance to shutdown normally */
crm_devel("Adding shutdown (%d) as an input to stonith (%d)",
shutdown_op->id, stonith_op->id);
order_new(NULL, shutdown_crm, shutdown_op,
NULL, stonith_node, stonith_op,
pecs_must, ordering_constraints);
+
}
/* add the stonith OP to the before lists so it counts as a pre-req */
slist_iter(
rsc, resource_t, node->details->running_rsc, lpc,
- /* make use of timeouts in the TE for cases such
- * as this.
- * ie. the node may be cactus and unable to receive the
- * stop let alone reply with failed.
- */
-
- stop_actions = find_actions(rsc->actions, stop_rsc, node);
- slist_iter(
- action, action_t, stop_actions, lpc2,
- action->discard = TRUE;
- );
-
- if(rsc->stopfail_type == pesf_block) {
+ if(stonith_op != NULL) {
+ stop_actions = find_actions(rsc->actions,stop_rsc,node);
+ slist_iter(
+ action, action_t, stop_actions, lpc2,
+ if(node->details->unclean || rsc->unclean) {
+ /* the stop would never complete and is
+ * now implied by the stonith operation
+ */
+ action->pseudo = TRUE;
+ order_new(NULL,stonith_node,stonith_op,
+ rsc, stop_rsc, NULL,
+ pecs_must, ordering_constraints);
+ } else {
+ /* stop healthy resources before the
+ * stonith op
+ */
+ order_new(rsc, stop_rsc, NULL,
+ NULL,stonith_node,stonith_op,
+ pecs_must, ordering_constraints);
+ }
+ );
+
+ crm_devel("Adding stonith (%d) as an input to stop",
+ stonith_op->id);
+
+ } else if((rsc->unclean || node->details->unclean)
+ && rsc->stopfail_type == pesf_block) {
/* depend on the stop action which will fail */
- crm_warn("SHARED RESOURCE %s WILL REMAIN BLOCKED"
+ crm_err("SHARED RESOURCE %s WILL REMAIN BLOCKED"
" UNTIL CLEANED UP MANUALLY ON NODE %s",
rsc->id, node->details->uname);
continue;
- } else if(rsc->stopfail_type == pesf_ignore) {
+ } else if((rsc->unclean || node->details->unclean)
+ && rsc->stopfail_type == pesf_ignore) {
/* nothing to do here */
- crm_warn("SHARED RESOURCE %s IS NOT PROTECTED",
+ crm_err("SHARED RESOURCE %s IS NOT PROTECTED",
rsc->id);
continue;
}
-
- /* case pesf_stonith: */
- /* remedial action:
- * shutdown (so all other resources are
- * stopped gracefully) and then STONITH node
- */
- if(stonith_enabled == FALSE) {
- /* depend on an action that will never complete */
- crm_err("STONITH is not enabled in this"
- " cluster but is required for "
- "resource %s after a failed stop",
- rsc->id);
- }
- crm_devel("Adding stonith (%d) as an input to start",
- stonith_op->id);
-
- /* stonith before start */
- order_new(NULL, stonith_node, stonith_op,
- rsc, start_rsc, NULL,
- pecs_must, ordering_constraints);
-
-/* a pointless optimization? probably */
-/* if(shutdown_op != NULL) { */
-/* /\* the next rule is implied *\/ */
-/* continue; */
-/* } */
-
- /* stop before stonith */
- order_new(rsc, stop_rsc, NULL,
- NULL, stonith_node, stonith_op,
- pecs_must, ordering_constraints);
);
return TRUE;
}
crm_data_t *
action2xml(action_t *action, gboolean as_input)
{
crm_data_t * action_xml = NULL;
crm_data_t * args_xml = NULL;
if(action == NULL) {
return NULL;
}
crm_devel("Dumping action %d as XML", action->id);
switch(action->task) {
case stonith_node:
case shutdown_crm:
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
set_xml_property_copy(
action_xml, XML_ATTR_ID, crm_itoa(action->id));
set_xml_property_copy(action_xml, XML_LRM_ATTR_TASK,
task2text(action->task));
break;
default:
if(action->pseudo) {
action_xml = create_xml_node(NULL,XML_GRAPH_TAG_PSEUDO_EVENT);
} else {
action_xml = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
}
if(!as_input && action->rsc != NULL) {
crm_data_t *rsc_xml = create_xml_node(
action_xml, crm_element_name(action->rsc->xml));
copy_in_properties(rsc_xml, action->rsc->xml);
}
set_xml_property_copy(
action_xml, XML_ATTR_ID, crm_itoa(action->id));
if(safe_val3(NULL, action, rsc, id) != NULL) {
set_xml_property_copy(
action_xml, XML_LRM_ATTR_RSCID,
safe_val3(NULL, action, rsc, id));
}
set_xml_property_copy(action_xml, XML_LRM_ATTR_TASK,
task2text(action->task));
break;
}
if(action->task != stonith_node
&& (action->pseudo == FALSE || action->node != NULL)) {
+ const char *default_value = NULL;
+ if(as_input) {
+ default_value = "__none__";
+ }
set_xml_property_copy(
action_xml, XML_LRM_ATTR_TARGET,
- safe_val4(NULL, action, node, details,uname));
+ safe_val4(default_value, action, node, details,uname));
set_xml_property_copy(
action_xml, XML_LRM_ATTR_TARGET_UUID,
- safe_val4(NULL, action, node, details, id));
+ safe_val4(default_value, action, node, details, id));
CRM_DEV_ASSERT(NULL != crm_element_value(
action_xml, XML_LRM_ATTR_TARGET));
CRM_DEV_ASSERT(NULL != crm_element_value(
action_xml, XML_LRM_ATTR_TARGET_UUID));
}
set_xml_property_copy(
action_xml, "allow_fail",
action->failure_is_fatal?XML_BOOLEAN_FALSE:XML_BOOLEAN_TRUE);
if(as_input) {
return action_xml;
}
args_xml = create_xml_node(action_xml, XML_TAG_ATTRS);
g_hash_table_foreach(action->extra, hash2nvpair, args_xml);
if(action->rsc != NULL) {
g_hash_table_foreach(
action->rsc->parameters, hash2nvpair, args_xml);
}
crm_xml_debug(args_xml, "copied in extra attributes");
return action_xml;
}
void
graph_element_from_action(action_t *action, crm_data_t * *graph)
{
char *syn_id = NULL;
crm_data_t * syn = NULL;
crm_data_t * set = NULL;
crm_data_t * in = NULL;
crm_data_t * input = NULL;
crm_data_t * xml_action = NULL;
if(action == NULL) {
crm_err("Cannot dump NULL action");
return;
} else if(action->optional) {
crm_trace("action %d was optional", action->id);
return;
} else if(action->runnable == FALSE) {
crm_trace("action %d was not runnable", action->id);
return;
} else if(action->dumped) {
crm_trace("action %d was already dumped", action->id);
return;
} else if(action->discard) {
crm_trace("action %d was discarded", action->id);
return;
} else if(action->node == NULL) {
crm_err("action %d was not allocated", action->id);
return;
} else if(action->node->details->online == FALSE) {
crm_err("action %d was scheduled for offline node", action->id);
return;
}
action->dumped = TRUE;
syn = create_xml_node(*graph, "synapse");
set = create_xml_node(syn, "action_set");
in = create_xml_node(syn, "inputs");
syn_id = crm_itoa(num_synapse++);
set_xml_property_copy(syn, XML_ATTR_ID, syn_id);
crm_free(syn_id);
xml_action = action2xml(action, FALSE);
add_node_copy(set, xml_action);
slist_iter(wrapper,action_wrapper_t,action->actions_before,lpc,
if(wrapper->action->optional == TRUE) {
continue;
} else if(wrapper->action->discard == TRUE) {
continue;
}
switch(wrapper->strength) {
case pecs_must_not:
case pecs_ignore:
/* ignore both */
break;
case pecs_startstop:
if(wrapper->action->runnable == FALSE){
break;
}
/* keep going */
case pecs_must:
input = create_xml_node(in, "trigger");
xml_action = action2xml(
wrapper->action, TRUE);
add_node_copy(input, xml_action);
break;
}
);
free_xml(xml_action);
}
diff --git a/crm/pengine/pengine.h b/crm/pengine/pengine.h
index fc09bb011f..a91531077a 100644
--- a/crm/pengine/pengine.h
+++ b/crm/pengine/pengine.h
@@ -1,341 +1,342 @@
-/* $Id: pengine.h,v 1.56 2005/04/08 16:57:10 andrew Exp $ */
+/* $Id: pengine.h,v 1.57 2005/04/11 10:51:05 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PENGINE__H
#define PENGINE__H
#include <clplumbing/ipc.h>
typedef struct node_s node_t;
typedef struct color_s color_t;
typedef struct rsc_to_node_s rsc_to_node_t;
typedef struct rsc_colocation_s rsc_colocation_t;
typedef struct resource_s resource_t;
typedef struct lrm_agent_s lrm_agent_t;
typedef struct order_constraint_s order_constraint_t;
typedef struct action_s action_t;
typedef struct action_wrapper_s action_wrapper_t;
#include <glib.h>
#include <crm/crm.h>
#include <crm/common/msg.h>
#include <complex.h>
enum con_type {
type_none,
rsc_colocation,
rsc_to_node,
rsc_to_attr,
base_weight
};
enum node_type {
node_ping,
node_member
};
enum con_strength {
pecs_ignore,
pecs_must,
pecs_must_not,
pecs_startstop
};
enum action_tasks {
no_action,
monitor_rsc,
stop_rsc,
stopped_rsc,
start_rsc,
started_rsc,
shutdown_crm,
stonith_node
};
enum rsc_recovery_type {
recovery_stop_start,
recovery_stop_only,
recovery_block
};
enum pe_stop_fail {
pesf_block,
pesf_stonith,
pesf_ignore
};
enum pe_restart {
pe_restart_restart,
pe_restart_recover,
pe_restart_ignore
};
struct node_shared_s {
const char *id;
const char *uname;
gboolean online;
gboolean unclean;
gboolean shutdown;
gboolean expected_up;
gboolean is_dc;
int num_resources;
GListPtr running_rsc; /* resource_t* */
GListPtr agents; /* lrm_agent_t* */
GHashTable *attrs; /* char* => char* */
enum node_type type;
};
struct node_s {
float weight;
gboolean fixed;
struct node_shared_s *details;
};
struct color_shared_s {
int id;
float highest_priority;
GListPtr candidate_nodes; /* node_t* */
GListPtr allocated_resources; /* resources_t* */
node_t *chosen_node;
gboolean pending;
int num_resources;
};
struct color_s {
int id;
struct color_shared_s *details;
float local_weight;
};
struct rsc_colocation_s {
const char *id;
resource_t *rsc_lh;
resource_t *rsc_rh;
enum con_strength strength;
};
struct rsc_to_node_s {
const char *id;
resource_t *rsc_lh;
float weight;
GListPtr node_list_rh; /* node_t* */
};
struct lrm_agent_s {
const char *class;
const char *type;
const char *version;
};
struct resource_s {
const char *id;
crm_data_t * xml;
crm_data_t * ops_xml;
void *variant_opaque;
enum pe_obj_types variant;
resource_object_functions_t *fns;
float priority;
float effective_priority;
gboolean starting;
gboolean stopping;
gboolean is_stonith;
gboolean runnable;
gboolean provisional;
+ gboolean unclean;
enum rsc_recovery_type recovery_type;
enum pe_stop_fail stopfail_type;
enum pe_restart restart_type;
GListPtr candidate_colors; /* color_t* */
GListPtr rsc_cons; /* rsc_colocation_t* */
GListPtr actions; /* action_t* */
GHashTable * parameters;
};
struct action_wrapper_s
{
enum con_strength strength;
action_t *action;
};
struct action_s
{
int id;
resource_t *rsc;
void *rsc_opaque;
node_t *node;
enum action_tasks task;
gboolean pseudo;
gboolean runnable;
gboolean dumped;
gboolean processed;
gboolean optional;
gboolean discard;
gboolean failure_is_fatal;
int seen_count;
const char *timeout;
/* crm_data_t *args; */
GHashTable *extra;
GListPtr actions_before; /* action_warpper_t* */
GListPtr actions_after; /* action_warpper_t* */
};
struct order_constraint_s
{
int id;
enum con_strength strength;
void *lh_opaque;
resource_t *lh_rsc;
action_t *lh_action;
enum action_tasks lh_action_task;
void *rh_opaque;
resource_t *rh_rsc;
action_t *rh_action;
enum action_tasks rh_action_task;
/* (soon to be) variant specific */
/* int lh_rsc_incarnation; */
/* int rh_rsc_incarnation; */
};
extern gboolean stage0(crm_data_t *cib,
GListPtr *nodes,
GListPtr *rscs,
GListPtr *cons,
GListPtr *actions, GListPtr *ordering_constraints,
GListPtr *stonith_list, GListPtr *shutdown_list);
extern gboolean stage1(GListPtr placement_constraints,
GListPtr nodes,
GListPtr resources);
extern gboolean stage2(GListPtr sorted_rscs,
GListPtr sorted_nodes,
GListPtr *colors);
extern gboolean stage3(GListPtr colors);
extern gboolean stage4(GListPtr colors);
extern gboolean stage5(GListPtr resources, GListPtr *ordering_constraints);
extern gboolean stage6(
GListPtr *actions, GListPtr *ordering_constraints,
GListPtr nodes, GListPtr resources);
extern gboolean stage7(
GListPtr resources, GListPtr actions, GListPtr ordering_constraints);
extern gboolean stage8(
GListPtr resources, GListPtr action_sets, crm_data_t **graph);
extern gboolean summary(GListPtr resources);
extern gboolean pe_msg_dispatch(IPC_Channel *sender, void *user_data);
extern gboolean process_pe_message(
HA_Message *msg, crm_data_t *xml_data, IPC_Channel *sender);
extern gboolean unpack_constraints(crm_data_t *xml_constraints,
GListPtr nodes, GListPtr resources,
GListPtr *placement_constraints,
GListPtr *ordering_constraints);
extern gboolean unpack_resources(crm_data_t *xml_resources,
GListPtr *resources,
GListPtr *actions,
GListPtr *ordering_constraints,
GListPtr *placement_constraints,
GListPtr all_nodes);
extern gboolean unpack_config(crm_data_t *config);
extern gboolean unpack_config(crm_data_t *config);
extern gboolean unpack_global_defaults(crm_data_t *defaults);
extern gboolean unpack_nodes(crm_data_t *xml_nodes, GListPtr *nodes);
extern gboolean unpack_status(crm_data_t *status,
GListPtr nodes,
GListPtr rsc_list,
GListPtr *actions,
GListPtr *placement_constraints);
extern gboolean apply_placement_constraints(GListPtr constraints, GListPtr nodes);
extern gboolean apply_agent_constraints(GListPtr resources);
extern void color_resource(resource_t *lh_resource,
GListPtr *colors,
GListPtr resources);
extern gboolean choose_node_from_list(color_t *color);
extern gboolean update_action_states(GListPtr actions);
extern gboolean shutdown_constraints(
node_t *node, action_t *shutdown_op, GListPtr *ordering_constraints);
extern gboolean stonith_constraints(
node_t *node, action_t *stonith_op, action_t *shutdown_op,
GListPtr *ordering_constraints);
extern gboolean order_new(
resource_t *lh_rsc, enum action_tasks lh_task, action_t *lh_action,
resource_t *rh_rsc, enum action_tasks rh_task, action_t *rh_action,
enum con_strength strength, GListPtr *ordering_constraints);
extern gboolean process_colored_constraints(resource_t *rsc);
extern void graph_element_from_action(action_t *action, crm_data_t **graph);
extern color_t *no_color;
extern int max_valid_nodes;
extern int order_id;
extern int action_id;
extern gboolean stonith_enabled;
extern gboolean have_quorum;
extern gboolean require_quorum;
extern gboolean symmetric_cluster;
extern GListPtr agent_defaults;
extern const char* transition_timeout;
extern int num_synapse;
extern int color_id;
extern char *dc_uuid;
#endif
diff --git a/crm/pengine/stages.c b/crm/pengine/stages.c
index e4a68d4d14..7a8f2081f8 100644
--- a/crm/pengine/stages.c
+++ b/crm/pengine/stages.c
@@ -1,480 +1,479 @@
-/* $Id: stages.c,v 1.50 2005/04/08 19:10:14 andrew Exp $ */
+/* $Id: stages.c,v 1.51 2005/04/11 10:51:05 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/param.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/msg.h>
#include <glib.h>
#include <pengine.h>
#include <pe_utils.h>
node_t *choose_fencer(action_t *stonith, node_t *node, GListPtr resources);
void order_actions(action_t *lh, action_t *rh, order_constraint_t *order);
int order_id = 1;
int max_valid_nodes = 0;
GListPtr agent_defaults = NULL;
gboolean have_quorum = FALSE;
gboolean require_quorum = FALSE;
gboolean stonith_enabled = FALSE;
gboolean symmetric_cluster = TRUE;
char *dc_uuid = NULL;
const char* transition_timeout = "60000"; /* 1 minute */
/*
* Unpack everything
* At the end you'll have:
* - A list of nodes
* - A list of resources (each with any dependancies on other resources)
* - A list of constraints between resources and nodes
* - A list of constraints between start/stop actions
* - A list of nodes that need to be stonith'd
* - A list of nodes that need to be shutdown
* - A list of the possible stop/start actions (without dependancies)
*/
gboolean
stage0(crm_data_t * cib,
GListPtr *resources,
GListPtr *nodes, GListPtr *placement_constraints,
GListPtr *actions, GListPtr *ordering_constraints,
GListPtr *stonith_list, GListPtr *shutdown_list)
{
/* int lpc; */
crm_data_t * cib_nodes = get_object_root(
XML_CIB_TAG_NODES, cib);
crm_data_t * cib_status = get_object_root(
XML_CIB_TAG_STATUS, cib);
crm_data_t * cib_resources = get_object_root(
XML_CIB_TAG_RESOURCES, cib);
crm_data_t * cib_constraints = get_object_root(
XML_CIB_TAG_CONSTRAINTS, cib);
crm_data_t * config = get_object_root(
XML_CIB_TAG_CRMCONFIG, cib);
crm_data_t * agent_defaults = NULL;
/*get_object_root(XML_CIB_TAG_RA_DEFAULTS, cib); */
crm_free(dc_uuid);
dc_uuid = NULL;
if(cib != NULL && crm_element_value(cib, XML_ATTR_DC_UUID) != NULL) {
/* this should always be present */
dc_uuid = crm_element_value_copy(cib, XML_ATTR_DC_UUID);
}
/* reset remaining global variables */
num_synapse = 0;
max_valid_nodes = 0;
order_id = 1;
action_id = 1;
color_id = 0;
have_quorum = FALSE;
require_quorum = FALSE;
stonith_enabled = FALSE;
unpack_config(config);
if(require_quorum) {
const char *value = crm_element_value(cib, XML_ATTR_HAVE_QUORUM);
if(value != NULL) {
crm_str_to_boolean(value, &have_quorum);
}
if(have_quorum == FALSE) {
crm_warn("We do not have quorum"
" - fencing and resource management disabled");
}
}
unpack_global_defaults(agent_defaults);
unpack_nodes(cib_nodes, nodes);
unpack_resources(cib_resources, resources, actions,
ordering_constraints, placement_constraints, *nodes);
unpack_status(cib_status, *nodes, *resources, actions,
placement_constraints);
unpack_constraints(cib_constraints, *nodes, *resources,
placement_constraints, ordering_constraints);
return TRUE;
}
/*
* Count how many valid nodes we have (so we know the maximum number of
* colors we can resolve).
*
* Apply node constraints (ie. filter the "allowed_nodes" part of resources
*/
gboolean
stage1(GListPtr placement_constraints, GListPtr nodes, GListPtr resources)
{
crm_devel("Processing stage 1");
slist_iter(
node, node_t, nodes, lpc,
if(node == NULL) {
/* error */
} else if(node->weight >= 0.0 /* global weight */
&& node->details->online
&& node->details->type == node_member) {
max_valid_nodes++;
}
);
apply_placement_constraints(placement_constraints, nodes);
/* will also filter -ve "final" weighted nodes from resources'
* allowed lists while we are there
*/
apply_agent_constraints(resources);
return TRUE;
}
/*
* Choose a color for all resources from highest priority and XML_STRENGTH_VAL_MUST
* dependancies to lowest, creating new colors as necessary (returned
* as "colors").
*
* Some nodes may be colored as a "no_color" meaning that it was unresolvable
* given the current node stati and constraints.
*/
gboolean
stage2(GListPtr sorted_rscs, GListPtr sorted_nodes, GListPtr *colors)
{
crm_devel("Processing stage 2");
if(no_color != NULL) {
crm_free(no_color->details);
crm_free(no_color);
}
crm_trace("create \"no color\"");
no_color = create_color(NULL, NULL, NULL);
/* Take (next) highest resource */
slist_iter(
lh_resource, resource_t, sorted_rscs, lpc,
/* if resource.provisional == FALSE, repeat */
if(lh_resource->provisional == FALSE) {
/* already processed this resource */
continue;
}
color_resource(lh_resource, colors, sorted_rscs);
/* next resource */
);
return TRUE;
}
/*
* not sure if this is a good idea or not, but eventually we might like
* to utilize as many nodes as possible... and this might be a convienient
* hook
*/
gboolean
stage3(GListPtr colors)
{
crm_devel("Processing stage 3");
/* not sure if this is a good idea or not */
if((ssize_t)g_list_length(colors) > max_valid_nodes) {
/* we need to consolidate some */
} else if((ssize_t)g_list_length(colors) < max_valid_nodes) {
/* we can create a few more */
}
return TRUE;
}
/*
* Choose a node for each (if possible) color
*/
gboolean
stage4(GListPtr colors)
{
crm_devel("Processing stage 4");
slist_iter(
color, color_t, colors, lpc,
crm_devel("assigning node to color %d", color->id);
if(color == NULL) {
crm_err("NULL color detected");
continue;
} else if(color->details->pending == FALSE) {
continue;
}
choose_node_from_list(color);
crm_devel("assigned %s to color %d",
safe_val5(NULL, color, details, chosen_node, details, uname),
color->id);
slist_iter(
rsc, resource_t, color->details->allocated_resources, lpc2,
slist_iter(
constraint, rsc_colocation_t, rsc->rsc_cons, lpc,
rsc->fns->rsc_colocation_lh(constraint);
);
);
);
crm_verbose("done");
return TRUE;
}
/*
* Attach nodes to the actions that need to be taken
*
* Mark actions XML_LRM_ATTR_OPTIONAL if possible (Ie. if the start and stop are
* for the same node)
*
* Mark unrunnable actions
*/
gboolean
stage5(GListPtr resources, GListPtr *ordering_constraints)
{
slist_iter(
rsc, resource_t, resources, lpc,
rsc->fns->create_actions(rsc, ordering_constraints);
rsc->fns->internal_constraints(rsc, ordering_constraints);
);
return TRUE;
}
/*
* Create dependacies for stonith and shutdown operations
*/
gboolean
stage6(GListPtr *actions, GListPtr *ordering_constraints,
GListPtr nodes, GListPtr resources)
{
action_t *down_op = NULL;
action_t *stonith_op = NULL;
crm_devel("Processing stage 6");
slist_iter(
node, node_t, nodes, lpc,
if(node->details->online && node->details->shutdown) {
crm_info("Scheduling Node %s for shutdown",
node->details->uname);
down_op = action_new(NULL, shutdown_crm, NULL, node);
down_op->runnable = TRUE;
*actions = g_list_append(*actions, down_op);
shutdown_constraints(
node, down_op, ordering_constraints);
}
if(node->details->unclean && stonith_enabled) {
crm_warn("Scheduling Node %s for STONITH",
node->details->uname);
stonith_op = action_new(NULL, stonith_node,NULL,NULL);
stonith_op->runnable = TRUE;
add_hash_param(
stonith_op->extra, XML_LRM_ATTR_TARGET,
node->details->uname);
add_hash_param(
stonith_op->extra, XML_LRM_ATTR_TARGET_UUID,
node->details->id);
if(down_op != NULL) {
down_op->failure_is_fatal = FALSE;
}
*actions = g_list_append(*actions, stonith_op);
- stonith_constraints(node, stonith_op, down_op,
- ordering_constraints);
- }
-
- if(node->details->online == FALSE
- && node->details->expected_up) {
- crm_warn("Node %s was expected to be up!",
- node->details->uname);
+ } else if(node->details->unclean) {
+ crm_err("Node %s is unclean!", node->details->uname);
crm_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
crm_warn("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
}
+
+ if(node->details->unclean) {
+ stonith_constraints(
+ node, stonith_op, down_op, ordering_constraints);
+ }
);
return TRUE;
}
/*
* Determin the sets of independant actions and the correct order for the
* actions in each set.
*
* Mark dependancies of un-runnable actions un-runnable
*
*/
gboolean
stage7(GListPtr resources, GListPtr actions, GListPtr ordering_constraints)
{
crm_devel("Processing stage 7");
slist_iter(
order, order_constraint_t, ordering_constraints, lpc,
/* try rsc_action-to-rsc_action */
resource_t *rsc = order->lh_rsc;
if(rsc == NULL && order->lh_action) {
rsc = order->lh_action->rsc;
}
if(rsc != NULL) {
rsc->fns->rsc_order_lh(rsc, order);
continue;
}
/* try action-to-rsc_action */
/* que off the rh resource */
rsc = order->rh_rsc;
if(rsc == NULL && order->rh_action) {
rsc = order->rh_action->rsc;
}
if(rsc != NULL) {
rsc->fns->rsc_order_rh(order->lh_action, rsc, order);
} else {
/* fall back to action-to-action */
order_actions(
order->lh_action, order->rh_action, order);
}
);
update_action_states(actions);
return TRUE;
}
/*
* Create a dependancy graph to send to the transitioner (via the CRMd)
*/
gboolean
stage8(GListPtr resources, GListPtr actions, crm_data_t * *graph)
{
crm_devel("Processing stage 8");
*graph = create_xml_node(NULL, XML_TAG_GRAPH);
set_xml_property_copy(
*graph, "global_timeout", transition_timeout);
/* errors...
slist_iter(action, action_t, action_list, lpc,
if(action->optional == FALSE && action->runnable == FALSE) {
print_action("Ignoring", action, TRUE);
}
);
*/
crm_verbose("========= Action List =========");
slist_iter(action, action_t, actions, lpc,
print_action(NULL, action, FALSE));
slist_iter(
rsc, resource_t, resources, lpc,
crm_devel("processing actions for rsc=%s", rsc->id);
rsc->fns->expand(rsc, graph);
);
crm_xml_devel(*graph, "created resource-driven action list");
/* catch any non-resource specific actions */
crm_devel("processing non-resource actions");
slist_iter(
action, action_t, actions, lpc,
graph_element_from_action(action, graph);
);
crm_xml_devel(*graph, "created generic action list");
return TRUE;
}
gboolean
choose_node_from_list(color_t *color)
{
/*
1. Sort by weight
2. color.chosen_node = the node (of those with the highest wieght)
with the fewest resources
3. remove color.chosen_node from all other colors
*/
GListPtr nodes = color->details->candidate_nodes;
node_t *chosen = NULL;
crm_devel("Choosing node for color %d", color->id);
nodes = g_list_sort(nodes, sort_node_weight);
chosen = g_list_nth_data(nodes, 0);
color->details->chosen_node = NULL;
color->details->pending = FALSE;
if(chosen == NULL) {
crm_debug("Could not allocate a node for color %d", color->id);
return FALSE;
} else if(chosen->details->unclean || chosen->details->shutdown) {
crm_debug("Even highest ranked node for color %d"
" is unclean or shutting down",
color->id);
return FALSE;
} else if(chosen->weight < 0) {
crm_debug("Even highest ranked node for color %d, had weight %f",
color->id, chosen->weight);
return FALSE;
}
/* todo: update the old node for each resource to reflect its
* new resource count
*/
chosen->details->num_resources += color->details->num_resources;
color->details->chosen_node = node_copy(chosen);
return TRUE;
}
diff --git a/crm/pengine/unpack.c b/crm/pengine/unpack.c
index 6bb21d6c13..0efaebb718 100644
--- a/crm/pengine/unpack.c
+++ b/crm/pengine/unpack.c
@@ -1,1143 +1,1199 @@
-/* $Id: unpack.c,v 1.71 2005/04/08 19:10:14 andrew Exp $ */
+/* $Id: unpack.c,v 1.72 2005/04/11 10:51:05 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <portability.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/msg.h>
#include <lrm/lrm_api.h>
#include <glib.h>
#include <heartbeat.h> /* for ONLINESTATUS */
#include <pengine.h>
#include <pe_utils.h>
#include <pe_rules.h>
gboolean unpack_rsc_to_attr(crm_data_t * xml_obj,
GListPtr rsc_list,
GListPtr node_list,
GListPtr *placement_constraints);
gboolean unpack_rsc_to_node(crm_data_t * xml_obj,
GListPtr rsc_list,
GListPtr node_list,
GListPtr *placement_constraints);
gboolean unpack_rsc_order(
crm_data_t * xml_obj, GListPtr rsc_list, GListPtr *ordering_constraints);
gboolean unpack_rsc_colocation(
crm_data_t * xml_obj, GListPtr rsc_list, GListPtr *ordering_constraints);
gboolean unpack_rsc_location(
crm_data_t * xml_obj, GListPtr rsc_list, GListPtr node_list,
GListPtr *ordering_constraints);
gboolean unpack_lrm_rsc_state(
node_t *node, crm_data_t * lrm_state,
GListPtr rsc_list, GListPtr nodes,
GListPtr *actions, GListPtr *placement_constraints);
gboolean add_node_attrs(crm_data_t * attrs, node_t *node);
gboolean unpack_healthy_resource(GListPtr *placement_constraints, GListPtr *actions,
crm_data_t * rsc_entry, resource_t *rsc_lh, node_t *node);
gboolean unpack_failed_resource(GListPtr *placement_constraints,
crm_data_t * rsc_entry, resource_t *rsc_lh, node_t *node);
gboolean determine_online_status(crm_data_t * node_state, node_t *this_node);
gboolean unpack_lrm_agents(node_t *node, crm_data_t * agent_list);
gboolean rsc_colocation_new(
const char *id, enum con_strength strength,
resource_t *rsc_lh, resource_t *rsc_rh);
gboolean create_ordering(
const char *id, enum con_strength strength,
resource_t *rsc_lh, resource_t *rsc_rh, GListPtr *ordering_constraints);
rsc_to_node_t *rsc2node_new(
const char *id, resource_t *rsc,
double weight, gboolean can_run, node_t *node,
GListPtr *placement_constraints);
const char *get_agent_param(resource_t *rsc, const char *param);
const char *get_agent_param_rsc(resource_t *rsc, const char *param);
const void *get_agent_param_metadata(resource_t *rsc, const char *param);
const char *get_agent_param_global(resource_t *rsc, const char *param);
const char *param_value(crm_data_t * parent, const char *name);
gboolean
unpack_config(crm_data_t * config)
{
const char *value = NULL;
value = param_value(config, "transition_timeout");
if(value != NULL) {
int tmp = atoi(value);
if(tmp > 0) {
transition_timeout = value;
} else {
crm_warn("Invalid value for %s: %s",
"transition_timeout", value);
}
}
crm_devel("%s set to: %s",
"transition_timeout", transition_timeout);
value = param_value(config, "stonith_enabled");
if(value != NULL) {
crm_str_to_boolean(value, &stonith_enabled);
}
crm_info("STONITH of failed nodes is %s", stonith_enabled?"enabled":"disabled");
value = param_value(config, "symmetric_cluster");
if(value != NULL) {
crm_str_to_boolean(value, &symmetric_cluster);
}
if(symmetric_cluster) {
crm_info("Cluster is symmetric"
" - resources can run anywhere by default");
}
value = param_value(config, "require_quorum");
if(value != NULL) {
crm_str_to_boolean(value, &require_quorum);
}
if(require_quorum) {
crm_info("Quorum required for fencing and resource management");
}
return TRUE;
}
const char *
param_value(crm_data_t * parent, const char *name)
{
crm_data_t * a_default = NULL;
if(parent != NULL) {
a_default = find_entity(
parent, XML_CIB_TAG_NVPAIR, name, FALSE);
}
if(a_default == NULL) {
crm_warn("Option %s not set", name);
return NULL;
}
return crm_element_value(a_default, XML_NVPAIR_ATTR_VALUE);
}
const char *
get_agent_param(resource_t *rsc, const char *param)
{
const char *value = NULL;
if(param == NULL) {
return NULL;
}
value = get_agent_param_rsc(rsc, param);
if(value == NULL) {
value = get_agent_param_metadata(rsc, param);
}
if(value == NULL) {
value = get_agent_param_global(rsc, param);
}
return value;
}
const char *
get_agent_param_rsc(resource_t *rsc, const char *param)
{
crm_data_t * xml_rsc = rsc->xml;
return crm_element_value(xml_rsc, param);
}
const void *
get_agent_param_metadata(resource_t *rsc, const char *param)
{
return NULL;
}
const char *
get_agent_param_global(resource_t *rsc, const char *param)
{
const char * value = NULL;/*g_hashtable_lookup(agent_global_defaults, param); */
if(value == NULL) {
crm_err("No global value default for %s", param);
}
return value;
}
gboolean
unpack_global_defaults(crm_data_t * defaults)
{
return TRUE;
}
gboolean
unpack_nodes(crm_data_t * xml_nodes, GListPtr *nodes)
{
node_t *new_node = NULL;
crm_data_t * attrs = NULL;
const char *id = NULL;
const char *uname = NULL;
const char *type = NULL;
crm_verbose("Begining unpack...");
xml_child_iter(
xml_nodes, xml_obj, XML_CIB_TAG_NODE,
id = crm_element_value(xml_obj, XML_ATTR_ID);
uname = crm_element_value(xml_obj, XML_ATTR_UNAME);
type = crm_element_value(xml_obj, XML_ATTR_TYPE);
crm_verbose("Processing node %s/%s", uname, id);
attrs = find_xml_node(xml_obj, "attributes", FALSE);
if(id == NULL) {
crm_err("Must specify id tag in <node>");
continue;
}
if(type == NULL) {
crm_err("Must specify type tag in <node>");
continue;
}
crm_malloc(new_node, sizeof(node_t));
if(new_node == NULL) {
return FALSE;
}
new_node->weight = 0;
new_node->fixed = FALSE;
crm_malloc(new_node->details,
sizeof(struct node_shared_s));
if(new_node->details == NULL) {
crm_free(new_node);
return FALSE;
}
crm_verbose("Creaing node for entry %s/%s", uname, id);
new_node->details->id = id;
new_node->details->uname = uname;
new_node->details->type = node_ping;
new_node->details->online = FALSE;
- new_node->details->unclean = TRUE; /* all nodes are unclean until we've seen their status entry */
new_node->details->shutdown = FALSE;
new_node->details->running_rsc = NULL;
new_node->details->agents = NULL;
new_node->details->attrs = g_hash_table_new(
g_str_hash, g_str_equal);
+
+ if(stonith_enabled) {
+ /* all nodes are unclean until we've seen their
+ * status entry
+ */
+ new_node->details->unclean = TRUE;
+ } else {
+ /* blind faith... */
+ new_node->details->unclean = FALSE;
+ }
+
if(safe_str_eq(type, "member")) {
new_node->details->type = node_member;
}
add_node_attrs(xml_obj, new_node);
if(crm_is_true(g_hash_table_lookup(
new_node->details->attrs, "standby"))) {
crm_info("Node %s is in standby-mode",
new_node->details->uname);
- new_node->weight = -1.0;
+ new_node->weight = -INFINITY;
}
*nodes = g_list_append(*nodes, new_node);
crm_verbose("Done with node %s",
crm_element_value(xml_obj, XML_ATTR_UNAME));
crm_devel_action(print_node("Added", new_node, FALSE));
);
*nodes = g_list_sort(*nodes, sort_node_weight);
return TRUE;
}
gboolean
unpack_resources(crm_data_t * xml_resources,
GListPtr *resources,
GListPtr *actions,
GListPtr *ordering_constraints,
GListPtr *placement_constraints,
GListPtr all_nodes)
{
crm_verbose("Begining unpack...");
xml_child_iter(
xml_resources, xml_obj, NULL,
resource_t *new_rsc = NULL;
if(common_unpack(xml_obj, &new_rsc)) {
*resources = g_list_append(*resources, new_rsc);
crm_devel_action(
print_resource("Added", new_rsc, FALSE));
if(symmetric_cluster) {
rsc_to_node_t *new_con = rsc2node_new(
"symmetric_default", new_rsc, 0,
TRUE, NULL, placement_constraints);
new_con->node_list_rh = node_list_dup(all_nodes, FALSE);
}
} else {
crm_err("Failed unpacking resource %s",
crm_element_value(xml_obj, XML_ATTR_ID));
}
);
*resources = g_list_sort(*resources, sort_rsc_priority);
return TRUE;
}
gboolean
unpack_constraints(crm_data_t * xml_constraints,
GListPtr nodes, GListPtr resources,
GListPtr *placement_constraints,
GListPtr *ordering_constraints)
{
crm_verbose("Begining unpack...");
xml_child_iter(
xml_constraints, xml_obj, NULL,
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
if(id == NULL) {
crm_err("Constraint <%s...> must have an id",
crm_element_name(xml_obj));
continue;
}
crm_verbose("Processing constraint %s %s", crm_element_name(xml_obj),id);
if(safe_str_eq(XML_CONS_TAG_RSC_ORDER, crm_element_name(xml_obj))) {
unpack_rsc_order(
xml_obj, resources, ordering_constraints);
} else if(safe_str_eq(XML_CONS_TAG_RSC_DEPEND, crm_element_name(xml_obj))) {
unpack_rsc_colocation(
xml_obj, resources, ordering_constraints);
} else if(safe_str_eq(XML_CONS_TAG_RSC_LOCATION, crm_element_name(xml_obj))) {
unpack_rsc_location(
xml_obj, resources, nodes, placement_constraints);
} else {
crm_err("Unsupported constraint type: %s", crm_element_name(xml_obj));
}
);
return TRUE;
}
rsc_to_node_t *
rsc2node_new(const char *id, resource_t *rsc,
double weight, gboolean can, node_t *node,
GListPtr *placement_constraints)
{
rsc_to_node_t *new_con = NULL;
if(rsc == NULL || id == NULL) {
crm_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc);
return NULL;
}
crm_malloc(new_con, sizeof(rsc_to_node_t));
if(new_con != NULL) {
new_con->id = id;
new_con->rsc_lh = rsc;
new_con->node_list_rh = NULL;
new_con->weight = weight;
if(node != NULL) {
new_con->node_list_rh = g_list_append(NULL, node);
}
*placement_constraints = g_list_append(*placement_constraints, new_con);
}
return new_con;
}
/* remove nodes that are down, stopping */
/* create +ve rsc_to_node constraints between resources and the nodes they are running on */
/* anything else? */
gboolean
unpack_status(crm_data_t * status,
GListPtr nodes, GListPtr rsc_list,
GListPtr *actions, GListPtr *placement_constraints)
{
const char *uname = NULL;
crm_data_t * lrm_rsc = NULL;
crm_data_t * lrm_agents = NULL;
crm_data_t * attrs = NULL;
node_t *this_node = NULL;
crm_verbose("Begining unpack");
xml_child_iter(
status, node_state, XML_CIB_TAG_STATE,
/* id = crm_element_value(node_state, XML_ATTR_ID); */
uname = crm_element_value(node_state, XML_ATTR_UNAME);
attrs = find_xml_node(node_state, XML_LRM_TAG_ATTRIBUTES,FALSE);
lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
lrm_agents = find_xml_node(lrm_rsc, XML_LRM_TAG_AGENTS, FALSE);
lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE);
crm_verbose("Processing node %s", uname);
this_node = pe_find_node(nodes, uname);
if(uname == NULL) {
/* error */
continue;
} else if(this_node == NULL) {
crm_warn("Node %s in status section no longer exists",
uname);
continue;
}
/* Mark the node as provisionally clean
* - at least we have seen it in the current cluster's lifetime
*/
this_node->details->unclean = FALSE;
crm_verbose("Adding runtime node attrs");
add_node_attrs(node_state, this_node);
crm_verbose("determining node state");
determine_online_status(node_state, this_node);
if(this_node->details->online || stonith_enabled) {
- /* offline nodes run no resources
+ /* offline nodes run no resources...
* unless stonith is enabled in which case we need to
- * know
+ * make sure rsc start events happen after the stonith
*/
crm_verbose("Processing lrm resource entries");
unpack_lrm_rsc_state(
this_node, lrm_rsc, rsc_list, nodes,
actions, placement_constraints);
}
);
return TRUE;
}
gboolean
determine_online_status(crm_data_t * node_state, node_t *this_node)
{
gboolean online = FALSE;
const char *uname = crm_element_value(node_state,XML_ATTR_UNAME);
-/* const char *state = crm_element_value(node_state,XML_NODE_ATTR_STATE); */
- const char *exp_state = crm_element_value(node_state,XML_CIB_ATTR_EXPSTATE);
- const char *join_state = crm_element_value(node_state,XML_CIB_ATTR_JOINSTATE);
- const char *crm_state = crm_element_value(node_state,XML_CIB_ATTR_CRMDSTATE);
- const char *ccm_state = crm_element_value(node_state,XML_CIB_ATTR_INCCM);
- const char *ha_state = crm_element_value(node_state,XML_CIB_ATTR_HASTATE);
- const char *shutdown = crm_element_value(node_state,XML_CIB_ATTR_SHUTDOWN);
+ const char *exp_state =
+ crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE);
+ const char *join_state =
+ crm_element_value(node_state, XML_CIB_ATTR_JOINSTATE);
+ const char *crm_state =
+ crm_element_value(node_state, XML_CIB_ATTR_CRMDSTATE);
+ const char *ccm_state =
+ crm_element_value(node_state, XML_CIB_ATTR_INCCM);
+ const char *ha_state =
+ crm_element_value(node_state, XML_CIB_ATTR_HASTATE);
+ const char *shutdown =
+ crm_element_value(node_state, XML_CIB_ATTR_SHUTDOWN);
if(this_node == NULL) {
return online;
}
if(shutdown != NULL) {
this_node->details->shutdown = TRUE;
}
if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) {
this_node->details->expected_up = TRUE;
}
- if(crm_is_true(ccm_state) == FALSE
- || ha_state == NULL
- || safe_str_eq(ha_state, DEADSTATUS)) {
- crm_debug("Node is down: ha_state=%s, ccm_state=%s",
- crm_str(ha_state), crm_str(ccm_state));
-
- } else if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)
- && safe_str_eq(crm_state, ONLINESTATUS)) {
- online = TRUE;
-
- } else if(this_node->details->expected_up == FALSE) {
- crm_debug("CRMd is down: ha_state=%s, ccm_state=%s",
- crm_str(ha_state), crm_str(ccm_state));
- crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
- crm_str(crm_state), crm_str(join_state),
- crm_str(exp_state));
-
+ if(stonith_enabled == FALSE) {
+ if(!crm_is_true(ccm_state) || safe_str_eq(ha_state,DEADSTATUS)){
+ crm_debug("Node is down: ha_state=%s, ccm_state=%s",
+ crm_str(ha_state), crm_str(ccm_state));
+
+ } else if(!crm_is_true(ccm_state)
+ || safe_str_eq(ha_state, DEADSTATUS)) {
+
+ } else if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)
+ && safe_str_eq(crm_state, ONLINESTATUS)) {
+ online = TRUE;
+
+ } else if(this_node->details->expected_up == FALSE) {
+ crm_debug("CRMd is down: ha_state=%s, ccm_state=%s",
+ crm_str(ha_state), crm_str(ccm_state));
+ crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
+ crm_str(crm_state), crm_str(join_state),
+ crm_str(exp_state));
+
+ } else {
+ /* mark it unclean */
+ this_node->details->unclean = TRUE;
+
+ crm_err("Node %s is partially & un-expectedly down",
+ uname);
+ crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
+ crm_str(crm_state), crm_str(join_state),
+ crm_str(exp_state));
+ }
} else {
- /* mark it unclean */
- this_node->details->unclean = TRUE;
-
- crm_warn("Node %s is un-expectedly down", uname);
- crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
- crm_str(crm_state), crm_str(join_state),
- crm_str(exp_state));
+ if(crm_is_true(ccm_state)
+ && (ha_state == NULL || safe_str_eq(ha_state, ACTIVESTATUS))
+ && safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) {
+ online = TRUE;
+
+ } else if(this_node->details->expected_up == FALSE) {
+ crm_debug("CRMd on %s is down: ha_state=%s, ccm_state=%s",
+ uname, crm_str(ha_state), crm_str(ccm_state));
+ crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
+ crm_str(crm_state), crm_str(join_state),
+ crm_str(exp_state));
+
+ } else {
+ /* mark it unclean */
+ this_node->details->unclean = TRUE;
+
+ crm_err("Node %s is un-expectedly down", uname);
+ crm_debug("\tha_state=%s, ccm_state=%s",
+ crm_str(ha_state), crm_str(ccm_state));
+ crm_debug("\tcrm_state=%s, join_state=%s, expected=%s",
+ crm_str(crm_state), crm_str(join_state),
+ crm_str(exp_state));
+ }
}
-
+
if(online) {
crm_debug("Node %s is online", uname);
this_node->details->online = TRUE;
+
} else {
/* remove node from contention */
crm_debug("Node %s is down", uname);
- this_node->weight = -1;
+ this_node->weight = -INFINITY;
this_node->fixed = TRUE;
}
+
if(this_node->details->unclean) {
crm_warn("Node %s is unclean", uname);
}
+
if(this_node->details->shutdown) {
/* dont run resources here */
- this_node->weight = -1;
+ this_node->weight = -INFINITY;
this_node->fixed = TRUE;
crm_debug("Node %s is due for shutdown", uname);
}
return online;
}
gboolean
unpack_lrm_agents(node_t *node, crm_data_t * agent_list)
{
/* if the agent is not listed, remove the node from
* the resource's list of allowed_nodes
*/
lrm_agent_t *agent = NULL;
const char *version = NULL;
if(agent_list == NULL) {
return FALSE;
}
xml_child_iter(
agent_list, xml_agent, XML_LRM_TAG_AGENT,
crm_malloc(agent, sizeof(lrm_agent_t));
if(agent == NULL) {
continue;
}
agent->class = crm_element_value(xml_agent, XML_AGENT_ATTR_CLASS);
agent->type = crm_element_value(xml_agent, XML_ATTR_TYPE);
version = crm_element_value(xml_agent, XML_ATTR_VERSION);
agent->version = version?version:"0.0";
- crm_trace("Adding agent %s/%s v%s to node %s",
+ crm_trace("Adding agent %s/%s %s to node %s",
agent->class,
agent->type,
agent->version,
node->details->uname);
node->details->agents = g_list_append(
node->details->agents, agent);
);
return TRUE;
}
gboolean
unpack_lrm_rsc_state(node_t *node, crm_data_t * lrm_rsc,
GListPtr rsc_list, GListPtr nodes,
GListPtr *actions, GListPtr *placement_constraints)
{
const char *rsc_id = NULL;
const char *node_id = NULL;
const char *rsc_state = NULL;
const char *op_status = NULL;
const char *last_rc = NULL;
const char *last_op = NULL;
resource_t *rsc_lh = NULL;
op_status_t action_status_i = LRM_OP_ERROR;
xml_child_iter(
lrm_rsc, rsc_entry, XML_LRM_TAG_RESOURCE,
rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID);
node_id = crm_element_value(rsc_entry, XML_LRM_ATTR_TARGET);
rsc_state = crm_element_value(rsc_entry, XML_LRM_ATTR_RSCSTATE);
op_status = crm_element_value(rsc_entry, XML_LRM_ATTR_OPSTATUS);
last_rc = crm_element_value(rsc_entry, XML_LRM_ATTR_RC);
last_op = crm_element_value(rsc_entry, XML_LRM_ATTR_LASTOP);
rsc_lh = pe_find_resource(rsc_list, rsc_id);
crm_verbose("[%s] Processing %s on %s (%s)",
crm_element_name(rsc_entry), rsc_id, node_id, rsc_state);
if(rsc_lh == NULL) {
crm_err("Could not find a match for resource"
" %s in %s's status section",
rsc_id, node_id);
continue;
} else if(op_status == NULL) {
crm_err("Invalid resource status entry for %s in %s",
rsc_id, node_id);
continue;
}
action_status_i = atoi(op_status);
if(node->details->unclean) {
crm_debug("Node %s (where %s is running) is unclean."
" Further action depends on the value of %s",
node->details->uname, rsc_lh->id,
XML_RSC_ATTR_STOPFAIL);
/* map the status to an error and then handle as a
* failed resource.
*/
action_status_i = LRM_OP_ERROR;
} else if(action_status_i == (op_status_t)-1) {
/*
* TODO: this may need some more thought
* Some cases:
* - PE reinvoked with pending action that will succeed
* - PE reinvoked with pending action that will fail
* - After DC election
* - After startup
*
* pending start - required start
* pending stop - required stop
* pending <any> on unavailable node - stonith
*
* For now this should do
*/
if(safe_str_eq(last_op, "stop")) {
/* map this to a timeout so it is re-issued */
action_status_i = LRM_OP_TIMEOUT;
} else {
/* map this to a "done" so it is not marked
* as failed, then make sure it is re-issued
*/
action_new(rsc_lh, start_rsc, NULL, node);
action_status_i = LRM_OP_DONE;
}
}
switch(action_status_i) {
case LRM_OP_DONE:
unpack_healthy_resource(
placement_constraints, actions,
rsc_entry, rsc_lh,node);
break;
case LRM_OP_ERROR:
case LRM_OP_TIMEOUT:
case LRM_OP_NOTSUPPORTED:
unpack_failed_resource(placement_constraints,
rsc_entry, rsc_lh,node);
break;
case LRM_OP_CANCELLED:
/* do nothing?? */
crm_warn("Dont know what to do for cancelled ops yet");
break;
}
);
return TRUE;
}
gboolean
unpack_failed_resource(GListPtr *placement_constraints,
crm_data_t * rsc_entry, resource_t *rsc_lh, node_t *node)
{
const char *last_op = crm_element_value(rsc_entry, XML_LRM_ATTR_LASTOP);
crm_devel("Unpacking failed action %s on %s", last_op, rsc_lh->id);
+ CRM_DEV_ASSERT(node != NULL);
+ if(crm_assert_failed) {
+ return FALSE;
+ }
/* make sure we dont allocate the resource here again*/
rsc2node_new("dont_run__generated",
rsc_lh, -INFINITY, FALSE, node, placement_constraints);
if(safe_str_eq(last_op, "start")) {
/* the resource is not actually running... nothing more to do*/
return TRUE;
- }
+ } else if(stonith_enabled == FALSE
+ && rsc_lh->stopfail_type == pesf_stonith) {
+ crm_err("Cannot fence node %s after %s on %s"
+ " as STONITH is disabled",
+ node->details->uname, last_op, rsc_lh->id);
+ return FALSE;
+ }
+
switch(rsc_lh->stopfail_type) {
case pesf_stonith:
/* treat it as if it is still running
* but also mark the node as unclean
*/
native_add_running(rsc_lh, node);
node->details->running_rsc = g_list_append(
node->details->running_rsc, rsc_lh);
-
- if(node->details->online) {
- node->details->shutdown = TRUE;
- }
+
+ rsc_lh->unclean = TRUE;
node->details->unclean = TRUE;
break;
case pesf_block:
/* let this depend on the stop action which will fail
* but make sure the transition continues...
*/
native_add_running(rsc_lh, node);
(node->details->num_resources)++;
node->details->running_rsc = g_list_append(
node->details->running_rsc, rsc_lh);
/* rsc_lh->stop->timeout = NULL; /\* wait forever *\/ */
+ rsc_lh->unclean = TRUE;
break;
case pesf_ignore:
/* pretend nothing happened */
break;
}
return TRUE;
}
gboolean
unpack_healthy_resource(GListPtr *placement_constraints, GListPtr *actions,
crm_data_t * rsc_entry, resource_t *rsc_lh, node_t *node)
{
const char *last_op = crm_element_value(rsc_entry, XML_LRM_ATTR_LASTOP);
crm_devel("Unpacking healthy action %s on %s", last_op, rsc_lh->id);
if(safe_str_neq(last_op, "stop")) {
/* create the link between this node and the rsc */
crm_verbose("Setting cur_node = %s for rsc = %s",
node->details->uname, rsc_lh->id);
native_add_running(rsc_lh, node);
(node->details->num_resources)++;
node->details->running_rsc = g_list_append(
node->details->running_rsc, rsc_lh);
}
return TRUE;
}
gboolean
rsc_colocation_new(const char *id, enum con_strength strength,
resource_t *rsc_lh, resource_t *rsc_rh)
{
rsc_colocation_t *new_con = NULL;
rsc_colocation_t *inverted_con = NULL;
if(rsc_lh == NULL || rsc_rh == NULL){
/* error */
return FALSE;
}
crm_malloc(new_con, sizeof(rsc_colocation_t));
if(new_con == NULL) {
return FALSE;
}
new_con->id = id;
new_con->rsc_lh = rsc_lh;
new_con->rsc_rh = rsc_rh;
new_con->strength = strength;
inverted_con = invert_constraint(new_con);
crm_devel("Adding constraint %s (%p) to %s",
new_con->id, new_con, rsc_lh->id);
rsc_lh->rsc_cons = g_list_insert_sorted(
rsc_lh->rsc_cons, new_con, sort_cons_strength);
crm_devel("Adding constraint %s (%p) to %s",
inverted_con->id, inverted_con, rsc_rh->id);
rsc_rh->rsc_cons = g_list_insert_sorted(
rsc_rh->rsc_cons, inverted_con, sort_cons_strength);
return TRUE;
}
gboolean
order_new(resource_t *lh_rsc, enum action_tasks lh_action_task, action_t *lh_action,
resource_t *rh_rsc, enum action_tasks rh_action_task, action_t *rh_action,
enum con_strength strength, GListPtr *ordering_constraints)
{
order_constraint_t *order = NULL;
if((lh_action == NULL && lh_rsc == NULL)
|| (rh_action == NULL && rh_rsc == NULL)
|| ordering_constraints == NULL){
crm_err("Invalid inputs lh_rsc=%p, lh_a=%p,"
" rh_rsc=%p, rh_a=%p, l=%p",
lh_rsc, lh_action, rh_rsc, rh_action,
ordering_constraints);
return FALSE;
}
crm_malloc(order, sizeof(order_constraint_t));
if(order == NULL) {
return FALSE;
}
order->id = order_id++;
order->strength = strength;
order->lh_rsc = lh_rsc;
order->rh_rsc = rh_rsc;
order->lh_action = lh_action;
order->rh_action = rh_action;
order->lh_action_task = lh_action_task;
order->rh_action_task = rh_action_task;
*ordering_constraints = g_list_append(
*ordering_constraints, order);
if(lh_rsc != NULL && rh_rsc != NULL) {
crm_devel("Created ordering constraint %d (%s):"
" %s/%s before %s/%s",
order->id, strength2text(order->strength),
lh_rsc->id, task2text(lh_action_task),
rh_rsc->id, task2text(rh_action_task));
} else if(lh_rsc != NULL) {
crm_devel("Created ordering constraint %d (%s):"
" %s/%s before action %d (%s)",
order->id, strength2text(order->strength),
lh_rsc->id, task2text(lh_action_task),
rh_action->id, task2text(rh_action_task));
} else if(rh_rsc != NULL) {
crm_devel("Created ordering constraint %d (%s):"
" action %d (%s) before %s/%s",
order->id, strength2text(order->strength),
lh_action->id, task2text(lh_action_task),
rh_rsc->id, task2text(rh_action_task));
} else {
crm_devel("Created ordering constraint %d (%s):"
" action %d (%s) before action %d (%s)",
order->id, strength2text(order->strength),
lh_action->id, task2text(lh_action_task),
rh_action->id, task2text(rh_action_task));
}
return TRUE;
}
gboolean
unpack_rsc_colocation(crm_data_t * xml_obj,
GListPtr rsc_list,
GListPtr *ordering_constraints)
{
enum con_strength strength_e = pecs_ignore;
const char *id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM);
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
const char *id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TO);
const char *type = crm_element_value(xml_obj, XML_ATTR_TYPE);
resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);
resource_t *rsc_rh = pe_find_resource(rsc_list, id_rh);
if(rsc_lh == NULL) {
crm_err("No resource (con=%s, rsc=%s)", id, id_lh);
return FALSE;
} else if(rsc_rh == NULL) {
crm_err("No resource (con=%s, rsc=%s)", id, id_rh);
return FALSE;
}
if(safe_str_eq(type, XML_STRENGTH_VAL_MUST)) {
strength_e = pecs_must;
} else if(safe_str_eq(type, XML_STRENGTH_VAL_SHOULD)) {
crm_err("Type %s is no longer supported", type);
strength_e = pecs_must;
} else if(safe_str_eq(type, XML_STRENGTH_VAL_SHOULDNOT)) {
crm_err("Type %s is no longer supported", type);
strength_e = pecs_must_not;
} else if(safe_str_eq(type, XML_STRENGTH_VAL_MUSTNOT)) {
strength_e = pecs_must_not;
} else {
crm_err("Unknown value for %s: %s", XML_ATTR_TYPE, type);
return FALSE;
}
return rsc_colocation_new(id, strength_e, rsc_lh, rsc_rh);
}
gboolean
unpack_rsc_order(
crm_data_t * xml_obj, GListPtr rsc_list, GListPtr *ordering_constraints)
{
gboolean symmetrical_bool = TRUE;
gboolean action_is_start = TRUE;
gboolean type_is_after = TRUE;
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
const char *id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM);
const char *id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TO);
const char *action = crm_element_value(xml_obj, XML_CONS_ATTR_ACTION);
const char *symmetrical = crm_element_value(xml_obj, XML_CONS_ATTR_SYMMETRICAL);
const char *type = crm_element_value(xml_obj, XML_ATTR_TYPE);
resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);
resource_t *rsc_rh = pe_find_resource(rsc_list, id_rh);
if(xml_obj == NULL) {
crm_err("No constraint object to process.");
return FALSE;
} else if(id == NULL) {
crm_err("%s constraint must have an id", crm_element_name(xml_obj));
return FALSE;
} else if(rsc_lh == NULL || rsc_rh == NULL) {
crm_err("Constraint %s needs two sides lh: %p rh: %p"
" (NULL indicates missing side)",
id, rsc_lh, rsc_rh);
return FALSE;
}
crm_str_to_boolean(symmetrical, &symmetrical_bool);
if(safe_str_eq(type, "before")) {
type_is_after = FALSE;
}
if(safe_str_eq(action, CRMD_RSCSTATE_STOP)) {
action_is_start = FALSE;
}
#if 1
if((type_is_after && action_is_start)
|| (type_is_after == FALSE && action_is_start == FALSE)){
if(symmetrical_bool || action_is_start == FALSE) {
order_new(rsc_lh, stop_rsc, NULL, rsc_rh, stop_rsc, NULL,
pecs_startstop, ordering_constraints);
}
if(symmetrical_bool || action_is_start) {
order_new(rsc_rh, start_rsc, NULL, rsc_lh, start_rsc, NULL,
pecs_startstop, ordering_constraints);
}
} else {
if(symmetrical_bool || action_is_start == FALSE) {
order_new(rsc_rh, stop_rsc, NULL, rsc_lh, stop_rsc, NULL,
pecs_startstop, ordering_constraints);
}
if(symmetrical_bool || action_is_start) {
order_new(rsc_lh, start_rsc, NULL, rsc_rh, start_rsc, NULL,
pecs_startstop, ordering_constraints);
}
}
#else
if(type_is_after) {
order_new(rsc_lh, stop_rsc, NULL, rsc_rh, stop_rsc, NULL,
pecs_startstop, ordering_constraints);
order_new(rsc_rh, start_rsc, NULL, rsc_lh, start_rsc, NULL,
pecs_startstop, ordering_constraints);
} else {
order_new(rsc_rh, stop_rsc, NULL, rsc_lh, stop_rsc, NULL,
pecs_startstop, ordering_constraints);
order_new(rsc_lh, start_rsc, NULL, rsc_rh, start_rsc, NULL,
pecs_startstop, ordering_constraints);
}
#endif
return TRUE;
}
gboolean
add_node_attrs(crm_data_t *xml_obj, node_t *node)
{
g_hash_table_insert(node->details->attrs,
crm_strdup(XML_ATTR_UNAME),
crm_strdup(node->details->uname));
g_hash_table_insert(node->details->attrs,
crm_strdup(XML_ATTR_ID),
crm_strdup(node->details->id));
if(safe_str_eq(node->details->id, dc_uuid)) {
node->details->is_dc = TRUE;
g_hash_table_insert(node->details->attrs,
crm_strdup(XML_ATTR_DC),
crm_strdup(XML_BOOLEAN_TRUE));
} else {
g_hash_table_insert(node->details->attrs,
crm_strdup(XML_ATTR_DC),
crm_strdup(XML_BOOLEAN_FALSE));
}
unpack_instance_attributes(xml_obj, node->details->attrs);
return TRUE;
}
gboolean
unpack_rsc_location(
crm_data_t * xml_obj,
GListPtr rsc_list, GListPtr node_list, GListPtr *placement_constraints)
{
gboolean were_rules = FALSE;
const char *id_lh = crm_element_value(xml_obj, "rsc");
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);
if(rsc_lh == NULL) {
crm_warn("No resource (con=%s, rsc=%s)", id, id_lh);
return FALSE;
}
xml_child_iter(
xml_obj, rule, XML_TAG_RULE,
gboolean first_expr = TRUE;
gboolean can_run = FALSE;
gboolean do_and = TRUE;
gboolean rule_has_expressions;
const char *rule_id = crm_element_value(rule, XML_ATTR_ID);
const char *score = crm_element_value(rule, XML_RULE_ATTR_SCORE);
const char *boolean = crm_element_value(rule, XML_RULE_ATTR_BOOLEAN_OP);
GListPtr match_L = NULL;
GListPtr old_list = NULL;
float score_f = 0.0;
rsc_to_node_t *new_con = NULL;
were_rules = TRUE;
if(score == NULL) {
score_f = 0.0;
} else if(safe_str_eq(score, MINUS_INFINITY_S)) {
score_f = -INFINITY;
} else if(safe_str_eq(score, INFINITY_S)) {
score_f = INFINITY;
} else {
score_f = atof(score);
}
if(safe_str_eq(boolean, "or")) {
do_and = FALSE;
}
if(score_f >= 0.0) {
can_run = TRUE;
}
new_con = rsc2node_new(rule_id, rsc_lh, score_f,
can_run, NULL, placement_constraints);
if(new_con == NULL) {
continue;
}
crm_trace("processing rule: %s",
crm_element_value(rule, XML_ATTR_ID));
rule_has_expressions = FALSE;
xml_child_iter(
rule, expr, XML_TAG_EXPRESSION,
const char *attr = crm_element_value(
expr, XML_EXPR_ATTR_ATTRIBUTE);
const char *op = crm_element_value(
expr, XML_EXPR_ATTR_OPERATION);
const char *value = crm_element_value(
expr, XML_EXPR_ATTR_VALUE);
const char *type = crm_element_value(
expr, XML_EXPR_ATTR_TYPE);
rule_has_expressions = TRUE;
crm_trace("processing expression: %s",
crm_element_value(expr, XML_ATTR_ID));
match_L = apply_node_expression(
attr, op, value, type, node_list);
if(first_expr) {
new_con->node_list_rh = node_list_dup(
match_L, FALSE);
first_expr = FALSE;
continue;
}
old_list = new_con->node_list_rh;
if(do_and) {
crm_trace("do_and");
new_con->node_list_rh = node_list_and(
old_list, match_L, FALSE);
} else {
crm_trace("do_or");
new_con->node_list_rh = node_list_or(
old_list, match_L, FALSE);
}
pe_free_shallow_adv(match_L, FALSE);
pe_free_shallow_adv(old_list, TRUE);
);
if(rule_has_expressions == FALSE && symmetric_cluster == FALSE) {
/* feels like a hack */
crm_devel("Rule %s had no expressions,"
" adding all nodes", crm_element_value(rule, XML_ATTR_ID));
new_con->node_list_rh = node_list_dup(node_list,FALSE);
}
if(new_con->node_list_rh == NULL) {
crm_debug("No matching nodes for constraint/rule %s/%s",
id, crm_element_value(rule, XML_ATTR_ID));
}
crm_devel_action(print_rsc_to_node("Added", new_con, FALSE));
);
if(were_rules == FALSE) {
crm_debug("no rules for constraint %s", id);
}
return TRUE;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 10, 3:21 AM (17 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2009913
Default Alt Text
(67 KB)

Event Timeline