diff --git a/crm/crmd/lrm.c b/crm/crmd/lrm.c index 79e24ddbb9..cd6faaa412 100644 --- a/crm/crmd/lrm.c +++ b/crm/crmd/lrm.c @@ -1,886 +1,895 @@ /* * 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 /* for access */ #include #include #include #include #include #include #include #include #include #include gboolean stop_all_resources(void); gboolean build_suppported_RAs( xmlNodePtr metadata_list, xmlNodePtr xml_agent_list); gboolean build_active_RAs(xmlNodePtr rsc_list); void do_update_resource(lrm_rsc_t *rsc, lrm_op_t *op); enum crmd_fsa_input do_lrm_rsc_op( lrm_rsc_t *rsc, char *rid, const char *operation, xmlNodePtr msg); enum crmd_fsa_input do_fake_lrm_op(gpointer data); GHashTable *xml2list(xmlNodePtr parent, const char **attr_path, int depth); GHashTable *monitors = NULL; int num_lrm_register_fails = 0; int max_lrm_register_fails = 30; const char *rsc_path[] = { "msg_data", "rsc_op", "resource", "instance_attributes", "rsc_parameters" }; enum crmd_rscstate { crmd_rscstate_NULL, crmd_rscstate_START, crmd_rscstate_START_PENDING, crmd_rscstate_START_OK, crmd_rscstate_START_FAIL, crmd_rscstate_STOP, crmd_rscstate_STOP_PENDING, crmd_rscstate_STOP_OK, crmd_rscstate_STOP_FAIL, crmd_rscstate_MON, crmd_rscstate_MON_PENDING, crmd_rscstate_MON_OK, crmd_rscstate_MON_FAIL, crmd_rscstate_GENERIC_PENDING, crmd_rscstate_GENERIC_OK, crmd_rscstate_GENERIC_FAIL }; const char *crmd_rscstate2string(enum crmd_rscstate state); const char * crmd_rscstate2string(enum crmd_rscstate state) { switch(state) { case crmd_rscstate_NULL: return NULL; case crmd_rscstate_START: return CRMD_RSCSTATE_START; case crmd_rscstate_START_PENDING: return CRMD_RSCSTATE_START_PENDING; case crmd_rscstate_START_OK: return CRMD_RSCSTATE_START_OK; case crmd_rscstate_START_FAIL: return CRMD_RSCSTATE_START_FAIL; case crmd_rscstate_STOP: return CRMD_RSCSTATE_STOP; case crmd_rscstate_STOP_PENDING: return CRMD_RSCSTATE_STOP_PENDING; case crmd_rscstate_STOP_OK: return CRMD_RSCSTATE_STOP_OK; case crmd_rscstate_STOP_FAIL: return CRMD_RSCSTATE_STOP_FAIL; case crmd_rscstate_MON: return CRMD_RSCSTATE_MON; case crmd_rscstate_MON_PENDING: return CRMD_RSCSTATE_MON_PENDING; case crmd_rscstate_MON_OK: return CRMD_RSCSTATE_MON_OK; case crmd_rscstate_MON_FAIL: return CRMD_RSCSTATE_MON_FAIL; case crmd_rscstate_GENERIC_PENDING: return CRMD_RSCSTATE_GENERIC_PENDING; case crmd_rscstate_GENERIC_OK: return CRMD_RSCSTATE_GENERIC_OK; case crmd_rscstate_GENERIC_FAIL: return CRMD_RSCSTATE_GENERIC_FAIL; } return ""; } /* A_LRM_CONNECT */ enum crmd_fsa_input do_lrm_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 failed = I_FAIL; int ret = HA_OK; if(action & A_LRM_DISCONNECT) { fsa_lrm_conn->lrm_ops->signoff(fsa_lrm_conn); /* TODO: Clean up the hashtable */ } if(action & A_LRM_CONNECT) { crm_trace("LRM: connect..."); monitors = g_hash_table_new(g_str_hash, g_str_equal); fsa_lrm_conn = ll_lrm_new(XML_CIB_TAG_LRM); if(NULL == fsa_lrm_conn) { return failed; } crm_trace("LRM: sigon..."); ret = fsa_lrm_conn->lrm_ops->signon( fsa_lrm_conn, CRM_SYSTEM_CRMD); if(ret != HA_OK) { if(++num_lrm_register_fails < max_lrm_register_fails) { crm_warn("Failed to sign on to the LRM %d" " (%d max) times", num_lrm_register_fails, max_lrm_register_fails); startTimer(wait_timer); crmd_fsa_stall(); return I_NULL; } else { crm_err("Failed to sign on to the LRM %d" " (max) times", num_lrm_register_fails); return failed; } } crm_trace("LRM: set_lrm_callback..."); ret = fsa_lrm_conn->lrm_ops->set_lrm_callback( fsa_lrm_conn, lrm_op_callback); if(ret != HA_OK) { crm_err("Failed to set LRM callbacks"); return failed; } /* TODO: create a destroy handler that causes * some recovery to happen */ G_main_add_fd(G_PRIORITY_LOW, fsa_lrm_conn->lrm_ops->inputfd(fsa_lrm_conn), FALSE, lrm_dispatch, fsa_lrm_conn, default_ipc_connection_destroy); set_bit_inplace(fsa_input_register, R_LRM_CONNECTED); } if(action & ~(A_LRM_CONNECT|A_LRM_DISCONNECT)) { crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__); } return I_NULL; } gboolean build_suppported_RAs(xmlNodePtr metadata_list, xmlNodePtr xml_agent_list) { GList *types = NULL; GList *classes = NULL; const char *version = NULL; const char *ra_data = NULL; /* GHashTable *metadata = NULL; */ xmlNodePtr xml_agent = NULL; xmlNodePtr xml_metadata = NULL; xmlNodePtr tmp = NULL; classes = fsa_lrm_conn->lrm_ops->get_rsc_class_supported(fsa_lrm_conn); slist_iter( class, char, classes, lpc, types = fsa_lrm_conn->lrm_ops->get_rsc_type_supported( fsa_lrm_conn, class); slist_iter( type, char, types, llpc, version = "1"; xml_agent = create_xml_node( xml_agent_list, "lrm_agent"); set_xml_property_copy(xml_agent, "class", class); set_xml_property_copy(xml_agent, XML_ATTR_TYPE, type); /* ra_data = g_hashtable_lookup(metadata, type); */ if(ra_data != NULL) { xml_metadata = create_xml_node( xml_metadata, "agent_metadata"); set_xml_property_copy( xml_metadata, "class", class); set_xml_property_copy( xml_metadata, XML_ATTR_TYPE, type); tmp = string2xml(ra_data); if(tmp != NULL) { xmlAddChild(xml_metadata, tmp); } /* extract version */ } set_xml_property_copy(xml_agent, "version", version); ) g_list_free(types); ); g_list_free(classes); return TRUE; } gboolean stop_all_resources(void) { GList *op_list = NULL; GList *lrm_list = NULL; state_flag_t cur_state = 0; const char *this_op = NULL; lrm_list = fsa_lrm_conn->lrm_ops->get_all_rscs(fsa_lrm_conn); slist_iter( rid, char, lrm_list, lpc, /* GHashTable* params; */ lrm_rsc_t *the_rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); crm_info("Processing lrm_rsc_t entry %s", rid); if(the_rsc == NULL) { crm_err("NULL resource returned from the LRM"); continue; } op_list = the_rsc->ops->get_cur_state(the_rsc, &cur_state); crm_verbose("\tcurrent state:%s\n", cur_state==LRM_RSC_IDLE?"Idle":"Busy"); slist_iter( op, lrm_op_t, op_list, llpc, this_op = op->op_type; crm_debug("Processing op %s for %s (status=%d, rc=%d)", op->op_type, the_rsc->id, op->op_status, op->rc); if(safe_str_neq(this_op, CRMD_RSCSTATE_STOP)){ do_lrm_rsc_op(the_rsc, the_rsc->id, CRMD_RSCSTATE_STOP, NULL); } break; ); ); return TRUE; } gboolean build_active_RAs(xmlNodePtr rsc_list) { GList *op_list = NULL; GList *lrm_list = NULL; gboolean found_op = FALSE; state_flag_t cur_state = 0; const char *this_op = NULL; char *tmp = NULL; lrm_list = fsa_lrm_conn->lrm_ops->get_all_rscs(fsa_lrm_conn); slist_iter( rid, char, lrm_list, lpc, /* GHashTable* params; */ lrm_rsc_t *the_rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); xmlNodePtr xml_rsc = create_xml_node( rsc_list, XML_LRM_TAG_RESOURCE); crm_info("Processing lrm_rsc_t entry %s", rid); if(the_rsc == NULL) { crm_err("NULL resource returned from the LRM"); continue; } set_xml_property_copy(xml_rsc, XML_ATTR_ID, the_rsc->id); set_xml_property_copy( xml_rsc, XML_LRM_ATTR_TARGET, fsa_our_uname); op_list = the_rsc->ops->get_cur_state(the_rsc, &cur_state); crm_verbose("\tcurrent state:%s\n", cur_state==LRM_RSC_IDLE?"Idle":"Busy"); slist_iter( op, lrm_op_t, op_list, llpc, this_op = op->op_type; crm_debug("Processing op %s for %s (status=%d, rc=%d)", op->op_type, the_rsc->id, op->op_status, op->rc); if(op->rc != 0 || safe_str_neq(this_op, CRMD_RSCSTATE_MON)){ set_xml_property_copy( xml_rsc, XML_LRM_ATTR_RSCSTATE, - crmd_rscstate2string((int)(op->user_data))); + op->user_data); set_xml_property_copy( xml_rsc, XML_LRM_ATTR_LASTOP, this_op); tmp = crm_itoa(op->rc); set_xml_property_copy( xml_rsc, XML_LRM_ATTR_RC, tmp); crm_free(tmp); tmp = crm_itoa(op->op_status); set_xml_property_copy( xml_rsc, XML_LRM_ATTR_OPSTATUS, tmp); crm_free(tmp); /* we only want the last one */ found_op = TRUE; break; } else { set_xml_property_copy( xml_rsc, XML_LRM_ATTR_RSCSTATE, CRMD_RSCSTATE_START_OK); set_xml_property_copy( xml_rsc, XML_LRM_ATTR_LASTOP, CRMD_RSCSTATE_START); tmp = crm_itoa(op->rc); set_xml_property_copy( xml_rsc, XML_LRM_ATTR_RC, tmp); crm_free(tmp); set_xml_property_copy( xml_rsc, XML_LRM_ATTR_OPSTATUS, "0"); /* we only want the last one */ found_op = TRUE; break; } ); if(found_op == FALSE) { crm_err("Could not properly determin last op" " for %s from %d entries", the_rsc->id, g_list_length(op_list)); } g_list_free(op_list); ); g_list_free(lrm_list); return TRUE; } xmlNodePtr do_lrm_query(gboolean is_replace) { xmlNodePtr xml_result= NULL; xmlNodePtr xml_state = create_xml_node(NULL, XML_CIB_TAG_STATE); xmlNodePtr xml_data = create_xml_node(xml_state, XML_CIB_TAG_LRM); xmlNodePtr rsc_list = create_xml_node(xml_data,XML_LRM_TAG_RESOURCES); xmlNodePtr xml_agent_list = create_xml_node(xml_data, "lrm_agents"); xmlNodePtr xml_metadata_list = create_xml_node(xml_data, "metatdata"); /* Build a list of supported agents and metadata */ build_suppported_RAs(xml_metadata_list, xml_agent_list); /* Build a list of active (not always running) resources */ build_active_RAs(rsc_list); if(is_replace) { set_xml_property_copy(xml_state, "replace", XML_CIB_TAG_LRM); } set_uuid(xml_state, XML_ATTR_UUID, fsa_our_uname); set_xml_property_copy(xml_state, XML_ATTR_UNAME, fsa_our_uname); xml_result = create_cib_fragment(xml_state, NULL); crm_xml_debug(xml_state, "Current state of the LRM"); return xml_result; } /* A_LRM_INVOKE */ enum crmd_fsa_input do_lrm_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 next_input = I_NULL; xmlNodePtr msg; const char *operation = NULL; char rid[64]; const char *id_from_cib = NULL; const char *crm_op = NULL; lrm_rsc_t *rsc = NULL; msg = (xmlNodePtr)msg_data->data; operation = get_xml_attr_nested( msg, rsc_path, DIMOF(rsc_path) -3, XML_LRM_ATTR_TASK, TRUE); /* xmlNodePtr tmp = find_xml_node_nested(msg, rsc_path, DIMOF(rsc_path) -3); */ /* operation = xmlGetProp(tmp, XML_LRM_ATTR_TASK); */ if(operation == NULL) { crm_err("No value for %s in message at level %d.", XML_LRM_ATTR_TASK, DIMOF(rsc_path) -3); return I_NULL; } id_from_cib = get_xml_attr_nested( msg, rsc_path, DIMOF(rsc_path) -2, XML_ATTR_ID, TRUE); if(id_from_cib == NULL) { crm_err("No value for %s in message at level %d.", XML_ATTR_ID, DIMOF(rsc_path) -2); return I_NULL; } /* only the first 16 chars are used by the LRM */ strncpy(rid, id_from_cib, 64); rid[63] = 0; crm_op = get_xml_attr(msg, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE); rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); if(crm_op != NULL && safe_str_eq(crm_op, "lrm_query")) { xmlNodePtr data, reply; data = do_lrm_query(FALSE); reply = create_reply(msg, data); relay_message(reply, TRUE); free_xml(data); free_xml(reply); } else if(operation != NULL) { next_input = do_lrm_rsc_op(rsc, rid, operation, msg); } else { next_input = I_ERROR; } return next_input; } enum crmd_fsa_input do_lrm_rsc_op( lrm_rsc_t *rsc, char *rid, const char *operation, xmlNodePtr msg) { lrm_op_t* op = NULL; int op_result = HA_OK; int monitor_call_id = 0; + int action_timeout = 0; + const char *class = get_xml_attr_nested( + msg, rsc_path, DIMOF(rsc_path) -2, "class", TRUE); + + const char *type = get_xml_attr_nested( + msg, rsc_path, DIMOF(rsc_path) -2, XML_ATTR_TYPE, TRUE); + + const char *timeout = get_xml_attr_nested( + msg, rsc_path, DIMOF(rsc_path) -2, "timeout", TRUE); + if(rsc == NULL) { /* add it to the list */ crm_verbose("adding rsc %s before operation", rid); fsa_lrm_conn->lrm_ops->add_rsc( - fsa_lrm_conn, rid, - get_xml_attr_nested( - msg, rsc_path, DIMOF(rsc_path) -2, - "class", TRUE), - get_xml_attr_nested( - msg, rsc_path, DIMOF(rsc_path) -2, - XML_ATTR_TYPE, TRUE), - NULL,NULL); + fsa_lrm_conn, rid, class, type, NULL, NULL); - rsc = fsa_lrm_conn->lrm_ops->get_rsc( - fsa_lrm_conn, rid); + rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); } if(rsc == NULL) { crm_err("Could not add resource to LRM"); return I_FAIL; } + if(timeout) { + action_timeout = atoi(timeout); + if(action_timeout < 0) { + action_timeout = 0; + } + } + /* now do the op */ crm_info("Performing op %s on %s", operation, rid); - op = g_new(lrm_op_t, 1); + op = g_new(lrm_op_t, 1); op->op_type = g_strdup(operation); op->params = xml2list(msg, rsc_path, DIMOF(rsc_path)); - op->timeout = 0; + op->timeout = action_timeout; op->interval = 0; op->user_data = NULL; op->target_rc = EVERYTIME; if(safe_str_eq(CRMD_RSCSTATE_START, operation)) { - op->user_data = (void*)crmd_rscstate_START_OK; + op->user_data = crm_strdup(CRMD_RSCSTATE_START_OK); + } else if(safe_str_eq(CRMD_RSCSTATE_STOP, operation)) { - op->user_data = (void*)crmd_rscstate_STOP_OK; + op->user_data = crm_strdup(CRMD_RSCSTATE_STOP_OK); + } else { crm_warn("Using status \"complete\" for op \"%s\"" "... this is still in the experimental stage.", operation); - op->user_data = (void*)crmd_rscstate_GENERIC_OK; + op->user_data = crm_strdup(CRMD_RSCSTATE_GENERIC_OK); } + op->user_data_len = 1+strlen(op->user_data); op_result = rsc->ops->perform_op(rsc, op); + crm_free(op->user_data); + if(op_result != EXECRA_OK) { crm_err("Operation %s on %s failed with code: %d", operation, rid, op_result); return I_FAIL; } if(safe_str_eq(operation, CRMD_RSCSTATE_START)) { /* initiate the monitor action */ op = g_new(lrm_op_t, 1); op->op_type = g_strdup(CRMD_RSCSTATE_MON); op->params = NULL; - op->user_data = (void*)crmd_rscstate_MON_OK; + op->user_data = crm_strdup(CRMD_RSCSTATE_MON_OK); op->timeout = 0; op->interval = 9000; op->target_rc = CHANGED; + op->user_data_len = 1+strlen(op->user_data); + monitor_call_id = rsc->ops->perform_op(rsc, op); + crm_free(op->user_data); + if (monitor_call_id > 0) { crm_debug("Adding monitor op for %s", rsc->id); g_hash_table_insert( monitors, strdup(rsc->id), GINT_TO_POINTER(monitor_call_id)); } else { crm_err("Monitor op for %s did not have a call id", rsc->id); } } else if(safe_str_eq(operation, CRMD_RSCSTATE_STOP)) { gpointer foo = g_hash_table_lookup(monitors, rsc->id); int monitor_call_id = GPOINTER_TO_INT(foo); if(monitor_call_id > 0) { crm_debug("Stopping status op for %s", rsc->id); rsc->ops->cancel_op(rsc, monitor_call_id); g_hash_table_remove(monitors, rsc->id); /* TODO: Clean up key */ } else { crm_warn("No monitor operation found for %s", rsc->id); } } return I_NULL; } GHashTable * xml2list(xmlNodePtr parent, const char**attr_path, int depth) { xmlNodePtr node_iter = NULL; xmlNodePtr nvpair_list = NULL; GHashTable *nvpair_hash = g_hash_table_new(&g_str_hash, &g_str_equal); if(parent != NULL) { nvpair_list = find_xml_node_nested(parent, attr_path, depth); } while(nvpair_list != NULL){ node_iter = nvpair_list->children; while(node_iter != NULL) { const char *key = xmlGetProp( node_iter, XML_NVPAIR_ATTR_NAME); const char *value = xmlGetProp( node_iter, XML_NVPAIR_ATTR_VALUE); crm_verbose("Added %s=%s", key, value); g_hash_table_insert (nvpair_hash, crm_strdup(key), crm_strdup(value)); node_iter = node_iter->next; } nvpair_list=nvpair_list->next; } return nvpair_hash; } void do_update_resource(lrm_rsc_t *rsc, lrm_op_t* op) { /* */ xmlNodePtr update, iter; char *tmp = NULL; xmlNodePtr fragment; int len = 0; char *fail_state = NULL; if(op == NULL || rsc == NULL) { crm_err("Either resouce or op was not specified"); return; } update = create_xml_node(NULL, XML_CIB_TAG_STATE); set_uuid(update, XML_ATTR_UUID, fsa_our_uname); set_xml_property_copy(update, XML_ATTR_UNAME, fsa_our_uname); iter = create_xml_node(update, XML_CIB_TAG_LRM); iter = create_xml_node(iter, XML_LRM_TAG_RESOURCES); iter = create_xml_node(iter, "lrm_resource"); set_xml_property_copy(iter, XML_ATTR_ID, rsc->id); set_xml_property_copy(iter, XML_LRM_ATTR_LASTOP, op->op_type); len = strlen(op->op_type); len += strlen("_failed_"); crm_malloc(fail_state, sizeof(char)*len); if(fail_state != NULL) { sprintf(fail_state, "%s_failed", op->op_type); } switch(op->op_status) { case LRM_OP_CANCELLED: break; case LRM_OP_ERROR: case LRM_OP_TIMEOUT: case LRM_OP_NOTSUPPORTED: crm_err("An LRM operation failed" " or was aborted"); set_xml_property_copy( iter, XML_LRM_ATTR_RSCSTATE, fail_state); break; case LRM_OP_DONE: set_xml_property_copy( iter, XML_LRM_ATTR_RSCSTATE, - crmd_rscstate2string((int)(op->user_data))); + op->user_data); break; } crm_free(fail_state); tmp = crm_itoa(op->rc); set_xml_property_copy(iter, XML_LRM_ATTR_RC, tmp); crm_free(tmp); tmp = crm_itoa(op->op_status); set_xml_property_copy(iter, XML_LRM_ATTR_OPSTATUS, tmp); crm_free(tmp); set_xml_property_copy(iter, XML_LRM_ATTR_TARGET, fsa_our_uname); fragment = create_cib_fragment(update, NULL); send_request(NULL, fragment, CRM_OP_UPDATE, fsa_our_dc, CRM_SYSTEM_DCIB, NULL); free_xml(fragment); free_xml(update); } enum crmd_fsa_input do_lrm_event(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input cur_input, fsa_data_t *msg_data) { lrm_op_t* op = NULL; lrm_rsc_t* rsc = NULL; if(msg_data->fsa_cause != C_LRM_OP_CALLBACK) { return I_FAIL; } op = (lrm_op_t*)msg_data->data; rsc = op->rsc; crm_debug("Processing %d event for %s/%s", op->op_status, op->op_type, rsc->id); switch(op->op_status) { case LRM_OP_ERROR: case LRM_OP_CANCELLED: case LRM_OP_TIMEOUT: case LRM_OP_NOTSUPPORTED: crm_err("An LRM operation failed" " or was aborted"); /* fall through */ case LRM_OP_DONE: do_update_resource(rsc, op); break; } return I_NULL; } enum crmd_fsa_input do_fake_lrm_op(gpointer data) { xmlNodePtr msg = NULL; const char *crm_op = NULL; const char *operation = NULL; const char *id_from_cib = NULL; long int op_code = 0; const char *op_status = NULL; xmlNodePtr update = NULL; xmlNodePtr state = NULL; xmlNodePtr iter = NULL; char *op_code_s = NULL; if(data == NULL) { return I_ERROR; } msg = (xmlNodePtr)data; operation = get_xml_attr_nested( msg, rsc_path, DIMOF(rsc_path) -3, XML_LRM_ATTR_TASK, TRUE); id_from_cib = get_xml_attr_nested( msg, rsc_path, DIMOF(rsc_path) -2, XML_ATTR_ID, TRUE); crm_op = get_xml_attr(msg, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE); if(safe_str_eq(crm_op, "rsc_op")) { state = create_xml_node(NULL, XML_CIB_TAG_STATE); iter = create_xml_node(state, XML_CIB_TAG_LRM); crm_info("Performing %s on %s", operation, id_from_cib); /* so we can identify where to do the update */ set_uuid(state, XML_ATTR_UUID, fsa_our_uname); iter = create_xml_node(iter, XML_LRM_TAG_RESOURCES); iter = create_xml_node(iter, "lrm_resource"); set_xml_property_copy(iter, XML_ATTR_ID, id_from_cib); set_xml_property_copy(iter, XML_LRM_ATTR_LASTOP, operation); - -#if 0 - /* introduce a 10% chance of an action failing */ - op_code = random(); -#endif - if((op_code % 10) == 1) { - op_code = 1; - } else { - op_code = 0; - } op_code_s = crm_itoa(op_code); if(op_code) { /* fail */ if(safe_str_eq(operation, "start")){ op_status = "stopped"; } else { op_status = "started"; } + } else { /* pass */ if(safe_str_eq(operation, "start")){ op_status = "started"; } else { op_status = "stopped"; } } - set_xml_property_copy(iter, XML_LRM_ATTR_RSCSTATE,op_status); + set_xml_property_copy(iter, XML_LRM_ATTR_RSCSTATE, op_status); set_xml_property_copy(iter, XML_LRM_ATTR_OPSTATUS, op_code_s); set_xml_property_copy( iter, XML_LRM_ATTR_TARGET, fsa_our_uname); crm_free(op_code_s); update = create_cib_fragment(state, NULL); send_request(NULL, update, CRM_OP_UPDATE, fsa_our_dc, CRM_SYSTEM_DCIB, NULL); } return I_NULL; }