Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F7609922
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
30 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crmd/cib.c b/crmd/cib.c
index 4c07ae99fc..01e679263d 100644
--- a/crmd/cib.c
+++ b/crmd/cib.c
@@ -1,204 +1,232 @@
/*
* 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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>
struct crm_subsystem_s *cib_subsystem = NULL;
int cib_retries = 0;
+static void
+do_cib_updated(const char *event, xmlNode *msg)
+{
+ int rc = -1;
+ xmlNode *diff = NULL;
+
+ CRM_CHECK(msg != NULL, return);
+ crm_element_value_int(msg, F_CIB_RC, &rc);
+ if(rc < cib_ok) {
+ crm_debug_3("Filter rc=%d (%s)", rc, cib_error2string(rc));
+ return;
+ }
+
+ diff = get_message_xml(msg, F_CIB_UPDATE_RESULT);
+ if(get_xpath_object(
+ "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_CIB_TAG_CRMCONFIG,
+ diff, LOG_DEBUG) != NULL) {
+ mainloop_set_trigger(config_read);
+ }
+}
static void
revision_check_callback(xmlNode *msg, int call_id, int rc,
xmlNode *output, void *user_data)
{
int cmp = -1;
const char *revision = NULL;
xmlNode *generation = NULL;
if(rc != cib_ok) {
fsa_data_t *msg_data = NULL;
register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
return;
}
generation = output;
CRM_CHECK(safe_str_eq(crm_element_name(generation), XML_TAG_CIB), crm_log_xml_err(output, __FUNCTION__); return);
crm_debug_3("Checking our feature revision is allowed: %s", CIB_FEATURE_SET);
revision = crm_element_value(generation, XML_ATTR_CRM_VERSION);
cmp = compare_version(revision, CRM_FEATURE_SET);
if(cmp > 0) {
crm_err("This build (%s) does not support the current"
" resource configuration", VERSION);
crm_err("We can only support up to CRM feature set %s (current=%s)",
CRM_FEATURE_SET, revision);
crm_err("Shutting down the CRM");
/* go into a stall state */
register_fsa_error_adv(
C_FSA_INTERNAL, I_SHUTDOWN, NULL, NULL, __FUNCTION__);
return;
}
}
static void
do_cib_replaced(const char *event, xmlNode *msg)
{
crm_debug("Updating the CIB after a replace: DC=%s", AM_I_DC?"true":"false");
if(AM_I_DC == FALSE) {
return;
} else if(fsa_state == S_FINALIZE_JOIN
&& is_set(fsa_input_register, R_CIB_ASKED)) {
/* no need to restart the join - we asked for this replace op */
return;
}
/* start the join process again so we get everyone's LRM status */
populate_cib_nodes(FALSE);
do_update_cib_nodes(TRUE, __FUNCTION__);
register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
}
/* A_CIB_STOP, A_CIB_START, A_CIB_RESTART, */
void
do_cib_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)
{
struct crm_subsystem_s *this_subsys = cib_subsystem;
long long stop_actions = A_CIB_STOP;
long long start_actions = A_CIB_START;
if(action & stop_actions) {
crm_info("Disconnecting CIB");
clear_bit_inplace(fsa_input_register, R_CIB_CONNECTED);
CRM_ASSERT(fsa_cib_conn != NULL);
+
+ fsa_cib_conn->cmds->del_notify_callback(
+ fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated);
+
if(fsa_cib_conn->state != cib_disconnected) {
fsa_cib_conn->cmds->set_slave(
fsa_cib_conn, cib_scope_local);
fsa_cib_conn->cmds->signoff(fsa_cib_conn);
}
}
if(action & start_actions) {
int rc = cib_ok;
CRM_ASSERT(fsa_cib_conn != NULL);
if(cur_state == S_STOPPING) {
crm_err("Ignoring request to start %s after shutdown",
this_subsys->name);
return;
}
rc = fsa_cib_conn->cmds->signon(
fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command);
if(rc != cib_ok) {
/* a short wait that usually avoids stalling the FSA */
sleep(1);
rc = fsa_cib_conn->cmds->signon(
fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command);
}
if(rc != cib_ok){
crm_info("Could not connect to the CIB service: %s", cib_error2string(rc));
} else if(cib_ok != fsa_cib_conn->cmds->set_connection_dnotify(
fsa_cib_conn, crmd_cib_connection_destroy)) {
crm_err("Could not set dnotify callback");
} else if(cib_ok != fsa_cib_conn->cmds->add_notify_callback(
fsa_cib_conn, T_CIB_REPLACE_NOTIFY,
do_cib_replaced)) {
crm_err("Could not set CIB notification callback");
+
+ } else if(cib_ok != fsa_cib_conn->cmds->add_notify_callback(
+ fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated)) {
+ crm_err("Could not set CIB notification callback");
} else {
set_bit_inplace(
fsa_input_register, R_CIB_CONNECTED);
}
if(is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) {
cib_retries++;
crm_warn("Couldn't complete CIB registration %d"
" times... pause and retry",
cib_retries);
if(cib_retries < 30) {
crm_timer_start(wait_timer);
crmd_fsa_stall(NULL);
} else {
crm_err("Could not complete CIB"
" registration %d times..."
" hard error", cib_retries);
register_fsa_error(
C_FSA_INTERNAL, I_ERROR, NULL);
}
} else {
int call_id = 0;
crm_info("CIB connection established");
call_id = fsa_cib_conn->cmds->query(
fsa_cib_conn, NULL, NULL, cib_scope_local);
add_cib_op_callback(fsa_cib_conn, call_id, FALSE, NULL,
revision_check_callback);
cib_retries = 0;
}
}
}
diff --git a/crmd/te_callbacks.c b/crmd/te_callbacks.c
index ae23d1573d..8527e2c71c 100644
--- a/crmd/te_callbacks.c
+++ b/crmd/te_callbacks.c
@@ -1,515 +1,508 @@
/*
* 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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);
- }
-
if(cib_config_changed(NULL, NULL, &diff)) {
abort_transition(INFINITY, tg_restart, "Non-status change", diff);
goto bail; /* configuration changed */
}
/* Transient Attributes - Added/Updated */
xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_TAG_TRANSIENT_NODEATTRS"//"XML_CIB_TAG_NVPAIR);
if(xpathObj && xpathObj->nodesetval->nodeNr > 0) {
int lpc;
for(lpc = 0; lpc < xpathObj->nodesetval->nodeNr; lpc++) {
xmlNode *attr = getXpathResult(xpathObj, lpc);
const char *name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME);
const char *value = NULL;
if(safe_str_eq(CRM_OP_PROBED, name)) {
value = crm_element_value(attr, XML_NVPAIR_ATTR_VALUE);
}
if(crm_is_true(value) == FALSE) {
abort_transition(INFINITY, tg_restart, "Transient attribute: update", attr);
crm_log_xml_trace(attr, "Abort");
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() */
crm_debug("Confirming %s op %d", task, shutdown->id);
/* match->confirmed = TRUE; */
stop_te_timer(shutdown->timer);
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);
if(op_match) {
xmlXPathFreeObject(op_match);
}
crm_free(rsc_op_xpath);
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: %s (%d)", call_id, (char*)userdata, stonith_error2string(rc), rc);
if(AM_I_DC == FALSE) {
return;
}
/* 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) {
const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
const char *uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);
crm_info("Stonith of %s passed", target);
send_stonith_update(action, target, uuid);
} 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("Fencing update %d for %s: failed - %s (%d)",
call_id, (char*)user_data, cib_error2string(rc), rc);
crm_log_xml_warn(msg, "Failed update");
abort_transition(INFINITY, tg_shutdown, "CIB update failed", NULL);
} else {
crm_info("Fencing update %d for %s: complete", call_id, (char*)user_data);
}
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);
/* Don't check the FSA state
*
* We might also be in S_INTEGRATION or some other state waiting for this
* action so we can close the transition and continue
*/
} 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;
}
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/tengine.c b/crmd/tengine.c
index fce326afb6..81776be73e 100644
--- a/crmd/tengine.c
+++ b/crmd/tengine.c
@@ -1,246 +1,240 @@
/*
* 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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)
{
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;
+ crm_err("Could not unset CIB notification callback");
}
clear_bit_inplace(fsa_input_register, te_subsystem->flag_connected);
crm_info("Transitioner is now inactive");
}
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(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) {
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
|| (fsa_state != S_TRANSITION_ENGINE && (action & A_TE_INVOKE))) {
crm_notice("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;
}
if(fsa_pe_ref == NULL || safe_str_neq(fsa_pe_ref, ref)) {
crm_info("Transition is redundant: %s vs. %s", crm_str(fsa_pe_ref), crm_str(ref));
abort_transition(INFINITY, tg_restart, "Transition Redundant", NULL);
}
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);
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Oct 16, 12:23 AM (22 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2530834
Default Alt Text
(30 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment