diff --git a/crm/crmd/tengine.c b/crm/crmd/tengine.c index e80a5b4818..c41784c678 100644 --- a/crm/crmd/tengine.c +++ b/crm/crmd/tengine.c @@ -1,188 +1,194 @@ /* * Copyright (C) 2004 Andrew Beekhof * * 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 #include #include #include #include #include #include /* for access */ #include #include #include /* for calls to open */ #include /* for calls to open */ #include /* for calls to open */ #include /* for getpwuid */ #include /* for initgroups */ #include /* for getrlimit */ #include /* for getrlimit */ #include #include #include #include #include #include #include #include struct crm_subsystem_s *te_subsystem = NULL; /* A_TE_START, A_TE_STOP, A_TE_RESTART */ enum crmd_fsa_input 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) { enum crmd_fsa_input result = I_NULL; struct crm_subsystem_s *this_subsys = te_subsystem; long long stop_actions = A_TE_STOP; long long start_actions = A_TE_START; /* if(action & stop_actions && cur_state != S_STOPPING */ /* && is_set(fsa_input_register, R_TE_PEND)) { */ /* result = I_WAIT_FOR_EVENT; */ /* return result; */ /* } */ if(action & stop_actions) { stop_subsystem(this_subsys, FALSE); } if(action & start_actions) { if(cur_state != S_STOPPING) { if(start_subsystem(this_subsys) == FALSE) { register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); } } else { crm_info("Ignoring request to start %s while shutting down", this_subsys->name); } } return result; } /* A_TE_INVOKE, A_TE_CANCEL */ enum crmd_fsa_input 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) { enum crmd_fsa_input ret = I_NULL; HA_Message *cmd = NULL; if(AM_I_DC == FALSE) { crm_debug("Not DC: No need to invoke the TE (anymore): %s", fsa_action2string(action)); return I_NULL; } else if(fsa_state != S_TRANSITION_ENGINE && (action & A_TE_INVOKE)) { crm_debug("No need to invoke the TE (%s) in state %s", fsa_action2string(action), fsa_state2string(fsa_state)); return I_NULL; } else if(is_set(fsa_input_register, R_TE_CONNECTED) == FALSE) { if(te_subsystem->pid > 0) { int pid_status = -1; int rc = waitpid( te_subsystem->pid, &pid_status, WNOHANG); if(rc > 0 && WIFEXITED(pid_status)) { clear_bit_inplace(fsa_input_register, te_subsystem->flag_connected); if(is_set(fsa_input_register, te_subsystem->flag_required)) { /* this wasnt supposed to happen */ crm_err("%s[%d] terminated during start", te_subsystem->name, te_subsystem->pid); register_fsa_error( C_FSA_INTERNAL, I_ERROR, NULL); } te_subsystem->pid = -1; return I_NULL; } } crm_info("Waiting for the TE to connect before action %s", fsa_action2string(action)); if(action & A_TE_INVOKE) { register_fsa_input( msg_data->fsa_cause, msg_data->fsa_input, msg_data->data); } crmd_fsa_stall(NULL); return I_NULL; } if(action & A_TE_INVOKE) { ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); - if(input->xml != NULL) { + const char *graph_file = cl_get_string(input->msg, F_CRM_TGRAPH); + const char *graph_input = cl_get_string(input->msg, F_CRM_TGRAPH_INPUT); + if(graph_file != NULL) { + crm_debug("Starting a transition"); set_bit_inplace(fsa_input_register, R_IN_TRANSITION); cmd = create_request( - CRM_OP_TRANSITION, input->xml, NULL, + CRM_OP_TRANSITION, NULL, NULL, CRM_SYSTEM_TENGINE, CRM_SYSTEM_DC, NULL); + + ha_msg_add(cmd, F_CRM_TGRAPH, graph_file); + ha_msg_add(cmd, F_CRM_TGRAPH_INPUT, graph_input); send_request(cmd, NULL); } else { register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); } } else if(action & A_TE_CANCEL) { crm_debug("Cancelling the active Transition"); cmd = create_request( CRM_OP_TEABORT, NULL, NULL, CRM_SYSTEM_TENGINE, CRM_SYSTEM_DC, NULL); send_request(cmd, NULL); } else if(action & A_TE_HALT) { cmd = create_request( CRM_OP_TE_HALT, NULL, NULL, CRM_SYSTEM_TENGINE, CRM_SYSTEM_DC, NULL); send_request(cmd, NULL); } return ret; } diff --git a/crm/pengine/pengine.c b/crm/pengine/pengine.c index dfb18123db..8b8e28c702 100755 --- a/crm/pengine/pengine.c +++ b/crm/pengine/pengine.c @@ -1,291 +1,304 @@ -/* $Id: pengine.c,v 1.116 2006/06/13 09:39:05 andrew Exp $ */ +/* $Id: pengine.c,v 1.117 2006/06/23 08:33:53 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 #include #include #include #include #include #include #include #include #include #include #include crm_data_t * do_calculations( pe_working_set_t *data_set, crm_data_t *xml_input, ha_time_t *now); #define PE_WORKING_DIR HA_VARLIBDIR"/heartbeat/pengine" extern int transition_id; #define get_series() was_processing_error?1:was_processing_warning?2:3 typedef struct series_s { int id; const char *name; const char *param; int wrap; } series_t; series_t series[] = { { 0, "pe-unknown", "_dont_match_anything_", -1 }, { 0, "pe-error", "pe-error-series-max", -1 }, { 0, "pe-warn", "pe-warn-series-max", 200 }, { 0, "pe-input", "pe-input-series-max", 400 }, }; gboolean process_pe_message(HA_Message *msg, crm_data_t * xml_data, IPC_Channel *sender) { const char *sys_to = cl_get_string(msg, F_CRM_SYS_TO); const char *op = cl_get_string(msg, F_CRM_TASK); const char *ref = cl_get_string(msg, XML_ATTR_REFERENCE); crm_debug_3("Processing %s op (ref=%s)...", op, ref); if(op == NULL){ /* error */ } else if(strcasecmp(op, CRM_OP_HELLO) == 0) { /* ignore */ } else if(safe_str_eq(cl_get_string(msg, F_CRM_MSG_TYPE), XML_ATTR_RESPONSE)) { /* ignore */ } else if(sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_PENGINE) != 0) { crm_debug_3("Bad sys-to %s", crm_str(sys_to)); return FALSE; } else if(strcasecmp(op, CRM_OP_PECALC) == 0) { int seq = -1; int series_id = 0; int series_wrap = 0; char *filename = NULL; + char *graph_file = NULL; const char *value = NULL; pe_working_set_t data_set; crm_data_t *generation = create_xml_node(NULL, XML_TAG_CIB); crm_data_t *log_input = copy_xml(xml_data); + HA_Message *reply = NULL; #if HAVE_BZLIB_H gboolean compress = TRUE; #else gboolean compress = FALSE; #endif - copy_in_properties(generation, xml_data); crm_log_xml_info(generation, "[generation]"); was_processing_error = FALSE; was_processing_warning = FALSE; + graph_file = crm_strdup(WORKING_DIR"/graph.XXXXXX"); + mktemp(graph_file); + crm_zero_mem_stats(NULL); do_calculations(&data_set, xml_data, NULL); - crm_log_xml_debug_3(data_set.graph, "[out]"); - if(send_ipc_reply(sender, msg, data_set.graph) == FALSE) { - crm_err("Answer could not be sent"); + crm_info("Writing the TE graph to %s", graph_file); + if(write_xml_file(data_set.graph, graph_file, FALSE) < 0) { + crm_err("TE graph could not be written to disk"); } series_id = get_series(); series_wrap = series[series_id].wrap; value = g_hash_table_lookup( data_set.config_hash, series[series_id].param); if(value != NULL) { series_wrap = crm_int_helper(value, NULL); if(errno != 0) { series_wrap = series[series_id].wrap; } } else { pe_config_warn("No value specified for cluster" " preference: %s", series[series_id].param); - } - + } + data_set.input = NULL; cleanup_alloc_calculations(&data_set); - if(is_ipc_empty(sender) && crm_mem_stats(NULL)) { + if(crm_mem_stats(NULL)) { pe_warn("Unfree'd memory"); } - + seq = get_last_sequence(PE_WORKING_DIR, series[series_id].name); filename = generate_series_filename( PE_WORKING_DIR, series[series_id].name, seq, compress); write_xml_file(log_input, filename, compress); write_last_sequence(PE_WORKING_DIR, series[series_id].name, seq+1, series_wrap); if(was_processing_error) { crm_err("Transition %d:" " ERRORs found during PE processing." " PEngine Input stored in: %s", transition_id, filename); } else if(was_processing_warning) { crm_warn("Transition %d:" " WARNINGs found during PE processing." " PEngine Input stored in: %s", transition_id, filename); } else { crm_info("Transition %d: PEngine Input stored in: %s", transition_id, filename); } if(was_config_error) { crm_info("Configuration ERRORs found during PE processing." " Please run \"crm_verify -L\" to identify issues."); } else if(was_processing_warning) { crm_info("Configuration WARNINGs found during PE processing." " Please run \"crm_verify -L\" to identify issues."); } + reply = create_reply(msg, NULL); + ha_msg_add(reply, F_CRM_TGRAPH, graph_file); + ha_msg_add(reply, F_CRM_TGRAPH_INPUT, filename); + CRM_ASSERT(reply != NULL); + if(send_ipc_message(sender, reply) == FALSE) { + crm_err("Answer could not be sent"); + } + free_xml(generation); + crm_free(graph_file); free_xml(log_input); crm_free(filename); } else if(strcasecmp(op, CRM_OP_QUIT) == 0) { crm_warn("Received quit message, terminating"); exit(0); } return TRUE; } #define MEMCHECK_STAGE_0 0 #define check_and_exit(stage) cleanup_calculations(data_set); \ crm_mem_stats(NULL); \ crm_err("Exiting: stage %d", stage); \ exit(1); crm_data_t * do_calculations(pe_working_set_t *data_set, crm_data_t *xml_input, ha_time_t *now) { int rsc_log_level = LOG_INFO; /* pe_debug_on(); */ set_working_set_defaults(data_set); data_set->input = xml_input; data_set->now = now; if(data_set->now == NULL) { data_set->now = new_ha_date(TRUE); } #if MEMCHECK_STAGE_SETUP check_and_exit(-1); #endif crm_debug_5("unpack constraints"); stage0(data_set); #if MEMCHECK_STAGE_0 check_and_exit(0); #endif slist_iter(rsc, resource_t, data_set->resources, lpc, rsc->fns->print(rsc, NULL, pe_print_log, &rsc_log_level); ); crm_debug_5("apply placement constraints"); stage1(data_set); #if MEMCHECK_STAGE_1 check_and_exit(1); #endif crm_debug_5("color resources"); stage2(data_set); #if MEMCHECK_STAGE_2 check_and_exit(2); #endif /* unused */ stage3(data_set); #if MEMCHECK_STAGE_3 check_and_exit(3); #endif crm_debug_5("assign nodes to colors"); stage4(data_set); #if MEMCHECK_STAGE_4 check_and_exit(4); #endif crm_debug_5("creating actions and internal ording constraints"); stage5(data_set); #if MEMCHECK_STAGE_5 check_and_exit(5); #endif crm_debug_5("processing fencing and shutdown cases"); stage6(data_set); #if MEMCHECK_STAGE_6 check_and_exit(6); #endif crm_debug_5("applying ordering constraints"); stage7(data_set); #if MEMCHECK_STAGE_7 check_and_exit(7); #endif crm_debug_5("creating transition graph"); stage8(data_set); #if MEMCHECK_STAGE_8 check_and_exit(8); #endif crm_debug_2("=#=#=#=#= Summary =#=#=#=#="); crm_debug_2("\t========= Set %d (Un-runnable) =========", -1); crm_action_debug_2( slist_iter(action, action_t, data_set->actions, lpc, if(action->optional == FALSE && action->runnable == FALSE && action->pseudo == FALSE) { log_action(LOG_DEBUG_2, "\t", action, TRUE); } ) ); return data_set->graph; } diff --git a/crm/tengine/callbacks.c b/crm/tengine/callbacks.c index a2e997322d..061dad7bdb 100644 --- a/crm/tengine/callbacks.c +++ b/crm/tengine/callbacks.c @@ -1,559 +1,573 @@ -/* $Id: callbacks.c,v 1.83 2006/06/06 20:59:17 andrew Exp $ */ +/* $Id: callbacks.c,v 1.84 2006/06/23 08:33:53 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 #include #include #include #include #include #include #include #include #include #include void te_update_confirm(const char *event, HA_Message *msg); void te_update_diff(const char *event, HA_Message *msg); crm_data_t *need_abort(crm_data_t *update); void cib_fencing_updated(const HA_Message *msg, int call_id, int rc, crm_data_t *output, void *user_data); extern char *te_uuid; gboolean shuttingdown = FALSE; crm_graph_t *transition_graph; GTRIGSource *transition_trigger = NULL; crm_action_timer_t *transition_timer = NULL; static gboolean start_global_timer(crm_action_timer_t *timer, int timeout) { CRM_ASSERT(timer != NULL); CRM_CHECK(timer > 0, return FALSE); CRM_CHECK(timer->source_id == 0, return FALSE); if(timeout <= 0) { crm_err("Tried to start timer with period: %d", timeout); } else if(timer->source_id == 0) { crm_debug_2("Starting abort timer: %dms", timeout); timer->timeout = timeout; timer->source_id = Gmain_timeout_add( timeout, global_timer_callback, (void*)timer); CRM_ASSERT(timer->source_id != 0); return TRUE; } else { crm_err("Timer is already active with period: %d", timer->timeout); } return FALSE; } void te_update_diff(const char *event, HA_Message *msg) { int rc = -1; const char *op = NULL; crm_data_t *diff = NULL; crm_data_t *aborted = NULL; const char *set_name = 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; if(msg == NULL) { crm_err("NULL update"); return; } ha_msg_value_int(msg, F_CIB_RC, &rc); op = cl_get_string(msg, F_CIB_OPERATION); if(rc < cib_ok) { crm_debug_2("Ignoring failed %s operation: %s", op, cib_error2string(rc)); return; } 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_info("Processing diff (%s): %d.%d.%d -> %d.%d.%d", op, diff_del_admin_epoch,diff_del_epoch,diff_del_updates, diff_add_admin_epoch,diff_add_epoch,diff_add_updates); log_cib_diff(LOG_DEBUG_2, diff, op); set_name = "diff-added"; if(diff != NULL) { crm_data_t *section = NULL; crm_data_t *change_set = find_xml_node(diff, set_name, FALSE); change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE); if(change_set != NULL) { crm_debug_2("Checking status changes"); section=get_object_root(XML_CIB_TAG_STATUS,change_set); } if(section != NULL) { extract_event(section); } crm_debug_2("Checking change set: %s", set_name); aborted = need_abort(change_set); } set_name = "diff-removed"; if(diff != NULL && aborted == NULL) { crm_data_t *attrs = NULL; crm_data_t *status = NULL; crm_data_t *change_set = find_xml_node(diff, set_name, FALSE); change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE); crm_debug_2("Checking change set: %s", set_name); aborted = need_abort(change_set); if(aborted == NULL && change_set != NULL) { status = get_object_root(XML_CIB_TAG_STATUS, change_set); xml_child_iter_filter( status, node_state, XML_CIB_TAG_STATE, attrs = find_xml_node( node_state, XML_TAG_TRANSIENT_NODEATTRS, FALSE); if(attrs != NULL) { crm_info("Aborting on "XML_TAG_TRANSIENT_NODEATTRS" deletions"); abort_transition(INFINITY, tg_restart, XML_TAG_TRANSIENT_NODEATTRS, attrs); } ); } } if(aborted != NULL) { abort_transition( INFINITY, tg_restart, "Non-status change", NULL); } free_xml(diff); return; } gboolean process_te_message(HA_Message *msg, crm_data_t *xml_data, IPC_Channel *sender) { crm_data_t *xml_obj = NULL; const char *from = cl_get_string(msg, F_ORIG); const char *sys_to = cl_get_string(msg, F_CRM_SYS_TO); const char *sys_from = cl_get_string(msg, F_CRM_SYS_FROM); const char *ref = cl_get_string(msg, XML_ATTR_REFERENCE); const char *op = cl_get_string(msg, F_CRM_TASK); const char *type = cl_get_string(msg, F_CRM_MSG_TYPE); crm_debug_2("Processing %s (%s) message", op, ref); crm_log_message(LOG_DEBUG_3, msg); if(op == NULL){ /* error */ } else if(strcasecmp(op, CRM_OP_HELLO) == 0) { /* ignore */ } 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) */ ){ #if CRM_DEPRECATED_SINCE_2_0_4 if(safe_str_eq(crm_element_name(xml_data), XML_TAG_CIB)) { xml_obj = xml_data; } else { xml_obj = find_xml_node(xml_data, XML_TAG_CIB, TRUE); } #else xml_obj = xml_data; CRM_CHECK(xml_obj != NULL, crm_log_message_adv(LOG_ERR, "Invalid (N)ACK", msg); return FALSE); #endif CRM_CHECK(xml_obj != NULL, crm_log_message_adv(LOG_ERR, "Invalid (N)ACK", msg); return FALSE); xml_obj = get_object_root(XML_CIB_TAG_STATUS, xml_obj); CRM_CHECK(xml_obj != NULL, crm_log_message_adv(LOG_ERR, "Invalid (N)ACK", msg); return FALSE); crm_log_message_adv(LOG_DEBUG_2, "Processing (N)ACK", msg); crm_debug("Processing (N)ACK from %s", from); extract_event(xml_obj); } else if(safe_str_eq(type, XML_ATTR_RESPONSE)) { crm_err("Message was a response not a request. Discarding"); return TRUE; } else if(strcasecmp(op, CRM_OP_TRANSITION) == 0) { + const char *graph_file = cl_get_string(msg, F_CRM_TGRAPH); +/* const char *graph_input = cl_get_string(msg, F_CRM_TGRAPH_INPUT); */ + CRM_CHECK(graph_file != NULL, crm_err("No graph filename provided"); return TRUE); + if(transition_graph->complete == FALSE) { crm_info("Another transition is already active"); abort_transition( INFINITY,tg_restart,"Transition Active",NULL); } else { + FILE *graph_fd = fopen(graph_file, "r"); + crm_data_t *graph_data = file2xml(graph_fd); + CRM_CHECK(graph_fd != NULL, + crm_err("Could not open graph filename: %s", graph_file); + return TRUE); + destroy_graph(transition_graph); - transition_graph = unpack_graph(xml_data); + crm_debug("Read graph from: %s", graph_file); + transition_graph = unpack_graph(graph_data); start_global_timer(transition_timer, transition_graph->transition_timeout); trigger_graph(); print_graph(LOG_DEBUG_2, transition_graph); + fclose(graph_fd); + free_xml(graph_data); } - + unlink(graph_file); + } else if(strcasecmp(op, CRM_OP_TE_HALT) == 0) { abort_transition(INFINITY, tg_stop, "Peer Halt", NULL); } else if(strcasecmp(op, CRM_OP_TEABORT) == 0) { abort_transition(INFINITY, tg_restart, "Peer Cancelled", NULL); } 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_ops_t * op) { const char *allow_fail = NULL; int stonith_id = -1; crm_action_t *stonith_action = NULL; char *op_key = NULL; char *call_id = NULL; if(op == NULL) { crm_err("Called with a NULL op!"); 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); /* this will mark the event complete if a match is found */ CRM_CHECK(op->private_data != NULL, return); /* filter out old STONITH actions */ decodeNVpair(op->private_data, ';', &call_id, &op_key); if(op_key != NULL) { char *key = generate_transition_key( transition_graph->id, te_uuid); gboolean key_matched = safe_str_eq(key, op_key); crm_free(key); if(key_matched == FALSE) { crm_info("Ignoring old STONITH op: %s", op->private_data); return; } } #if 1 stonith_id = crm_parse_int(call_id, "-1"); if(stonith_id < 0) { crm_err("Stonith action not matched: %s (%s)", call_id, op->private_data); return; } #endif stonith_action = match_down_event( stonith_id, op->node_uuid, CRM_OP_FENCE); if(stonith_action == NULL) { crm_err("Stonith action not matched"); return; } switch(op->op_result) { case STONITH_SUCCEEDED: send_stonith_update(op); break; case STONITH_CANNOT: case STONITH_TIMEOUT: case STONITH_GENERIC: stonith_action->failed = TRUE; allow_fail = g_hash_table_lookup( stonith_action->params, crm_meta_name(XML_ATTR_TE_ALLOWFAIL)); if(FALSE == crm_is_true(allow_fail)) { crm_err("Stonith of %s failed (%d)..." " aborting transition.", op->node_name, op->op_result); abort_transition(INFINITY, tg_restart, "Stonith failed", NULL); } break; default: crm_err("Unsupported action result: %d", op->op_result); abort_transition(INFINITY, tg_restart, "Unsupport Stonith result", NULL); } update_graph(transition_graph, stonith_action); trigger_graph(); return; } void tengine_stonith_connection_destroy(gpointer user_data) { #if 0 crm_err("Fencing daemon has left us: Shutting down...NOW"); /* shutdown properly later */ CRM_CHECK(FALSE/* fencing daemon died */); #else crm_err("Fencing daemon has left us"); #endif return; } gboolean tengine_stonith_dispatch(IPC_Channel *sender, void *user_data) { int lpc = 0; while(stonithd_op_result_ready()) { if (sender->ch_status == IPC_DISCONNECT) { /* The message which was pending for us is that * the IPC status is now IPC_DISCONNECT */ break; } if(ST_FAIL == stonithd_receive_ops_result(FALSE)) { crm_err("stonithd_receive_ops_result() failed"); } else { lpc++; } } crm_debug_2("Processed %d messages", lpc); if (sender->ch_status == IPC_DISCONNECT) { return FALSE; } return TRUE; } void cib_fencing_updated(const HA_Message *msg, int call_id, int rc, crm_data_t *output, void *user_data) { trigger_graph(); if(rc < cib_ok) { crm_err("CIB update failed: %s", cib_error2string(rc)); crm_log_xml_warn(msg, "[Failed Update]"); } } void cib_action_updated(const HA_Message *msg, int call_id, int rc, crm_data_t *output, void *user_data) { trigger_graph(); 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; if(data == NULL) { crm_err("Timer popped with no data"); return FALSE; } timer = (crm_action_timer_t*)data; stop_te_timer(timer); crm_warn("Timer popped (abort_level=%d, complete=%s)", transition_graph->abort_priority, transition_graph->complete?"true":"false"); CRM_CHECK(timer->action != NULL, return FALSE); if(transition_graph->complete) { crm_err("Ignoring timeout while not in transition"); } else if(timer->reason == timeout_action_warn) { print_action( LOG_WARNING,"Action missed its timeout", timer->action); } else { /* fail the action */ cib_action_update(timer->action, LRM_OP_TIMEOUT); } return FALSE; } static int unconfirmed_actions(gboolean send_updates) { int unconfirmed = 0; const char *task = NULL; crm_debug_2("Unconfirmed actions..."); slist_iter( synapse, synapse_t, transition_graph->synapses, lpc, /* lookup event */ slist_iter( action, crm_action_t, synapse->actions, lpc2, if(action->executed == FALSE) { continue; } else if(action->confirmed) { continue; } unconfirmed++; crm_debug("Action %d: unconfirmed",action->id); task = crm_element_value(action->xml,XML_LRM_ATTR_TASK); if(action->type != action_type_rsc) { continue; } else if(send_updates == FALSE) { continue; } else if(safe_str_eq(task, "cancel")) { /* we dont need to update the CIB with these */ continue; } cib_action_update(action, LRM_OP_PENDING); ); ); if(unconfirmed > 0) { crm_info("Waiting on %d unconfirmed actions", unconfirmed); } return unconfirmed; } gboolean global_timer_callback(gpointer data) { crm_action_timer_t *timer = NULL; if(data == NULL) { crm_err("Timer popped with no data"); return FALSE; } timer = (crm_action_timer_t*)data; stop_te_timer(timer); crm_warn("Timer popped (abort_level=%d, complete=%s)", transition_graph->abort_priority, transition_graph->complete?"true":"false"); CRM_CHECK(timer->action == NULL, return FALSE); if(transition_graph->complete) { crm_err("Ignoring timeout while not in transition"); } else if(timer->reason == timeout_abort) { int unconfirmed = unconfirmed_actions(FALSE); crm_warn("Transition abort timeout reached..." " marking transition complete."); transition_graph->complete = TRUE; abort_transition(INFINITY, tg_restart, "Global Timeout", NULL); if(unconfirmed != 0) { crm_warn("Writing %d unconfirmed actions to the CIB", unconfirmed); unconfirmed_actions(TRUE); } } return FALSE; } gboolean te_graph_trigger(gpointer user_data) { int timeout = 0; enum transition_status graph_rc = -1; if(transition_graph->complete) { notify_crmd(transition_graph); return TRUE; } graph_rc = run_graph(transition_graph); timeout = transition_graph->transition_timeout; print_graph(LOG_DEBUG_3, transition_graph); if(graph_rc == transition_active) { crm_debug_3("Transition not yet complete"); stop_te_timer(transition_timer); start_global_timer(transition_timer, timeout); return TRUE; } else if(graph_rc == transition_pending) { timeout = transition_timer->timeout; 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); } transition_graph->complete = TRUE; notify_crmd(transition_graph); return TRUE; } diff --git a/include/crm/msg_xml.h b/include/crm/msg_xml.h index 4ca5b8da1f..18635b2051 100644 --- a/include/crm/msg_xml.h +++ b/include/crm/msg_xml.h @@ -1,258 +1,260 @@ -/* $Id: msg_xml.h,v 1.55 2006/06/02 15:52:13 andrew Exp $ */ +/* $Id: msg_xml.h,v 1.56 2006/06/23 08:33:53 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 XML_TAGS__H #define XML_TAGS__H #define F_CRM_TASK "crm_task" #define F_CRM_HOST_TO "crm_host_to" #define F_CRM_MSG_TYPE F_SUBTYPE #define F_CRM_SYS_TO "crm_sys_to" #define F_CRM_SYS_FROM "crm_sys_from" #define F_CRM_HOST_FROM F_ORIG #define F_CRM_REFERENCE XML_ATTR_REFERENCE #define F_CRM_VERSION XML_ATTR_VERSION #define F_CRM_ORIGIN "origin" #define F_CRM_JOIN_ID "join_id" #define F_CRM_ELECTION_ID "election-id" #define F_CRM_ELECTION_OWNER "election-owner" +#define F_CRM_TGRAPH "crm-tgraph" +#define F_CRM_TGRAPH_INPUT "crm-tgraph-in" /*---- Common tags/attrs */ #define XML_DIFF_MARKER "__crm_diff_marker__" #define XML_ATTR_TAGNAME F_XML_TAGNAME #define XML_ATTR_PARENT F_XML_PARENT #define XML_TAG_CIB "cib" #define XML_TAG_FAILED "failed" #define XML_ATTR_CRM_VERSION "crm_feature_set" #define XML_ATTR_NUMPEERS "num_peers" #define XML_ATTR_HAVE_QUORUM "have_quorum" #define XML_ATTR_CCM_TRANSITION "ccm_transition" #define XML_ATTR_GENERATION "epoch" #define XML_ATTR_GENERATION_ADMIN "admin_epoch" #define XML_ATTR_NUMUPDATES "num_updates" #define XML_ATTR_TIMEOUT "timeout" #define XML_ATTR_ORIGIN "crm-debug-origin" #define XML_ATTR_TSTAMP "crm-timestamp" #define XML_CIB_ATTR_WRITTEN "cib-last-written" #define XML_ATTR_VERSION "version" #define XML_ATTR_DESC "description" #define XML_ATTR_ID "id" #define XML_ATTR_ID_LONG "long-id" #define XML_ATTR_TYPE "type" #define XML_ATTR_FILTER_TYPE "type_filter" #define XML_ATTR_FILTER_ID "id_filter" #define XML_ATTR_FILTER_PRIORITY "priority_filter" #define XML_ATTR_VERBOSE "verbose" #define XML_ATTR_OP "op" #define XML_ATTR_DC "is_dc" #define XML_ATTR_DC_UUID "dc_uuid" #define XML_ATTR_CIB_REVISION "cib_feature_revision" #define XML_ATTR_CIB_REVISION_MAX "cib_feature_revision_max" #define XML_BOOLEAN_TRUE "true" #define XML_BOOLEAN_FALSE "false" #define XML_BOOLEAN_YES XML_BOOLEAN_TRUE #define XML_BOOLEAN_NO XML_BOOLEAN_FALSE #define XML_TAG_OPTIONS "options" /*---- top level tags/attrs */ #define XML_MSG_TAG "crm_message" #define XML_MSG_TAG_DATA "msg_data" #define XML_ATTR_REQUEST "request" #define XML_ATTR_RESPONSE "response" #define XML_ATTR_UNAME "uname" #define XML_ATTR_UUID "id" #define XML_ATTR_REFERENCE "reference" #define XML_FAIL_TAG_RESOURCE "failed_resource" #define XML_FAILRES_ATTR_RESID "resource_id" #define XML_FAILRES_ATTR_REASON "reason" #define XML_FAILRES_ATTR_RESSTATUS "resource_status" #define XML_CRM_TAG_PING "ping_response" #define XML_PING_ATTR_STATUS "result" #define XML_PING_ATTR_SYSFROM "crm_subsystem" #define XML_TAG_FRAGMENT "cib_fragment" #define XML_ATTR_RESULT "result" #define XML_ATTR_SECTION "section" #define XML_FAIL_TAG_CIB "failed_update" #define XML_FAILCIB_ATTR_ID "id" #define XML_FAILCIB_ATTR_OBJTYPE "object_type" #define XML_FAILCIB_ATTR_OP "operation" #define XML_FAILCIB_ATTR_REASON "reason" /*---- CIB specific tags/attrs */ #define XML_CIB_TAG_SECTION_ALL "all" #define XML_CIB_TAG_CONFIGURATION "configuration" #define XML_CIB_TAG_STATUS "status" #define XML_CIB_TAG_RESOURCES "resources" #define XML_CIB_TAG_NODES "nodes" #define XML_CIB_TAG_CONSTRAINTS "constraints" #define XML_CIB_TAG_CRMCONFIG "crm_config" #define XML_CIB_TAG_STATE "node_state" #define XML_CIB_TAG_NODE "node" #define XML_CIB_TAG_CONSTRAINT "constraint" #define XML_CIB_TAG_NVPAIR "nvpair" #define XML_CIB_TAG_PROPSET "cluster_property_set" #define XML_TAG_ATTR_SETS "instance_attributes" #define XML_TAG_META_SETS "meta_attributes" #define XML_TAG_ATTRS "attributes" #define XML_TAG_PARAMS "parameters" #define XML_CIB_TAG_RESOURCE "primitive" #define XML_CIB_TAG_GROUP "group" #define XML_CIB_TAG_INCARNATION "clone" #define XML_CIB_TAG_MASTER "master_slave" #define XML_RSC_ATTR_STOPFAIL "on_stopfail" #define XML_RSC_ATTR_RESTART "restart_type" #define XML_RSC_ATTR_START_TIMEOUT "start_timeout" #define XML_RSC_ATTR_STOP_TIMEOUT "stop_timeout" #define XML_RSC_ATTR_ORDERED "ordered" #define XML_RSC_ATTR_INTERLEAVE "interleave" #define XML_RSC_ATTR_INCARNATION "clone" #define XML_RSC_ATTR_INCARNATION_MAX "clone_max" #define XML_RSC_ATTR_INCARNATION_NODEMAX "clone_node_max" #define XML_RSC_ATTR_MASTER_MAX "master_max" #define XML_RSC_ATTR_MASTER_NODEMAX "master_node_max" #define XML_RSC_ATTR_STATE "clone_state" #define XML_RSC_ATTR_MANAGED "is_managed" #define XML_RSC_ATTR_TARGET_ROLE "target_role" #define XML_RSC_ATTR_UNIQUE "globally_unique" #define XML_RSC_ATTR_NOTIFY "notify" #define XML_RSC_ATTR_STICKINESS "resource_stickiness" #define XML_RSC_ATTR_FAIL_STICKINESS "resource_failure_stickiness" #define XML_RSC_ATTR_MULTIPLE "multiple_active" #define XML_RSC_ATTR_START "start_prereq" #define XML_RSC_ATTR_PRIORITY "priority" #define XML_CIB_TAG_LRM "lrm" #define XML_LRM_TAG_RESOURCES "lrm_resources" #define XML_LRM_TAG_RESOURCE "lrm_resource" #define XML_LRM_TAG_AGENTS "lrm_agents" #define XML_LRM_TAG_AGENT "lrm_agent" #define XML_LRM_TAG_RSC_OP "lrm_rsc_op" #define XML_AGENT_ATTR_CLASS "class" #define XML_AGENT_ATTR_PROVIDER "provider" #define XML_LRM_TAG_ATTRIBUTES "attributes" #define XML_CIB_ATTR_REPLACE "replace" #define XML_CIB_ATTR_SOURCE "source" #define XML_CIB_ATTR_HEALTH "health" #define XML_CIB_ATTR_WEIGHT "weight" #define XML_CIB_ATTR_PRIORITY "priority" #define XML_CIB_ATTR_CLEAR "clear_on" #define XML_CIB_ATTR_SOURCE "source" #define XML_CIB_ATTR_JOINSTATE "join" #define XML_CIB_ATTR_EXPSTATE "expected" #define XML_CIB_ATTR_INCCM "in_ccm" #define XML_CIB_ATTR_CRMDSTATE "crmd" #define XML_CIB_ATTR_HASTATE "ha" #define XML_CIB_ATTR_SHUTDOWN "shutdown" #define XML_CIB_ATTR_STONITH "stonith" #define XML_LRM_ATTR_INTERVAL "interval" #define XML_LRM_ATTR_TASK "operation" #define XML_LRM_ATTR_TASK_KEY "operation_key" #define XML_LRM_ATTR_TARGET "on_node" #define XML_LRM_ATTR_TARGET_UUID "on_node_uuid" #define XML_LRM_ATTR_RSCID "rsc_id" #define XML_LRM_ATTR_OPSTATUS "op_status" #define XML_LRM_ATTR_RC "rc_code" #define XML_LRM_ATTR_CALLID "call_id" #define XML_LRM_ATTR_OP_DIGEST "op_digest" #define XML_TAG_GRAPH "transition_graph" #define XML_GRAPH_TAG_RSC_OP "rsc_op" #define XML_GRAPH_TAG_PSEUDO_EVENT "pseudo_event" #define XML_GRAPH_TAG_CRM_EVENT "crm_event" #define XML_TAG_RULE "rule" #define XML_RULE_ATTR_SCORE "score" #define XML_RULE_ATTR_SCORE_ATTRIBUTE "score_attribute" #define XML_RULE_ATTR_SCORE_MANGLED "score_attribute_mangled" #define XML_RULE_ATTR_ROLE "role" #define XML_RULE_ATTR_RESULT "result" #define XML_RULE_ATTR_BOOLEAN_OP "boolean_op" #define XML_RULE_ATTR_FROMSTATE "from_state" #define XML_RULE_ATTR_TOSTATE "to_state" #define XML_TAG_EXPRESSION "expression" #define XML_EXPR_ATTR_ATTRIBUTE "attribute" #define XML_EXPR_ATTR_OPERATION "operation" #define XML_EXPR_ATTR_VALUE "value" #define XML_EXPR_ATTR_TYPE "type" #define XML_CONS_TAG_RSC_DEPEND "rsc_colocation" #define XML_CONS_TAG_RSC_ORDER "rsc_order" #define XML_CONS_TAG_RSC_LOCATION "rsc_location" #define XML_CONS_ATTR_FROM "from" #define XML_CONS_ATTR_TO "to" #define XML_CONS_ATTR_ACTION "action" #define XML_CONS_ATTR_TOACTION "to_action" #define XML_CONS_ATTR_SYMMETRICAL "symmetrical" #define XML_NVPAIR_ATTR_NAME "name" #define XML_NVPAIR_ATTR_VALUE "value" #define XML_STRENGTH_VAL_MUST "must" #define XML_STRENGTH_VAL_SHOULD "should" #define XML_STRENGTH_VAL_SHOULDNOT "should_not" #define XML_STRENGTH_VAL_MUSTNOT "must_not" #define XML_NODE_ATTR_STATE "state" #define XML_CONFIG_ATTR_DC_DEADTIME "dc_deadtime" #define XML_CONFIG_ATTR_ELECTION_FAIL "election_timeout" #define XML_CONFIG_ATTR_FORCE_QUIT "shutdown_escalation" #define XML_CONFIG_ATTR_REANNOUNCE "join_reannouce" #define XML_CONFIG_ATTR_RECHECK "cluster_recheck_interval" #define XML_CIB_TAG_GENERATION_TUPPLE "generation_tuple" #define XML_ATTR_TRANSITION_MAGIC "transition_magic" #define XML_ATTR_TRANSITION_KEY "transition_key" #define XML_ATTR_TE_NOWAIT "op_no_wait" #define XML_ATTR_TE_TARGET_RC "op_target_rc" #define XML_ATTR_TE_ALLOWFAIL "op_allow_fail" #define XML_ATTR_LRM_PROBE "lrm-is-probe" #define XML_TAG_TRANSIENT_NODEATTRS "transient_attributes" #include #define ID(x) crm_element_value(x, XML_ATTR_ID) #define INSTANCE(x) crm_element_value(x, XML_CIB_ATTR_INSTANCE) #define TSTAMP(x) crm_element_value(x, XML_ATTR_TSTAMP) #define TYPE(x) crm_element_name(x) #endif