Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624173
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
31 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crmd/te_callbacks.c b/crmd/te_callbacks.c
index 4cf7451c82..0d95a87b7b 100644
--- a/crmd/te_callbacks.c
+++ b/crmd/te_callbacks.c
@@ -1,496 +1,496 @@
/*
* 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_internal.h>
#include <sys/stat.h>
#include <crm/crm.h>
#include <crm/common/xml.h>
#include <crm/msg_xml.h>
#include <crm/cib.h>
#include <tengine.h>
#include <te_callbacks.h>
#include <crmd_fsa.h>
#include <crm/common/cluster.h> /* For ONLINESTATUS etc */
void te_update_confirm(const char *event, xmlNode *msg);
extern char *te_uuid;
gboolean shuttingdown = FALSE;
crm_graph_t *transition_graph;
crm_trigger_t *transition_trigger = NULL;
/* #define rsc_op_template "//"XML_TAG_DIFF_ADDED"//"XML_TAG_CIB"//"XML_CIB_TAG_STATE"[@uname='%s']"//"XML_LRM_TAG_RSC_OP"[@id='%s]" */
#define rsc_op_template "//"XML_TAG_DIFF_ADDED"//"XML_TAG_CIB"//"XML_LRM_TAG_RSC_OP"[@id='%s']"
static const char *get_node_id(xmlNode *rsc_op)
{
xmlNode *node = rsc_op;
while(node != NULL && safe_str_neq(XML_CIB_TAG_STATE, TYPE(node))) {
node = node->parent;
}
CRM_CHECK(node != NULL, return NULL);
return ID(node);
}
static void process_resource_updates(xmlXPathObject *xpathObj)
{
/*
<status>
<node_state id="node1" state=CRMD_STATE_ACTIVE exp_state="active">
<lrm>
<lrm_resources>
<rsc_state id="" rsc_id="rsc4" node_id="node1" rsc_state="stopped"/>
*/
int lpc = 0, max = xpathObj->nodesetval->nodeNr;
for(lpc = 0; lpc < max; lpc++) {
xmlNode *rsc_op = getXpathResult(xpathObj, lpc);
const char *node = get_node_id(rsc_op);
process_graph_event(rsc_op, node);
}
}
void
te_update_diff(const char *event, xmlNode *msg)
{
int rc = -1;
const char *op = NULL;
xmlNode *diff = NULL;
xmlNode *cib_top = NULL;
xmlXPathObject *xpathObj = NULL;
int diff_add_updates = 0;
int diff_add_epoch = 0;
int diff_add_admin_epoch = 0;
int diff_del_updates = 0;
int diff_del_epoch = 0;
int diff_del_admin_epoch = 0;
CRM_CHECK(msg != NULL, return);
crm_element_value_int(msg, F_CIB_RC, &rc);
if(transition_graph == NULL) {
crm_debug_3("No graph");
return;
} else if(rc < cib_ok) {
crm_debug_3("Filter rc=%d (%s)", rc, cib_error2string(rc));
return;
} else if(transition_graph->complete == TRUE
&& fsa_state != S_IDLE
&& fsa_state != S_TRANSITION_ENGINE
&& fsa_state != S_POLICY_ENGINE) {
crm_debug_2("Filter state=%s, complete=%d", fsa_state2string(fsa_state), transition_graph->complete);
return;
}
op = crm_element_value(msg, F_CIB_OPERATION);
diff = get_message_xml(msg, F_CIB_UPDATE_RESULT);
cib_diff_version_details(
diff,
&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
crm_debug("Processing diff (%s): %d.%d.%d -> %d.%d.%d (%s)", op,
diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
diff_add_admin_epoch,diff_add_epoch,diff_add_updates,
fsa_state2string(fsa_state));
log_cib_diff(LOG_DEBUG_2, diff, op);
/* Process crm_config updates */
cib_top = get_xpath_object("//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_CIB_TAG_CRMCONFIG, diff, LOG_DEBUG);
if(cib_top != NULL) {
mainloop_set_trigger(config_read);
}
/* Process anything that was added */
cib_top = get_xpath_object("//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_TAG_CIB, diff, LOG_ERR);
if(need_abort(cib_top)) {
goto bail; /* configuration changed */
}
/* Process anything that was removed */
cib_top = get_xpath_object("//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_REMOVED"//"XML_TAG_CIB, diff, LOG_ERR);
if(need_abort(cib_top)) {
goto bail; /* configuration changed */
}
/* Transient Attributes - Added/Updated */
xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_TAG_TRANSIENT_NODEATTRS);
if(xpathObj && xpathObj->nodesetval->nodeNr > 0) {
xmlNode *aborted = getXpathResult(xpathObj, 0);
abort_transition(INFINITY, tg_restart, "Transient attribute: update", aborted);
goto bail;
} else if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
/* Transient Attributes - Removed */
xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_REMOVED"//"XML_TAG_TRANSIENT_NODEATTRS);
if(xpathObj && xpathObj->nodesetval->nodeNr > 0) {
xmlNode *aborted = getXpathResult(xpathObj, 0);
abort_transition(INFINITY, tg_restart, "Transient attribute: removal", aborted);
goto bail;
} else if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
/* Check for node state updates... possibly from a shutdown we requested */
xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_CIB_TAG_STATE);
if(xpathObj) {
int lpc = 0, max = xpathObj->nodesetval->nodeNr;
for(lpc = 0; lpc < max; lpc++) {
xmlNode *node = getXpathResult(xpathObj, lpc);
const char *event_node = crm_element_value(node, XML_ATTR_ID);
const char *ccm_state = crm_element_value(node, XML_CIB_ATTR_INCCM);
const char *ha_state = crm_element_value(node, XML_CIB_ATTR_HASTATE);
const char *shutdown_s = crm_element_value(node, XML_CIB_ATTR_SHUTDOWN);
const char *crmd_state = crm_element_value(node, XML_CIB_ATTR_CRMDSTATE);
if(safe_str_eq(ccm_state, XML_BOOLEAN_FALSE)
|| safe_str_eq(ha_state, DEADSTATUS)
|| safe_str_eq(crmd_state, CRMD_JOINSTATE_DOWN)) {
crm_action_t *shutdown = match_down_event(0, event_node, NULL);
if(shutdown != NULL) {
const char *task = crm_element_value(shutdown->xml, XML_LRM_ATTR_TASK);
if(safe_str_neq(task, CRM_OP_FENCE)) {
/* Wait for stonithd to tell us it is complete via tengine_stonith_callback() */
update_graph(transition_graph, shutdown);
trigger_graph();
}
} else {
crm_info("Stonith/shutdown of %s not matched", event_node);
abort_transition(INFINITY, tg_restart, "Node failure", node);
}
fail_incompletable_actions(transition_graph, event_node);
}
if(shutdown_s) {
int shutdown = crm_parse_int(shutdown_s, NULL);
if(shutdown > 0) {
crm_info("Aborting on "XML_CIB_ATTR_SHUTDOWN" attribute for %s", event_node);
abort_transition(INFINITY, tg_restart, "Shutdown request", node);
}
}
}
xmlXPathFreeObject(xpathObj);
}
/*
* Check for and fast-track the processing of LRM refreshes
* In large clusters this can result in _huge_ speedups
*
* Unfortunately we can only do so when there are no pending actions
* Otherwise we could miss updates we're waiting for and stall
*
*/
xpathObj = NULL;
if(transition_graph->pending == 0) {
xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_LRM_TAG_RESOURCE);
}
if(xpathObj) {
int updates = xpathObj->nodesetval->nodeNr;
if(updates > 1) {
/* Updates by, or in response to, TE actions will never contain updates
* for more than one resource at a time
*/
crm_info("Detected LRM refresh - %d resources updated: Skipping all resource events", updates);
abort_transition(INFINITY, tg_restart, "LRM Refresh", diff);
goto bail;
}
xmlXPathFreeObject(xpathObj);
}
/* Process operation updates */
xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_LRM_TAG_RSC_OP);
if(xpathObj) {
process_resource_updates(xpathObj);
xmlXPathFreeObject(xpathObj);
}
/* Detect deleted (as opposed to replaced or added) actions - eg. crm_resource -C */
xpathObj = xpath_search(diff, "//"XML_TAG_DIFF_REMOVED"//"XML_LRM_TAG_RSC_OP);
if(xpathObj) {
int lpc = 0, max = xpathObj->nodesetval->nodeNr;
for(lpc = 0; lpc < max; lpc++) {
int max = 0;
const char *op_id = NULL;
char *rsc_op_xpath = NULL;
xmlXPathObject *op_match = NULL;
xmlNode *match = getXpathResult(xpathObj, lpc);
CRM_CHECK(match != NULL, continue);
op_id = ID(match);
max = strlen(rsc_op_template) + strlen(op_id) + 1;
crm_malloc0(rsc_op_xpath, max);
snprintf(rsc_op_xpath, max, rsc_op_template, op_id);
op_match = xpath_search(diff, rsc_op_xpath);
if(op_match == NULL || op_match->nodesetval->nodeNr == 0) {
/* Prevent false positives by matching cancelations too */
const char *node = get_node_id(match);
crm_action_t *cancelled = get_cancel_action(op_id, node);
if(cancelled == NULL) {
crm_debug("No match for deleted action %s (%s on %s)", rsc_op_xpath, op_id, node);
abort_transition(INFINITY, tg_restart, "Resource op removal", match);
goto bail;
} else {
crm_debug("Deleted lrm_rsc_op %s on %s was for graph event %d",
op_id, node, cancelled->id);
}
}
if(op_match) {
xmlXPathFreeObject(op_match);
}
crm_free(rsc_op_xpath);
}
}
bail:
if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
}
gboolean
process_te_message(xmlNode *msg, xmlNode *xml_data)
{
const char *from = crm_element_value(msg, F_ORIG);
const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO);
const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM);
const char *ref = crm_element_value(msg, XML_ATTR_REFERENCE);
const char *op = crm_element_value(msg, F_CRM_TASK);
const char *type = crm_element_value(msg, F_CRM_MSG_TYPE);
crm_debug_2("Processing %s (%s) message", op, ref);
crm_log_xml(LOG_DEBUG_3, "ipc", msg);
if(op == NULL){
/* error */
} else if(sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_TENGINE) != 0) {
crm_debug_2("Bad sys-to %s", crm_str(sys_to));
return FALSE;
} else if(safe_str_eq(op, CRM_OP_INVOKE_LRM)
&& safe_str_eq(sys_from, CRM_SYSTEM_LRMD)
/* && safe_str_eq(type, XML_ATTR_RESPONSE) */
){
xmlXPathObject *xpathObj = NULL;
crm_log_xml(LOG_DEBUG_2, "Processing (N)ACK", msg);
crm_info("Processing (N)ACK %s from %s",
crm_element_value(msg, XML_ATTR_REFERENCE), from);
xpathObj = xpath_search(xml_data, "//"XML_LRM_TAG_RSC_OP);
if(xpathObj) {
process_resource_updates(xpathObj);
xmlXPathFreeObject(xpathObj);
xpathObj = NULL;
} else {
crm_log_xml(LOG_ERR, "Invalid (N)ACK", msg);
return FALSE;
}
} else {
crm_err("Unknown command: %s::%s from %s", type, op, sys_from);
}
crm_debug_3("finished processing message");
return TRUE;
}
void
tengine_stonith_callback(
stonith_t *stonith, const xmlNode *msg, int call_id, int rc, xmlNode *output, void *userdata)
{
char *uuid = NULL;
int target_rc = -1;
int stonith_id = -1;
int transition_id = -1;
crm_action_t *action = NULL;
CRM_CHECK(userdata != NULL, return);
crm_log_xml_info(output, "StonithOp");
- crm_info("Stonith operation %d/%s returned %d", call_id, (char*)userdata, rc);
+ crm_info("Stonith operation %d/%s result=%d", call_id, (char*)userdata, rc);
/* crm_info("call=%d, optype=%d, node_name=%s, result=%d, node_list=%s, action=%s", */
/* op->call_id, op->optype, op->node_name, op->op_result, */
/* (char *)op->node_list, op->private_data); */
/* filter out old STONITH actions */
CRM_CHECK(decode_transition_key(userdata, &uuid, &transition_id, &stonith_id, &target_rc),
crm_err("Invalid event detected");
goto bail;
);
if(transition_graph->complete
|| stonith_id < 0
|| safe_str_neq(uuid, te_uuid)
|| transition_graph->id != transition_id) {
crm_info("Ignoring STONITH action initiated outside"
" of the current transition");
goto bail;
}
/* this will mark the event complete if a match is found */
action = get_action(stonith_id, TRUE);
if(action == NULL) {
crm_err("Stonith action not matched");
goto bail;
}
if(rc == stonith_ok) {
crm_info("Stonith of %s passed",
crm_element_value_const(action->xml, XML_LRM_ATTR_TARGET));
send_stonith_update(action);
} else {
const char *target = crm_element_value_const(action->xml, XML_LRM_ATTR_TARGET);
const char *allow_fail = crm_meta_value(action->params, XML_ATTR_TE_ALLOWFAIL);
action->failed = TRUE;
if(crm_is_true(allow_fail) == FALSE) {
crm_err("Stonith of %s failed (%d)... aborting transition.", target, rc);
abort_transition(INFINITY, tg_restart, "Stonith failed", NULL);
}
}
update_graph(transition_graph, action);
trigger_graph();
bail:
crm_free(userdata);
crm_free(uuid);
return;
}
void
cib_fencing_updated(xmlNode *msg, int call_id, int rc,
xmlNode *output, void *user_data)
{
if(rc < cib_ok) {
crm_err("CIB update failed: %s", cib_error2string(rc));
crm_log_xml_warn(msg, "Failed update");
}
crm_free(user_data);
}
void
cib_action_updated(xmlNode *msg, int call_id, int rc,
xmlNode *output, void *user_data)
{
if(rc < cib_ok) {
crm_err("Update %d FAILED: %s", call_id, cib_error2string(rc));
}
}
void
cib_failcount_updated(xmlNode *msg, int call_id, int rc,
xmlNode *output, void *user_data)
{
if(rc < cib_ok) {
crm_err("Update %d FAILED: %s", call_id, cib_error2string(rc));
}
}
gboolean
action_timer_callback(gpointer data)
{
crm_action_timer_t *timer = NULL;
CRM_CHECK(data != NULL, return FALSE);
timer = (crm_action_timer_t*)data;
stop_te_timer(timer);
crm_warn("Timer popped (timeout=%d, abort_level=%d, complete=%s)",
timer->timeout,
transition_graph->abort_priority,
transition_graph->complete?"true":"false");
CRM_CHECK(timer->action != NULL, return FALSE);
if(transition_graph->complete) {
crm_warn("Ignoring timeout while not in transition");
} else if(timer->reason == timeout_action_warn) {
print_action(
LOG_WARNING,"Action missed its timeout: ", timer->action);
} else if(fsa_state != S_TRANSITION_ENGINE && fsa_state != S_POLICY_ENGINE) {
crm_err("Discarding action timeout in state: %s", fsa_state2string(fsa_state));
} else if(transition_graph->complete) {
crm_err("Ignoring action timeout while not in transition");
} else {
/* fail the action */
gboolean send_update = TRUE;
const char *task = crm_element_value(timer->action->xml, XML_LRM_ATTR_TASK);
print_action(LOG_ERR, "Aborting transition, action lost: ", timer->action);
timer->action->failed = TRUE;
timer->action->confirmed = TRUE;
abort_transition(INFINITY, tg_restart, "Action lost", NULL);
update_graph(transition_graph, timer->action);
trigger_graph();
if(timer->action->type != action_type_rsc) {
send_update = FALSE;
} else if(safe_str_eq(task, "cancel")) {
/* we dont need to update the CIB with these */
send_update = FALSE;
} else if(safe_str_eq(task, "stop")) {
/* *never* update the CIB with these */
send_update = FALSE;
}
if(send_update) {
/* cib_action_update(timer->action, LRM_OP_PENDING, EXECRA_STATUS_UNKNOWN); */
cib_action_update(timer->action, LRM_OP_TIMEOUT, EXECRA_UNKNOWN_ERROR);
}
}
return FALSE;
}
diff --git a/crmd/te_utils.c b/crmd/te_utils.c
index 082e19fce9..ebbfa56030 100644
--- a/crmd/te_utils.c
+++ b/crmd/te_utils.c
@@ -1,292 +1,296 @@
/*
* 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_internal.h>
#include <sys/param.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/msg.h>
#include <crm/common/xml.h>
#include <tengine.h>
#include <crmd_fsa.h>
#include <crmd_messages.h>
GCHSource *stonith_src = NULL;
crm_trigger_t *stonith_reconnect = NULL;
static gboolean
fail_incompletable_stonith(crm_graph_t *graph)
{
const char *task = NULL;
xmlNode *last_action = NULL;
if(graph == NULL) {
return FALSE;
}
slist_iter(
synapse, synapse_t, graph->synapses, lpc,
if (synapse->confirmed) {
continue;
}
slist_iter(
action, crm_action_t, synapse->actions, lpc,
if(action->type != action_type_crm || action->confirmed) {
continue;
}
task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
if(task && safe_str_eq(task, CRM_OP_FENCE)) {
action->failed = TRUE;
last_action = action->xml;
update_graph(graph, action);
crm_notice("Failing action %d (%s): STONITHd terminated",
action->id, ID(action->xml));
}
);
);
if(last_action != NULL) {
crm_warn("STONITHd failure resulted in un-runnable actions");
abort_transition(INFINITY, tg_restart, "Stonith failure", last_action);
return TRUE;
}
return FALSE;
}
static void
tengine_stonith_connection_destroy(stonith_t *st, const char *event, xmlNode *msg)
{
if(stonith_api == NULL) {
crm_info("Fencing daemon disconnected");
} else {
crm_crit("Fencing daemon connection failed");
mainloop_set_trigger(stonith_reconnect);
}
/* cbchan will be garbage at this point, arrange for it to be reset */
stonith_api->state = stonith_disconnected;
fail_incompletable_stonith(transition_graph);
trigger_graph();
return;
}
gboolean
te_connect_stonith(gpointer user_data)
{
int lpc = 0;
int rc = stonith_ok;
if(stonith_api == NULL) {
stonith_api = stonith_api_new();
}
if(stonith_api->state != stonith_disconnected) {
crm_debug_2("Still connected");
return TRUE;
}
for(lpc = 0; lpc < 30; lpc++) {
crm_info("Attempting connection to fencing daemon...");
sleep(1);
rc = stonith_api->cmds->connect(stonith_api, crm_system_name, NULL, NULL);
+ if(rc == stonith_ok) {
+ break;
+ }
+
if(user_data != NULL) {
crm_err("Sign-in failed: triggered a retry");
mainloop_set_trigger(stonith_reconnect);
return TRUE;
- }
-
+ }
+
crm_err("Sign-in failed: pausing and trying again in 2s...");
sleep(1);
}
CRM_CHECK(rc == stonith_ok, return TRUE); /* If not, we failed 30 times... just get out */
rc = stonith_api->cmds->register_notification(
stonith_api, T_STONITH_NOTIFY_DISCONNECT, tengine_stonith_connection_destroy);
crm_info("Connected");
return TRUE;
}
gboolean
stop_te_timer(crm_action_timer_t *timer)
{
const char *timer_desc = "action timer";
if(timer == NULL) {
return FALSE;
}
if(timer->reason == timeout_abort) {
timer_desc = "global timer";
crm_debug_2("Stopping %s", timer_desc);
}
if(timer->source_id != 0) {
crm_debug_2("Stopping %s", timer_desc);
g_source_remove(timer->source_id);
timer->source_id = 0;
} else {
crm_debug_2("%s was already stopped", timer_desc);
return FALSE;
}
return TRUE;
}
gboolean
te_graph_trigger(gpointer user_data)
{
enum transition_status graph_rc = -1;
if(transition_graph == NULL) {
crm_debug("Nothing to do");
return TRUE;
}
crm_debug_2("Invoking graph %d in state %s",
transition_graph->id, fsa_state2string(fsa_state));
switch(fsa_state) {
case S_STARTING:
case S_PENDING:
case S_NOT_DC:
case S_HALT:
case S_ILLEGAL:
case S_STOPPING:
case S_TERMINATE:
return TRUE;
break;
default:
break;
}
if(transition_graph->complete == FALSE) {
graph_rc = run_graph(transition_graph);
print_graph(LOG_DEBUG_3, transition_graph);
if(graph_rc == transition_active) {
crm_debug_3("Transition not yet complete");
return TRUE;
} else if(graph_rc == transition_pending) {
crm_debug_3("Transition not yet complete - no actions fired");
return TRUE;
}
if(graph_rc != transition_complete) {
crm_err("Transition failed: %s", transition_status(graph_rc));
print_graph(LOG_WARNING, transition_graph);
}
}
crm_info("Transition %d is now complete", transition_graph->id);
transition_graph->complete = TRUE;
notify_crmd(transition_graph);
return TRUE;
}
void
trigger_graph_processing(const char *fn, int line)
{
mainloop_set_trigger(transition_trigger);
crm_debug_2("%s:%d - Triggered graph processing", fn, line);
}
void
abort_transition_graph(
int abort_priority, enum transition_action abort_action,
const char *abort_text, xmlNode *reason, const char *fn, int line)
{
int log_level = LOG_INFO;
const char *magic = NULL;
CRM_CHECK(transition_graph != NULL, return);
if(reason) {
int diff_add_updates = 0;
int diff_add_epoch = 0;
int diff_add_admin_epoch = 0;
int diff_del_updates = 0;
int diff_del_epoch = 0;
int diff_del_admin_epoch = 0;
xmlNode *diff = get_xpath_object("//"F_CIB_UPDATE_RESULT"//diff", reason, LOG_DEBUG_2);
magic = crm_element_value(reason, XML_ATTR_TRANSITION_MAGIC);
if(diff) {
cib_diff_version_details(
diff,
&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
do_crm_log(log_level,
"%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, magic=%s, cib=%d.%d.%d) : %s",
fn, line, transition_graph->complete, TYPE(reason), ID(reason), magic?magic:"NA",
diff_add_admin_epoch,diff_add_epoch,diff_add_updates, abort_text);
} else {
do_crm_log(log_level,
"%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, magic=%s) : %s",
fn, line, transition_graph->complete, TYPE(reason), ID(reason), magic?magic:"NA", abort_text);
}
} else {
do_crm_log(log_level,
"%s:%d - Triggered transition abort (complete=%d) : %s",
fn, line, transition_graph->complete, abort_text);
}
switch(fsa_state) {
case S_STARTING:
case S_PENDING:
case S_NOT_DC:
case S_HALT:
case S_ILLEGAL:
case S_STOPPING:
case S_TERMINATE:
do_crm_log(log_level,
"Abort suppressed: state=%s (complete=%d)",
fsa_state2string(fsa_state), transition_graph->complete);
return;
default:
break;
}
if(magic == NULL && reason != NULL) {
crm_log_xml(log_level+1, "Cause", reason);
}
if(transition_graph->complete) {
register_fsa_input(C_FSA_INTERNAL, I_PE_CALC, NULL);
return;
}
update_abort_priority(
transition_graph, abort_priority, abort_action, abort_text);
mainloop_set_trigger(transition_trigger);
}
diff --git a/crmd/tengine.c b/crmd/tengine.c
index c3c3dec7ca..b610faf56e 100644
--- a/crmd/tengine.c
+++ b/crmd/tengine.c
@@ -1,282 +1,284 @@
/*
* 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_internal.h>
#include <sys/param.h>
#include <crm/crm.h>
#include <crmd_fsa.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h> /* for access */
#include <sys/types.h> /* for calls to open */
#include <sys/stat.h> /* for calls to open */
#include <fcntl.h> /* for calls to open */
#include <pwd.h> /* for getpwuid */
#include <grp.h> /* for initgroups */
#include <sys/time.h> /* for getrlimit */
#include <sys/resource.h>/* for getrlimit */
#include <errno.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crmd_messages.h>
#include <crmd_callbacks.h>
#include <crm/cib.h>
#include <crmd.h>
#include <tengine.h>
#include <te_callbacks.h>
extern crm_graph_functions_t te_graph_fns;
struct crm_subsystem_s *te_subsystem = NULL;
stonith_t *stonith_api = NULL;
static void global_cib_callback(const xmlNode *msg, int callid ,int rc, xmlNode *output)
{
}
static crm_graph_t *create_blank_graph(void)
{
crm_graph_t *a_graph = unpack_graph(NULL, NULL);
a_graph->complete = TRUE;
a_graph->abort_reason = "DC Takeover";
a_graph->completion_action = tg_restart;
return a_graph;
}
/* A_TE_START, A_TE_STOP, A_TE_RESTART */
void
do_te_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
int dummy;
gboolean init_ok = TRUE;
cl_uuid_t new_uuid;
char uuid_str[UU_UNPARSE_SIZEOF];
if(action & A_TE_STOP) {
if(transition_graph) {
destroy_graph(transition_graph);
transition_graph = NULL;
}
if(fsa_cib_conn && cib_ok != fsa_cib_conn->cmds->del_notify_callback(
fsa_cib_conn, T_CIB_DIFF_NOTIFY, te_update_diff)) {
crm_err("Could not set CIB notification callback");
init_ok = FALSE;
}
clear_bit_inplace(fsa_input_register, te_subsystem->flag_connected);
crm_info("Transitioner is now inactive");
if(stonith_api) {
+ stonith_t *api = stonith_api;
crm_info("Disconnecting STONITH...");
- stonith_api->cmds->disconnect(stonith_api);
- stonith_api->cmds->free(stonith_api);
+
stonith_api = NULL; /* Prevent it from comming up again */
+ api->cmds->disconnect(api);
+ api->cmds->free(api);
}
}
if((action & A_TE_START) == 0) {
return;
} else if(is_set(fsa_input_register, te_subsystem->flag_connected)) {
crm_debug("The transitioner is already active");
return;
} else if((action & A_TE_START) && cur_state == S_STOPPING) {
crm_info("Ignoring request to start %s while shutting down",
te_subsystem->name);
return;
}
cl_uuid_generate(&new_uuid);
cl_uuid_unparse(&new_uuid, uuid_str);
te_uuid = crm_strdup(uuid_str);
crm_info("Registering TE UUID: %s", te_uuid);
if(transition_trigger == NULL) {
transition_trigger = mainloop_add_trigger(
G_PRIORITY_LOW, te_graph_trigger, NULL);
}
if(stonith_reconnect == NULL) {
stonith_reconnect = mainloop_add_trigger(
G_PRIORITY_LOW, te_connect_stonith, &dummy);
}
if(cib_ok != fsa_cib_conn->cmds->add_notify_callback(
fsa_cib_conn, T_CIB_DIFF_NOTIFY, te_update_diff)) {
crm_err("Could not set CIB notification callback");
init_ok = FALSE;
}
if(cib_EXISTS != fsa_cib_conn->cmds->add_notify_callback(
fsa_cib_conn, T_CIB_DIFF_NOTIFY, te_update_diff)) {
crm_err("Set duplicate CIB notification callback");
}
if(cib_ok != fsa_cib_conn->cmds->set_op_callback(fsa_cib_conn, global_cib_callback)) {
crm_err("Could not set CIB global callback");
init_ok = FALSE;
}
if(init_ok) {
mainloop_set_trigger(stonith_reconnect);
set_graph_functions(&te_graph_fns);
if(transition_graph) {
destroy_graph(transition_graph);
}
/* create a blank one */
crm_debug("Transitioner is now active");
transition_graph = create_blank_graph();
set_bit_inplace(fsa_input_register, te_subsystem->flag_connected);
}
}
/* A_TE_INVOKE, A_TE_CANCEL */
void
do_te_invoke(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
if(AM_I_DC == FALSE) {
crm_err("Not DC: No need to invoke the TE (anymore): %s",
fsa_action2string(action));
return;
} else if(fsa_state != S_TRANSITION_ENGINE && (action & A_TE_INVOKE)) {
crm_err("No need to invoke the TE (%s) in state %s",
fsa_action2string(action),
fsa_state2string(fsa_state));
return;
}
if(action & A_TE_CANCEL) {
crm_debug("Cancelling the transition: %s",
transition_graph->complete?"inactive":"active");
abort_transition(INFINITY, tg_restart, "Peer Cancelled", NULL);
if(transition_graph->complete == FALSE) {
crmd_fsa_stall(NULL);
}
} else if(action & A_TE_HALT) {
crm_debug("Halting the transition: %s",
transition_graph->complete?"inactive":"active");
abort_transition(INFINITY, tg_stop, "Peer Halt", NULL);
if(transition_graph->complete == FALSE) {
crmd_fsa_stall(NULL);
}
} else if(action & A_TE_INVOKE) {
const char *value = NULL;
xmlNode *graph_data = NULL;
ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg);
const char *ref = crm_element_value(input->msg, XML_ATTR_REFERENCE);
const char *graph_file = crm_element_value(input->msg, F_CRM_TGRAPH);
const char *graph_input = crm_element_value(input->msg, F_CRM_TGRAPH_INPUT);
if(graph_file == NULL && input->xml == NULL) {
crm_log_xml_err(input->msg, "Bad command");
register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);
return;
}
if(transition_graph->complete == FALSE) {
crm_info("Another transition is already active");
abort_transition(INFINITY, tg_restart, "Transition Active", NULL);
return;
}
graph_data = input->xml;
if(graph_data == NULL && graph_file != NULL) {
graph_data = filename2xml(graph_file);
}
CRM_CHECK(graph_data != NULL,
crm_err("Input raised by %s is invalid", msg_data->origin);
crm_log_xml_err(input->msg, "Bad command");
return);
destroy_graph(transition_graph);
transition_graph = unpack_graph(graph_data, graph_input);
CRM_CHECK(transition_graph != NULL, transition_graph = create_blank_graph(); return);
crm_info("Processing graph %d (ref=%s) derived from %s", transition_graph->id, ref, graph_input);
value = crm_element_value(graph_data, "failed-stop-offset");
if(value) {
crm_free(failed_stop_offset);
failed_stop_offset = crm_strdup(value);
}
value = crm_element_value(graph_data, "failed-start-offset");
if(value) {
crm_free(failed_start_offset);
failed_start_offset = crm_strdup(value);
}
trigger_graph();
print_graph(LOG_DEBUG_2, transition_graph);
if(graph_data != input->xml) {
free_xml(graph_data);
}
}
}
#if 0
gboolean shuttingdown;
gboolean tengine_shutdown(int nsig, gpointer unused)
{
shuttingdown = TRUE;
abort_transition(INFINITY, tg_shutdown, "Shutdown", NULL);
return TRUE;
}
gboolean te_stop(void)
{
destroy_graph(transition_graph);
#if SUPPORT_HEARTBEAT
if(is_heartbeat_cluster()) {
stonithd_signoff();
}
#endif
crm_free(te_uuid);
}
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:03 PM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002443
Default Alt Text
(31 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment