示例#1
0
void
cib_pre_notify(
	int options, const char *op, xmlNode *existing, xmlNode *update) 
{
	xmlNode *update_msg = NULL;
	const char *type = NULL;
	const char *id = NULL;
	gboolean needed = FALSE;

	g_hash_table_foreach(client_list, need_pre_notify, &needed);
	if(needed == FALSE) {
	    return;
	}

	/* TODO: consider pre-notification for removal */
	update_msg = create_xml_node(NULL, "pre-notify");

	if(update != NULL) {
		id = crm_element_value(update, XML_ATTR_ID);
	}
	
	crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY);
	crm_xml_add(update_msg, F_SUBTYPE, T_CIB_PRE_NOTIFY);
	crm_xml_add(update_msg, F_CIB_OPERATION, op);

	if(id != NULL) {
		crm_xml_add(update_msg, F_CIB_OBJID, id);
	}

	if(update != NULL) {
		crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
	} else if(existing != NULL) {
		crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(existing));
	}

	type = crm_element_value(update_msg, F_CIB_OBJTYPE);	
	attach_cib_generation(update_msg, "cib_generation", the_cib);
	
	if(existing != NULL) {
		add_message_xml(update_msg, F_CIB_EXISTING, existing);
	}
	if(update != NULL) {
		add_message_xml(update_msg, F_CIB_UPDATE, update);
	}

	g_hash_table_foreach(client_list, cib_notify_client, update_msg);
	
	if(update == NULL) {
		crm_debug_2("Performing operation %s (on section=%s)",
			    op, type);

	} else {
		crm_debug_2("Performing %s on <%s%s%s>",
			    op, type, id?" id=":"", id?id:"");
	}
		
	free_xml(update_msg);
}
示例#2
0
void
do_cib_notify(
	int options, const char *op, xmlNode *update,
	enum cib_errors result, xmlNode *result_data, const char *msg_type) 
{
	xmlNode *update_msg = NULL;
	const char *type = NULL;
	const char *id = NULL;

	update_msg = create_xml_node(NULL, "notify");

	if(result_data != NULL) {
		id = crm_element_value(result_data, XML_ATTR_ID);
	}
	
	crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY);
	crm_xml_add(update_msg, F_SUBTYPE, msg_type);
	crm_xml_add(update_msg, F_CIB_OPERATION, op);
	crm_xml_add_int(update_msg, F_CIB_RC, result);
	
	if(id != NULL) {
		crm_xml_add(update_msg, F_CIB_OBJID, id);
	}

	if(update != NULL) {
		crm_debug_4("Setting type to update->name: %s",
			    crm_element_name(update));
		crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
		type = crm_element_name(update);

	} else if(result_data != NULL) {
		crm_debug_4("Setting type to new_obj->name: %s",
			    crm_element_name(result_data));
		crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data));
		type = crm_element_name(result_data);
		
	} else {
		crm_debug_4("Not Setting type");
	}

	attach_cib_generation(update_msg, "cib_generation", the_cib);
	if(update != NULL) {
		add_message_xml(update_msg, F_CIB_UPDATE, update);
	}
	if(result_data != NULL) {
		add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data);
	}

	crm_debug_3("Notifying clients");
	g_hash_table_foreach(client_list, cib_notify_client, update_msg);
	free_xml(update_msg);
	crm_debug_3("Notify complete");
}
示例#3
0
void
cib_pre_notify(
	int options, const char *op, crm_data_t *existing, crm_data_t *update) 
{
	HA_Message *update_msg = NULL;
	const char *type = NULL;
	const char *id = NULL;

	update_msg = ha_msg_new(6);

	if(update != NULL) {
		id = crm_element_value(update, XML_ATTR_ID);
	}
	
	ha_msg_add(update_msg, F_TYPE, T_CIB_NOTIFY);
	ha_msg_add(update_msg, F_SUBTYPE, T_CIB_PRE_NOTIFY);
	ha_msg_add(update_msg, F_CIB_OPERATION, op);

	if(id != NULL) {
		ha_msg_add(update_msg, F_CIB_OBJID, id);
	}

	if(update != NULL) {
		ha_msg_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
	} else if(existing != NULL) {
		ha_msg_add(update_msg, F_CIB_OBJTYPE, crm_element_name(existing));
	}

	type = cl_get_string(update_msg, F_CIB_OBJTYPE);	
	attach_cib_generation(update_msg, "cib_generation", the_cib);
	
	if(existing != NULL) {
		add_message_xml(update_msg, F_CIB_EXISTING, existing);
	}
	if(update != NULL) {
		add_message_xml(update_msg, F_CIB_UPDATE, update);
	}

	g_hash_table_foreach(client_list, cib_notify_client, update_msg);
	
	if(update == NULL) {
		crm_debug_2("Performing operation %s (on section=%s)",
			    op, type);

	} else {
		crm_debug_2("Performing %s on <%s%s%s>",
			    op, type, id?" id=":"", id?id:"");
	}
		
	crm_msg_del(update_msg);
}
示例#4
0
int
cib_process_ping(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
#ifdef CIBPIPE
    return -EINVAL;
#else
    const char *host = crm_element_value(req, F_ORIG);
    const char *seq = crm_element_value(req, F_CIB_PING_ID);
    char *digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, CRM_FEATURE_SET);

    static struct qb_log_callsite *cs = NULL;

    crm_trace("Processing \"%s\" event %s from %s", op, seq, host);
    *answer = create_xml_node(NULL, XML_CRM_TAG_PING);

    crm_xml_add(*answer, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
    crm_xml_add(*answer, XML_ATTR_DIGEST, digest);
    crm_xml_add(*answer, F_CIB_PING_ID, seq);

    if (cs == NULL) {
        cs = qb_log_callsite_get(__func__, __FILE__, __FUNCTION__, LOG_TRACE, __LINE__, crm_trace_nonlog);
    }
    if (cs && cs->targets) {
        /* Append additional detail so the reciever can log the differences */
        add_message_xml(*answer, F_CIB_CALLDATA, the_cib);

    } else {
        /* Always include at least the version details */
        const char *tag = TYPE(the_cib);
        xmlNode *shallow = create_xml_node(NULL, tag);

        copy_in_properties(shallow, the_cib);
        add_message_xml(*answer, F_CIB_CALLDATA, shallow);
        free_xml(shallow);
    }

    crm_info("Reporting our current digest to %s: %s for %s.%s.%s (%p %d)",
             host, digest,
             crm_element_value(existing_cib, XML_ATTR_GENERATION_ADMIN),
             crm_element_value(existing_cib, XML_ATTR_GENERATION),
             crm_element_value(existing_cib, XML_ATTR_NUMUPDATES),
             existing_cib,
             cs && cs->targets);

    free(digest);

    return pcmk_ok;
#endif
}
示例#5
0
xmlNode *
cib_construct_reply(xmlNode * request, xmlNode * output, int rc)
{
    int lpc = 0;
    xmlNode *reply = NULL;
    const char *name = NULL;
    const char *value = NULL;

    const char *names[] = {
        F_CIB_OPERATION,
        F_CIB_CALLID,
        F_CIB_CLIENTID,
        F_CIB_CALLOPTS
    };
    static int max = DIMOF(names);

    crm_trace("Creating a basic reply");
    reply = create_xml_node(NULL, "cib-reply");
    crm_xml_add(reply, F_TYPE, T_CIB);

    for (lpc = 0; lpc < max; lpc++) {
        name = names[lpc];
        value = crm_element_value(request, name);
        crm_xml_add(reply, name, value);
    }

    crm_xml_add_int(reply, F_CIB_RC, rc);

    if (output != NULL) {
        crm_trace("Attaching reply output");
        add_message_xml(reply, F_CIB_CALLDATA, output);
    }
    return reply;
}
示例#6
0
static int32_t
ipc_proxy_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
{
    uint32_t id = 0;
    uint32_t flags = 0;
    crm_client_t *client = crm_client_get(c);
    crm_client_t *ipc_proxy = crm_client_get_by_id(client->userdata);
    xmlNode *request = NULL;
    xmlNode *msg = NULL;

    if (!ipc_proxy) {
        qb_ipcs_disconnect(client->ipcs);
        return 0;
    }

    /* This is a request from the local ipc client going
     * to the ipc provider.
     *
     * Looking at the chain of events.
     *
     * -----remote node----------------|---- cluster node ------
     * ipc_client <--1--> this code <--2--> crmd:remote_proxy_dispatch_internal() <----3----> ipc server
     *
     * This function is receiving a request from connection
     * 1 and forwarding it to connection 2.
     */
    request = crm_ipcs_recv(client, data, size, &id, &flags);

    if (!request) {
        return 0;
    }

    CRM_CHECK(client != NULL, crm_err("Invalid client");
              return FALSE);
    CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client);
              return FALSE);

    /* this ensures that synced request/responses happen over the event channel
     * in the crmd, allowing the crmd to process the messages async */
    set_bit(flags, crm_ipc_proxied);
    client->request_id = id;

    msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
    crm_xml_add(msg, F_LRMD_IPC_OP, "request");
    crm_xml_add(msg, F_LRMD_IPC_SESSION, client->id);
    crm_xml_add(msg, F_LRMD_IPC_CLIENT, crm_client_name(client));
    crm_xml_add(msg, F_LRMD_IPC_USER, client->user);
    crm_xml_add_int(msg, F_LRMD_IPC_MSG_ID, id);
    crm_xml_add_int(msg, F_LRMD_IPC_MSG_FLAGS, flags);
    add_message_xml(msg, F_LRMD_IPC_MSG, request);
    lrmd_server_send_notify(ipc_proxy, msg);
    free_xml(msg);

    return 0;
}
示例#7
0
void
attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib)
{
    xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);

    if (a_cib != NULL) {
        copy_in_properties(generation, a_cib);
    }
    add_message_xml(msg, field, generation);
    free_xml(generation);
}
示例#8
0
static gboolean
send_peer_reply(xmlNode * msg, xmlNode * result_diff, const char *originator, gboolean broadcast)
{
    CRM_ASSERT(msg != NULL);

    if (broadcast) {
        /* this (successful) call modified the CIB _and_ the
         * change needs to be broadcast...
         *   send via HA to other nodes
         */
        int diff_add_updates = 0;
        int diff_add_epoch = 0;
        int diff_add_admin_epoch = 0;

        int diff_del_updates = 0;
        int diff_del_epoch = 0;
        int diff_del_admin_epoch = 0;

        char *digest = NULL;

        cib_diff_version_details(result_diff,
                                 &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
                                 &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);

        crm_trace("Sending update diff %d.%d.%d -> %d.%d.%d",
                    diff_del_admin_epoch, diff_del_epoch, diff_del_updates,
                    diff_add_admin_epoch, diff_add_epoch, diff_add_updates);

        crm_xml_add(msg, F_CIB_ISREPLY, originator);
        crm_xml_add(msg, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE);
        crm_xml_add(msg, F_CIB_OPERATION, CIB_OP_APPLY_DIFF);

        /* Its safe to always use the latest version since the election
         * ensures the software on this node is the oldest node in the cluster
         */
        digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, CRM_FEATURE_SET);
        crm_xml_add(result_diff, XML_ATTR_DIGEST, digest);
        crm_log_xml_trace(the_cib, digest);
        free(digest);

        add_message_xml(msg, F_CIB_UPDATE_DIFF, result_diff);
        crm_log_xml_trace(msg, "copy");
        return send_cluster_message(NULL, crm_msg_cib, msg, TRUE);

    } else if (originator != NULL) {
        /* send reply via HA to originating node */
        crm_trace("Sending request result to originator only");
        crm_xml_add(msg, F_CIB_ISREPLY, originator);
        return send_cluster_message(originator, crm_msg_cib, msg, FALSE);
    }

    return FALSE;
}
示例#9
0
文件: ipc.c 项目: credativ/pacemaker
/*
 * This method adds a copy of xml_response_data
 */
xmlNode *
create_reply_adv(xmlNode * original_request, xmlNode * xml_response_data, const char *origin)
{
    xmlNode *reply = NULL;

    const char *host_from = crm_element_value(original_request, F_CRM_HOST_FROM);
    const char *sys_from = crm_element_value(original_request, F_CRM_SYS_FROM);
    const char *sys_to = crm_element_value(original_request, F_CRM_SYS_TO);
    const char *type = crm_element_value(original_request, F_CRM_MSG_TYPE);
    const char *operation = crm_element_value(original_request, F_CRM_TASK);
    const char *crm_msg_reference = crm_element_value(original_request, F_CRM_REFERENCE);

    if (type == NULL) {
        crm_err("Cannot create new_message, no message type in original message");
        CRM_ASSERT(type != NULL);
        return NULL;
#if 0
    } else if (strcasecmp(XML_ATTR_REQUEST, type) != 0) {
        crm_err("Cannot create new_message, original message was not a request");
        return NULL;
#endif
    }
    reply = create_xml_node(NULL, __FUNCTION__);
    if (reply == NULL) {
        crm_err("Cannot create new_message, malloc failed");
        return NULL;
    }

    crm_xml_add(reply, F_CRM_ORIGIN, origin);
    crm_xml_add(reply, F_TYPE, T_CRM);
    crm_xml_add(reply, F_CRM_VERSION, CRM_FEATURE_SET);
    crm_xml_add(reply, F_CRM_MSG_TYPE, XML_ATTR_RESPONSE);
    crm_xml_add(reply, F_CRM_REFERENCE, crm_msg_reference);
    crm_xml_add(reply, F_CRM_TASK, operation);

    /* since this is a reply, we reverse the from and to */
    crm_xml_add(reply, F_CRM_SYS_TO, sys_from);
    crm_xml_add(reply, F_CRM_SYS_FROM, sys_to);

    /* HOSTTO will be ignored if it is to the DC anyway. */
    if (host_from != NULL && strlen(host_from) > 0) {
        crm_xml_add(reply, F_CRM_HOST_TO, host_from);
    }

    if (xml_response_data != NULL) {
        add_message_xml(reply, F_CRM_DATA, xml_response_data);
    }

    return reply;
}
示例#10
0
static gboolean
send_peer_reply(xmlNode * msg, xmlNode * result_diff, const char *originator, gboolean broadcast)
{
    CRM_ASSERT(msg != NULL);

    if (broadcast) {
        /* this (successful) call modified the CIB _and_ the
         * change needs to be broadcast...
         *   send via HA to other nodes
         */
        int diff_add_updates = 0;
        int diff_add_epoch = 0;
        int diff_add_admin_epoch = 0;

        int diff_del_updates = 0;
        int diff_del_epoch = 0;
        int diff_del_admin_epoch = 0;

        const char *digest = NULL;

        CRM_LOG_ASSERT(result_diff != NULL);
        digest = crm_element_value(result_diff, XML_ATTR_DIGEST);
        cib_diff_version_details(result_diff,
                                 &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
                                 &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);

        crm_trace("Sending update diff %d.%d.%d -> %d.%d.%d %s",
                  diff_del_admin_epoch, diff_del_epoch, diff_del_updates,
                  diff_add_admin_epoch, diff_add_epoch, diff_add_updates, digest);

        crm_xml_add(msg, F_CIB_ISREPLY, originator);
        crm_xml_add(msg, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE);
        crm_xml_add(msg, F_CIB_OPERATION, CIB_OP_APPLY_DIFF);

        CRM_ASSERT(digest != NULL);

        add_message_xml(msg, F_CIB_UPDATE_DIFF, result_diff);
        crm_log_xml_explicit(msg, "copy");
        return send_cluster_message(NULL, crm_msg_cib, msg, TRUE);

    } else if (originator != NULL) {
        /* send reply via HA to originating node */
        crm_trace("Sending request result to %s only", originator);
        crm_xml_add(msg, F_CIB_ISREPLY, originator);
        return send_cluster_message(crm_get_peer(0, originator), crm_msg_cib, msg, FALSE);
    }

    return FALSE;
}
示例#11
0
xmlNode *
create_request_adv(const char *task, xmlNode *msg_data,
		   const char *host_to,  const char *sys_to,
		   const char *sys_from, const char *uuid_from,
		   const char *origin)
{
	char *true_from = NULL;
	xmlNode *request = NULL;
	char *reference = generateReference(task, sys_from);

	if (uuid_from != NULL) {
		true_from = generate_hash_key(sys_from, uuid_from);
	} else if(sys_from != NULL) {
		true_from = crm_strdup(sys_from);
	} else {
		crm_err("No sys from specified");
	}
	
	/* host_from will get set for us if necessary by CRMd when routed */
	request = create_xml_node(NULL, __FUNCTION__);
	crm_xml_add(request, F_CRM_ORIGIN,	origin);
	crm_xml_add(request, F_TYPE,		T_CRM);
	crm_xml_add(request, F_CRM_VERSION,	CRM_FEATURE_SET);
	crm_xml_add(request, F_CRM_MSG_TYPE,     XML_ATTR_REQUEST);
	crm_xml_add(request, XML_ATTR_REFERENCE, reference);
	crm_xml_add(request, F_CRM_TASK,		task);
	crm_xml_add(request, F_CRM_SYS_TO,       sys_to);
	crm_xml_add(request, F_CRM_SYS_FROM,     true_from);

	/* HOSTTO will be ignored if it is to the DC anyway. */
	if(host_to != NULL && strlen(host_to) > 0) {
		crm_xml_add(request, F_CRM_HOST_TO,  host_to);
	}

	if (msg_data != NULL) {
		add_message_xml(request, F_CRM_DATA, msg_data);
	}
	crm_free(reference);
	crm_free(true_from);
	
	return request;
}
示例#12
0
static void
bcast_result_to_peers(remote_fencing_op_t * op, int rc)
{
    static int count = 0;
    xmlNode *bcast = create_xml_node(NULL, T_STONITH_REPLY);
    xmlNode *notify_data = create_op_done_notify(op, rc);

    count++;
    crm_trace("Broadcasting result to peers");
    crm_xml_add(bcast, F_TYPE, T_STONITH_NOTIFY);
    crm_xml_add(bcast, F_SUBTYPE, "broadcast");
    crm_xml_add(bcast, F_STONITH_OPERATION, T_STONITH_NOTIFY);
    crm_xml_add_int(bcast, "count", count);
    add_message_xml(bcast, F_STONITH_CALLDATA, notify_data);
    send_cluster_message(NULL, crm_msg_stonith_ng, bcast, FALSE);
    free_xml(notify_data);
    free_xml(bcast);

    return;
}
示例#13
0
/*!
 * \internal
 * \brief Send a broadcast to all nodes to trigger cleanup or
 *        history synchronisation
 *
 * \param[in] history   Optional history to be attached
 * \param[in] callopts  We control cleanup via a flag in the callopts
 * \param[in] target    Cleanup can be limited to certain fence-targets
 */
static void
stonith_send_broadcast_history(xmlNode *history,
                               int callopts,
                               const char *target)
{
    xmlNode *bcast = create_xml_node(NULL, "stonith_command");
    xmlNode *data = create_xml_node(NULL, __FUNCTION__);

    if (target) {
        crm_xml_add(data, F_STONITH_TARGET, target);
    }
    crm_xml_add(bcast, F_TYPE, T_STONITH_NG);
    crm_xml_add(bcast, F_SUBTYPE, "broadcast");
    crm_xml_add(bcast, F_STONITH_OPERATION, STONITH_OP_FENCE_HISTORY);
    crm_xml_add_int(bcast, F_STONITH_CALLOPTS, callopts);
    if (history) {
        add_node_copy(data, history);
    }
    add_message_xml(bcast, F_STONITH_CALLDATA, data);
    send_cluster_message(NULL, crm_msg_stonith_ng, bcast, FALSE);

    free_xml(data);
    free_xml(bcast);
}
示例#14
0
xmlNode *
cib_msg_copy(xmlNode * msg, gboolean with_data)
{
    int lpc = 0;
    const char *field = NULL;
    const char *value = NULL;
    xmlNode *value_struct = NULL;

    static const char *field_list[] = {
        F_XML_TAGNAME,
        F_TYPE,
        F_CIB_CLIENTID,
        F_CIB_CALLOPTS,
        F_CIB_CALLID,
        F_CIB_OPERATION,
        F_CIB_ISREPLY,
        F_CIB_SECTION,
        F_CIB_HOST,
        F_CIB_RC,
        F_CIB_DELEGATED,
        F_CIB_OBJID,
        F_CIB_OBJTYPE,
        F_CIB_EXISTING,
        F_CIB_SEENCOUNT,
        F_CIB_TIMEOUT,
        F_CIB_CALLBACK_TOKEN,
        F_CIB_GLOBAL_UPDATE,
        F_CIB_CLIENTNAME,
#if ENABLE_ACL
        F_CIB_USER,
#endif
        F_CIB_NOTIFY_TYPE,
        F_CIB_NOTIFY_ACTIVATE
    };

    static const char *data_list[] = {
        F_CIB_CALLDATA,
        F_CIB_UPDATE,
        F_CIB_UPDATE_RESULT
    };

    xmlNode *copy = create_xml_node(NULL, "copy");

    CRM_ASSERT(copy != NULL);

    for (lpc = 0; lpc < DIMOF(field_list); lpc++) {
        field = field_list[lpc];
        value = crm_element_value(msg, field);
        if (value != NULL) {
            crm_xml_add(copy, field, value);
        }
    }
    for (lpc = 0; with_data && lpc < DIMOF(data_list); lpc++) {
        field = data_list[lpc];
        value_struct = get_message_xml(msg, field);
        if (value_struct != NULL) {
            add_message_xml(copy, field, value_struct);
        }
    }

    return copy;
}
示例#15
0
void
do_cib_notify(
	int options, const char *op, crm_data_t *update,
	enum cib_errors result, crm_data_t *result_data, const char *msg_type) 
{
	HA_Message *update_msg = NULL;
	const char *type = NULL;
	const char *id = NULL;

	update_msg = ha_msg_new(8);

	if(result_data != NULL) {
		id = crm_element_value(result_data, XML_ATTR_ID);
	}
	
	ha_msg_add(update_msg, F_TYPE, T_CIB_NOTIFY);
	ha_msg_add(update_msg, F_SUBTYPE, msg_type);
	ha_msg_add(update_msg, F_CIB_OPERATION, op);
	ha_msg_add_int(update_msg, F_CIB_RC, result);
	
	if(id != NULL) {
		ha_msg_add(update_msg, F_CIB_OBJID, id);
	}

	if(update != NULL) {
		crm_debug_4("Setting type to update->name: %s",
			    crm_element_name(update));
		ha_msg_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
		type = crm_element_name(update);

	} else if(result_data != NULL) {
		crm_debug_4("Setting type to new_obj->name: %s",
			    crm_element_name(result_data));
		ha_msg_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data));
		type = crm_element_name(result_data);
		
	} else {
		crm_debug_4("Not Setting type");
	}

	attach_cib_generation(update_msg, "cib_generation", the_cib);
	if(update != NULL) {
		add_message_xml(update_msg, F_CIB_UPDATE, update);
	}
	if(result_data != NULL) {
		add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data);
	}

	crm_debug_3("Notifying clients");
	g_hash_table_foreach(client_list, cib_notify_client, update_msg);
	crm_msg_del(update_msg);

	if(update == NULL) {
		if(result == cib_ok) {
			crm_debug_2("Operation %s (on section=%s) completed",
				    op, crm_str(type));
			
		} else {
			crm_warn("Operation %s (on section=%s) FAILED: (%d) %s",
				 op, crm_str(type), result,
				 cib_error2string(result));
		}
		
	} else {
		if(result == cib_ok) {
			crm_debug_2("Completed %s of <%s %s%s>",
				    op, crm_str(type), id?"id=":"", id?id:"");
			
		} else {
			crm_warn("%s of <%s %s%s> FAILED: %s", op,crm_str(type),
				 id?"id=":"", id?id:"", cib_error2string(result));
		}
	}

	crm_debug_3("Notify complete");
}
示例#16
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;
}
示例#17
0
int
cib_process_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff, gboolean privileged)
{
    xmlNode *input = NULL;
    xmlNode *output = NULL;
    xmlNode *result_cib = NULL;
    xmlNode *current_cib = NULL;

    int call_type = 0;
    int call_options = 0;

    const char *op = NULL;
    const char *section = NULL;
    const char *call_id = crm_element_value(request, F_CIB_CALLID);

    int rc = pcmk_ok;
    int rc2 = pcmk_ok;

    gboolean send_r_notify = FALSE;
    gboolean global_update = FALSE;
    gboolean config_changed = FALSE;
    gboolean manage_counters = TRUE;

    static mainloop_timer_t *digest_timer = NULL;

    CRM_ASSERT(cib_status == pcmk_ok);

    if(digest_timer == NULL) {
        digest_timer = mainloop_timer_add("digester", 5000, FALSE, cib_digester_cb, NULL);
    }

    *reply = NULL;
    *cib_diff = NULL;
    current_cib = the_cib;

    /* Start processing the request... */
    op = crm_element_value(request, F_CIB_OPERATION);
    crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
    rc = cib_get_operation_id(op, &call_type);

    if (rc == pcmk_ok && privileged == FALSE) {
        rc = cib_op_can_run(call_type, call_options, privileged, global_update);
    }

    rc2 = cib_op_prepare(call_type, request, &input, &section);
    if (rc == pcmk_ok) {
        rc = rc2;
    }

    if (rc != pcmk_ok) {
        crm_trace("Call setup failed: %s", pcmk_strerror(rc));
        goto done;

    } else if (cib_op_modifies(call_type) == FALSE) {
        rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
                            section, request, input, FALSE, &config_changed,
                            current_cib, &result_cib, NULL, &output);

        CRM_CHECK(result_cib == NULL, free_xml(result_cib));
        goto done;
    }

    /* Handle a valid write action */
    global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE));
    if (global_update) {
        /* legacy code */
        manage_counters = FALSE;
        call_options |= cib_force_diff;
        crm_trace("Global update detected");

        CRM_CHECK(call_type == 3 || call_type == 4, crm_err("Call type: %d", call_type);
                  crm_log_xml_err(request, "bad op"));
    }

    if (rc == pcmk_ok) {
        ping_modified_since = TRUE;
        if (call_options & cib_inhibit_bcast) {
            /* skip */
            crm_trace("Skipping update: inhibit broadcast");
            manage_counters = FALSE;
        }

        if (is_not_set(call_options, cib_dryrun) && safe_str_eq(section, XML_CIB_TAG_STATUS)) {
            /* Copying large CIBs accounts for a huge percentage of our CIB usage */
            call_options |= cib_zero_copy;
        } else {
            clear_bit(call_options, cib_zero_copy);
        }

        /* result_cib must not be modified after cib_perform_op() returns */
        rc = cib_perform_op(op, call_options, cib_op_func(call_type), FALSE,
                            section, request, input, manage_counters, &config_changed,
                            current_cib, &result_cib, cib_diff, &output);

        if (manage_counters == FALSE) {
            /* Legacy code
             * If the diff is NULL at this point, its because nothing changed
             */
            config_changed = cib_config_changed(NULL, NULL, cib_diff);
        }

        /* Always write to disk for replace ops,
         * this also negates the need to detect ordering changes
         */
        if (crm_str_eq(CIB_OP_REPLACE, op, TRUE)) {
            config_changed = TRUE;
        }
    }

    if (rc == pcmk_ok && is_not_set(call_options, cib_dryrun)) {
        if(is_not_set(call_options, cib_zero_copy)) {
            rc = activateCibXml(result_cib, config_changed, op);
        }

        if (rc == pcmk_ok && cib_internal_config_changed(*cib_diff)) {
            cib_read_config(config_hash, result_cib);
        }

        if (crm_str_eq(CIB_OP_REPLACE, op, TRUE)) {
            if (section == NULL) {
                send_r_notify = TRUE;

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

            } else if (safe_str_eq(section, XML_CIB_TAG_NODES)) {
                send_r_notify = TRUE;

            } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) {
                send_r_notify = TRUE;
            }

        } else if (crm_str_eq(CIB_OP_ERASE, op, TRUE)) {
            send_r_notify = TRUE;
        }

        mainloop_timer_stop(digest_timer);
        mainloop_timer_start(digest_timer);

    } else if (rc == -pcmk_err_schema_validation) {
        CRM_ASSERT(is_not_set(call_options, cib_zero_copy));

        if (output != NULL) {
            crm_log_xml_info(output, "cib:output");
            free_xml(output);
        }

        output = result_cib;

    } else {
        if(is_not_set(call_options, cib_zero_copy)) {
            free_xml(result_cib);
        }
    }

    if ((call_options & cib_inhibit_notify) == 0) {
        const char *client = crm_element_value(request, F_CIB_CLIENTNAME);

        crm_trace("Sending notifications");
        cib_diff_notify(call_options, client, call_id, op, input, rc, *cib_diff);
    }

    if (send_r_notify) {
        const char *origin = crm_element_value(request, F_ORIG);

        cib_replace_notify(origin, the_cib, rc, *cib_diff);
    }

    xml_log_patchset(LOG_TRACE, "cib:diff", *cib_diff);
  done:
    if ((call_options & cib_discard_reply) == 0) {
        const char *caller = crm_element_value(request, F_CIB_CLIENTID);

        *reply = create_xml_node(NULL, "cib-reply");
        crm_xml_add(*reply, F_TYPE, T_CIB);
        crm_xml_add(*reply, F_CIB_OPERATION, op);
        crm_xml_add(*reply, F_CIB_CALLID, call_id);
        crm_xml_add(*reply, F_CIB_CLIENTID, caller);
        crm_xml_add_int(*reply, F_CIB_CALLOPTS, call_options);
        crm_xml_add_int(*reply, F_CIB_RC, rc);

        if (output != NULL) {
            crm_trace("Attaching reply output");
            add_message_xml(*reply, F_CIB_CALLDATA, output);
        }

        crm_log_xml_explicit(*reply, "cib:reply");
    }

    crm_trace("cleanup");

    if (cib_op_modifies(call_type) == FALSE && output != current_cib) {
        free_xml(output);
        output = NULL;
    }

    if (call_type >= 0) {
        cib_op_cleanup(call_type, call_options, &input, &output);
    }

    crm_trace("done");
    return rc;
}