예제 #1
0
파일: main.c 프로젝트: SynetoNet/pacemaker
static void
stonith_notify_client(gpointer key, gpointer value, gpointer user_data)
{

    xmlNode *update_msg = user_data;
    crm_client_t *client = value;
    const char *type = NULL;

    CRM_CHECK(client != NULL, return);
    CRM_CHECK(update_msg != NULL, return);

    type = crm_element_value(update_msg, F_SUBTYPE);
    CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return);

    if (client->ipcs == NULL) {
        crm_trace("Skipping client with NULL channel");
        return;
    }

    if (client->options & get_stonith_flag(type)) {
        int rc = crm_ipcs_send(client, 0, update_msg, crm_ipc_server_event | crm_ipc_server_error);

        if (rc <= 0) {
            crm_warn("%s notification of client %s.%.6s failed: %s (%d)",
                     type, crm_client_name(client), client->id, pcmk_strerror(rc), rc);
        } else {
            crm_trace("Sent %s notification to client %s.%.6s", type, crm_client_name(client),
                      client->id);
        }
    }
}
예제 #2
0
void
cibadmin_op_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    exit_code = rc;

    if (rc != 0) {
        crm_warn("Call %s failed (%d): %s", cib_action, rc, pcmk_strerror(rc));
        fprintf(stderr, "Call %s failed (%d): %s\n", cib_action, rc, pcmk_strerror(rc));
        print_xml_output(output);

    } else if (safe_str_eq(cib_action, CIB_OP_QUERY) && output == NULL) {
        crm_err("Output expected in query response");
        crm_log_xml_err(msg, "no output");

    } else if (output == NULL) {
        crm_info("Call passed");

    } else {
        crm_info("Call passed");
        print_xml_output(output);
    }

    if (call_id == request_id) {
        g_main_quit(mainloop);

    } else {
        crm_info("Message was not the response we were looking for (%d vs. %d", call_id,
                 request_id);
    }
}
예제 #3
0
void
cibadmin_op_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    exit_code = crm_errno2exit(rc);

    if (rc == -pcmk_err_schema_unchanged) {
        report_schema_unchanged();

    } else if (rc != pcmk_ok) {
        crm_warn("Call %s failed (%d): %s", cib_action, rc, pcmk_strerror(rc));
        fprintf(stderr, "Call %s failed (%d): %s\n", cib_action, rc, pcmk_strerror(rc));
        print_xml_output(output);

    } else if (safe_str_eq(cib_action, CIB_OP_QUERY) && output == NULL) {
        crm_err("Query returned no output");
        crm_log_xml_err(msg, "no output");

    } else if (output == NULL) {
        crm_info("Call passed");

    } else {
        crm_info("Call passed");
        print_xml_output(output);
    }

    if (call_id == request_id) {
        g_main_loop_quit(mainloop);

    } else {
        crm_info("Message was not the response we were looking for (%d vs. %d)",
                 call_id, request_id);
    }
}
예제 #4
0
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 support up to CRM feature set %s (current=%s)",
			revision, CRM_FEATURE_SET);
		crm_err("Shutting down the CRM");
		/* go into a stall state */
		register_fsa_error_adv(
			C_FSA_INTERNAL, I_SHUTDOWN, NULL, NULL, __FUNCTION__);
		return;
	}
}
예제 #5
0
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, F_CRM_REFERENCE);
    const char *op = crm_element_value(msg, F_CRM_TASK);
    const char *type = crm_element_value(msg, F_CRM_MSG_TYPE);

    crm_trace("Processing %s (%s) message", op, ref);
    crm_log_xml_trace(msg, "ipc");

    if (op == NULL) {
        /* error */

    } else if (sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_TENGINE) != 0) {
        crm_trace("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_trace(msg, "Processing (N)ACK");
        crm_debug("Processing (N)ACK %s from %s", crm_element_value(msg, F_CRM_REFERENCE), from);

        xpathObj = xpath_search(xml_data, "//" XML_LRM_TAG_RSC_OP);
        if (numXpathResults(xpathObj)) {
            int lpc = 0, max = numXpathResults(xpathObj);

            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);
            }
            freeXpathObject(xpathObj);

        } else {
            crm_log_xml_err(msg, "Invalid (N)ACK");
            freeXpathObject(xpathObj);
            return FALSE;
        }

    } else {
        crm_err("Unknown command: %s::%s from %s", type, op, sys_from);
    }

    crm_trace("finished processing message");

    return TRUE;
}
예제 #6
0
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, F_CRM_REFERENCE);
    const char *op = crm_element_value(msg, F_CRM_TASK);
    const char *type = crm_element_value(msg, F_CRM_MSG_TYPE);

    crm_trace("Processing %s (%s) message", op, ref);
    crm_log_xml_trace(msg, "ipc");

    if (op == NULL) {
        /* error */

    } else if (sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_TENGINE) != 0) {
        crm_trace("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_trace(msg, "Processing (N)ACK");
        crm_debug("Processing (N)ACK %s from %s", crm_element_value(msg, F_CRM_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_err(msg, "Invalid (N)ACK");
            return FALSE;
        }

    } else {
        crm_err("Unknown command: %s::%s from %s", type, op, sys_from);
    }

    crm_trace("finished processing message");

    return TRUE;
}
예제 #7
0
int
cib_process_delete_absolute(const char *op, int options, const char *section, xmlNode * req,
                            xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                            xmlNode ** answer)
{
    xmlNode *failed = NULL;
    int result = pcmk_ok;
    xmlNode *update_section = NULL;

    crm_trace("Processing \"%s\" event for section=%s", op, crm_str(section));
    if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
        section = NULL;

    } else if (safe_str_eq(XML_TAG_CIB, section)) {
        section = NULL;

    } else if (safe_str_eq(crm_element_name(input), XML_TAG_CIB)) {
        section = NULL;
    }

    CRM_CHECK(strcasecmp(CIB_OP_DELETE, op) == 0, return -EINVAL);

    if (input == NULL) {
        crm_err("Cannot perform modification with no data");
        return -EINVAL;
    }

    failed = create_xml_node(NULL, XML_TAG_FAILED);

    update_section = get_object_root(section, *result_cib);
    result = delete_cib_object(update_section, input);
    update_results(failed, input, op, result);

    if (xml_has_children(failed)) {
        CRM_CHECK(result != pcmk_ok, result = -EINVAL);
    }

    if (result != pcmk_ok) {
        crm_log_xml_err(failed, "CIB Update failures");
        *answer = failed;

    } else {
        free_xml(failed);
    }

    return result;
}
예제 #8
0
void
cibadmin_op_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    char *admin_input_xml = NULL;

    exit_code = rc;

    if (output != NULL) {
        admin_input_xml = dump_xml_formatted(output);
    }

    if (safe_str_eq(cib_action, CIB_OP_ISMASTER) && rc != pcmk_ok) {
        crm_info("CIB on %s is _not_ the master instance", host ? host : "localhost");
        fprintf(stderr, "CIB on %s is _not_ the master instance\n", host ? host : "localhost");

    } else if (safe_str_eq(cib_action, CIB_OP_ISMASTER)) {
        crm_info("CIB on %s _is_ the master instance", host ? host : "localhost");
        fprintf(stderr, "CIB on %s _is_ the master instance\n", host ? host : "localhost");

    } else if (rc != 0) {
        crm_warn("Call %s failed (%d): %s", cib_action, rc, pcmk_strerror(rc));
        fprintf(stderr, "Call %s failed (%d): %s\n", cib_action, rc, pcmk_strerror(rc));
        fprintf(stdout, "%s\n", crm_str(admin_input_xml));

    } else if (safe_str_eq(cib_action, CIB_OP_QUERY) && output == NULL) {
        crm_err("Output expected in query response");
        crm_log_xml_err(msg, "no output");

    } else if (output == NULL) {
        crm_info("Call passed");

    } else {
        crm_info("Call passed");
        fprintf(stdout, "%s\n", crm_str(admin_input_xml));
    }
    free(admin_input_xml);

    if (call_id == request_id) {
        g_main_quit(mainloop);

    } else {
        crm_info("Message was not the response we were looking for (%d vs. %d", call_id,
                 request_id);
    }
}
예제 #9
0
파일: main.c 프로젝트: tserong/pacemaker
static void
stonith_notify_client(gpointer key, gpointer value, gpointer user_data)
{

    IPC_Channel *ipc_client = NULL;
    xmlNode *update_msg = user_data;
    stonith_client_t *client = value;
    const char *type = NULL;

    CRM_CHECK(client != NULL, return);
    CRM_CHECK(update_msg != NULL, return);

    type = crm_element_value(update_msg, F_SUBTYPE);
    CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return);

    if(client == NULL) {
	crm_trace("Skipping NULL client");
	return;

    } else if(client->channel == NULL) {
	crm_trace("Skipping client with NULL channel");
	return;

    } else if(client->name == NULL) {
	crm_trace("Skipping unnammed client / comamnd channel");
	return;
    }

    ipc_client = client->channel;
    if(client->flags & get_stonith_flag(type)) {
	crm_trace("Sending %s-notification to client %s/%s", type, client->name, client->id);
	if(ipc_client->send_queue->current_qlen >= ipc_client->send_queue->max_qlen) {
	    /* We never want the STONITH to exit because our client is slow */
	    crm_debug("%s-notification of client %s/%s failed - queue saturated",
		     type, client->name, client->id);
			
	} else if(send_ipc_message(ipc_client, update_msg) == FALSE) {
	    crm_warn("%s-Notification of client %s/%s failed",
		     type, client->name, client->id);
	}
    }
}
예제 #10
0
void
handle_response(xmlNode * stored_msg)
{
    const char *op = crm_element_value(stored_msg, F_CRM_TASK);

    if (op == NULL) {
        crm_log_xml_err(stored_msg, "Bad message");

    } else if (AM_I_DC && strcmp(op, CRM_OP_PECALC) == 0) {
        /* Check if the PE answer been superceeded by a subsequent request? */
        const char *msg_ref = crm_element_value(stored_msg, XML_ATTR_REFERENCE);

        if (msg_ref == NULL) {
            crm_err("%s - Ignoring calculation with no reference", op);

        } else if (safe_str_eq(msg_ref, fsa_pe_ref)) {
            ha_msg_input_t fsa_input;

            fsa_input.msg = stored_msg;
            register_fsa_input_later(C_IPC_MESSAGE, I_PE_SUCCESS, &fsa_input);
            crm_trace("Completed: %s...", fsa_pe_ref);

        } else {
            crm_info("%s calculation %s is obsolete", op, msg_ref);
        }

    } else if (strcmp(op, CRM_OP_VOTE) == 0
               || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0 || strcmp(op, CRM_OP_SHUTDOWN) == 0) {

    } else {
        const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);

        crm_err("Unexpected response (op=%s, src=%s) sent to the %s",
                op, host_from, AM_I_DC ? "DC" : "CRMd");
    }
}
예제 #11
0
crm_action_t *
match_down_event(int id, const char *target, const char *filter, bool quiet)
{
    const char *this_action = NULL;
    const char *this_node = NULL;
    crm_action_t *match = NULL;

    GListPtr gIter = NULL;
    GListPtr gIter2 = NULL;

    gIter = transition_graph->synapses;
    for (; gIter != NULL; gIter = gIter->next) {
        synapse_t *synapse = (synapse_t *) gIter->data;

        /* lookup event */
        gIter2 = synapse->actions;
        for (; gIter2 != NULL; gIter2 = gIter2->next) {
            crm_action_t *action = (crm_action_t *) gIter2->data;

            if (id > 0 && action->id == id) {
                match = action;
                break;
            }

            this_action = crm_element_value(action->xml, XML_LRM_ATTR_TASK);

            if (action->type != action_type_crm) {
                continue;

            } else if (safe_str_eq(this_action, CRM_OP_LRM_REFRESH)) {
                continue;

            } else if (filter != NULL && safe_str_neq(this_action, filter)) {
                continue;
            }

            this_node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);

            if (this_node == NULL) {
                crm_log_xml_err(action->xml, "No node uuid");
            }

            if (safe_str_neq(this_node, target)) {
                crm_debug("Action %d : Node mismatch: %s", action->id, this_node);
                continue;
            }

            match = action;
            id = action->id;
            break;
        }

        if (match != NULL) {
            /* stop this event's timer if it had one */
            break;
        }
    }

    if (match != NULL) {
        /* stop this event's timer if it had one */
        crm_debug("Match found for action %d: %s on %s", id,
                  crm_element_value(match->xml, XML_LRM_ATTR_TASK_KEY), target);

    } else if (id > 0) {
        crm_err("No match for action %d", id);

    } else if(quiet == FALSE) {
        crm_warn("No match for shutdown action on %s", target);
    }

    return match;
}
예제 #12
0
파일: cib_ops.c 프로젝트: fghaas/pacemaker
enum cib_errors
cib_process_create(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
    xmlNode *failed = NULL;
    enum cib_errors result = cib_ok;
    xmlNode *update_section = NULL;

    crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section));
    if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
        section = NULL;

    } else if (safe_str_eq(XML_TAG_CIB, section)) {
        section = NULL;

    } else if (safe_str_eq(crm_element_name(input), XML_TAG_CIB)) {
        section = NULL;
    }

    CRM_CHECK(strcasecmp(CIB_OP_CREATE, op) == 0, return cib_operation);

    if (input == NULL) {
        crm_err("Cannot perform modification with no data");
        return cib_NOOBJECT;
    }

    if (section == NULL) {
        return cib_process_modify(op, options, section, req, input, existing_cib, result_cib,
                                  answer);
    }

    failed = create_xml_node(NULL, XML_TAG_FAILED);

    update_section = get_object_root(section, *result_cib);
    if (safe_str_eq(crm_element_name(input), section)) {
        xmlNode *a_child = NULL;

        for (a_child = __xml_first_child(input); a_child != NULL; a_child = __xml_next(a_child)) {
            result = add_cib_object(update_section, a_child);
            if (update_results(failed, a_child, op, result)) {
                break;
            }
        }

    } else {
        result = add_cib_object(update_section, input);
        update_results(failed, input, op, result);
    }

    if (xml_has_children(failed)) {
        CRM_CHECK(result != cib_ok, result = cib_unknown);
    }

    if (result != cib_ok) {
        crm_log_xml_err(failed, "CIB Update failures");
        *answer = failed;

    } else {
        free_xml(failed);
    }

    return result;
}
예제 #13
0
enum crmd_fsa_input
handle_request(xmlNode * stored_msg)
{
    xmlNode *msg = NULL;
    const char *op = crm_element_value(stored_msg, F_CRM_TASK);

    /* Optimize this for the DC - it has the most to do */

    if (op == NULL) {
        crm_log_xml_err(stored_msg, "Bad message");
        return I_NULL;
    }

    /*========== DC-Only Actions ==========*/
    if (AM_I_DC) {
        if (strcmp(op, CRM_OP_JOIN_ANNOUNCE) == 0) {
            return I_NODE_JOIN;

        } else if (strcmp(op, CRM_OP_JOIN_REQUEST) == 0) {
            return I_JOIN_REQUEST;

        } else if (strcmp(op, CRM_OP_JOIN_CONFIRM) == 0) {
            return I_JOIN_RESULT;

        } else if (strcmp(op, CRM_OP_SHUTDOWN) == 0) {
            const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
            gboolean dc_match = safe_str_eq(host_from, fsa_our_dc);

            if (is_set(fsa_input_register, R_SHUTDOWN)) {
                crm_info("Shutting ourselves down (DC)");
                return I_STOP;

            } else if (dc_match) {
                crm_err("We didnt ask to be shut down, yet our"
                        " TE is telling us too." " Better get out now!");
                return I_TERMINATE;

            } else if (fsa_state != S_STOPPING) {
                crm_err("Another node is asking us to shutdown" " but we think we're ok.");
                return I_ELECTION;
            }

        } else if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
            /* a slave wants to shut down */
            /* create cib fragment and add to message */
            return handle_shutdown_request(stored_msg);
        }
    }

    /*========== common actions ==========*/
    if (strcmp(op, CRM_OP_NOVOTE) == 0) {
        ha_msg_input_t fsa_input;

        fsa_input.msg = stored_msg;
        register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
                               A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__);

    } else if (strcmp(op, CRM_OP_CLEAR_FAILCOUNT) == 0) {
        return handle_failcount_op(stored_msg);

    } else if (strcmp(op, CRM_OP_VOTE) == 0) {
        /* count the vote and decide what to do after that */
        ha_msg_input_t fsa_input;

        fsa_input.msg = stored_msg;
        register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
                               A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__);

        /* Sometimes we _must_ go into S_ELECTION */
        if (fsa_state == S_HALT) {
            crm_debug("Forcing an election from S_HALT");
            return I_ELECTION;
#if 0
        } else if (AM_I_DC) {
            /* This is the old way of doing things but what is gained? */
            return I_ELECTION;
#endif
        }

    } else if (strcmp(op, CRM_OP_JOIN_OFFER) == 0) {
        crm_debug("Raising I_JOIN_OFFER: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
        return I_JOIN_OFFER;

    } else if (strcmp(op, CRM_OP_JOIN_ACKNAK) == 0) {
        crm_debug("Raising I_JOIN_RESULT: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
        return I_JOIN_RESULT;

    } else if (strcmp(op, CRM_OP_LRM_DELETE) == 0
               || strcmp(op, CRM_OP_LRM_FAIL) == 0
               || strcmp(op, CRM_OP_LRM_REFRESH) == 0 || strcmp(op, CRM_OP_REPROBE) == 0) {

        crm_xml_add(stored_msg, F_CRM_SYS_TO, CRM_SYSTEM_LRMD);
        return I_ROUTER;

    } else if (strcmp(op, CRM_OP_NOOP) == 0) {
        return I_NULL;

    } else if (strcmp(op, CRM_OP_LOCAL_SHUTDOWN) == 0) {

        crm_shutdown(SIGTERM);
        /*return I_SHUTDOWN; */
        return I_NULL;

        /*========== (NOT_DC)-Only Actions ==========*/
    } else if (AM_I_DC == FALSE && strcmp(op, CRM_OP_SHUTDOWN) == 0) {

        const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
        gboolean dc_match = safe_str_eq(host_from, fsa_our_dc);

        if (dc_match || fsa_our_dc == NULL) {
            if (is_set(fsa_input_register, R_SHUTDOWN) == FALSE) {
                crm_err("We didn't ask to be shut down, yet our" " DC is telling us too.");
                set_bit(fsa_input_register, R_STAYDOWN);
                return I_STOP;
            }
            crm_info("Shutting down");
            return I_STOP;

        } else {
            crm_warn("Discarding %s op from %s", op, host_from);
        }

    } else if (strcmp(op, CRM_OP_PING) == 0) {
        /* eventually do some stuff to figure out
         * if we /are/ ok
         */
        const char *sys_to = crm_element_value(stored_msg, F_CRM_SYS_TO);
        xmlNode *ping = create_xml_node(NULL, XML_CRM_TAG_PING);

        crm_xml_add(ping, XML_PING_ATTR_STATUS, "ok");
        crm_xml_add(ping, XML_PING_ATTR_SYSFROM, sys_to);
        crm_xml_add(ping, "crmd_state", fsa_state2string(fsa_state));

        /* Ok, so technically not so interesting, but CTS needs to see this */
        crm_notice("Current ping state: %s", fsa_state2string(fsa_state));

        msg = create_reply(stored_msg, ping);
        relay_message(msg, TRUE);

        free_xml(ping);
        free_xml(msg);

    } else if (strcmp(op, CRM_OP_RM_NODE_CACHE) == 0) {
        int id = 0;
        const char *name = NULL;
        xmlNode *options = get_xpath_object("//" XML_TAG_OPTIONS, stored_msg, LOG_ERR);

        if (options) {
            crm_element_value_int(options, XML_ATTR_ID, &id);
            name = crm_element_value(options, XML_ATTR_UNAME);
        }

        reap_crm_member(id, name);

    } else {
        crm_err("Unexpected request (%s) sent to %s", op, AM_I_DC ? "the DC" : "non-DC node");
        crm_log_xml_err(stored_msg, "Unexpected");
    }

    return I_NULL;
}
예제 #14
0
static gboolean
exec_rsc_action(crm_graph_t *graph, crm_action_t *action)
{
	lrm_op_t *op = NULL;
	struct pe_operation *pe_op;
	const char *target_rc_s = crm_meta_value(action->params, XML_ATTR_TE_TARGET_RC);
	xmlNode *action_rsc = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
	char *node = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET);
	char *uuid;
	const char *tmp_provider;
	xmlNode *params_all;

	qb_enter();

	if (safe_str_eq(crm_element_value(action->xml, "operation"), "probe_complete")) {
		crm_free(node);
		action->confirmed = TRUE;
		update_graph(graph, action);
		graph_updated = TRUE;
		qb_leave();
		return TRUE;
	}

	if (action_rsc == NULL) {
		crm_log_xml_err(action->xml, "Bad");
		crm_free(node);
		qb_leave();
		return FALSE;
	}
	uuid = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET_UUID);

	pe_op = calloc(1, sizeof(struct pe_operation));
	pe_op->refcount = 1;
	pe_op->hostname = node;
	pe_op->node_uuid = uuid;
	pe_op->user_data = run_user_data;
	pe_op->rname = strdup(ID(action_rsc));
	pe_op->rclass = strdup(crm_element_value(action_rsc, XML_AGENT_ATTR_CLASS));
	tmp_provider = crm_element_value(action_rsc, XML_AGENT_ATTR_PROVIDER);
	if (tmp_provider) {
		pe_op->rprovider = strdup(tmp_provider);
	}
	pe_op->rtype = strdup(crm_element_value(action_rsc, XML_ATTR_TYPE));

	if (target_rc_s != NULL) {
		pe_op->target_outcome = crm_parse_int(target_rc_s, "0");
	}
	op = convert_graph_action(NULL, action, 0, pe_op->target_outcome);

	params_all = create_xml_node(NULL, XML_TAG_PARAMS);
	g_hash_table_foreach(op->params, hash2field, params_all);
/*
 * TODO at some point.
	g_hash_table_foreach(action->extra, hash2field, params_all);
	g_hash_table_foreach(rsc->parameters, hash2field, params_all);
	g_hash_table_foreach(action->meta, hash2metafield, params_all);
*/
	filter_action_parameters(params_all, PE_CRM_VERSION);
	pe_op->op_digest = calculate_operation_digest(params_all, PE_CRM_VERSION);

	pe_op->method = strdup(op->op_type);

	pe_op->params = qb_skiplist_create();
	if (op->params != NULL) {
		g_hash_table_foreach(op->params, dup_attr, pe_op->params);
	}

	pe_op->interval = op->interval;
	pe_op->timeout = op->timeout;
	if (pe_op->timeout == 0) {
		if (pe_op->interval == 0) {
			pe_op->timeout = PE_DEFAULT_TIMEOUT;
		} else {
			pe_op->timeout = pe_op->interval / 2;
		}
	}
	pe_op->action = action;
	pe_op->graph = graph;
	pe_op->action_id = action->id;
	pe_op->graph_id = graph->id;
	pe_op->time_execed = qb_util_stopwatch_create();

	free_lrm_op(op);
	free_xml(params_all);

	run_fn(pe_op);

	qb_leave();

	return TRUE;
}
예제 #15
0
/*	 A_TE_INVOKE, A_TE_CANCEL	*/
void
do_te_invoke(long long action,
	     enum crmd_fsa_cause cause,
	     enum crmd_fsa_state cur_state,
	     enum crmd_fsa_input current_input,
	     fsa_data_t *msg_data)
{
	if(AM_I_DC == FALSE) {
		crm_err("Not DC: No need to invoke the TE (anymore): %s",
			fsa_action2string(action));
		return;
		
	} else if(fsa_state != S_TRANSITION_ENGINE && (action & A_TE_INVOKE)) {
		crm_err("No need to invoke the TE (%s) in state %s",
			fsa_action2string(action),
			fsa_state2string(fsa_state));
		return;
	}

	if(action & A_TE_CANCEL) {
		crm_debug("Cancelling the transition: %s",
			  transition_graph->complete?"inactive":"active");
		abort_transition(INFINITY, tg_restart, "Peer Cancelled", NULL);
		if(transition_graph && 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 && 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 && 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);
		}

		if (is_timer_started(transition_timer)) {
		    crm_debug("The transitioner wait for a transition timer");
		    return;
		}

		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);
		}	
	}
}
예제 #16
0
enum cib_errors 
cib_process_change(
	const char *op, int options, const char *section, crm_data_t *input,
	crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer)
{
	gboolean verbose = FALSE;
	crm_data_t *failed = NULL;
	enum cib_errors result = cib_ok;
	int cib_update_op = CIB_UPDATE_OP_NONE;

	crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section));


	if (strcasecmp(CIB_OP_CREATE, op) == 0) {
		cib_update_op = CIB_UPDATE_OP_ADD;
		
	} else if (strcasecmp(CIB_OP_UPDATE, op) == 0) {
		cib_update_op = CIB_UPDATE_OP_MODIFY;
		
	} else if (strcasecmp(CIB_OP_DELETE_ALT, op) == 0) {
		cib_update_op = CIB_UPDATE_OP_DELETE;
		
	} else {
		crm_err("Incorrect request handler invoked for \"%s\" op",
			crm_str(op));
		return cib_operation;
	}

	result = cib_ok;
	if (options & cib_verbose) {
		verbose = TRUE;
	}
	
	if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
		section = NULL;
	}

	if(input == NULL) {
		crm_err("Cannot perform modification with no data");
		return cib_NOOBJECT;
	}
	
	crm_validate_data(input);
	crm_validate_data(*result_cib);
	failed = create_xml_node(NULL, XML_TAG_FAILED);
	
	/* make changes to a temp copy then activate */
	if(section == NULL) {
		int lpc = 0;
		const char *type = NULL;
		crm_data_t *sub_input = NULL;

		/* order is no longer important here */
		const char *type_list[] = {
			XML_CIB_TAG_NODES,
			XML_CIB_TAG_CONSTRAINTS,
			XML_CIB_TAG_RESOURCES,
			XML_CIB_TAG_STATUS,
			XML_CIB_TAG_CRMCONFIG
		};

		copy_in_properties(*result_cib, input);
	
		for(lpc = 0; lpc < DIMOF(type_list); lpc++) {
			type = type_list[lpc];
	
			if(result == cib_ok) {
				crm_debug_2("Processing section=%s", type);
				sub_input = get_object_root(type, input);
				result = updateList(
					*result_cib, sub_input, failed,
					cib_update_op, type);
			}
		}

	} else {
		result = updateList(
			*result_cib, input, failed, cib_update_op, section);
	}

	if (result != cib_ok || xml_has_children(failed)) {
		if(result == cib_ok) {
			result = cib_unknown;
		}
		crm_log_xml_err(failed, "CIB Update failures");
		*answer = failed;
	} else {
		free_xml(failed);
	}

	return result;
}
gboolean
cib_action_update(crm_action_t *action, int status, int op_rc)
{
	char *op_id  = NULL;
	char *code   = NULL;
	char *digest = NULL;
	xmlNode *tmp      = NULL;
	xmlNode *params   = NULL;
	xmlNode *state    = NULL;
	xmlNode *rsc      = NULL;
	xmlNode *xml_op   = NULL;
	xmlNode *action_rsc = NULL;

	enum cib_errors rc = cib_ok;

	const char *name   = NULL;
	const char *value  = NULL;
	const char *rsc_id = NULL;
	const char *task   = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
	const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
	const char *task_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
	const char *target_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);

	int call_options = cib_quorum_override|cib_scope_local;

	if(status == LRM_OP_PENDING) {
	    crm_debug("%s %d: Recording pending operation %s on %s",
		     crm_element_name(action->xml), action->id, task_uuid, target);
	} else {
	    crm_warn("%s %d: %s on %s timed out",
		     crm_element_name(action->xml), action->id, task_uuid, target);
	}
	
	action_rsc = find_xml_node(action->xml, XML_CIB_TAG_RESOURCE, TRUE);
	if(action_rsc == NULL) {
		return FALSE;
	}
	
	rsc_id = ID(action_rsc);
	CRM_CHECK(rsc_id != NULL,
		  crm_log_xml_err(action->xml, "Bad:action");
		  return FALSE);
	
/*
  update the CIB

<node_state id="hadev">
      <lrm>
        <lrm_resources>
          <lrm_resource id="rsc2" last_op="start" op_code="0" target="hadev"/>
*/

	state = create_xml_node(NULL, XML_CIB_TAG_STATE);

	crm_xml_add(state, XML_ATTR_UUID,  target_uuid);
	crm_xml_add(state, XML_ATTR_UNAME, target);
	
	rsc = create_xml_node(state, XML_CIB_TAG_LRM);
	crm_xml_add(rsc, XML_ATTR_ID, target_uuid);

	rsc = create_xml_node(rsc,   XML_LRM_TAG_RESOURCES);
	rsc = create_xml_node(rsc,   XML_LRM_TAG_RESOURCE);
	crm_xml_add(rsc, XML_ATTR_ID, rsc_id);

	name = XML_ATTR_TYPE;
	value = crm_element_value(action_rsc, name);
	crm_xml_add(rsc, name, value);
	name = XML_AGENT_ATTR_CLASS;
	value = crm_element_value(action_rsc, name);
	crm_xml_add(rsc, name, value);
	name = XML_AGENT_ATTR_PROVIDER;
	value = crm_element_value(action_rsc, name);
	crm_xml_add(rsc, name, value);

	xml_op = create_xml_node(rsc, XML_LRM_TAG_RSC_OP);	
	crm_xml_add(xml_op, XML_ATTR_ID, task);
	
	op_id = generate_op_key(rsc_id, task, action->interval);
	crm_xml_add(xml_op, XML_ATTR_ID, op_id);
	crm_free(op_id);
	
	crm_xml_add_int(xml_op, XML_LRM_ATTR_CALLID, -1);
	crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task);
	crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
	crm_xml_add_int(xml_op, XML_LRM_ATTR_OPSTATUS, status);
	crm_xml_add_int(xml_op, XML_LRM_ATTR_INTERVAL, action->interval);
	crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op_rc);
	crm_xml_add(xml_op, XML_ATTR_ORIGIN, __FUNCTION__);

	if(crm_str_eq(task, CRMD_ACTION_MIGRATED, TRUE)) {
	    char *key = crm_meta_name("migrate_source_uuid");
	    xmlNode *attrs = first_named_child(action->xml, XML_TAG_ATTRS);
	    const char *host = crm_element_value(attrs, key);
	    CRM_CHECK(host != NULL, crm_log_xml_err(action->xml, "Bad Op"));
	    crm_xml_add(xml_op, CRMD_ACTION_MIGRATED, host);
	    crm_free(key);
	}	
	
	code = generate_transition_key(
	    transition_graph->id, action->id, get_target_rc(action), te_uuid);
	crm_xml_add(xml_op, XML_ATTR_TRANSITION_KEY, code);
	crm_free(code);

	code = generate_transition_magic(
		crm_element_value(xml_op, XML_ATTR_TRANSITION_KEY), status, op_rc);
	crm_xml_add(xml_op,  XML_ATTR_TRANSITION_MAGIC, code);
	crm_free(code);

	tmp = find_xml_node(action->xml, "attributes", TRUE);
	params = create_xml_node(NULL, XML_TAG_PARAMS);
	copy_in_properties(params, tmp);
	
	filter_action_parameters(params, CRM_FEATURE_SET);
	digest = calculate_xml_digest(params, TRUE, FALSE);

	/* info for now as this area has been problematic to debug */
	crm_debug("Calculated digest %s for %s (%s)\n", 
		  digest, ID(xml_op),
		  crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
	crm_log_xml(LOG_DEBUG,  "digest:source", params);

	crm_xml_add(xml_op, XML_LRM_ATTR_OP_DIGEST, digest);
	crm_free(digest);
	free_xml(params);
	
	crm_debug_3("Updating CIB with \"%s\" (%s): %s %s on %s",
		  status<0?"new action":XML_ATTR_TIMEOUT,
		  crm_element_name(action->xml), crm_str(task), rsc_id, target);
	
	rc = fsa_cib_conn->cmds->update(
		fsa_cib_conn, XML_CIB_TAG_STATUS, state, call_options);

	crm_debug_2("Updating CIB with %s action %d: %s on %s (call_id=%d)",
		  op_status2text(status), action->id, task_uuid, target, rc);

	add_cib_op_callback(fsa_cib_conn, rc, FALSE, NULL, cib_action_updated);
	free_xml(state);

	action->sent_update = TRUE;
	
	if(rc < cib_ok) {
		return FALSE;
	}

	return TRUE;
}
예제 #18
0
static void
tengine_stonith_notify(stonith_t * st, const char *event, xmlNode * msg)
{
    int rc = -99;
    const char *origin = NULL;
    const char *target = NULL;
    const char *executioner = NULL;
    xmlNode *action = get_xpath_object("//st-data", msg, LOG_ERR);

    if (action == NULL) {
        crm_log_xml_err(msg, "Notify data not found");
        return;
    }

    crm_log_xml_debug(msg, "stonith_notify");
    crm_element_value_int(msg, F_STONITH_RC, &rc);
    origin = crm_element_value(action, F_STONITH_ORIGIN);
    target = crm_element_value(action, F_STONITH_TARGET);
    executioner = crm_element_value(action, F_STONITH_DELEGATE);

    if (rc == stonith_ok && crm_str_eq(target, fsa_our_uname, TRUE)) {
        crm_err("We were alegedly just fenced by %s for %s!", executioner, origin);
        register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);
        return;
        
    }

    crm_notice("Peer %s was%s terminated (%s) by %s for %s: %s (ref=%s)",
               target, rc == stonith_ok?"":" not",
               crm_element_value(action, F_STONITH_OPERATION),
               executioner ? executioner : "<anyone>", origin,
               stonith_error2string(rc), crm_element_value(action, F_STONITH_REMOTE));

#if SUPPORT_CMAN
    if (rc == stonith_ok && is_cman_cluster()) {
        int local_rc = 0;
        int confirm = 0;
        char *target_copy = crm_strdup(target);

        /* In case fenced hasn't noticed yet */
        local_rc = fenced_external(target_copy);
        if (local_rc != 0) {
            crm_err("Could not notify CMAN that '%s' is now fenced: %d", target, local_rc);
        } else {
            crm_notice("Notified CMAN that '%s' is now fenced", target);
        }

        /* In case fenced is already trying to shoot it */
        confirm = open("/var/run/cluster/fenced_override", O_NONBLOCK|O_WRONLY);
        if (confirm) {
            int len = strlen(target_copy);

            errno = 0;
            local_rc = write(confirm, target_copy, len);
            write(confirm, "\n", 1);

            if(errno == EBADF) {
                crm_trace("CMAN not expecting %s to be fenced (yet)", target);
                
            } else if (local_rc < len) {
                crm_perror(LOG_ERR, "Confirmation of CMAN fencing event for '%s' failed: %d", target, local_rc);

            } else {
                fsync(confirm);
                crm_notice("Confirmed CMAN fencing event for '%s'", target);
            }
            close(confirm);
        }
    }
#endif

    if (rc == stonith_ok && safe_str_eq(target, origin)) {
        if (fsa_our_dc == NULL || safe_str_eq(fsa_our_dc, target)) {
            crm_notice("Target was our leader %s (recorded: %s)",
                       target, fsa_our_dc ? fsa_our_dc : "<unset>");
            /* Given the CIB resyncing that occurs around elections,
             * have one node update the CIB now and, if the new DC is different,
             * have them do so too after the election
             */
            if (safe_str_eq(executioner, fsa_our_uname)) {
                const char *uuid = get_uuid(target);

                send_stonith_update(NULL, target, uuid);
            } else {
                stonith_cleanup_list = g_list_append(stonith_cleanup_list, crm_strdup(target));
            }
        }
    }
}
예제 #19
0
void
cib_process_request(xmlNode * request, gboolean force_synchronous, gboolean privileged,
                    gboolean unused, crm_client_t * cib_client)
{
    int call_type = 0;
    int call_options = 0;

    gboolean process = TRUE;
    gboolean is_update = TRUE;
    gboolean from_peer = TRUE;
    gboolean needs_reply = TRUE;
    gboolean local_notify = FALSE;
    gboolean needs_forward = FALSE;
    gboolean global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE));

    xmlNode *op_reply = NULL;
    xmlNode *result_diff = NULL;

    int rc = pcmk_ok;
    const char *op = crm_element_value(request, F_CIB_OPERATION);
    const char *originator = crm_element_value(request, F_ORIG);
    const char *host = crm_element_value(request, F_CIB_HOST);
    const char *target = NULL;
    const char *call_id = crm_element_value(request, F_CIB_CALLID);
    const char *client_id = crm_element_value(request, F_CIB_CLIENTID);
    const char *client_name = crm_element_value(request, F_CIB_CLIENTNAME);
    const char *reply_to = crm_element_value(request, F_CIB_ISREPLY);

    if (cib_client) {
        from_peer = FALSE;
    }

    cib_num_ops++;
    if (cib_num_ops == 0) {
        cib_num_fail = 0;
        cib_num_local = 0;
        cib_num_updates = 0;
        crm_info("Stats wrapped around");
    }

    crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
    if (force_synchronous) {
        call_options |= cib_sync_call;
    }

    if (host != NULL && strlen(host) == 0) {
        host = NULL;
    }

    if (host) {
        target = host;

    } else if (call_options & cib_scope_local) {
        target = "local host";

    } else {
        target = "master";
    }

    if (from_peer) {
        crm_trace("Processing peer %s operation from %s/%s on %s intended for %s (reply=%s)",
                  op, client_name, call_id, originator, target, reply_to);
    } else {
        crm_xml_add(request, F_ORIG, cib_our_uname);
        crm_trace("Processing local %s operation from %s/%s intended for %s", op, client_name, call_id, target);
    }

    rc = cib_get_operation_id(op, &call_type);
    if (rc != pcmk_ok) {
        /* TODO: construct error reply? */
        crm_err("Pre-processing of command failed: %s", pcmk_strerror(rc));
        return;
    }

    if (from_peer == FALSE) {
        parse_local_options(cib_client, call_type, call_options, host, op,
                            &local_notify, &needs_reply, &process, &needs_forward);

    } else if (parse_peer_options(call_type, request, &local_notify,
                                  &needs_reply, &process, &needs_forward) == FALSE) {
        return;
    }

    is_update = cib_op_modifies(call_type);
    if (is_update) {
        cib_num_updates++;
    }

    if (call_options & cib_discard_reply) {
        needs_reply = is_update;
        local_notify = FALSE;
    }

    if (needs_forward) {
        const char *host = crm_element_value(request, F_CIB_HOST);
        const char *section = crm_element_value(request, F_CIB_SECTION);

        crm_info("Forwarding %s operation for section %s to %s (origin=%s/%s/%s)",
                 op,
                 section ? section : "'all'",
                 host ? host : "master",
                 originator ? originator : "local",
                 client_name, call_id);

        forward_request(request, cib_client, call_options);
        return;
    }

    if (cib_status != pcmk_ok) {
        const char *call = crm_element_value(request, F_CIB_CALLID);

        rc = cib_status;
        crm_err("Operation ignored, cluster configuration is invalid."
                " Please repair and restart: %s", pcmk_strerror(cib_status));

        op_reply = create_xml_node(NULL, "cib-reply");
        crm_xml_add(op_reply, F_TYPE, T_CIB);
        crm_xml_add(op_reply, F_CIB_OPERATION, op);
        crm_xml_add(op_reply, F_CIB_CALLID, call);
        crm_xml_add(op_reply, F_CIB_CLIENTID, client_id);
        crm_xml_add_int(op_reply, F_CIB_CALLOPTS, call_options);
        crm_xml_add_int(op_reply, F_CIB_RC, rc);

        crm_trace("Attaching reply output");
        add_message_xml(op_reply, F_CIB_CALLDATA, the_cib);

        crm_log_xml_explicit(op_reply, "cib:reply");

    } else if (process) {
        time_t finished = 0;

        int now = time(NULL);
        int level = LOG_INFO;
        const char *section = crm_element_value(request, F_CIB_SECTION);

        cib_num_local++;
        rc = cib_process_command(request, &op_reply, &result_diff, privileged);

        if (is_update == FALSE) {
            level = LOG_TRACE;

        } else if (global_update) {
            switch (rc) {
                case pcmk_ok:
                    level = LOG_INFO;
                    break;
                case -pcmk_err_old_data:
                case -pcmk_err_diff_resync:
                case -pcmk_err_diff_failed:
                    level = LOG_TRACE;
                    break;
                default:
                    level = LOG_ERR;
            }

        } else if (rc != pcmk_ok && is_update) {
            cib_num_fail++;
            level = LOG_WARNING;
        }

        do_crm_log(level,
                   "Completed %s operation for section %s: %s (rc=%d, origin=%s/%s/%s, version=%s.%s.%s)",
                   op, section ? section : "'all'", pcmk_strerror(rc), rc,
                   originator ? originator : "local", client_name, call_id,
                   the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN) : "0",
                   the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION) : "0",
                   the_cib ? crm_element_value(the_cib, XML_ATTR_NUMUPDATES) : "0");

        finished = time(NULL);
        if (finished - now > 3) {
            crm_trace("%s operation took %ds to complete", op, finished - now);
            crm_write_blackbox(0, NULL);
        }

        if (op_reply == NULL && (needs_reply || local_notify)) {
            crm_err("Unexpected NULL reply to message");
            crm_log_xml_err(request, "null reply");
            needs_reply = FALSE;
            local_notify = FALSE;
        }
    }

    /* from now on we are the server */
    if(is_update && cib_legacy_mode() == FALSE) {
        crm_trace("Completed pre-sync update from %s/%s/%s%s",
                  originator ? originator : "local", client_name, call_id,
                  local_notify?" with local notification":"");

    } else if (needs_reply == FALSE || stand_alone) {
        /* nothing more to do...
         * this was a non-originating slave update
         */
        crm_trace("Completed slave update");

    } else if (call_options & cib_discard_reply) {
        crm_trace("Caller isn't interested in reply");

    } else if (from_peer) {
        if (is_update == FALSE || result_diff == NULL) {
            crm_trace("Request not broadcast: R/O call");

        } else if (call_options & cib_inhibit_bcast) {
            crm_trace("Request not broadcast: inhibited");

        } else if (rc != pcmk_ok) {
            crm_trace("Request not broadcast: call failed: %s", pcmk_strerror(rc));

        } else {
            crm_trace("Directing reply to %s", originator);
        }

        send_peer_reply(op_reply, result_diff, originator, FALSE);
    }

    if (local_notify && client_id) {
        crm_trace("Performing local %ssync notification for %s",
                  (call_options & cib_sync_call) ? "" : "a-", client_id);
        if (process == FALSE) {
            do_local_notify(request, client_id, call_options & cib_sync_call, from_peer);
        } else {
            do_local_notify(op_reply, client_id, call_options & cib_sync_call, from_peer);
        }
    }

    free_xml(op_reply);
    free_xml(result_diff);

    return;
}
예제 #20
0
static void
crmd_cs_dispatch(cpg_handle_t handle,
                         const struct cpg_name *groupName,
                         uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
{
    int seq = 0;
    xmlNode *xml = NULL;
    const char *seq_s = NULL;
    crm_node_t *peer = NULL;
    enum crm_proc_flag flag = crm_proc_cpg;

    uint32_t kind = 0;
    const char *from = NULL;
    char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);

    if(data == NULL) {
        return;
    }
    xml = string2xml(data);
    if (xml == NULL) {
        crm_err("Could not parse message content (%d): %.100s", kind, data);
        free(data);
        return;
    }

    switch (kind) {
        case crm_class_members:
            seq_s = crm_element_value(xml, "id");
            seq = crm_int_helper(seq_s, NULL);
            set_bit(fsa_input_register, R_PEER_DATA);
            post_cache_update(seq);

            /* fall through */
        case crm_class_quorum:
            crm_update_quorum(crm_have_quorum, FALSE);
            if (AM_I_DC) {
                const char *votes = crm_element_value(xml, "expected");

                if (votes == NULL || check_number(votes) == FALSE) {
                    crm_log_xml_err(xml, "Invalid quorum/membership update");

                } else {
                    int rc = update_attr_delegate(fsa_cib_conn,
                                                  cib_quorum_override | cib_scope_local |
                                                  cib_inhibit_notify,
                                                  XML_CIB_TAG_CRMCONFIG, NULL, NULL, NULL, NULL,
                                                  XML_ATTR_EXPECTED_VOTES, votes, FALSE, NULL);

                    crm_info("Setting expected votes to %s", votes);
                    if (pcmk_ok > rc) {
                        crm_err("Quorum update failed: %s", pcmk_strerror(rc));
                    }
                }
            }
            break;

        case crm_class_cluster:
            crm_xml_add(xml, F_ORIG, from);
            /* crm_xml_add_int(xml, F_SEQ, wrapper->id); Fake? */

            if (is_heartbeat_cluster()) {
                flag = crm_proc_heartbeat;

            } else if (is_classic_ais_cluster()) {
                flag = crm_proc_plugin;
            }

            peer = crm_get_peer(0, from);
            if (is_not_set(peer->processes, flag)) {
                /* If we can still talk to our peer process on that node,
                 * then its also part of the corosync membership
                 */
                crm_warn("Receiving messages from a node we think is dead: %s[%d]", peer->uname,
                         peer->id);
                crm_update_peer_proc(__FUNCTION__, peer, flag, ONLINESTATUS);
            }
            crmd_ha_msg_filter(xml);
            break;

        case crm_class_rmpeer:
            /* Ignore */
            break;

        case crm_class_notify:
        case crm_class_nodeid:
            crm_err("Unexpected message class (%d): %.100s", kind, data);
            break;

        default:
            crm_err("Invalid message class (%d): %.100s", kind, data);
    }

    free(data);
    free_xml(xml);
}
예제 #21
0
파일: messages.c 프로젝트: grueni/pacemaker
enum crmd_fsa_input
handle_request(xmlNode * stored_msg, enum crmd_fsa_cause cause)
{
    xmlNode *msg = NULL;
    const char *op = crm_element_value(stored_msg, F_CRM_TASK);

    /* Optimize this for the DC - it has the most to do */

    if (op == NULL) {
        crm_log_xml_err(stored_msg, "Bad message");
        return I_NULL;
    }

    if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
        const char *from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
        crm_node_t *node = crm_find_peer(0, from);

        crm_update_peer_expected(__FUNCTION__, node, CRMD_JOINSTATE_DOWN);
        if(AM_I_DC == FALSE) {
            return I_NULL; /* Done */
        }
    }

    /*========== DC-Only Actions ==========*/
    if (AM_I_DC) {
        if (strcmp(op, CRM_OP_JOIN_ANNOUNCE) == 0) {
            return I_NODE_JOIN;

        } else if (strcmp(op, CRM_OP_JOIN_REQUEST) == 0) {
            return I_JOIN_REQUEST;

        } else if (strcmp(op, CRM_OP_JOIN_CONFIRM) == 0) {
            return I_JOIN_RESULT;

        } else if (strcmp(op, CRM_OP_SHUTDOWN) == 0) {
            const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
            gboolean dc_match = safe_str_eq(host_from, fsa_our_dc);

            if (is_set(fsa_input_register, R_SHUTDOWN)) {
                crm_info("Shutting ourselves down (DC)");
                return I_STOP;

            } else if (dc_match) {
                crm_err("We didn't ask to be shut down, yet our"
                        " TE is telling us to. Better get out now!");
                return I_TERMINATE;

            } else if (fsa_state != S_STOPPING) {
                crm_err("Another node is asking us to shutdown" " but we think we're ok.");
                return I_ELECTION;
            }

        } else if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
            /* a slave wants to shut down */
            /* create cib fragment and add to message */
            return handle_shutdown_request(stored_msg);
        }
    }

    /*========== common actions ==========*/
    if (strcmp(op, CRM_OP_NOVOTE) == 0) {
        ha_msg_input_t fsa_input;

        fsa_input.msg = stored_msg;
        register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
                               A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__);

    } else if (strcmp(op, CRM_OP_THROTTLE) == 0) {
        throttle_update(stored_msg);
        return I_NULL;

    } else if (strcmp(op, CRM_OP_CLEAR_FAILCOUNT) == 0) {
        return handle_failcount_op(stored_msg);

    } else if (strcmp(op, CRM_OP_VOTE) == 0) {
        /* count the vote and decide what to do after that */
        ha_msg_input_t fsa_input;

        fsa_input.msg = stored_msg;
        register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
                               A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__);

        /* Sometimes we _must_ go into S_ELECTION */
        if (fsa_state == S_HALT) {
            crm_debug("Forcing an election from S_HALT");
            return I_ELECTION;
#if 0
        } else if (AM_I_DC) {
            /* This is the old way of doing things but what is gained? */
            return I_ELECTION;
#endif
        }

    } else if (strcmp(op, CRM_OP_JOIN_OFFER) == 0) {
        crm_debug("Raising I_JOIN_OFFER: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
        return I_JOIN_OFFER;

    } else if (strcmp(op, CRM_OP_JOIN_ACKNAK) == 0) {
        crm_debug("Raising I_JOIN_RESULT: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
        return I_JOIN_RESULT;

    } else if (strcmp(op, CRM_OP_LRM_DELETE) == 0
               || strcmp(op, CRM_OP_LRM_FAIL) == 0
               || strcmp(op, CRM_OP_LRM_REFRESH) == 0 || strcmp(op, CRM_OP_REPROBE) == 0) {

        crm_xml_add(stored_msg, F_CRM_SYS_TO, CRM_SYSTEM_LRMD);
        return I_ROUTER;

    } else if (strcmp(op, CRM_OP_NOOP) == 0) {
        return I_NULL;

    } else if (strcmp(op, CRM_OP_LOCAL_SHUTDOWN) == 0) {

        crm_shutdown(SIGTERM);
        /*return I_SHUTDOWN; */
        return I_NULL;

        /*========== (NOT_DC)-Only Actions ==========*/
    } else if (AM_I_DC == FALSE && strcmp(op, CRM_OP_SHUTDOWN) == 0) {

        const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
        gboolean dc_match = safe_str_eq(host_from, fsa_our_dc);

        if (dc_match || fsa_our_dc == NULL) {
            if (is_set(fsa_input_register, R_SHUTDOWN) == FALSE) {
                crm_err("We didn't ask to be shut down, yet our DC is telling us to.");
                set_bit(fsa_input_register, R_STAYDOWN);
                return I_STOP;
            }
            crm_info("Shutting down");
            return I_STOP;

        } else {
            crm_warn("Discarding %s op from %s", op, host_from);
        }

    } else if (strcmp(op, CRM_OP_PING) == 0) {
        /* eventually do some stuff to figure out
         * if we /are/ ok
         */
        const char *sys_to = crm_element_value(stored_msg, F_CRM_SYS_TO);
        xmlNode *ping = create_xml_node(NULL, XML_CRM_TAG_PING);

        crm_xml_add(ping, XML_PING_ATTR_STATUS, "ok");
        crm_xml_add(ping, XML_PING_ATTR_SYSFROM, sys_to);
        crm_xml_add(ping, "crmd_state", fsa_state2string(fsa_state));

        /* Ok, so technically not so interesting, but CTS needs to see this */
        crm_notice("Current ping state: %s", fsa_state2string(fsa_state));

        msg = create_reply(stored_msg, ping);
        if (msg) {
            (void)relay_message(msg, TRUE);
        }

        free_xml(ping);
        free_xml(msg);

    } else if (strcmp(op, CRM_OP_RM_NODE_CACHE) == 0) {
        int id = 0;
        const char *name = NULL;

        crm_element_value_int(stored_msg, XML_ATTR_ID, &id);
        name = crm_element_value(stored_msg, XML_ATTR_UNAME);

        if(cause == C_IPC_MESSAGE) {
            msg = create_request(CRM_OP_RM_NODE_CACHE, NULL, NULL, CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL);
            if (send_cluster_message(NULL, crm_msg_crmd, msg, TRUE) == FALSE) {
                crm_err("Could not instruct peers to remove references to node %s/%u", name, id);
            } else {
                crm_notice("Instructing peers to remove references to node %s/%u", name, id);
            }
            free_xml(msg);

        } else {

            reap_crm_member(id, name);
            if(attrd_ipc) {
                int rc = 0;
                xmlNode *update = create_xml_node(NULL, __FUNCTION__);

                crm_xml_add(update, F_TYPE, T_ATTRD);
                crm_xml_add(update, F_ORIG, crm_system_name);

                crm_xml_add(update, F_ATTRD_TASK, "peer-remove");
                crm_xml_add(update, F_ATTRD_HOST, name);
                crm_xml_add_int(update, F_ATTRD_HOST_ID, id);

                rc = crm_ipc_send(attrd_ipc, update, crm_ipc_client_response, 0, NULL);
                if (rc > 0) {
                    rc = pcmk_ok;
                }

                crm_debug("Peer cache cleanup for %s (%d): %s (%d)", name, id, pcmk_strerror(rc), rc);
                free_xml(update);
            }
        }

    } else {
        crm_err("Unexpected request (%s) sent to %s", op, AM_I_DC ? "the DC" : "non-DC node");
        crm_log_xml_err(stored_msg, "Unexpected");
    }

    return I_NULL;
}
예제 #22
0
static gboolean
crmd_ais_dispatch(AIS_Message * wrapper, char *data, int sender)
{
    int seq = 0;
    xmlNode *xml = NULL;
    const char *seq_s = NULL;

    xml = string2xml(data);
    if (xml == NULL) {
        crm_err("Could not parse message content (%d): %.100s", wrapper->header.id, data);
        return TRUE;
    }

    switch (wrapper->header.id) {
        case crm_class_members:
            seq_s = crm_element_value(xml, "id");
            seq = crm_int_helper(seq_s, NULL);
            set_bit_inplace(fsa_input_register, R_PEER_DATA);
            post_cache_update(seq);

            /* fall through */
        case crm_class_quorum:
            crm_update_quorum(crm_have_quorum, FALSE);
            if (AM_I_DC) {
                const char *votes = crm_element_value(xml, "expected");

                if (votes == NULL || check_number(votes) == FALSE) {
                    crm_log_xml_err(xml, "Invalid quorum/membership update");

                } else {
                    int rc = update_attr(fsa_cib_conn,
                                         cib_quorum_override | cib_scope_local | cib_inhibit_notify,
                                         XML_CIB_TAG_CRMCONFIG, NULL, NULL, NULL, NULL,
                                         XML_ATTR_EXPECTED_VOTES, votes, FALSE);

                    crm_info("Setting expected votes to %s", votes);
                    if (cib_ok > rc) {
                        crm_err("Quorum update failed: %s", cib_error2string(rc));
                    }
                }
            }
            break;

        case crm_class_cluster:
            crm_xml_add(xml, F_ORIG, wrapper->sender.uname);
            crm_xml_add_int(xml, F_SEQ, wrapper->id);
            crmd_ha_msg_filter(xml);
            break;

        case crm_class_rmpeer:
            /* Ignore */
            break;

        case crm_class_notify:
        case crm_class_nodeid:
            crm_err("Unexpected message class (%d): %.100s", wrapper->header.id, data);
            break;

        default:
            crm_err("Invalid message class (%d): %.100s", wrapper->header.id, data);
    }

    free_xml(xml);
    return TRUE;
}
예제 #23
0
gboolean
cib_action_update(crm_action_t * action, int status, int op_rc)
{
    lrm_op_t *op = NULL;
    xmlNode *state = NULL;
    xmlNode *rsc = NULL;
    xmlNode *xml_op = NULL;
    xmlNode *action_rsc = NULL;

    enum cib_errors rc = cib_ok;

    const char *name = NULL;
    const char *value = NULL;
    const char *rsc_id = NULL;
    const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
    const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
    const char *task_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
    const char *target_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);

    int call_options = cib_quorum_override | cib_scope_local;
    int target_rc = get_target_rc(action);

    if (status == LRM_OP_PENDING) {
        crm_debug("%s %d: Recording pending operation %s on %s",
                  crm_element_name(action->xml), action->id, task_uuid, target);
    } else {
        crm_warn("%s %d: %s on %s timed out",
                 crm_element_name(action->xml), action->id, task_uuid, target);
    }

    action_rsc = find_xml_node(action->xml, XML_CIB_TAG_RESOURCE, TRUE);
    if (action_rsc == NULL) {
        return FALSE;
    }

    rsc_id = ID(action_rsc);
    CRM_CHECK(rsc_id != NULL, crm_log_xml_err(action->xml, "Bad:action");
              return FALSE);

/*
  update the CIB

<node_state id="hadev">
      <lrm>
        <lrm_resources>
          <lrm_resource id="rsc2" last_op="start" op_code="0" target="hadev"/>
*/

    state = create_xml_node(NULL, XML_CIB_TAG_STATE);

    crm_xml_add(state, XML_ATTR_UUID, target_uuid);
    crm_xml_add(state, XML_ATTR_UNAME, target);

    rsc = create_xml_node(state, XML_CIB_TAG_LRM);
    crm_xml_add(rsc, XML_ATTR_ID, target_uuid);

    rsc = create_xml_node(rsc, XML_LRM_TAG_RESOURCES);
    rsc = create_xml_node(rsc, XML_LRM_TAG_RESOURCE);
    crm_xml_add(rsc, XML_ATTR_ID, rsc_id);

    name = XML_ATTR_TYPE;
    value = crm_element_value(action_rsc, name);
    crm_xml_add(rsc, name, value);
    name = XML_AGENT_ATTR_CLASS;
    value = crm_element_value(action_rsc, name);
    crm_xml_add(rsc, name, value);
    name = XML_AGENT_ATTR_PROVIDER;
    value = crm_element_value(action_rsc, name);
    crm_xml_add(rsc, name, value);

    op = convert_graph_action(NULL, action, status, op_rc);
    op->call_id = -1;
    op->user_data = generate_transition_key(transition_graph->id, action->id, target_rc, te_uuid);

    xml_op = create_operation_update(rsc, op, CRM_FEATURE_SET, target_rc, __FUNCTION__, LOG_INFO);
    free_lrm_op(op);

    crm_debug_3("Updating CIB with \"%s\" (%s): %s %s on %s",
                status < 0 ? "new action" : XML_ATTR_TIMEOUT,
                crm_element_name(action->xml), crm_str(task), rsc_id, target);
    crm_log_xml_trace(xml_op, "Op");

    rc = fsa_cib_conn->cmds->update(fsa_cib_conn, XML_CIB_TAG_STATUS, state, call_options);

    crm_debug_2("Updating CIB with %s action %d: %s on %s (call_id=%d)",
                op_status2text(status), action->id, task_uuid, target, rc);

    add_cib_op_callback(fsa_cib_conn, rc, FALSE, NULL, cib_action_updated);
    free_xml(state);

    action->sent_update = TRUE;

    if (rc < cib_ok) {
        return FALSE;
    }

    return TRUE;
}
예제 #24
0
static gboolean
parse_peer_options(int call_type, xmlNode * request,
                   gboolean * local_notify, gboolean * needs_reply, gboolean * process,
                   gboolean * needs_forward)
{
    const char *op = NULL;
    const char *host = NULL;
    const char *delegated = NULL;
    const char *originator = crm_element_value(request, F_ORIG);
    const char *reply_to = crm_element_value(request, F_CIB_ISREPLY);
    const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE);

    gboolean is_reply = safe_str_eq(reply_to, cib_our_uname);

    if (crm_is_true(update)) {
        *needs_reply = FALSE;
        if (is_reply) {
            *local_notify = TRUE;
            crm_trace("Processing global/peer update from %s"
                      " that originated from us", originator);
        } else {
            crm_trace("Processing global/peer update from %s", originator);
        }
        return TRUE;
    }

    host = crm_element_value(request, F_CIB_HOST);
    if (host != NULL && safe_str_eq(host, cib_our_uname)) {
        crm_trace("Processing request sent to us from %s", originator);
        return TRUE;

    } else if (host == NULL && cib_is_master == TRUE) {
        crm_trace("Processing request sent to master instance from %s", originator);
        return TRUE;
    }

    op = crm_element_value(request, F_CIB_OPERATION);
    if(safe_str_eq(op, "cib_shutdown_req")) {
        /* Always process these */
        *local_notify = FALSE;
        if(reply_to == NULL || is_reply) {
            *process = TRUE;
        }
        if(is_reply) {
            *needs_reply = FALSE;
        }
        return *process;
    }

    if (is_reply) {
        crm_trace("Forward reply sent from %s to local clients", originator);
        *process = FALSE;
        *needs_reply = FALSE;
        *local_notify = TRUE;
        return TRUE;
    }

    delegated = crm_element_value(request, F_CIB_DELEGATED);
    if (delegated != NULL) {
        crm_trace("Ignoring msg for master instance");

    } else if (host != NULL) {
        /* this is for a specific instance and we're not it */
        crm_trace("Ignoring msg for instance on %s", crm_str(host));

    } else if (reply_to == NULL && cib_is_master == FALSE) {
        /* this is for the master instance and we're not it */
        crm_trace("Ignoring reply to %s", crm_str(reply_to));

    } else if (safe_str_eq(op, "cib_shutdown_req")) {
        if (reply_to != NULL) {
            crm_debug("Processing %s from %s", op, host);
            *needs_reply = FALSE;

        } else {
            crm_debug("Processing %s reply from %s", op, host);
        }
        return TRUE;

    } else {
        crm_err("Nothing for us to do?");
        crm_log_xml_err(request, "Peer[inbound]");
    }

    return FALSE;
}
예제 #25
0
void
cib_process_request(xmlNode * request, gboolean force_synchronous, gboolean privileged,
                    gboolean from_peer, cib_client_t * cib_client)
{
    int call_type = 0;
    int call_options = 0;

    gboolean process = TRUE;
    gboolean is_update = TRUE;
    gboolean needs_reply = TRUE;
    gboolean local_notify = FALSE;
    gboolean needs_forward = FALSE;
    gboolean global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE));

    xmlNode *op_reply = NULL;
    xmlNode *result_diff = NULL;

    int rc = pcmk_ok;
    const char *op = crm_element_value(request, F_CIB_OPERATION);
    const char *originator = crm_element_value(request, F_ORIG);
    const char *host = crm_element_value(request, F_CIB_HOST);
    const char *client_id = crm_element_value(request, F_CIB_CLIENTID);

    crm_trace("%s Processing msg %s", cib_our_uname, crm_element_value(request, F_SEQ));

    cib_num_ops++;
    if (cib_num_ops == 0) {
        cib_num_fail = 0;
        cib_num_local = 0;
        cib_num_updates = 0;
        crm_info("Stats wrapped around");
    }

    if (host != NULL && strlen(host) == 0) {
        host = NULL;
    }

    crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
    if (force_synchronous) {
        call_options |= cib_sync_call;
    }

    crm_trace("Processing %s message (%s) for %s...",
                from_peer ? "peer" : "local",
                from_peer ? originator : cib_our_uname, host ? host : "master");

    rc = cib_get_operation_id(op, &call_type);
    if (rc != pcmk_ok) {
        /* TODO: construct error reply? */
        crm_err("Pre-processing of command failed: %s", pcmk_strerror(rc));
        return;
    }

    is_update = cib_op_modifies(call_type);
    if (is_update) {
        cib_num_updates++;
    }

    if (from_peer == FALSE) {
        parse_local_options(cib_client, call_type, call_options, host, op,
                            &local_notify, &needs_reply, &process, &needs_forward);

    } else if (parse_peer_options(call_type, request, &local_notify,
                                  &needs_reply, &process, &needs_forward) == FALSE) {
        return;
    }
    crm_trace("Finished determining processing actions");

    if (call_options & cib_discard_reply) {
        needs_reply = is_update;
        local_notify = FALSE;
    }

    if (needs_forward) {
        forward_request(request, cib_client, call_options);
        return;
    }

    if (cib_status != pcmk_ok) {
        rc = cib_status;
        crm_err("Operation ignored, cluster configuration is invalid."
                " Please repair and restart: %s", pcmk_strerror(cib_status));
        op_reply = cib_construct_reply(request, the_cib, cib_status);

    } else if (process) {
        int level = LOG_INFO;
        const char *section = crm_element_value(request, F_CIB_SECTION);

        cib_num_local++;
        rc = cib_process_command(request, &op_reply, &result_diff, privileged);

        if (global_update) {
            switch (rc) {
                case pcmk_ok:
                case -pcmk_err_old_data:
                case -pcmk_err_diff_resync:
                case -pcmk_err_diff_failed:
                    level = LOG_DEBUG_2;
                    break;
                default:
                    level = LOG_ERR;
            }

        } else if (safe_str_eq(op, CIB_OP_QUERY)) {
            level = LOG_DEBUG_2;

        } else if (rc != pcmk_ok) {
            cib_num_fail++;
            level = LOG_WARNING;

        } else if (safe_str_eq(op, CIB_OP_SLAVE)) {
            level = LOG_DEBUG_2;

        } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) {
            level = LOG_DEBUG_2;
        }

        do_crm_log_unlikely(level,
                       "Operation complete: op %s for section %s (origin=%s/%s/%s, version=%s.%s.%s): %s (rc=%d)",
                       op, section ? section : "'all'", originator ? originator : "local",
                       crm_element_value(request, F_CIB_CLIENTNAME), crm_element_value(request,
                                                                                       F_CIB_CALLID),
                       the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN) : "0",
                       the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION) : "0",
                       the_cib ? crm_element_value(the_cib, XML_ATTR_NUMUPDATES) : "0",
                       pcmk_strerror(rc), rc);

        if (op_reply == NULL && (needs_reply || local_notify)) {
            crm_err("Unexpected NULL reply to message");
            crm_log_xml_err(request, "null reply");
            needs_reply = FALSE;
            local_notify = FALSE;
        }
    }
    crm_trace("processing response cases %.16x %.16x", call_options, cib_sync_call);

    /* from now on we are the server */
    if (needs_reply == FALSE || stand_alone) {
        /* nothing more to do...
         * this was a non-originating slave update
         */
        crm_trace("Completed slave update");

    } else if (rc == pcmk_ok && result_diff != NULL && !(call_options & cib_inhibit_bcast)) {
        gboolean broadcast = FALSE;

        cib_local_bcast_num++;
        crm_xml_add_int(request, F_CIB_LOCAL_NOTIFY_ID, cib_local_bcast_num);
        broadcast = send_peer_reply(request, result_diff, originator, TRUE);

        if (broadcast &&
            client_id &&
            local_notify &&
            op_reply) {

            /* If we have been asked to sync the reply,
             * and a bcast msg has gone out, we queue the local notify
             * until we know the bcast message has been received */
            local_notify = FALSE;
            queue_local_notify(op_reply, client_id, (call_options & cib_sync_call), from_peer);
            op_reply = NULL; /* the reply is queued, so don't free here */
        }

    } else if (call_options & cib_discard_reply) {
        crm_trace("Caller isn't interested in reply");

    } else if (from_peer) {
        if (is_update == FALSE || result_diff == NULL) {
            crm_trace("Request not broadcast: R/O call");

        } else if (call_options & cib_inhibit_bcast) {
            crm_trace("Request not broadcast: inhibited");

        } else if (rc != pcmk_ok) {
            crm_trace("Request not broadcast: call failed: %s", pcmk_strerror(rc));
        } else {
            crm_trace("Directing reply to %s", originator);
        }

        send_peer_reply(op_reply, result_diff, originator, FALSE);
    }

    if (local_notify && client_id) {
        if (process == FALSE) {
            do_local_notify(request, client_id, call_options & cib_sync_call, from_peer);
        } else {
            do_local_notify(op_reply, client_id, call_options & cib_sync_call, from_peer);
        }
    }

    free_xml(op_reply);
    free_xml(result_diff);

    return;
}
예제 #26
0
파일: group.c 프로젝트: fghaas/pacemaker
gboolean
group_unpack(resource_t * rsc, pe_working_set_t * data_set)
{
    resource_t *self = NULL;
    xmlNode *xml_obj = rsc->xml;
    xmlNode *xml_self = copy_xml(rsc->xml);
    xmlNode *xml_native_rsc = NULL;
    group_variant_data_t *group_data = NULL;
    const char *group_ordered = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ORDERED);
    const char *group_colocated = g_hash_table_lookup(rsc->meta, "collocated");
    const char *clone_id = NULL;

    crm_debug_3("Processing resource %s...", rsc->id);

    crm_malloc0(group_data, sizeof(group_variant_data_t));
    group_data->num_children = 0;
    group_data->self = NULL;
    group_data->first_child = NULL;
    group_data->last_child = NULL;
    rsc->variant_opaque = group_data;

    group_data->ordered = TRUE;
    group_data->colocated = TRUE;

    if (group_ordered != NULL) {
        crm_str_to_boolean(group_ordered, &(group_data->ordered));
    }
    if (group_colocated != NULL) {
        crm_str_to_boolean(group_colocated, &(group_data->colocated));
    }

    /* this is a bit of a hack - but simplifies everything else */
    xmlNodeSetName(xml_self, ((const xmlChar *)XML_CIB_TAG_RESOURCE));
    if (common_unpack(xml_self, &self, NULL, data_set)) {
        group_data->self = self;
        self->restart_type = pe_restart_restart;

    } else {
        crm_log_xml_err(xml_self, "Couldnt unpack dummy child");
        return FALSE;
    }

    clone_id = crm_element_value(rsc->xml, XML_RSC_ATTR_INCARNATION);

    for (xml_native_rsc = __xml_first_child(xml_obj); xml_native_rsc != NULL;
         xml_native_rsc = __xml_next(xml_native_rsc)) {
        if (crm_str_eq((const char *)xml_native_rsc->name, XML_CIB_TAG_RESOURCE, TRUE)) {
            resource_t *new_rsc = NULL;

            crm_xml_add(xml_native_rsc, XML_RSC_ATTR_INCARNATION, clone_id);
            if (common_unpack(xml_native_rsc, &new_rsc, rsc, data_set) == FALSE) {
                pe_err("Failed unpacking resource %s", crm_element_value(xml_obj, XML_ATTR_ID));
                if (new_rsc != NULL && new_rsc->fns != NULL) {
                    new_rsc->fns->free(new_rsc);
                }
            }

            group_data->num_children++;
            rsc->children = g_list_append(rsc->children, new_rsc);

            if (group_data->first_child == NULL) {
                group_data->first_child = new_rsc;
            }
            group_data->last_child = new_rsc;
            print_resource(LOG_DEBUG_3, "Added", new_rsc, FALSE);
        }
    }

    if (group_data->num_children == 0) {
#if 0
        /* Bug #1287 */
        crm_config_err("Group %s did not have any children", rsc->id);
        return FALSE;
#else
        crm_config_warn("Group %s did not have any children", rsc->id);
        return TRUE;
#endif
    }

    crm_debug_3("Added %d children to resource %s...", group_data->num_children, rsc->id);

    return TRUE;
}