tengine.c
来自「linux集群服务器软件代码包」· C语言 代码 · 共 606 行
C
606 行
/* $Id: tengine.c,v 1.46 2005/02/19 18:11:04 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/msg.h>#include <crm/common/xml.h>#include <tengine.h>#include <heartbeat.h>#include <clplumbing/Gmain_timeout.h>#include <lrm/lrm_api.h>gboolean graph_complete = FALSE;GListPtr graph = NULL;IPC_Channel *crm_ch = NULL;uint transition_timeout = 30*1000; /* 30 seconds */uint transition_fuzz_timeout = 0;uint default_transition_timeout = 30*1000; /* 30 seconds */uint next_transition_timeout = 30*1000; /* 30 seconds */void fire_synapse(synapse_t *synapse);gboolean initiate_action(action_t *action);gboolean confirm_synapse(synapse_t *synapse, int action_id);void check_synapse_triggers(synapse_t *synapse, int action_id);gboolean in_transition = FALSE;te_timer_t *transition_timer = NULL;te_timer_t *transition_fuzz_timer = NULL;int transition_counter = 1;gbooleaninitialize_graph(void){ if(transition_timer == NULL) { crm_malloc(transition_timer, sizeof(te_timer_t)); transition_timer->timeout = 10; transition_timer->source_id = -1; transition_timer->reason = timeout_timeout; transition_timer->action = NULL; } else { stop_te_timer(transition_timer); } if(transition_fuzz_timer == NULL) { crm_malloc(transition_fuzz_timer, sizeof(te_timer_t)); transition_fuzz_timer->timeout = 10; transition_fuzz_timer->source_id = -1; transition_fuzz_timer->reason = timeout_fuzz; transition_fuzz_timer->action = NULL; } else { stop_te_timer(transition_fuzz_timer); } while(g_list_length(graph) > 0) { synapse_t *synapse = g_list_nth_data(graph, 0); while(g_list_length(synapse->actions) > 0) { action_t *action = g_list_nth_data(synapse->actions,0); synapse->actions = g_list_remove( synapse->actions, action); if(action->timer->source_id > 0) { crm_devel("Removing timer for action: %d", action->id); g_source_remove(action->timer->source_id); } free_xml(action->xml); crm_free(action->timer); crm_free(action); } while(g_list_length(synapse->inputs) > 0) { action_t *action = g_list_nth_data(synapse->inputs, 0); synapse->inputs = g_list_remove(synapse->inputs, action); free_xml(action->xml); crm_free(action); } graph = g_list_remove(graph, synapse); crm_free(synapse); } graph = NULL; return TRUE;}/* * returns the ID of the action if a match is found * returns -1 if a match was not found * returns -2 if a match was found but the action failed (and was * not allowed to) */intmatch_graph_event(action_t *action, crm_data_t *event){ const char *allow_fail = NULL; const char *this_action = NULL; const char *this_node = NULL; const char *this_rsc = NULL; const char *event_node; const char *event_rsc; const char *rsc_state; const char *event_action; const char *event_rc; const char *op_status; action_t *match = NULL; int op_status_i = -3; if(event == NULL) { crm_trace("Ignoring NULL event"); return -1; } event_node = crm_element_value(event, XML_LRM_ATTR_TARGET); event_action = crm_element_value(event, XML_LRM_ATTR_LASTOP); event_rsc = crm_element_value(event, XML_ATTR_ID); event_rc = crm_element_value(event, XML_LRM_ATTR_RC); rsc_state = crm_element_value(event, XML_LRM_ATTR_RSCSTATE); op_status = crm_element_value(event, XML_LRM_ATTR_OPSTATUS); if(op_status != NULL) { op_status_i = atoi(op_status); } this_action = crm_element_value(action->xml, XML_LRM_ATTR_TASK); this_node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); this_rsc = crm_element_value(action->xml, XML_LRM_ATTR_RSCID); crm_devel("matching against: <%s task=%s node=%s rsc_id=%s/>", crm_element_name(action->xml), this_action, this_node, this_rsc); if(safe_str_neq(this_node, event_node)) { crm_devel("node mismatch: %s", event_node); } else if(safe_str_neq(this_action, event_action)) { crm_devel("action mismatch: %s", event_action); } else if(safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_RSC_OP)) { crm_devel(XML_GRAPH_TAG_RSC_OP); if(safe_str_eq(this_rsc, event_rsc)) { match = action; } else { crm_devel("bad rsc (%s) != (%s)", this_rsc, event_rsc); } } else if(safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_CRM_EVENT)) { crm_devel(XML_GRAPH_TAG_CRM_EVENT); match = action; } else { crm_devel("no match"); } if(match == NULL) { crm_devel("didnt match current action"); return -1; } crm_devel("matched"); /* stop this event's timer if it had one */ stop_te_timer(match->timer); /* Process OP status */ allow_fail = crm_element_value(match->xml, "allow_fail"); switch(op_status_i) { case LRM_OP_DONE: break; case LRM_OP_ERROR: case LRM_OP_TIMEOUT: case LRM_OP_NOTSUPPORTED: if(safe_str_neq(allow_fail, XML_BOOLEAN_TRUE)) { crm_err("Action %s to %s on %s resulted in" " failure... aborting transition.", event_action, event_rsc, event_node); send_abort("Action failed", match->xml); return -2; } break; case LRM_OP_CANCELLED: /* do nothing?? */ crm_warn("Dont know what to do for cancelled ops yet"); break; default: crm_err("Unsupported action result: %d", op_status_i); send_abort("Unsupport action result", match->xml); return -2; } crm_devel("Action %d was successful, looking for next action", match->id); match->complete = TRUE; return match->id;}gbooleanprocess_graph_event(crm_data_t *event){ int action_id = -1; int op_status_i = 0; const char *op_status = NULL; if(event != NULL) { op_status = crm_element_value(event, XML_LRM_ATTR_OPSTATUS); } next_transition_timeout = transition_timeout; if(op_status != NULL) { op_status_i = atoi(op_status); } if(op_status_i == -1) { /* just information that the action was sent */ crm_trace("Ignoring TE initiated updates"); return TRUE; } slist_iter( synapse, synapse_t, graph, lpc, /* lookup event */ slist_iter( action, action_t, synapse->actions, lpc2, action_id = match_graph_event(action, event); if(action_id != -1) { break; } ); if(action_id != -1) { break; } ); if(event == NULL) { crm_debug("a transition is starting"); } else if(action_id > -1) { crm_xml_devel(event, "Event found"); } else if(action_id == -2) { crm_xml_info(event, "Event found but failed"); } else { /* unexpected event, trigger a pe-recompute */ /* possibly do this only for certain types of actions */ send_abort("Event not matched", event); return FALSE; } process_trigger(action_id); check_for_completion(); return TRUE;}voidcheck_for_completion(void){ if(graph_complete) { /* allow some slack until we are pretty sure nothing * else is happening */ crm_info("Transition complete"); if(transition_fuzz_timer->timeout > 0) { crm_info("Allowing the system to stabilize for %d ms" " before S_IDLE transition", transition_fuzz_timer->timeout); start_te_timer(transition_fuzz_timer); } else { send_success("complete"); } } else { /* restart the transition timer again */ crm_devel("Transition not yet complete"); print_state(LOG_DEV); transition_timer->timeout = next_transition_timeout; start_te_timer(transition_timer); }}gbooleaninitiate_action(action_t *action) { gboolean ret = FALSE; const char *on_node = NULL; const char *id = NULL; const char *task = NULL; const char *timeout = NULL; const char *destination = NULL; const char *msg_task = XML_GRAPH_TAG_RSC_OP; crm_data_t *rsc_op = NULL; on_node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); id = crm_element_value(action->xml, XML_ATTR_ID); task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); timeout = crm_element_value(action->xml, XML_ATTR_TIMEOUT); if(id == NULL || strlen(id) == 0 || task == NULL || strlen(task) == 0) { /* error */ crm_err("Failed on corrupted command: %s (id=%s) %s", crm_element_name(action->xml), crm_str(id), crm_str(task)); } else if(action->type == action_type_pseudo){ crm_info("Executing pseudo-event (%d): " "%s on %s", action->id, task, on_node); action->complete = TRUE; process_trigger(action->id); ret = TRUE; } else if(action->type == action_type_crm && safe_str_eq(task, XML_CIB_ATTR_STONITH)){ /* <args target="node1"/> */ stonith_ops_t * st_op = NULL; crm_data_t *action_args = find_xml_node( action->xml, "args", TRUE); const char *target = crm_element_value(action_args, "target"); crm_malloc(st_op, sizeof(stonith_ops_t)); st_op->optype = RESET; st_op->timeout = crm_atoi(timeout, "10"); /* one second */ st_op->node_name = crm_strdup(target);#ifdef TESTING ret = TRUE;#else if (ST_OK == stonithd_node_fence( st_op )) { ret = TRUE; }#endif } else if(on_node == NULL || strlen(on_node) == 0) { /* error */ crm_err("Failed on corrupted command: %s (id=%s) %s on %s", crm_element_name(action->xml), crm_str(id), crm_str(task), crm_str(on_node)); } else if(action->type == action_type_crm){ /* <crm_msg op=XML_LRM_ATTR_TASK to=XML_RES_ATTR_TARGET> */ crm_info("Executing crm-event (%s): %s on %s", id, task, on_node); action->complete = TRUE; destination = CRM_SYSTEM_CRMD; msg_task = task; ret = TRUE; } else if(action->type == action_type_rsc){ crm_data_t *rsc = find_xml_node( action->xml, XML_CIB_TAG_RESOURCE, TRUE); crm_info("Executing rsc-op (%s): %s %s on %s", id, task, crm_element_value(rsc, XML_ATTR_ID), on_node); /* let everyone know this was invoked */ do_update_cib(action->xml, -1); /* <msg_data> <rsc_op id="operation number" on_node="" task=""> <resource>...</resource> */ rsc_op = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP); set_xml_property_copy(rsc_op, XML_ATTR_ID, id); set_xml_property_copy(rsc_op, XML_LRM_ATTR_TASK, task); set_xml_property_copy(rsc_op, XML_LRM_ATTR_TARGET, on_node); add_node_copy(rsc_op, rsc); destination = CRM_SYSTEM_LRMD; ret = TRUE; } else { crm_err("Failed on unsupported command type: " "%s, %s (id=%s) on %s", crm_element_name(action->xml), task, id, on_node); } if(ret) { HA_Message *cmd = NULL; char *counter = crm_itoa(transition_counter); if(rsc_op != NULL) { crm_xml_debug(rsc_op, "Performing"); } cmd = create_request(msg_task, rsc_op, on_node, destination, CRM_SYSTEM_TENGINE, NULL); ha_msg_add(cmd, "transition_id", crm_str(counter));#ifndef TESTING send_ipc_message(crm_ch, cmd);#else cl_log_message(LOG_DEBUG, cmd);#endif crm_free(counter); if(action->timeout > 0) { crm_devel("Setting timer for action %d",action->id); start_te_timer(action->timer); } } free_xml(rsc_op); return ret;}gbooleaninitiate_transition(void){ crm_info("Initating transition"); process_graph_event(NULL); return TRUE;}voidcheck_synapse_triggers(synapse_t *synapse, int action_id){ synapse->triggers_complete = TRUE; if(synapse->confirmed) { crm_devel("Skipping confirmed synapse %d", synapse->id); return; } else if(synapse->complete == FALSE) { crm_devel("Checking pre-reqs for %d", synapse->id); /* lookup prereqs */ slist_iter( prereq, action_t, synapse->inputs, lpc, crm_devel("Processing input %d", prereq->id); if(prereq->id == action_id) { crm_devel("Marking input %d complete", action_id); prereq->complete = TRUE; } else if(prereq->complete == FALSE) { crm_devel("Inputs for synapse %d not satisfied", synapse->id); synapse->triggers_complete = FALSE; } ); }}voidfire_synapse(synapse_t *synapse) { if(synapse == NULL) { crm_err("Synapse was NULL!"); return; } crm_devel("Checking if synapse %d needs to be fired", synapse->id); if(synapse->complete) { crm_devel("Skipping complete synapse %d", synapse->id); return; } else if(synapse->triggers_complete == FALSE) { crm_devel("Synapse %d not yet satisfied", synapse->id); return; } crm_devel("All inputs for synapse %d satisfied... invoking actions", synapse->id); synapse->complete = TRUE; slist_iter( action, action_t, synapse->actions, lpc, /* allow some leway */ int tmp_time = 2 * action->timeout; gboolean passed = FALSE; action->invoked = TRUE; /* Invoke the action and start the timer */ passed = initiate_action(action); if(passed == FALSE) { crm_err("Failed initiating <%s id=%d> in synapse %d", crm_element_name(action->xml), action->id, synapse->id); send_abort("Action init failed", action->xml); return; } if(tmp_time > next_transition_timeout) { next_transition_timeout = tmp_time; } ); crm_debug("Synapse %d complete", synapse->id);}gbooleanconfirm_synapse(synapse_t *synapse, int action_id) { gboolean complete = TRUE; synapse->confirmed = TRUE; slist_iter( action, action_t, synapse->actions, lpc, if(action->type == action_type_rsc && action->complete == FALSE) { complete = FALSE; synapse->confirmed = FALSE; crm_devel("Found an incomplete action" " - transition not complete"); break; } ); return complete;}voidprocess_trigger(int action_id) { graph_complete = TRUE; crm_devel("Processing trigger from action %d", action_id); /* something happened, stop the timer and start it again at the end */ stop_te_timer(transition_timer); slist_iter( synapse, synapse_t, graph, lpc, if(synapse->confirmed) { crm_devel("Skipping confirmed synapse %d", synapse->id); continue; } check_synapse_triggers(synapse, action_id); fire_synapse(synapse); if(graph == NULL) { crm_err("Trigger processing aborted after failed synapse"); break; } crm_devel("Checking if %d is confirmed", synapse->id); if(synapse->complete == FALSE) { crm_devel("Found an incomplete synapse" " - transition not complete"); /* indicate that the transition is not yet complete */ graph_complete = FALSE; } else if(synapse->confirmed == FALSE) { graph_complete = graph_complete && confirm_synapse(synapse, action_id); } crm_devel("%d is %s", synapse->id, synapse->confirmed?"confirmed":synapse->complete?"complete":"pending"); );}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?