|
rpm-build |
3ee90c |
/*
|
|
rpm-build |
3ee90c |
* Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
|
|
rpm-build |
3ee90c |
*
|
|
rpm-build |
3ee90c |
* This source code is licensed under the GNU General Public License version 2
|
|
rpm-build |
3ee90c |
* or later (GPLv2+) WITHOUT ANY WARRANTY.
|
|
rpm-build |
3ee90c |
*/
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#include <crm_internal.h>
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#include <sys/param.h>
|
|
rpm-build |
3ee90c |
#include <stdio.h>
|
|
rpm-build |
3ee90c |
#include <sys/types.h>
|
|
rpm-build |
3ee90c |
#include <unistd.h>
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#include <stdlib.h>
|
|
rpm-build |
3ee90c |
#include <errno.h>
|
|
rpm-build |
3ee90c |
#include <fcntl.h>
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#include <time.h>
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#include <crm/crm.h>
|
|
rpm-build |
3ee90c |
#include <crm/cib/internal.h>
|
|
rpm-build |
3ee90c |
#include <crm/msg_xml.h>
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#include <crm/common/xml.h>
|
|
rpm-build |
3ee90c |
#include <crm/common/remote_internal.h>
|
|
rpm-build |
3ee90c |
#include <pacemaker-based.h>
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
int pending_updates = 0;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
struct cib_notification_s {
|
|
rpm-build |
3ee90c |
xmlNode *msg;
|
|
rpm-build |
3ee90c |
struct iovec *iov;
|
|
rpm-build |
3ee90c |
int32_t iov_size;
|
|
rpm-build |
3ee90c |
};
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
void attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
void do_cib_notify(int options, const char *op, xmlNode * update,
|
|
rpm-build |
3ee90c |
int result, xmlNode * result_data, const char *msg_type);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static gboolean
|
|
rpm-build |
3ee90c |
cib_notify_send_one(gpointer key, gpointer value, gpointer user_data)
|
|
rpm-build |
3ee90c |
{
|
|
rpm-build |
3ee90c |
const char *type = NULL;
|
|
rpm-build |
3ee90c |
gboolean do_send = FALSE;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
crm_client_t *client = value;
|
|
rpm-build |
3ee90c |
struct cib_notification_s *update = user_data;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
CRM_CHECK(client != NULL, return TRUE);
|
|
rpm-build |
3ee90c |
CRM_CHECK(update != NULL, return TRUE);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (client->ipcs == NULL && client->remote == NULL) {
|
|
rpm-build |
3ee90c |
crm_warn("Skipping client with NULL channel");
|
|
rpm-build |
3ee90c |
return FALSE;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
type = crm_element_value(update->msg, F_SUBTYPE);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
CRM_LOG_ASSERT(type != NULL);
|
|
rpm-build |
3ee90c |
if (is_set(client->options, cib_notify_diff) && safe_str_eq(type, T_CIB_DIFF_NOTIFY)) {
|
|
rpm-build |
3ee90c |
do_send = TRUE;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
} else if (is_set(client->options, cib_notify_replace)
|
|
rpm-build |
3ee90c |
&& safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) {
|
|
rpm-build |
3ee90c |
do_send = TRUE;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
} else if (is_set(client->options, cib_notify_confirm)
|
|
rpm-build |
3ee90c |
&& safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) {
|
|
rpm-build |
3ee90c |
do_send = TRUE;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
} else if (is_set(client->options, cib_notify_pre) && safe_str_eq(type, T_CIB_PRE_NOTIFY)) {
|
|
rpm-build |
3ee90c |
do_send = TRUE;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
} else if (is_set(client->options, cib_notify_post) && safe_str_eq(type, T_CIB_POST_NOTIFY)) {
|
|
rpm-build |
3ee90c |
do_send = TRUE;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (do_send) {
|
|
rpm-build |
3ee90c |
switch (client->kind) {
|
|
rpm-build |
3ee90c |
case CRM_CLIENT_IPC:
|
|
rpm-build |
3ee90c |
if (crm_ipcs_sendv(client, update->iov, crm_ipc_server_event) < 0) {
|
|
rpm-build |
3ee90c |
crm_warn("Notification of client %s/%s failed", client->name, client->id);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
break;
|
|
rpm-build |
3ee90c |
#ifdef HAVE_GNUTLS_GNUTLS_H
|
|
rpm-build |
3ee90c |
case CRM_CLIENT_TLS:
|
|
rpm-build |
3ee90c |
#endif
|
|
rpm-build |
3ee90c |
case CRM_CLIENT_TCP:
|
|
rpm-build |
3ee90c |
crm_debug("Sent %s notification to client %s/%s", type, client->name, client->id);
|
|
rpm-build |
3ee90c |
crm_remote_send(client->remote, update->msg);
|
|
rpm-build |
3ee90c |
break;
|
|
rpm-build |
3ee90c |
default:
|
|
rpm-build |
3ee90c |
crm_err("Unknown transport %d for %s", client->kind, client->name);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
return FALSE;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
cib_notify_send(xmlNode * xml)
|
|
rpm-build |
3ee90c |
{
|
|
rpm-build |
3ee90c |
struct iovec *iov;
|
|
rpm-build |
3ee90c |
struct cib_notification_s update;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
ssize_t rc = crm_ipc_prepare(0, xml, &iov, 0);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
crm_trace("Notifying clients");
|
|
rpm-build |
3ee90c |
if (rc > 0) {
|
|
rpm-build |
3ee90c |
update.msg = xml;
|
|
rpm-build |
3ee90c |
update.iov = iov;
|
|
rpm-build |
3ee90c |
update.iov_size = rc;
|
|
rpm-build |
3ee90c |
g_hash_table_foreach_remove(client_connections, cib_notify_send_one, &update);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
} else {
|
|
rpm-build |
3ee90c |
crm_notice("Could not notify clients: %s " CRM_XS " rc=%lld",
|
|
rpm-build |
3ee90c |
pcmk_strerror(rc), (long long) rc);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
pcmk_free_ipc_event(iov);
|
|
rpm-build |
3ee90c |
crm_trace("Notify complete");
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
void
|
|
rpm-build |
3ee90c |
cib_diff_notify(int options, const char *client, const char *call_id, const char *op,
|
|
rpm-build |
3ee90c |
xmlNode * update, int result, xmlNode * diff)
|
|
rpm-build |
3ee90c |
{
|
|
rpm-build |
3ee90c |
int add_updates = 0;
|
|
rpm-build |
3ee90c |
int add_epoch = 0;
|
|
rpm-build |
3ee90c |
int add_admin_epoch = 0;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
int del_updates = 0;
|
|
rpm-build |
3ee90c |
int del_epoch = 0;
|
|
rpm-build |
3ee90c |
int del_admin_epoch = 0;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
int log_level = LOG_TRACE;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (diff == NULL) {
|
|
rpm-build |
3ee90c |
return;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (result != pcmk_ok) {
|
|
rpm-build |
3ee90c |
log_level = LOG_WARNING;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
|
|
rpm-build |
3ee90c |
&del_admin_epoch, &del_epoch, &del_updates);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (add_updates != del_updates) {
|
|
rpm-build |
3ee90c |
do_crm_log(log_level,
|
|
rpm-build |
3ee90c |
"Update (client: %s%s%s): %d.%d.%d -> %d.%d.%d (%s)",
|
|
rpm-build |
3ee90c |
client, call_id ? ", call:" : "", call_id ? call_id : "",
|
|
rpm-build |
3ee90c |
del_admin_epoch, del_epoch, del_updates,
|
|
rpm-build |
3ee90c |
add_admin_epoch, add_epoch, add_updates, pcmk_strerror(result));
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
} else if (diff != NULL) {
|
|
rpm-build |
3ee90c |
do_crm_log(log_level,
|
|
rpm-build |
3ee90c |
"Local-only Change (client:%s%s%s): %d.%d.%d (%s)",
|
|
rpm-build |
3ee90c |
client, call_id ? ", call: " : "", call_id ? call_id : "",
|
|
rpm-build |
3ee90c |
add_admin_epoch, add_epoch, add_updates, pcmk_strerror(result));
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
do_cib_notify(options, op, update, result, diff, T_CIB_DIFF_NOTIFY);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
void
|
|
rpm-build |
3ee90c |
do_cib_notify(int options, const char *op, xmlNode * update,
|
|
rpm-build |
3ee90c |
int result, xmlNode * result_data, const char *msg_type)
|
|
rpm-build |
3ee90c |
{
|
|
rpm-build |
3ee90c |
xmlNode *update_msg = NULL;
|
|
rpm-build |
3ee90c |
const char *id = NULL;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
update_msg = create_xml_node(NULL, "notify");
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (result_data != NULL) {
|
|
rpm-build |
3ee90c |
id = crm_element_value(result_data, XML_ATTR_ID);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY);
|
|
rpm-build |
3ee90c |
crm_xml_add(update_msg, F_SUBTYPE, msg_type);
|
|
rpm-build |
3ee90c |
crm_xml_add(update_msg, F_CIB_OPERATION, op);
|
|
rpm-build |
3ee90c |
crm_xml_add_int(update_msg, F_CIB_RC, result);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (id != NULL) {
|
|
rpm-build |
3ee90c |
crm_xml_add(update_msg, F_CIB_OBJID, id);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (update != NULL) {
|
|
rpm-build |
3ee90c |
crm_trace("Setting type to update->name: %s", crm_element_name(update));
|
|
rpm-build |
3ee90c |
crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
} else if (result_data != NULL) {
|
|
rpm-build |
3ee90c |
crm_trace("Setting type to new_obj->name: %s", crm_element_name(result_data));
|
|
rpm-build |
3ee90c |
crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data));
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
} else {
|
|
rpm-build |
3ee90c |
crm_trace("Not Setting type");
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
attach_cib_generation(update_msg, "cib_generation", the_cib);
|
|
rpm-build |
3ee90c |
if (update != NULL) {
|
|
rpm-build |
3ee90c |
add_message_xml(update_msg, F_CIB_UPDATE, update);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
if (result_data != NULL) {
|
|
rpm-build |
3ee90c |
add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
cib_notify_send(update_msg);
|
|
rpm-build |
3ee90c |
free_xml(update_msg);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
void
|
|
rpm-build |
3ee90c |
attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib)
|
|
rpm-build |
3ee90c |
{
|
|
rpm-build |
3ee90c |
xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (a_cib != NULL) {
|
|
rpm-build |
3ee90c |
copy_in_properties(generation, a_cib);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
add_message_xml(msg, field, generation);
|
|
rpm-build |
3ee90c |
free_xml(generation);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
void
|
|
rpm-build |
3ee90c |
cib_replace_notify(const char *origin, xmlNode * update, int result, xmlNode * diff)
|
|
rpm-build |
3ee90c |
{
|
|
rpm-build |
3ee90c |
xmlNode *replace_msg = NULL;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
int add_updates = 0;
|
|
rpm-build |
3ee90c |
int add_epoch = 0;
|
|
rpm-build |
3ee90c |
int add_admin_epoch = 0;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
int del_updates = 0;
|
|
rpm-build |
3ee90c |
int del_epoch = 0;
|
|
rpm-build |
3ee90c |
int del_admin_epoch = 0;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (diff == NULL) {
|
|
rpm-build |
3ee90c |
return;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
|
|
rpm-build |
3ee90c |
&del_admin_epoch, &del_epoch, &del_updates);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (del_updates < 0) {
|
|
rpm-build |
3ee90c |
crm_log_xml_debug(diff, "Bad replace diff");
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (add_updates != del_updates) {
|
|
rpm-build |
3ee90c |
crm_info("Replaced: %d.%d.%d -> %d.%d.%d from %s",
|
|
rpm-build |
3ee90c |
del_admin_epoch, del_epoch, del_updates,
|
|
rpm-build |
3ee90c |
add_admin_epoch, add_epoch, add_updates, crm_str(origin));
|
|
rpm-build |
3ee90c |
} else if (diff != NULL) {
|
|
rpm-build |
3ee90c |
crm_info("Local-only Replace: %d.%d.%d from %s",
|
|
rpm-build |
3ee90c |
add_admin_epoch, add_epoch, add_updates, crm_str(origin));
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
replace_msg = create_xml_node(NULL, "notify-replace");
|
|
rpm-build |
3ee90c |
crm_xml_add(replace_msg, F_TYPE, T_CIB_NOTIFY);
|
|
rpm-build |
3ee90c |
crm_xml_add(replace_msg, F_SUBTYPE, T_CIB_REPLACE_NOTIFY);
|
|
rpm-build |
3ee90c |
crm_xml_add(replace_msg, F_CIB_OPERATION, CIB_OP_REPLACE);
|
|
rpm-build |
3ee90c |
crm_xml_add_int(replace_msg, F_CIB_RC, result);
|
|
rpm-build |
3ee90c |
attach_cib_generation(replace_msg, "cib-replace-generation", update);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
crm_log_xml_trace(replace_msg, "CIB Replaced");
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
cib_notify_send(replace_msg);
|
|
rpm-build |
3ee90c |
free_xml(replace_msg);
|
|
rpm-build |
3ee90c |
}
|