summaryrefslogtreecommitdiffstats
path: root/daemons/attrd
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--daemons/attrd/attrd_alerts.c14
-rw-r--r--daemons/attrd/attrd_attributes.c125
-rw-r--r--daemons/attrd/attrd_cib.c316
-rw-r--r--daemons/attrd/attrd_corosync.c295
-rw-r--r--daemons/attrd/attrd_elections.c10
-rw-r--r--daemons/attrd/attrd_ipc.c99
-rw-r--r--daemons/attrd/attrd_messages.c57
-rw-r--r--daemons/attrd/attrd_sync.c48
-rw-r--r--daemons/attrd/attrd_utils.c43
-rw-r--r--daemons/attrd/pacemaker-attrd.c10
-rw-r--r--daemons/attrd/pacemaker-attrd.h104
11 files changed, 579 insertions, 542 deletions
diff --git a/daemons/attrd/attrd_alerts.c b/daemons/attrd/attrd_alerts.c
index 495e18f..4e97743 100644
--- a/daemons/attrd/attrd_alerts.c
+++ b/daemons/attrd/attrd_alerts.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2023 the Pacemaker project contributors
+ * Copyright 2015-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -10,11 +10,11 @@
#include <crm_internal.h>
#include <crm/crm.h>
#include <crm/cib/internal.h>
-#include <crm/msg_xml.h>
#include <crm/cluster/internal.h>
#include <crm/cluster/election_internal.h>
#include <crm/common/alerts_internal.h>
#include <crm/common/cib_internal.h>
+#include <crm/common/xml.h>
#include <crm/pengine/rules_internal.h>
#include <crm/lrmd_internal.h>
#include "pacemaker-attrd.h"
@@ -48,7 +48,7 @@ attrd_lrmd_connect(void)
int ret = -ENOTCONN;
for (int fails = 0; fails < max_attempts; ++fails) {
- ret = the_lrmd->cmds->connect(the_lrmd, T_ATTRD, NULL);
+ ret = the_lrmd->cmds->connect(the_lrmd, PCMK__VALUE_ATTRD, NULL);
if (ret == pcmk_ok) {
break;
}
@@ -93,11 +93,11 @@ config_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void
}
crmalerts = output;
- if ((crmalerts != NULL) && !pcmk__xe_is(crmalerts, XML_CIB_TAG_ALERTS)) {
- crmalerts = first_named_child(crmalerts, XML_CIB_TAG_ALERTS);
+ if ((crmalerts != NULL) && !pcmk__xe_is(crmalerts, PCMK_XE_ALERTS)) {
+ crmalerts = pcmk__xe_first_child(crmalerts, PCMK_XE_ALERTS, NULL, NULL);
}
if (!crmalerts) {
- crm_notice("CIB query result has no " XML_CIB_TAG_ALERTS " section");
+ crm_notice("CIB query result has no " PCMK_XE_ALERTS " section");
return;
}
@@ -113,7 +113,7 @@ attrd_read_options(gpointer user_data)
CRM_CHECK(the_cib != NULL, return TRUE);
call_id = the_cib->cmds->query(the_cib,
- pcmk__cib_abs_xpath_for(XML_CIB_TAG_ALERTS),
+ pcmk__cib_abs_xpath_for(PCMK_XE_ALERTS),
NULL, cib_xpath|cib_scope_local);
the_cib->cmds->register_callback_full(the_cib, call_id, 120, FALSE, NULL,
diff --git a/daemons/attrd/attrd_attributes.c b/daemons/attrd/attrd_attributes.c
index 388c181..974de89 100644
--- a/daemons/attrd/attrd_attributes.c
+++ b/daemons/attrd/attrd_attributes.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2022 the Pacemaker project contributors
+ * Copyright 2013-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -14,7 +14,6 @@
#include <stdlib.h>
#include <glib.h>
-#include <crm/msg_xml.h>
#include <crm/common/logging.h>
#include <crm/common/results.h>
#include <crm/common/strings_internal.h>
@@ -26,55 +25,56 @@ static attribute_t *
attrd_create_attribute(xmlNode *xml)
{
int is_private = 0;
- int dampen = 0;
+ long long dampen = 0;
const char *name = crm_element_value(xml, PCMK__XA_ATTR_NAME);
const char *set_type = crm_element_value(xml, PCMK__XA_ATTR_SET_TYPE);
const char *dampen_s = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
attribute_t *a = NULL;
if (set_type == NULL) {
- set_type = XML_TAG_ATTR_SETS;
+ set_type = PCMK_XE_INSTANCE_ATTRIBUTES;
}
/* Set type is meaningful only when writing to the CIB. Private
* attributes are not written.
*/
crm_element_value_int(xml, PCMK__XA_ATTR_IS_PRIVATE, &is_private);
- if ((is_private != 0)
- && !pcmk__str_any_of(set_type, XML_TAG_ATTR_SETS, XML_TAG_UTILIZATION,
- NULL)) {
+ if (!is_private && !pcmk__str_any_of(set_type,
+ PCMK_XE_INSTANCE_ATTRIBUTES,
+ PCMK_XE_UTILIZATION, NULL)) {
crm_warn("Ignoring attribute %s with invalid set type %s",
pcmk__s(name, "(unidentified)"), set_type);
return NULL;
}
- a = calloc(1, sizeof(attribute_t));
- CRM_ASSERT(a != NULL);
-
- a->is_private = is_private;
- pcmk__str_update(&a->id, name);
- pcmk__str_update(&a->set_type, set_type);
+ a = pcmk__assert_alloc(1, sizeof(attribute_t));
+ a->id = pcmk__str_copy(name);
+ a->set_type = pcmk__str_copy(set_type);
a->set_id = crm_element_value_copy(xml, PCMK__XA_ATTR_SET);
- a->uuid = crm_element_value_copy(xml, PCMK__XA_ATTR_UUID);
+ a->user = crm_element_value_copy(xml, PCMK__XA_ATTR_USER);
a->values = pcmk__strikey_table(NULL, attrd_free_attribute_value);
- a->user = crm_element_value_copy(xml, PCMK__XA_ATTR_USER);
- crm_trace("Performing all %s operations as user '%s'", a->id, a->user);
+ if (is_private) {
+ attrd_set_attr_flags(a, attrd_attr_is_private);
+ }
if (dampen_s != NULL) {
dampen = crm_get_msec(dampen_s);
}
- crm_trace("Created attribute %s with %s write delay", a->id,
- (a->timeout_ms == 0)? "no" : pcmk__readable_interval(a->timeout_ms));
- if(dampen > 0) {
- a->timeout_ms = dampen;
+ if (dampen > 0) {
+ a->timeout_ms = (int) QB_MIN(dampen, INT_MAX);
a->timer = attrd_add_timer(a->id, a->timeout_ms, a);
} else if (dampen < 0) {
crm_warn("Ignoring invalid delay %s for attribute %s", dampen_s, a->id);
}
+ crm_trace("Created attribute %s with %s write delay and %s CIB user",
+ a->id,
+ ((dampen > 0)? pcmk__readable_interval(a->timeout_ms) : "no"),
+ pcmk__s(a->user, "default"));
+
g_hash_table_replace(attributes, a->id, a);
return a;
}
@@ -83,7 +83,7 @@ static int
attrd_update_dampening(attribute_t *a, xmlNode *xml, const char *attr)
{
const char *dvalue = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
- int dampen = 0;
+ long long dampen = 0;
if (dvalue == NULL) {
crm_warn("Could not update %s: peer did not specify value for delay",
@@ -100,7 +100,7 @@ attrd_update_dampening(attribute_t *a, xmlNode *xml, const char *attr)
if (a->timeout_ms != dampen) {
mainloop_timer_del(a->timer);
- a->timeout_ms = dampen;
+ a->timeout_ms = (int) QB_MIN(dampen, INT_MAX);
if (dampen > 0) {
a->timer = attrd_add_timer(attr, a->timeout_ms, a);
crm_info("Update attribute %s delay to %dms (%s)",
@@ -136,20 +136,21 @@ xmlNode *
attrd_add_value_xml(xmlNode *parent, const attribute_t *a,
const attribute_value_t *v, bool force_write)
{
- xmlNode *xml = create_xml_node(parent, __func__);
+ xmlNode *xml = pcmk__xe_create(parent, __func__);
crm_xml_add(xml, PCMK__XA_ATTR_NAME, a->id);
+ crm_xml_add(xml, PCMK__XA_ATTR_SET_TYPE, a->set_type);
crm_xml_add(xml, PCMK__XA_ATTR_SET, a->set_id);
- crm_xml_add(xml, PCMK__XA_ATTR_UUID, a->uuid);
crm_xml_add(xml, PCMK__XA_ATTR_USER, a->user);
pcmk__xe_add_node(xml, v->nodename, v->nodeid);
- if (v->is_remote != 0) {
+ if (pcmk_is_set(v->flags, attrd_value_remote)) {
crm_xml_add_int(xml, PCMK__XA_ATTR_IS_REMOTE, 1);
}
crm_xml_add(xml, PCMK__XA_ATTR_VALUE, v->current);
crm_xml_add_int(xml, PCMK__XA_ATTR_DAMPENING, a->timeout_ms / 1000);
- crm_xml_add_int(xml, PCMK__XA_ATTR_IS_PRIVATE, a->is_private);
- crm_xml_add_int(xml, PCMK__XA_ATTR_FORCE, force_write);
+ crm_xml_add_int(xml, PCMK__XA_ATTR_IS_PRIVATE,
+ pcmk_is_set(a->flags, attrd_attr_is_private));
+ crm_xml_add_int(xml, PCMK__XA_ATTRD_IS_FORCE_WRITE, force_write);
return xml;
}
@@ -166,8 +167,7 @@ attrd_clear_value_seen(void)
while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
g_hash_table_iter_init(&vIter, a->values);
while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
- v->seen = FALSE;
- crm_trace("Clear seen flag %s[%s] = %s.", a->id, v->nodename, v->current);
+ attrd_clear_value_flags(v, attrd_value_from_peer);
}
}
}
@@ -178,9 +178,9 @@ attrd_populate_attribute(xmlNode *xml, const char *attr)
attribute_t *a = NULL;
bool update_both = false;
- const char *op = crm_element_value(xml, PCMK__XA_TASK);
+ const char *op = crm_element_value(xml, PCMK_XA_TASK);
- // NULL because PCMK__ATTRD_CMD_SYNC_RESPONSE has no PCMK__XA_TASK
+ // NULL because PCMK__ATTRD_CMD_SYNC_RESPONSE has no PCMK_XA_TASK
update_both = pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_BOTH,
pcmk__str_null_matches);
@@ -210,3 +210,66 @@ attrd_populate_attribute(xmlNode *xml, const char *attr)
return a;
}
+
+/*!
+ * \internal
+ * \brief Get the XML ID used to write out an attribute set
+ *
+ * \param[in] attr Attribute to get set ID for
+ * \param[in] node_state_id XML ID of node state that attribute value is for
+ *
+ * \return Newly allocated string with XML ID to use for \p attr set
+ */
+char *
+attrd_set_id(const attribute_t *attr, const char *node_state_id)
+{
+ char *set_id = NULL;
+
+ CRM_ASSERT((attr != NULL) && (node_state_id != NULL));
+
+ if (attr->set_id == NULL) {
+ /* @COMPAT This should really take the set type into account. Currently
+ * we use the same XML ID for transient attributes and utilization
+ * attributes. It doesn't cause problems because the status section is
+ * not limited by the schema in any way, but it's still unfortunate.
+ * For backward compatibility reasons, we can't change this.
+ */
+ set_id = crm_strdup_printf("%s-%s", PCMK_XE_STATUS, node_state_id);
+ } else {
+ /* @COMPAT When the user specifies a set ID for an attribute, it is the
+ * same for every node. That is less than ideal, but again, the schema
+ * doesn't enforce anything for the status section. We couldn't change
+ * it without allowing the set ID to vary per value rather than per
+ * attribute, which would break backward compatibility, pose design
+ * challenges, and potentially cause problems in rolling upgrades.
+ */
+ set_id = pcmk__str_copy(attr->set_id);
+ }
+ crm_xml_sanitize_id(set_id);
+ return set_id;
+}
+
+/*!
+ * \internal
+ * \brief Get the XML ID used to write out an attribute value
+ *
+ * \param[in] attr Attribute to get value XML ID for
+ * \param[in] node_state_id UUID of node that attribute value is for
+ *
+ * \return Newly allocated string with XML ID of \p attr value
+ */
+char *
+attrd_nvpair_id(const attribute_t *attr, const char *node_state_id)
+{
+ char *nvpair_id = NULL;
+
+ if (attr->set_id != NULL) {
+ nvpair_id = crm_strdup_printf("%s-%s", attr->set_id, attr->id);
+
+ } else {
+ nvpair_id = crm_strdup_printf(PCMK_XE_STATUS "-%s-%s",
+ node_state_id, attr->id);
+ }
+ crm_xml_sanitize_id(nvpair_id);
+ return nvpair_id;
+}
diff --git a/daemons/attrd/attrd_cib.c b/daemons/attrd/attrd_cib.c
index 80e5580..2537ade 100644
--- a/daemons/attrd/attrd_cib.c
+++ b/daemons/attrd/attrd_cib.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the Pacemaker project contributors
+ * Copyright 2013-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -15,11 +15,12 @@
#include <stdlib.h>
#include <glib.h>
-#include <crm/msg_xml.h>
+#include <crm/cib/internal.h> // cib__*
#include <crm/common/logging.h>
#include <crm/common/results.h>
#include <crm/common/strings_internal.h>
#include <crm/common/xml.h>
+#include <crm/cluster/internal.h> // pcmk__get_node()
#include "pacemaker-attrd.h"
@@ -50,8 +51,10 @@ attrd_cib_updated_cb(const char *event, xmlNode *msg)
{
const xmlNode *patchset = NULL;
const char *client_name = NULL;
+ bool status_changed = false;
if (attrd_shutting_down(true)) {
+ crm_debug("Ignoring CIB change during shutdown");
return;
}
@@ -59,29 +62,32 @@ attrd_cib_updated_cb(const char *event, xmlNode *msg)
return;
}
- if (cib__element_in_patchset(patchset, XML_CIB_TAG_ALERTS)) {
+ if (cib__element_in_patchset(patchset, PCMK_XE_ALERTS)) {
mainloop_set_trigger(attrd_config_read);
}
- if (!attrd_election_won()) {
- // Don't write attributes if we're not the writer
- return;
- }
+ status_changed = cib__element_in_patchset(patchset, PCMK_XE_STATUS);
- client_name = crm_element_value(msg, F_CIB_CLIENTNAME);
+ client_name = crm_element_value(msg, PCMK__XA_CIB_CLIENTNAME);
if (!cib__client_triggers_refresh(client_name)) {
- // The CIB is still accurate
+ /* This change came from a source that ensured the CIB is consistent
+ * with our attributes table, so we don't need to write anything out.
+ */
return;
}
- if (cib__element_in_patchset(patchset, XML_CIB_TAG_NODES)
- || cib__element_in_patchset(patchset, XML_CIB_TAG_STATUS)) {
+ if (!attrd_election_won()) {
+ // Don't write attributes if we're not the writer
+ return;
+ }
- /* An unsafe client modified the nodes or status section. Write
- * transient attributes to ensure they're up-to-date in the CIB.
+ if (status_changed || cib__element_in_patchset(patchset, PCMK_XE_NODES)) {
+ /* An unsafe client modified the PCMK_XE_NODES or PCMK_XE_STATUS
+ * section. Write transient attributes to ensure they're up-to-date in
+ * the CIB.
*/
if (client_name == NULL) {
- client_name = crm_element_value(msg, F_CIB_CLIENTID);
+ client_name = crm_element_value(msg, PCMK__XA_CIB_CLIENTID);
}
crm_notice("Updating all attributes after %s event triggered by %s",
event, pcmk__s(client_name, "(unidentified client)"));
@@ -108,7 +114,7 @@ attrd_cib_connect(int max_retry)
}
attempts++;
crm_debug("Connection attempt %d to the CIB manager", attempts);
- rc = the_cib->cmds->signon(the_cib, T_ATTRD, cib_command);
+ rc = the_cib->cmds->signon(the_cib, PCMK__VALUE_ATTRD, cib_command);
} while ((rc != pcmk_ok) && (attempts < max_retry));
@@ -126,7 +132,8 @@ attrd_cib_connect(int max_retry)
goto cleanup;
}
- rc = the_cib->cmds->add_notify_callback(the_cib, T_CIB_DIFF_NOTIFY,
+ rc = the_cib->cmds->add_notify_callback(the_cib,
+ PCMK__VALUE_CIB_DIFF_NOTIFY,
attrd_cib_updated_cb);
if (rc != pcmk_ok) {
crm_err("Could not set CIB notification callback");
@@ -144,7 +151,7 @@ void
attrd_cib_disconnect(void)
{
CRM_CHECK(the_cib != NULL, return);
- the_cib->cmds->del_notify_callback(the_cib, T_CIB_DIFF_NOTIFY,
+ the_cib->cmds->del_notify_callback(the_cib, PCMK__VALUE_CIB_DIFF_NOTIFY,
attrd_cib_updated_cb);
cib__clean_up_connection(&the_cib);
}
@@ -153,39 +160,44 @@ static void
attrd_erase_cb(xmlNode *msg, int call_id, int rc, xmlNode *output,
void *user_data)
{
- do_crm_log_unlikely(((rc != pcmk_ok)? LOG_NOTICE : LOG_DEBUG),
- "Cleared transient attributes: %s "
- CRM_XS " xpath=%s rc=%d",
- pcmk_strerror(rc), (char *) user_data, rc);
+ const char *node = pcmk__s((const char *) user_data, "a node");
+
+ if (rc == pcmk_ok) {
+ crm_info("Cleared transient node attributes for %s from CIB", node);
+ } else {
+ crm_err("Unable to clear transient node attributes for %s from CIB: %s",
+ node, pcmk_strerror(rc));
+ }
}
-#define XPATH_TRANSIENT "//node_state[@uname='%s']/" XML_TAG_TRANSIENT_NODEATTRS
+#define XPATH_TRANSIENT "//" PCMK__XE_NODE_STATE \
+ "[@" PCMK_XA_UNAME "='%s']" \
+ "/" PCMK__XE_TRANSIENT_ATTRIBUTES
/*!
* \internal
- * \brief Wipe all transient attributes for this node from the CIB
- *
- * Clear any previous transient node attributes from the CIB. This is
- * normally done by the DC's controller when this node leaves the cluster, but
- * this handles the case where the node restarted so quickly that the
- * cluster layer didn't notice.
+ * \brief Wipe all transient node attributes for a node from the CIB
*
- * \todo If pacemaker-attrd respawns after crashing (see PCMK_ENV_RESPAWNED),
- * ideally we'd skip this and sync our attributes from the writer.
- * However, currently we reject any values for us that the writer has, in
- * attrd_peer_update().
+ * \param[in] node Node to clear attributes for
*/
-static void
-attrd_erase_attrs(void)
+void
+attrd_cib_erase_transient_attrs(const char *node)
{
int call_id = 0;
- char *xpath = crm_strdup_printf(XPATH_TRANSIENT, attrd_cluster->uname);
+ char *xpath = NULL;
+
+ CRM_CHECK(node != NULL, return);
+
+ xpath = crm_strdup_printf(XPATH_TRANSIENT, node);
- crm_info("Clearing transient attributes from CIB " CRM_XS " xpath=%s",
- xpath);
+ crm_debug("Clearing transient node attributes for %s from CIB using %s",
+ node, xpath);
call_id = the_cib->cmds->remove(the_cib, xpath, NULL, cib_xpath);
- the_cib->cmds->register_callback_full(the_cib, call_id, 120, FALSE, xpath,
+ free(xpath);
+
+ the_cib->cmds->register_callback_full(the_cib, call_id, 120, FALSE,
+ pcmk__str_copy(node),
"attrd_erase_cb", attrd_erase_cb,
free);
}
@@ -197,8 +209,17 @@ attrd_erase_attrs(void)
void
attrd_cib_init(void)
{
- // We have no attribute values in memory, wipe the CIB to match
- attrd_erase_attrs();
+ /* We have no attribute values in memory, so wipe the CIB to match. This is
+ * normally done by the DC's controller when this node leaves the cluster, but
+ * this handles the case where the node restarted so quickly that the
+ * cluster layer didn't notice.
+ *
+ * \todo If pacemaker-attrd respawns after crashing (see PCMK_ENV_RESPAWNED),
+ * ideally we'd skip this and sync our attributes from the writer.
+ * However, currently we reject any values for us that the writer has, in
+ * attrd_peer_update().
+ */
+ attrd_cib_erase_transient_attrs(attrd_cluster->uname);
// Set a trigger for reading the CIB (for the alerts section)
attrd_config_read = mainloop_add_trigger(G_PRIORITY_HIGH, attrd_read_options, NULL);
@@ -262,19 +283,24 @@ attrd_cib_callback(xmlNode *msg, int call_id, int rc, xmlNode *output, void *use
g_hash_table_iter_init(&iter, a->values);
while (g_hash_table_iter_next(&iter, (gpointer *) & peer, (gpointer *) & v)) {
- do_crm_log(level, "* %s[%s]=%s", a->id, peer, v->requested);
- free(v->requested);
- v->requested = NULL;
- if (rc != pcmk_ok) {
- a->changed = true; /* Attempt write out again */
+ if (rc == pcmk_ok) {
+ crm_info("* Wrote %s[%s]=%s",
+ a->id, peer, pcmk__s(v->requested, "(unset)"));
+ pcmk__str_update(&(v->requested), NULL);
+ } else {
+ do_crm_log(level, "* Could not write %s[%s]=%s",
+ a->id, peer, pcmk__s(v->requested, "(unset)"));
+ /* Reattempt write below if we are still the writer */
+ attrd_set_attr_flags(a, attrd_attr_changed);
}
}
- if (a->changed && attrd_election_won()) {
+ if (pcmk_is_set(a->flags, attrd_attr_changed) && attrd_election_won()) {
if (rc == pcmk_ok) {
/* We deferred a write of a new update because this update was in
* progress. Write out the new value without additional delay.
*/
+ crm_debug("Pending update for %s can be written now", a->id);
write_attribute(a, false);
/* We're re-attempting a write because the original failed; delay
@@ -320,40 +346,27 @@ static int
add_set_attr_update(const attribute_t *attr, const char *attr_id,
const char *node_id, const char *set_id, const char *value)
{
- xmlNode *update = create_xml_node(NULL, XML_CIB_TAG_STATE);
+ xmlNode *update = pcmk__xe_create(NULL, PCMK__XE_NODE_STATE);
xmlNode *child = update;
int rc = ENOMEM;
- if (child == NULL) {
- goto done;
- }
- crm_xml_add(child, XML_ATTR_ID, node_id);
+ crm_xml_add(child, PCMK_XA_ID, node_id);
- child = create_xml_node(child, XML_TAG_TRANSIENT_NODEATTRS);
- if (child == NULL) {
- goto done;
- }
- crm_xml_add(child, XML_ATTR_ID, node_id);
+ child = pcmk__xe_create(child, PCMK__XE_TRANSIENT_ATTRIBUTES);
+ crm_xml_add(child, PCMK_XA_ID, node_id);
- child = create_xml_node(child, attr->set_type);
- if (child == NULL) {
- goto done;
- }
- crm_xml_add(child, XML_ATTR_ID, set_id);
+ child = pcmk__xe_create(child, attr->set_type);
+ crm_xml_add(child, PCMK_XA_ID, set_id);
- child = create_xml_node(child, XML_CIB_TAG_NVPAIR);
- if (child == NULL) {
- goto done;
- }
- crm_xml_add(child, XML_ATTR_ID, attr_id);
- crm_xml_add(child, XML_NVPAIR_ATTR_NAME, attr->id);
- crm_xml_add(child, XML_NVPAIR_ATTR_VALUE, value);
+ child = pcmk__xe_create(child, PCMK_XE_NVPAIR);
+ crm_xml_add(child, PCMK_XA_ID, attr_id);
+ crm_xml_add(child, PCMK_XA_NAME, attr->id);
+ crm_xml_add(child, PCMK_XA_VALUE, value);
- rc = the_cib->cmds->modify(the_cib, XML_CIB_TAG_STATUS, update,
+ rc = the_cib->cmds->modify(the_cib, PCMK_XE_STATUS, update,
cib_can_create|cib_transaction);
rc = pcmk_legacy2rc(rc);
-done:
free_xml(update);
return rc;
}
@@ -373,16 +386,16 @@ static int
add_unset_attr_update(const attribute_t *attr, const char *attr_id,
const char *node_id, const char *set_id)
{
- char *xpath = crm_strdup_printf("/" XML_TAG_CIB
- "/" XML_CIB_TAG_STATUS
- "/" XML_CIB_TAG_STATE
- "[@" XML_ATTR_ID "='%s']"
- "/" XML_TAG_TRANSIENT_NODEATTRS
- "[@" XML_ATTR_ID "='%s']"
- "/%s[@" XML_ATTR_ID "='%s']"
- "/" XML_CIB_TAG_NVPAIR
- "[@" XML_ATTR_ID "='%s' "
- "and @" XML_NVPAIR_ATTR_NAME "='%s']",
+ char *xpath = crm_strdup_printf("/" PCMK_XE_CIB
+ "/" PCMK_XE_STATUS
+ "/" PCMK__XE_NODE_STATE
+ "[@" PCMK_XA_ID "='%s']"
+ "/" PCMK__XE_TRANSIENT_ATTRIBUTES
+ "[@" PCMK_XA_ID "='%s']"
+ "/%s[@" PCMK_XA_ID "='%s']"
+ "/" PCMK_XE_NVPAIR
+ "[@" PCMK_XA_ID "='%s' "
+ "and @" PCMK_XA_NAME "='%s']",
node_id, node_id, attr->set_type, set_id,
attr_id, attr->id);
@@ -406,31 +419,17 @@ add_unset_attr_update(const attribute_t *attr, const char *attr_id,
static int
add_attr_update(const attribute_t *attr, const char *value, const char *node_id)
{
- char *set_id = NULL;
- char *attr_id = NULL;
+ char *set_id = attrd_set_id(attr, node_id);
+ char *nvpair_id = attrd_nvpair_id(attr, node_id);
int rc = pcmk_rc_ok;
- if (attr->set_id != NULL) {
- pcmk__str_update(&set_id, attr->set_id);
- } else {
- set_id = crm_strdup_printf("%s-%s", XML_CIB_TAG_STATUS, node_id);
- }
- crm_xml_sanitize_id(set_id);
-
- if (attr->uuid != NULL) {
- pcmk__str_update(&attr_id, attr->uuid);
- } else {
- attr_id = crm_strdup_printf("%s-%s", set_id, attr->id);
- }
- crm_xml_sanitize_id(attr_id);
-
- if (value != NULL) {
- rc = add_set_attr_update(attr, attr_id, node_id, set_id, value);
+ if (value == NULL) {
+ rc = add_unset_attr_update(attr, nvpair_id, node_id, set_id);
} else {
- rc = add_unset_attr_update(attr, attr_id, node_id, set_id);
+ rc = add_set_attr_update(attr, nvpair_id, node_id, set_id, value);
}
free(set_id);
- free(attr_id);
+ free(nvpair_id);
return rc;
}
@@ -454,13 +453,11 @@ send_alert_attributes_value(attribute_t *a, GHashTable *t)
static void
set_alert_attribute_value(GHashTable *t, attribute_value_t *v)
{
- attribute_value_t *a_v = NULL;
- a_v = calloc(1, sizeof(attribute_value_t));
- CRM_ASSERT(a_v != NULL);
+ attribute_value_t *a_v = pcmk__assert_alloc(1, sizeof(attribute_value_t));
a_v->nodeid = v->nodeid;
- a_v->nodename = strdup(v->nodename);
- pcmk__str_update(&a_v->current, v->current);
+ a_v->nodename = pcmk__str_copy(v->nodename);
+ a_v->current = pcmk__str_copy(v->current);
g_hash_table_replace(t, a_v->nodename, a_v);
}
@@ -493,7 +490,7 @@ write_attribute(attribute_t *a, bool ignore_delay)
}
/* If this attribute will be written to the CIB ... */
- if (!stand_alone && !a->is_private) {
+ if (!stand_alone && !pcmk_is_set(a->flags, attrd_attr_is_private)) {
/* Defer the write if now's not a good time */
if (a->update && (a->update < last_cib_op_done)) {
crm_info("Write out of '%s' continuing: update %d considered lost",
@@ -520,21 +517,17 @@ write_attribute(attribute_t *a, bool ignore_delay)
the_cib->cmds->set_user(the_cib, a->user);
rc = the_cib->cmds->init_transaction(the_cib);
if (rc != pcmk_ok) {
- crm_err("Failed to write %s (id %s, set %s): Could not initiate "
+ crm_err("Failed to write %s (set %s): Could not initiate "
"CIB transaction",
- a->id, pcmk__s(a->uuid, "n/a"), pcmk__s(a->set_id, "n/a"));
+ a->id, pcmk__s(a->set_id, "unspecified"));
goto done;
}
}
- /* Attribute will be written shortly, so clear changed flag */
- a->changed = false;
-
- /* We will check all peers' uuids shortly, so initialize this to false */
- a->unknown_peer_uuids = false;
-
- /* Attribute will be written shortly, so clear forced write flag */
- a->force_write = FALSE;
+ /* Attribute will be written shortly, so clear changed flag and force
+ * write flag, and initialize UUID missing flag to false.
+ */
+ attrd_clear_attr_flags(a, attrd_attr_changed|attrd_attr_uuid_missing|attrd_attr_force_write);
/* Make the table for the attribute trap */
alert_attribute_value = pcmk__strikey_table(NULL,
@@ -543,79 +536,80 @@ write_attribute(attribute_t *a, bool ignore_delay)
/* Iterate over each peer value of this attribute */
g_hash_table_iter_init(&iter, a->values);
while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &v)) {
- crm_node_t *peer = crm_get_peer_full(v->nodeid, v->nodename,
- CRM_GET_PEER_ANY);
+ const char *uuid = NULL;
- /* If the value's peer info does not correspond to a peer, ignore it */
- if (peer == NULL) {
- crm_notice("Cannot update %s[%s]=%s because peer not known",
- a->id, v->nodename, v->current);
- continue;
- }
+ if (pcmk_is_set(v->flags, attrd_value_remote)) {
+ /* If this is a Pacemaker Remote node, the node's UUID is the same
+ * as its name, which we already have.
+ */
+ uuid = v->nodename;
- /* If we're just learning the peer's node id, remember it */
- if (peer->id && (v->nodeid == 0)) {
- crm_trace("Learned ID %u for node %s", peer->id, v->nodename);
- v->nodeid = peer->id;
+ } else {
+ // This will create a cluster node cache entry if none exists
+ crm_node_t *peer = pcmk__get_node(v->nodeid, v->nodename, NULL,
+ pcmk__node_search_any);
+
+ uuid = peer->uuid;
+
+ // Remember peer's node ID if we're just now learning it
+ if ((peer->id != 0) && (v->nodeid == 0)) {
+ crm_trace("Learned ID %u for node %s", peer->id, v->nodename);
+ v->nodeid = peer->id;
+ }
}
/* If this is a private attribute, no update needs to be sent */
- if (stand_alone || a->is_private) {
+ if (stand_alone || pcmk_is_set(a->flags, attrd_attr_is_private)) {
private_updates++;
continue;
}
- /* If the peer is found, but its uuid is unknown, defer write */
- if (peer->uuid == NULL) {
- a->unknown_peer_uuids = true;
- crm_notice("Cannot update %s[%s]=%s because peer UUID not known "
- "(will retry if learned)",
+ // Defer write if this is a cluster node that's never been seen
+ if (uuid == NULL) {
+ attrd_set_attr_flags(a, attrd_attr_uuid_missing);
+ crm_notice("Cannot update %s[%s]='%s' now because node's UUID is "
+ "unknown (will retry if learned)",
a->id, v->nodename, v->current);
continue;
}
// Update this value as part of the CIB transaction we're building
- rc = add_attr_update(a, v->current, peer->uuid);
+ rc = add_attr_update(a, v->current, uuid);
if (rc != pcmk_rc_ok) {
- crm_err("Failed to update %s[%s]=%s (peer known as %s, UUID %s, "
- "ID %" PRIu32 "/%" PRIu32 "): %s",
- a->id, v->nodename, v->current, peer->uname, peer->uuid,
- peer->id, v->nodeid, pcmk_rc_str(rc));
+ crm_err("Failed to update %s[%s]='%s': %s "
+ CRM_XS " node uuid=%s id=%" PRIu32,
+ a->id, v->nodename, v->current, pcmk_rc_str(rc),
+ uuid, v->nodeid);
continue;
}
- crm_debug("Updating %s[%s]=%s (peer known as %s, UUID %s, ID "
- "%" PRIu32 "/%" PRIu32 ")",
- a->id, v->nodename, v->current,
- peer->uname, peer->uuid, peer->id, v->nodeid);
+ crm_debug("Writing %s[%s]=%s (node-state-id=%s node-id=%" PRIu32 ")",
+ a->id, v->nodename, pcmk__s(v->current, "(unset)"),
+ uuid, v->nodeid);
cib_updates++;
/* Preservation of the attribute to transmit alert */
set_alert_attribute_value(alert_attribute_value, v);
- free(v->requested);
- v->requested = NULL;
- if (v->current) {
- v->requested = strdup(v->current);
- }
+ // Save this value so we can log it when write completes
+ pcmk__str_update(&(v->requested), v->current);
}
if (private_updates) {
- crm_info("Processed %d private change%s for %s, id=%s, set=%s",
+ crm_info("Processed %d private change%s for %s (set %s)",
private_updates, pcmk__plural_s(private_updates),
- a->id, pcmk__s(a->uuid, "n/a"), pcmk__s(a->set_id, "n/a"));
+ a->id, pcmk__s(a->set_id, "unspecified"));
}
if (cib_updates > 0) {
- char *id = NULL;
+ char *id = pcmk__str_copy(a->id);
// Commit transaction
a->update = the_cib->cmds->end_transaction(the_cib, true, cib_none);
- crm_info("Sent CIB request %d with %d change%s for %s (id %s, set %s)",
+ crm_info("Sent CIB request %d with %d change%s for %s (set %s)",
a->update, cib_updates, pcmk__plural_s(cib_updates),
- a->id, pcmk__s(a->uuid, "n/a"), pcmk__s(a->set_id, "n/a"));
+ a->id, pcmk__s(a->set_id, "unspecified"));
- pcmk__str_update(&id, a->id);
if (the_cib->cmds->register_callback_full(the_cib, a->update,
CIB_OP_TIMEOUT_S, FALSE, id,
"attrd_cib_callback",
@@ -653,18 +647,20 @@ attrd_write_attributes(uint32_t options)
pcmk_is_set(options, attrd_write_all)? "all" : "changed");
g_hash_table_iter_init(&iter, attributes);
while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & a)) {
- if (!pcmk_is_set(options, attrd_write_all) && a->unknown_peer_uuids) {
+ if (!pcmk_is_set(options, attrd_write_all) &&
+ pcmk_is_set(a->flags, attrd_attr_uuid_missing)) {
// Try writing this attribute again, in case peer ID was learned
- a->changed = true;
- } else if (a->force_write) {
+ attrd_set_attr_flags(a, attrd_attr_changed);
+ } else if (pcmk_is_set(a->flags, attrd_attr_force_write)) {
/* If the force_write flag is set, write the attribute. */
- a->changed = true;
+ attrd_set_attr_flags(a, attrd_attr_changed);
}
- if (pcmk_is_set(options, attrd_write_all) || a->changed) {
+ if (pcmk_is_set(options, attrd_write_all) ||
+ pcmk_is_set(a->flags, attrd_attr_changed)) {
bool ignore_delay = pcmk_is_set(options, attrd_write_no_delay);
- if (a->force_write) {
+ if (pcmk_is_set(a->flags, attrd_attr_force_write)) {
// Always ignore delay when forced write flag is set
ignore_delay = true;
}
diff --git a/daemons/attrd/attrd_corosync.c b/daemons/attrd/attrd_corosync.c
index 86dc67b..fb3b4e5 100644
--- a/daemons/attrd/attrd_corosync.c
+++ b/daemons/attrd/attrd_corosync.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the Pacemaker project contributors
+ * Copyright 2013-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -19,19 +19,19 @@
#include <crm/common/logging.h>
#include <crm/common/results.h>
#include <crm/common/strings_internal.h>
-#include <crm/msg_xml.h>
+#include <crm/common/xml.h>
#include "pacemaker-attrd.h"
static xmlNode *
attrd_confirmation(int callid)
{
- xmlNode *node = create_xml_node(NULL, __func__);
+ xmlNode *node = pcmk__xe_create(NULL, __func__);
- crm_xml_add(node, F_TYPE, T_ATTRD);
- crm_xml_add(node, F_ORIG, get_local_node_name());
- crm_xml_add(node, PCMK__XA_TASK, PCMK__ATTRD_CMD_CONFIRM);
- crm_xml_add_int(node, XML_LRM_ATTR_CALLID, callid);
+ crm_xml_add(node, PCMK__XA_T, PCMK__VALUE_ATTRD);
+ crm_xml_add(node, PCMK__XA_SRC, pcmk__cluster_local_node_name());
+ crm_xml_add(node, PCMK_XA_TASK, PCMK__ATTRD_CMD_CONFIRM);
+ crm_xml_add_int(node, PCMK__XA_CALL_ID, callid);
return node;
}
@@ -39,7 +39,7 @@ attrd_confirmation(int callid)
static void
attrd_peer_message(crm_node_t *peer, xmlNode *xml)
{
- const char *election_op = crm_element_value(xml, F_CRM_TASK);
+ const char *election_op = crm_element_value(xml, PCMK__XA_CRM_TASK);
if (election_op) {
attrd_handle_election_op(peer, xml);
@@ -64,7 +64,7 @@ attrd_peer_message(crm_node_t *peer, xmlNode *xml)
.result = PCMK__UNKNOWN_RESULT,
};
- request.op = crm_element_value_copy(request.xml, PCMK__XA_TASK);
+ request.op = crm_element_value_copy(request.xml, PCMK_XA_TASK);
CRM_CHECK(request.op != NULL, return);
attrd_handle_request(&request);
@@ -81,7 +81,7 @@ attrd_peer_message(crm_node_t *peer, xmlNode *xml)
* response so the originating peer knows what they're a confirmation
* for.
*/
- crm_element_value_int(xml, XML_LRM_ATTR_CALLID, &callid);
+ crm_element_value_int(xml, PCMK__XA_CALL_ID, &callid);
reply = attrd_confirmation(callid);
/* And then send the confirmation back to the originating peer. This
@@ -106,22 +106,22 @@ attrd_cpg_dispatch(cpg_handle_t handle,
uint32_t kind = 0;
xmlNode *xml = NULL;
const char *from = NULL;
- char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);
+ char *data = pcmk__cpg_message_data(handle, nodeid, pid, msg, &kind, &from);
if(data == NULL) {
return;
}
if (kind == crm_class_cluster) {
- xml = string2xml(data);
+ xml = pcmk__xml_parse(data);
}
if (xml == NULL) {
crm_err("Bad message of class %d received from %s[%u]: '%.120s'", kind, from, nodeid, data);
} else {
- crm_node_t *peer = crm_get_peer(nodeid, from);
-
- attrd_peer_message(peer, xml);
+ attrd_peer_message(pcmk__get_node(nodeid, from, NULL,
+ pcmk__node_search_cluster_member),
+ xml);
}
free_xml(xml);
@@ -143,86 +143,24 @@ attrd_cpg_destroy(gpointer unused)
/*!
* \internal
- * \brief Override an attribute sync with a local value
- *
- * Broadcast the local node's value for an attribute that's different from the
- * value provided in a peer's attribute synchronization response. This ensures a
- * node's values for itself take precedence and all peers are kept in sync.
+ * \brief Broadcast an update for a single attribute value
*
- * \param[in] a Attribute entry to override
- *
- * \return Local instance of attribute value
+ * \param[in] a Attribute to broadcast
+ * \param[in] v Attribute value to broadcast
*/
-static attribute_value_t *
-broadcast_local_value(const attribute_t *a)
-{
- attribute_value_t *v = g_hash_table_lookup(a->values, attrd_cluster->uname);
- xmlNode *sync = create_xml_node(NULL, __func__);
-
- crm_xml_add(sync, PCMK__XA_TASK, PCMK__ATTRD_CMD_SYNC_RESPONSE);
- attrd_add_value_xml(sync, a, v, false);
- attrd_send_message(NULL, sync, false);
- free_xml(sync);
- return v;
-}
-
-/*!
- * \internal
- * \brief Ensure a Pacemaker Remote node is in the correct peer cache
- *
- * \param[in] node_name Name of Pacemaker Remote node to check
- */
-static void
-cache_remote_node(const char *node_name)
+void
+attrd_broadcast_value(const attribute_t *a, const attribute_value_t *v)
{
- /* If we previously assumed this node was an unseen cluster node,
- * remove its entry from the cluster peer cache.
- */
- crm_node_t *dup = pcmk__search_cluster_node_cache(0, node_name, NULL);
+ xmlNode *op = pcmk__xe_create(NULL, PCMK_XE_OP);
- if (dup && (dup->uuid == NULL)) {
- reap_crm_member(0, node_name);
- }
-
- // Ensure node is in the remote peer cache
- CRM_ASSERT(crm_remote_peer_get(node_name) != NULL);
+ crm_xml_add(op, PCMK_XA_TASK, PCMK__ATTRD_CMD_UPDATE);
+ attrd_add_value_xml(op, a, v, false);
+ attrd_send_message(NULL, op, false);
+ free_xml(op);
}
#define state_text(state) pcmk__s((state), "in unknown state")
-/*!
- * \internal
- * \brief Return host's hash table entry (creating one if needed)
- *
- * \param[in,out] values Hash table of values
- * \param[in] host Name of peer to look up
- * \param[in] xml XML describing the attribute
- *
- * \return Pointer to new or existing hash table entry
- */
-static attribute_value_t *
-attrd_lookup_or_create_value(GHashTable *values, const char *host,
- const xmlNode *xml)
-{
- attribute_value_t *v = g_hash_table_lookup(values, host);
- int is_remote = 0;
-
- crm_element_value_int(xml, PCMK__XA_ATTR_IS_REMOTE, &is_remote);
- if (is_remote) {
- cache_remote_node(host);
- }
-
- if (v == NULL) {
- v = calloc(1, sizeof(attribute_value_t));
- CRM_ASSERT(v != NULL);
-
- pcmk__str_update(&v->nodename, host);
- v->is_remote = is_remote;
- g_hash_table_replace(values, v->nodename, v);
- }
- return(v);
-}
-
static void
attrd_peer_change_cb(enum crm_status_type kind, crm_node_t *peer, const void *data)
{
@@ -254,7 +192,7 @@ attrd_peer_change_cb(enum crm_status_type kind, crm_node_t *peer, const void *da
*/
if (attrd_election_won()
&& !pcmk_is_set(peer->flags, crm_remote_node)) {
- attrd_peer_sync(peer, NULL);
+ attrd_peer_sync(peer);
}
} else {
// Remove all attribute values associated with lost nodes
@@ -269,17 +207,14 @@ attrd_peer_change_cb(enum crm_status_type kind, crm_node_t *peer, const void *da
attrd_remove_voter(peer);
attrd_remove_peer_protocol_ver(peer->uname);
attrd_do_not_expect_from_peer(peer->uname);
-
- // Ensure remote nodes that come up are in the remote node cache
- } else if (!gone && is_remote) {
- cache_remote_node(peer->uname);
}
}
static void
record_peer_nodeid(attribute_value_t *v, const char *host)
{
- crm_node_t *known_peer = crm_get_peer(v->nodeid, host);
+ crm_node_t *known_peer = pcmk__get_node(v->nodeid, host, NULL,
+ pcmk__node_search_cluster_member);
crm_trace("Learned %s has node id %s", known_peer->uname, known_peer->uuid);
if (attrd_election_won()) {
@@ -287,34 +222,63 @@ record_peer_nodeid(attribute_value_t *v, const char *host)
}
}
+#define readable_value(rv_v) pcmk__s((rv_v)->current, "(unset)")
+
+#define readable_peer(p) \
+ (((p) == NULL)? "all peers" : pcmk__s((p)->uname, "unknown peer"))
+
static void
update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
const char *attr, const char *value, const char *host,
- bool filter, int is_force_write)
+ bool filter)
{
+ int is_remote = 0;
+ bool changed = false;
attribute_value_t *v = NULL;
- v = attrd_lookup_or_create_value(a->values, host, xml);
+ // Create entry for value if not already existing
+ v = g_hash_table_lookup(a->values, host);
+ if (v == NULL) {
+ v = pcmk__assert_alloc(1, sizeof(attribute_value_t));
+
+ v->nodename = pcmk__str_copy(host);
+ g_hash_table_replace(a->values, v->nodename, v);
+ }
+
+ // If value is for a Pacemaker Remote node, remember that
+ crm_element_value_int(xml, PCMK__XA_ATTR_IS_REMOTE, &is_remote);
+ if (is_remote) {
+ attrd_set_value_flags(v, attrd_value_remote);
+ CRM_ASSERT(pcmk__cluster_lookup_remote_node(host) != NULL);
+ }
- if (filter && !pcmk__str_eq(v->current, value, pcmk__str_casei)
- && pcmk__str_eq(host, attrd_cluster->uname, pcmk__str_casei)) {
+ // Check whether the value changed
+ changed = !pcmk__str_eq(v->current, value, pcmk__str_casei);
+ if (changed && filter && pcmk__str_eq(host, attrd_cluster->uname,
+ pcmk__str_casei)) {
+ /* Broadcast the local value for an attribute that differs from the
+ * value provided in a peer's attribute synchronization response. This
+ * ensures a node's values for itself take precedence and all peers are
+ * kept in sync.
+ */
+ v = g_hash_table_lookup(a->values, attrd_cluster->uname);
crm_notice("%s[%s]: local value '%s' takes priority over '%s' from %s",
- attr, host, v->current, value, peer->uname);
- v = broadcast_local_value(a);
+ attr, host, readable_value(v), value, peer->uname);
+ attrd_broadcast_value(a, v);
- } else if (!pcmk__str_eq(v->current, value, pcmk__str_casei)) {
+ } else if (changed) {
crm_notice("Setting %s[%s]%s%s: %s -> %s "
CRM_XS " from %s with %s write delay",
attr, host, a->set_type ? " in " : "",
- pcmk__s(a->set_type, ""), pcmk__s(v->current, "(unset)"),
+ pcmk__s(a->set_type, ""), readable_value(v),
pcmk__s(value, "(unset)"), peer->uname,
(a->timeout_ms == 0)? "no" : pcmk__readable_interval(a->timeout_ms));
pcmk__str_update(&v->current, value);
- a->changed = true;
+ attrd_set_attr_flags(a, attrd_attr_changed);
if (pcmk__str_eq(host, attrd_cluster->uname, pcmk__str_casei)
- && pcmk__str_eq(attr, XML_CIB_ATTR_SHUTDOWN, pcmk__str_none)) {
+ && pcmk__str_eq(attr, PCMK__NODE_ATTR_SHUTDOWN, pcmk__str_none)) {
if (!pcmk__str_eq(value, "0", pcmk__str_null_matches)) {
attrd_set_requesting_shutdown();
@@ -326,30 +290,37 @@ update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
// Write out new value or start dampening timer
if (a->timeout_ms && a->timer) {
- crm_trace("Delayed write out (%dms) for %s", a->timeout_ms, attr);
+ crm_trace("Delaying write of %s %s for dampening",
+ attr, pcmk__readable_interval(a->timeout_ms));
mainloop_timer_start(a->timer);
} else {
attrd_write_or_elect_attribute(a);
}
} else {
+ int is_force_write = 0;
+
+ crm_element_value_int(xml, PCMK__XA_ATTRD_IS_FORCE_WRITE,
+ &is_force_write);
+
if (is_force_write == 1 && a->timeout_ms && a->timer) {
/* Save forced writing and set change flag. */
/* The actual attribute is written by Writer after election. */
- crm_trace("Unchanged %s[%s] from %s is %s(Set the forced write flag)",
- attr, host, peer->uname, value);
- a->force_write = TRUE;
+ crm_trace("%s[%s] from %s is unchanged (%s), forcing write",
+ attr, host, peer->uname, pcmk__s(value, "unset"));
+ attrd_set_attr_flags(a, attrd_attr_force_write);
} else {
- crm_trace("Unchanged %s[%s] from %s is %s", attr, host, peer->uname, value);
+ crm_trace("%s[%s] from %s is unchanged (%s)",
+ attr, host, peer->uname, pcmk__s(value, "unset"));
}
}
- /* Set the seen flag for attribute processing held only in the own node. */
- v->seen = TRUE;
+ // This allows us to later detect local values that peer doesn't know about
+ attrd_set_value_flags(v, attrd_value_from_peer);
/* If this is a cluster node whose node ID we are learning, remember it */
- if ((v->nodeid == 0) && (v->is_remote == FALSE)
- && (crm_element_value_int(xml, PCMK__XA_ATTR_NODE_ID,
+ if ((v->nodeid == 0) && !pcmk_is_set(v->flags, attrd_value_remote)
+ && (crm_element_value_int(xml, PCMK__XA_ATTR_HOST_ID,
(int*)&v->nodeid) == 0) && (v->nodeid > 0)) {
record_peer_nodeid(v, host);
}
@@ -361,16 +332,13 @@ attrd_peer_update_one(const crm_node_t *peer, xmlNode *xml, bool filter)
attribute_t *a = NULL;
const char *attr = crm_element_value(xml, PCMK__XA_ATTR_NAME);
const char *value = crm_element_value(xml, PCMK__XA_ATTR_VALUE);
- const char *host = crm_element_value(xml, PCMK__XA_ATTR_NODE_NAME);
- int is_force_write = 0;
+ const char *host = crm_element_value(xml, PCMK__XA_ATTR_HOST);
if (attr == NULL) {
crm_warn("Could not update attribute: peer did not specify name");
return;
}
- crm_element_value_int(xml, PCMK__XA_ATTR_FORCE, &is_force_write);
-
a = attrd_populate_attribute(xml, attr);
if (a == NULL) {
return;
@@ -381,16 +349,16 @@ attrd_peer_update_one(const crm_node_t *peer, xmlNode *xml, bool filter)
GHashTableIter vIter;
crm_debug("Setting %s for all hosts to %s", attr, value);
- xml_remove_prop(xml, PCMK__XA_ATTR_NODE_ID);
+ pcmk__xe_remove_attr(xml, PCMK__XA_ATTR_HOST_ID);
g_hash_table_iter_init(&vIter, a->values);
while (g_hash_table_iter_next(&vIter, (gpointer *) & host, NULL)) {
- update_attr_on_host(a, peer, xml, attr, value, host, filter, is_force_write);
+ update_attr_on_host(a, peer, xml, attr, value, host, filter);
}
} else {
// Update attribute value for the given host
- update_attr_on_host(a, peer, xml, attr, value, host, filter, is_force_write);
+ update_attr_on_host(a, peer, xml, attr, value, host, filter);
}
/* If this is a message from some attrd instance broadcasting its protocol
@@ -412,13 +380,18 @@ broadcast_unseen_local_values(void)
g_hash_table_iter_init(&aIter, attributes);
while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
+
g_hash_table_iter_init(&vIter, a->values);
while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
- if (!(v->seen) && pcmk__str_eq(v->nodename, attrd_cluster->uname,
- pcmk__str_casei)) {
+
+ if (!pcmk_is_set(v->flags, attrd_value_from_peer)
+ && pcmk__str_eq(v->nodename, attrd_cluster->uname,
+ pcmk__str_casei)) {
+ crm_trace("* %s[%s]='%s' is local-only",
+ a->id, v->nodename, readable_value(v));
if (sync == NULL) {
- sync = create_xml_node(NULL, __func__);
- crm_xml_add(sync, PCMK__XA_TASK, PCMK__ATTRD_CMD_SYNC_RESPONSE);
+ sync = pcmk__xe_create(NULL, __func__);
+ crm_xml_add(sync, PCMK_XA_TASK, PCMK__ATTRD_CMD_SYNC_RESPONSE);
}
attrd_add_value_xml(sync, a, v, a->timeout_ms && a->timer);
}
@@ -435,17 +408,21 @@ broadcast_unseen_local_values(void)
int
attrd_cluster_connect(void)
{
+ int rc = pcmk_rc_ok;
+
attrd_cluster = pcmk_cluster_new();
- attrd_cluster->destroy = attrd_cpg_destroy;
- attrd_cluster->cpg.cpg_deliver_fn = attrd_cpg_dispatch;
- attrd_cluster->cpg.cpg_confchg_fn = pcmk_cpg_membership;
+ pcmk_cluster_set_destroy_fn(attrd_cluster, attrd_cpg_destroy);
+ pcmk_cpg_set_deliver_fn(attrd_cluster, attrd_cpg_dispatch);
+ pcmk_cpg_set_confchg_fn(attrd_cluster, pcmk__cpg_confchg_cb);
- crm_set_status_callback(&attrd_peer_change_cb);
+ pcmk__cluster_set_status_callback(&attrd_peer_change_cb);
- if (crm_cluster_connect(attrd_cluster) == FALSE) {
+ rc = pcmk_cluster_connect(attrd_cluster);
+ rc = pcmk_rc2legacy(rc);
+ if (rc != pcmk_ok) {
crm_err("Cluster connection failed");
- return -ENOTCONN;
+ return rc;
}
return pcmk_ok;
}
@@ -455,15 +432,19 @@ attrd_peer_clear_failure(pcmk__request_t *request)
{
xmlNode *xml = request->xml;
const char *rsc = crm_element_value(xml, PCMK__XA_ATTR_RESOURCE);
- const char *host = crm_element_value(xml, PCMK__XA_ATTR_NODE_NAME);
- const char *op = crm_element_value(xml, PCMK__XA_ATTR_OPERATION);
- const char *interval_spec = crm_element_value(xml, PCMK__XA_ATTR_INTERVAL);
- guint interval_ms = crm_parse_interval_spec(interval_spec);
+ const char *host = crm_element_value(xml, PCMK__XA_ATTR_HOST);
+ const char *op = crm_element_value(xml, PCMK__XA_ATTR_CLEAR_OPERATION);
+ const char *interval_spec = crm_element_value(xml,
+ PCMK__XA_ATTR_CLEAR_INTERVAL);
+ guint interval_ms = 0U;
char *attr = NULL;
GHashTableIter iter;
regex_t regex;
- crm_node_t *peer = crm_get_peer(0, request->peer);
+ crm_node_t *peer = pcmk__get_node(0, request->peer, NULL,
+ pcmk__node_search_cluster_member);
+
+ pcmk_parse_interval_spec(interval_spec, &interval_ms);
if (attrd_failure_regex(&regex, rsc, op, interval_ms) != pcmk_ok) {
crm_info("Ignoring invalid request to clear failures for %s",
@@ -471,10 +452,10 @@ attrd_peer_clear_failure(pcmk__request_t *request)
return;
}
- crm_xml_add(xml, PCMK__XA_TASK, PCMK__ATTRD_CMD_UPDATE);
+ crm_xml_add(xml, PCMK_XA_TASK, PCMK__ATTRD_CMD_UPDATE);
/* Make sure value is not set, so we delete */
- xml_remove_prop(xml, PCMK__XA_ATTR_VALUE);
+ pcmk__xe_remove_attr(xml, PCMK__XA_ATTR_VALUE);
g_hash_table_iter_init(&iter, attributes);
while (g_hash_table_iter_next(&iter, (gpointer *) &attr, NULL)) {
@@ -492,7 +473,7 @@ attrd_peer_clear_failure(pcmk__request_t *request)
* \internal
* \brief Load attributes from a peer sync response
*
- * \param[in] peer Peer that sent clear request
+ * \param[in] peer Peer that sent sync response
* \param[in] peer_won Whether peer is the attribute writer
* \param[in,out] xml Request XML
*/
@@ -510,11 +491,11 @@ attrd_peer_sync_response(const crm_node_t *peer, bool peer_won, xmlNode *xml)
}
// Process each attribute update in the sync response
- for (xmlNode *child = pcmk__xml_first_child(xml); child != NULL;
- child = pcmk__xml_next(child)) {
+ for (xmlNode *child = pcmk__xe_first_child(xml, NULL, NULL, NULL);
+ child != NULL; child = pcmk__xe_next(child)) {
+
attrd_peer_update(peer, child,
- crm_element_value(child, PCMK__XA_ATTR_NODE_NAME),
- true);
+ crm_element_value(child, PCMK__XA_ATTR_HOST), true);
}
if (peer_won) {
@@ -540,7 +521,9 @@ attrd_peer_remove(const char *host, bool uncache, const char *source)
GHashTableIter aIter;
CRM_CHECK(host != NULL, return);
- crm_notice("Removing all %s attributes for peer %s", host, source);
+ crm_notice("Removing all %s attributes for node %s "
+ CRM_XS " %s reaping node from cache",
+ host, source, (uncache? "and" : "without"));
g_hash_table_iter_init(&aIter, attributes);
while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
@@ -550,33 +533,40 @@ attrd_peer_remove(const char *host, bool uncache, const char *source)
}
if (uncache) {
- crm_remote_peer_cache_remove(host);
- reap_crm_member(0, host);
+ pcmk__purge_node_from_cache(host, 0);
}
}
+/*!
+ * \internal
+ * \brief Send all known attributes and values to a peer
+ *
+ * \param[in] peer Peer to send sync to (if NULL, broadcast to all peers)
+ */
void
-attrd_peer_sync(crm_node_t *peer, xmlNode *xml)
+attrd_peer_sync(crm_node_t *peer)
{
GHashTableIter aIter;
GHashTableIter vIter;
attribute_t *a = NULL;
attribute_value_t *v = NULL;
- xmlNode *sync = create_xml_node(NULL, __func__);
+ xmlNode *sync = pcmk__xe_create(NULL, __func__);
- crm_xml_add(sync, PCMK__XA_TASK, PCMK__ATTRD_CMD_SYNC_RESPONSE);
+ crm_xml_add(sync, PCMK_XA_TASK, PCMK__ATTRD_CMD_SYNC_RESPONSE);
g_hash_table_iter_init(&aIter, attributes);
while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
g_hash_table_iter_init(&vIter, a->values);
while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
- crm_debug("Syncing %s[%s] = %s to %s", a->id, v->nodename, v->current, peer?peer->uname:"everyone");
+ crm_debug("Syncing %s[%s]='%s' to %s",
+ a->id, v->nodename, readable_value(v),
+ readable_peer(peer));
attrd_add_value_xml(sync, a, v, false);
}
}
- crm_debug("Syncing values to %s", peer?peer->uname:"everyone");
+ crm_debug("Syncing values to %s", readable_peer(peer));
attrd_send_message(peer, sync, false);
free_xml(sync);
}
@@ -589,9 +579,10 @@ attrd_peer_update(const crm_node_t *peer, xmlNode *xml, const char *host,
CRM_CHECK((peer != NULL) && (xml != NULL), return);
if (xml->children != NULL) {
- for (xmlNode *child = first_named_child(xml, XML_ATTR_OP); child != NULL;
- child = crm_next_same_xml(child)) {
- attrd_copy_xml_attributes(xml, child);
+ for (xmlNode *child = pcmk__xe_first_child(xml, PCMK_XE_OP, NULL, NULL);
+ child != NULL; child = pcmk__xe_next_same(child)) {
+
+ pcmk__xe_copy_attrs(child, xml, pcmk__xaf_no_overwrite);
attrd_peer_update_one(peer, child, filter);
if (attrd_request_has_sync_point(child)) {
diff --git a/daemons/attrd/attrd_elections.c b/daemons/attrd/attrd_elections.c
index 82fbe8a..0abd9c0 100644
--- a/daemons/attrd/attrd_elections.c
+++ b/daemons/attrd/attrd_elections.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the Pacemaker project contributors
+ * Copyright 2013-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -8,9 +8,9 @@
*/
#include <crm_internal.h>
-#include <crm/msg_xml.h>
#include <crm/cluster.h>
#include <crm/cluster/election_internal.h>
+#include <crm/common/xml.h>
#include "pacemaker-attrd.h"
@@ -23,7 +23,7 @@ attrd_election_cb(gpointer user_data)
attrd_declare_winner();
/* Update the peers after an election */
- attrd_peer_sync(NULL, NULL);
+ attrd_peer_sync(NULL);
/* After winning an election, update the CIB with the values of all
* attributes as the winner knows them.
@@ -35,7 +35,7 @@ attrd_election_cb(gpointer user_data)
void
attrd_election_init(void)
{
- writer = election_init(T_ATTRD, attrd_cluster->uname, 120000,
+ writer = election_init(PCMK__VALUE_ATTRD, attrd_cluster->uname, 120000,
attrd_election_cb);
}
@@ -69,7 +69,7 @@ attrd_handle_election_op(const crm_node_t *peer, xmlNode *xml)
enum election_result rc = 0;
enum election_result previous = election_state(writer);
- crm_xml_add(xml, F_CRM_HOST_FROM, peer->uname);
+ crm_xml_add(xml, PCMK__XA_SRC, peer->uname);
// Don't become writer if we're shutting down
rc = election_count_vote(writer, xml, !attrd_shutting_down(false));
diff --git a/daemons/attrd/attrd_ipc.c b/daemons/attrd/attrd_ipc.c
index 05c4a69..0a2688e 100644
--- a/daemons/attrd/attrd_ipc.c
+++ b/daemons/attrd/attrd_ipc.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2023 the Pacemaker project contributors
+ * Copyright 2004-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -16,13 +16,13 @@
#include <crm/cluster.h>
#include <crm/cluster/internal.h>
-#include <crm/msg_xml.h>
#include <crm/common/acl_internal.h>
#include <crm/common/ipc_internal.h>
#include <crm/common/logging.h>
#include <crm/common/results.h>
#include <crm/common/strings_internal.h>
#include <crm/common/util.h>
+#include <crm/common/xml.h>
#include "pacemaker-attrd.h"
@@ -32,22 +32,19 @@ static qb_ipcs_service_t *ipcs = NULL;
* \internal
* \brief Build the XML reply to a client query
*
- * param[in] attr Name of requested attribute
- * param[in] host Name of requested host (or NULL for all hosts)
+ * \param[in] attr Name of requested attribute
+ * \param[in] host Name of requested host (or NULL for all hosts)
*
* \return New XML reply
* \note Caller is responsible for freeing the resulting XML
*/
static xmlNode *build_query_reply(const char *attr, const char *host)
{
- xmlNode *reply = create_xml_node(NULL, __func__);
+ xmlNode *reply = pcmk__xe_create(NULL, __func__);
attribute_t *a;
- if (reply == NULL) {
- return NULL;
- }
- crm_xml_add(reply, F_TYPE, T_ATTRD);
- crm_xml_add(reply, F_SUBTYPE, PCMK__ATTRD_CMD_QUERY);
+ crm_xml_add(reply, PCMK__XA_T, PCMK__VALUE_ATTRD);
+ crm_xml_add(reply, PCMK__XA_SUBT, PCMK__ATTRD_CMD_QUERY);
crm_xml_add(reply, PCMK__XA_ATTR_VERSION, ATTRD_PROTOCOL_VERSION);
/* If desired attribute exists, add its value(s) to the reply */
@@ -67,11 +64,7 @@ static xmlNode *build_query_reply(const char *attr, const char *host)
/* If a specific node was requested, add its value */
if (host) {
v = g_hash_table_lookup(a->values, host);
- host_value = create_xml_node(reply, XML_CIB_TAG_NODE);
- if (host_value == NULL) {
- free_xml(reply);
- return NULL;
- }
+ host_value = pcmk__xe_create(reply, PCMK_XE_NODE);
pcmk__xe_add_node(host_value, host, 0);
crm_xml_add(host_value, PCMK__XA_ATTR_VALUE,
(v? v->current : NULL));
@@ -82,11 +75,7 @@ static xmlNode *build_query_reply(const char *attr, const char *host)
g_hash_table_iter_init(&iter, a->values);
while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &v)) {
- host_value = create_xml_node(reply, XML_CIB_TAG_NODE);
- if (host_value == NULL) {
- free_xml(reply);
- return NULL;
- }
+ host_value = pcmk__xe_create(reply, PCMK_XE_NODE);
pcmk__xe_add_node(host_value, v->nodename, 0);
crm_xml_add(host_value, PCMK__XA_ATTR_VALUE, v->current);
}
@@ -111,11 +100,11 @@ attrd_client_clear_failure(pcmk__request_t *request)
}
rsc = crm_element_value(xml, PCMK__XA_ATTR_RESOURCE);
- op = crm_element_value(xml, PCMK__XA_ATTR_OPERATION);
- interval_spec = crm_element_value(xml, PCMK__XA_ATTR_INTERVAL);
+ op = crm_element_value(xml, PCMK__XA_ATTR_CLEAR_OPERATION);
+ interval_spec = crm_element_value(xml, PCMK__XA_ATTR_CLEAR_INTERVAL);
/* Map this to an update */
- crm_xml_add(xml, PCMK__XA_TASK, PCMK__ATTRD_CMD_UPDATE);
+ crm_xml_add(xml, PCMK_XA_TASK, PCMK__ATTRD_CMD_UPDATE);
/* Add regular expression matching desired attributes */
@@ -126,22 +115,23 @@ attrd_client_clear_failure(pcmk__request_t *request)
pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc);
} else {
- guint interval_ms = crm_parse_interval_spec(interval_spec);
+ guint interval_ms = 0U;
+ pcmk_parse_interval_spec(interval_spec, &interval_ms);
pattern = crm_strdup_printf(ATTRD_RE_CLEAR_OP,
rsc, op, interval_ms);
}
- crm_xml_add(xml, PCMK__XA_ATTR_PATTERN, pattern);
+ crm_xml_add(xml, PCMK__XA_ATTR_REGEX, pattern);
free(pattern);
} else {
- crm_xml_add(xml, PCMK__XA_ATTR_PATTERN, ATTRD_RE_CLEAR_ALL);
+ crm_xml_add(xml, PCMK__XA_ATTR_REGEX, ATTRD_RE_CLEAR_ALL);
}
/* Make sure attribute and value are not set, so we delete via regex */
- xml_remove_prop(xml, PCMK__XA_ATTR_NAME);
- xml_remove_prop(xml, PCMK__XA_ATTR_VALUE);
+ pcmk__xe_remove_attr(xml, PCMK__XA_ATTR_NAME);
+ pcmk__xe_remove_attr(xml, PCMK__XA_ATTR_VALUE);
return attrd_client_update(request);
}
@@ -152,7 +142,7 @@ attrd_client_peer_remove(pcmk__request_t *request)
xmlNode *xml = request->xml;
// Host and ID are not used in combination, rather host has precedence
- const char *host = crm_element_value(xml, PCMK__XA_ATTR_NODE_NAME);
+ const char *host = crm_element_value(xml, PCMK__XA_ATTR_HOST);
char *host_alloc = NULL;
attrd_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags);
@@ -160,18 +150,19 @@ attrd_client_peer_remove(pcmk__request_t *request)
if (host == NULL) {
int nodeid = 0;
- crm_element_value_int(xml, PCMK__XA_ATTR_NODE_ID, &nodeid);
+ crm_element_value_int(xml, PCMK__XA_ATTR_HOST_ID, &nodeid);
if (nodeid > 0) {
- crm_node_t *node = pcmk__search_cluster_node_cache(nodeid, NULL,
- NULL);
+ crm_node_t *node = NULL;
char *host_alloc = NULL;
+ node = pcmk__search_node_caches(nodeid, NULL,
+ pcmk__node_search_cluster_member);
if (node && node->uname) {
// Use cached name if available
host = node->uname;
} else {
// Otherwise ask cluster layer
- host_alloc = get_node_name(nodeid);
+ host_alloc = pcmk__cluster_node_name(nodeid);
host = host_alloc;
}
pcmk__xe_add_node(xml, host, 0);
@@ -211,8 +202,8 @@ attrd_client_query(pcmk__request_t *request)
}
/* Build the XML reply */
- reply = build_query_reply(attr, crm_element_value(query,
- PCMK__XA_ATTR_NODE_NAME));
+ reply = build_query_reply(attr,
+ crm_element_value(query, PCMK__XA_ATTR_HOST));
if (reply == NULL) {
pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
"Could not respond to query from %s: could not create XML reply",
@@ -241,7 +232,7 @@ attrd_client_refresh(pcmk__request_t *request)
static void
handle_missing_host(xmlNode *xml)
{
- const char *host = crm_element_value(xml, PCMK__XA_ATTR_NODE_NAME);
+ const char *host = crm_element_value(xml, PCMK__XA_ATTR_HOST);
if (host == NULL) {
crm_trace("Inferring host");
@@ -270,16 +261,16 @@ expand_regexes(xmlNode *xml, const char *attr, const char *value, const char *re
int status = regexec(&r_patt, attr, 0, NULL, 0);
if (status == 0) {
- xmlNode *child = create_xml_node(xml, XML_ATTR_OP);
+ xmlNode *child = pcmk__xe_create(xml, PCMK_XE_OP);
crm_trace("Matched %s with %s", attr, regex);
matched = true;
- /* Copy all the attributes from the parent over, but remove the
- * regex and replace it with the name.
+ /* Copy all the non-conflicting attributes from the parent over,
+ * but remove the regex and replace it with the name.
*/
- attrd_copy_xml_attributes(xml, child);
- xml_remove_prop(child, PCMK__XA_ATTR_PATTERN);
+ pcmk__xe_copy_attrs(child, xml, pcmk__xaf_no_overwrite);
+ pcmk__xe_remove_attr(child, PCMK__XA_ATTR_REGEX);
crm_xml_add(child, PCMK__XA_ATTR_NAME, attr);
}
}
@@ -310,7 +301,7 @@ handle_regexes(pcmk__request_t *request)
const char *attr = crm_element_value(xml, PCMK__XA_ATTR_NAME);
const char *value = crm_element_value(xml, PCMK__XA_ATTR_VALUE);
- const char *regex = crm_element_value(xml, PCMK__XA_ATTR_PATTERN);
+ const char *regex = crm_element_value(xml, PCMK__XA_ATTR_REGEX);
rc = expand_regexes(xml, attr, value, regex);
@@ -344,7 +335,7 @@ handle_value_expansion(const char **value, xmlNode *xml, const char *op,
attribute_value_t *v = NULL;
if (a) {
- const char *host = crm_element_value(xml, PCMK__XA_ATTR_NODE_NAME);
+ const char *host = crm_element_value(xml, PCMK__XA_ATTR_HOST);
v = g_hash_table_lookup(a->values, host);
}
@@ -416,8 +407,10 @@ attrd_client_update(pcmk__request_t *request)
* we also need to apply all the transformations in this function
* to the children since they don't happen anywhere else.
*/
- for (xmlNode *child = first_named_child(xml, XML_ATTR_OP); child != NULL;
- child = crm_next_same_xml(child)) {
+ for (xmlNode *child = pcmk__xe_first_child(xml, PCMK_XE_OP, NULL,
+ NULL);
+ child != NULL; child = pcmk__xe_next_same(child)) {
+
attr = crm_element_value(child, PCMK__XA_ATTR_NAME);
value = crm_element_value(child, PCMK__XA_ATTR_VALUE);
@@ -443,7 +436,7 @@ attrd_client_update(pcmk__request_t *request)
* up into individual messages and call attrd_client_update on
* each one.
*/
- pcmk__xe_foreach_child(xml, XML_ATTR_OP, send_child_update, request);
+ pcmk__xe_foreach_child(xml, PCMK_XE_OP, send_child_update, request);
request->xml = orig_xml;
}
@@ -452,7 +445,7 @@ attrd_client_update(pcmk__request_t *request)
attr = crm_element_value(xml, PCMK__XA_ATTR_NAME);
value = crm_element_value(xml, PCMK__XA_ATTR_VALUE);
- regex = crm_element_value(xml, PCMK__XA_ATTR_PATTERN);
+ regex = crm_element_value(xml, PCMK__XA_ATTR_REGEX);
if (handle_regexes(request) != pcmk_rc_ok) {
/* Error handling was already dealt with in handle_regexes, so just return. */
@@ -473,7 +466,8 @@ attrd_client_update(pcmk__request_t *request)
return NULL;
}
- crm_debug("Broadcasting %s[%s]=%s%s", attr, crm_element_value(xml, PCMK__XA_ATTR_NODE_NAME),
+ crm_debug("Broadcasting %s[%s]=%s%s",
+ attr, crm_element_value(xml, PCMK__XA_ATTR_HOST),
value, (attrd_election_won()? " (writer)" : ""));
send_update_msg_to_cluster(request, xml);
@@ -498,11 +492,11 @@ attrd_ipc_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
if (attrd_shutting_down(false)) {
crm_info("Ignoring new connection from pid %d during shutdown",
pcmk__client_pid(c));
- return -EPERM;
+ return -ECONNREFUSED;
}
if (pcmk__new_client(c, uid, gid) == NULL) {
- return -EIO;
+ return -ENOMEM;
}
return pcmk_ok;
}
@@ -572,7 +566,8 @@ attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
if (xml == NULL) {
crm_debug("Unrecognizable IPC data from PID %d", pcmk__client_pid(c));
- pcmk__ipc_send_ack(client, id, flags, "ack", NULL, CRM_EX_PROTOCOL);
+ pcmk__ipc_send_ack(client, id, flags, PCMK__XE_ACK, NULL,
+ CRM_EX_PROTOCOL);
return 0;
} else {
@@ -589,7 +584,7 @@ attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
CRM_ASSERT(client->user != NULL);
pcmk__update_acl_user(xml, PCMK__XA_ATTR_USER, client->user);
- request.op = crm_element_value_copy(request.xml, PCMK__XA_TASK);
+ request.op = crm_element_value_copy(request.xml, PCMK_XA_TASK);
CRM_CHECK(request.op != NULL, return 0);
attrd_handle_request(&request);
diff --git a/daemons/attrd/attrd_messages.c b/daemons/attrd/attrd_messages.c
index 89da6d8..edb33a5 100644
--- a/daemons/attrd/attrd_messages.c
+++ b/daemons/attrd/attrd_messages.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 the Pacemaker project contributors
+ * Copyright 2022-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -12,7 +12,8 @@
#include <glib.h>
#include <crm/common/messages_internal.h>
-#include <crm/msg_xml.h>
+#include <crm/cluster/internal.h> // pcmk__get_node()
+#include <crm/common/xml.h>
#include "pacemaker-attrd.h"
@@ -30,7 +31,7 @@ static int
remove_sync_point_attribute(xmlNode *xml, void *data)
{
pcmk__xe_remove_matching_attrs(xml, is_sync_point_attr, NULL);
- pcmk__xe_foreach_child(xml, XML_ATTR_OP, remove_sync_point_attribute, NULL);
+ pcmk__xe_foreach_child(xml, PCMK_XE_OP, remove_sync_point_attribute, NULL);
return pcmk_rc_ok;
}
@@ -105,7 +106,8 @@ handle_confirm_request(pcmk__request_t *request)
crm_debug("Received confirmation from %s", request->peer);
- if (crm_element_value_int(request->xml, XML_LRM_ATTR_CALLID, &callid) == -1) {
+ if (crm_element_value_int(request->xml, PCMK__XA_CALL_ID,
+ &callid) == -1) {
pcmk__set_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
"Could not get callid from XML");
} else {
@@ -147,8 +149,14 @@ static xmlNode *
handle_remove_request(pcmk__request_t *request)
{
if (request->peer != NULL) {
- const char *host = crm_element_value(request->xml, PCMK__XA_ATTR_NODE_NAME);
- attrd_peer_remove(host, true, request->peer);
+ const char *host = crm_element_value(request->xml, PCMK__XA_ATTR_HOST);
+ bool reap = false;
+
+ if (pcmk__xe_get_bool_attr(request->xml, PCMK__XA_REAP,
+ &reap) != pcmk_rc_ok) {
+ reap = true; // Default to true for backward compatibility
+ }
+ attrd_peer_remove(host, reap, request->peer);
pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
return NULL;
} else {
@@ -167,27 +175,14 @@ handle_refresh_request(pcmk__request_t *request)
}
static xmlNode *
-handle_sync_request(pcmk__request_t *request)
-{
- if (request->peer != NULL) {
- crm_node_t *peer = crm_get_peer(0, request->peer);
-
- attrd_peer_sync(peer, request->xml);
- pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
- return NULL;
- } else {
- return handle_unknown_request(request);
- }
-}
-
-static xmlNode *
handle_sync_response_request(pcmk__request_t *request)
{
if (request->ipc_client != NULL) {
return handle_unknown_request(request);
} else {
if (request->peer != NULL) {
- crm_node_t *peer = crm_get_peer(0, request->peer);
+ crm_node_t *peer = pcmk__get_node(0, request->peer, NULL,
+ pcmk__node_search_cluster_member);
bool peer_won = attrd_check_for_new_writer(peer, request->xml);
if (!pcmk__str_eq(peer->uname, attrd_cluster->uname, pcmk__str_casei)) {
@@ -204,8 +199,9 @@ static xmlNode *
handle_update_request(pcmk__request_t *request)
{
if (request->peer != NULL) {
- const char *host = crm_element_value(request->xml, PCMK__XA_ATTR_NODE_NAME);
- crm_node_t *peer = crm_get_peer(0, request->peer);
+ const char *host = crm_element_value(request->xml, PCMK__XA_ATTR_HOST);
+ crm_node_t *peer = pcmk__get_node(0, request->peer, NULL,
+ pcmk__node_search_cluster_member);
attrd_peer_update(peer, request->xml, host, false);
pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
@@ -251,7 +247,6 @@ attrd_register_handlers(void)
{ PCMK__ATTRD_CMD_PEER_REMOVE, handle_remove_request },
{ PCMK__ATTRD_CMD_QUERY, handle_query_request },
{ PCMK__ATTRD_CMD_REFRESH, handle_refresh_request },
- { PCMK__ATTRD_CMD_SYNC, handle_sync_request },
{ PCMK__ATTRD_CMD_SYNC_RESPONSE, handle_sync_response_request },
{ PCMK__ATTRD_CMD_UPDATE, handle_update_request },
{ PCMK__ATTRD_CMD_UPDATE_DELAY, handle_update_request },
@@ -323,11 +318,11 @@ attrd_handle_request(pcmk__request_t *request)
void
attrd_broadcast_protocol(void)
{
- xmlNode *attrd_op = create_xml_node(NULL, __func__);
+ xmlNode *attrd_op = pcmk__xe_create(NULL, __func__);
- crm_xml_add(attrd_op, F_TYPE, T_ATTRD);
- crm_xml_add(attrd_op, F_ORIG, crm_system_name);
- crm_xml_add(attrd_op, PCMK__XA_TASK, PCMK__ATTRD_CMD_UPDATE);
+ crm_xml_add(attrd_op, PCMK__XA_T, PCMK__VALUE_ATTRD);
+ crm_xml_add(attrd_op, PCMK__XA_SRC, crm_system_name);
+ crm_xml_add(attrd_op, PCMK_XA_TASK, PCMK__ATTRD_CMD_UPDATE);
crm_xml_add(attrd_op, PCMK__XA_ATTR_NAME, CRM_ATTR_PROTOCOL);
crm_xml_add(attrd_op, PCMK__XA_ATTR_VALUE, ATTRD_PROTOCOL_VERSION);
crm_xml_add_int(attrd_op, PCMK__XA_ATTR_IS_PRIVATE, 1);
@@ -344,9 +339,9 @@ attrd_broadcast_protocol(void)
gboolean
attrd_send_message(crm_node_t *node, xmlNode *data, bool confirm)
{
- const char *op = crm_element_value(data, PCMK__XA_TASK);
+ const char *op = crm_element_value(data, PCMK_XA_TASK);
- crm_xml_add(data, F_TYPE, T_ATTRD);
+ crm_xml_add(data, PCMK__XA_T, PCMK__VALUE_ATTRD);
crm_xml_add(data, PCMK__XA_ATTR_VERSION, ATTRD_PROTOCOL_VERSION);
/* Request a confirmation from the destination peer node (which could
@@ -358,5 +353,5 @@ attrd_send_message(crm_node_t *node, xmlNode *data, bool confirm)
}
attrd_xml_add_writer(data);
- return send_cluster_message(node, crm_msg_attrd, data, TRUE);
+ return pcmk__cluster_send_message(node, crm_msg_attrd, data);
}
diff --git a/daemons/attrd/attrd_sync.c b/daemons/attrd/attrd_sync.c
index 1a6c24c..de99db2 100644
--- a/daemons/attrd/attrd_sync.c
+++ b/daemons/attrd/attrd_sync.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2023 the Pacemaker project contributors
+ * Copyright 2022-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -9,8 +9,8 @@
#include <crm_internal.h>
-#include <crm/msg_xml.h>
-#include <crm/common/attrd_internal.h>
+#include <crm/common/xml.h>
+#include <crm/common/attrs_internal.h>
#include "pacemaker-attrd.h"
@@ -113,7 +113,7 @@ sync_point_str(enum attrd_sync_point sync_point)
} else if (sync_point == attrd_sync_point_cluster) {
return PCMK__VALUE_CLUSTER;
} else {
- return "unknown";
+ return PCMK_VALUE_UNKNOWN;
}
}
@@ -145,13 +145,7 @@ attrd_add_client_to_waitlist(pcmk__request_t *request)
waitlist = pcmk__intkey_table(free_waitlist_node);
}
- wl = calloc(sizeof(struct waitlist_node), 1);
-
- CRM_ASSERT(wl != NULL);
-
- wl->client_id = strdup(request->ipc_client->id);
-
- CRM_ASSERT(wl->client_id);
+ wl = pcmk__assert_alloc(1, sizeof(struct waitlist_node));
if (pcmk__str_eq(sync_point, PCMK__VALUE_LOCAL, pcmk__str_none)) {
wl->sync_point = attrd_sync_point_local;
@@ -162,6 +156,7 @@ attrd_add_client_to_waitlist(pcmk__request_t *request)
return;
}
+ wl->client_id = pcmk__str_copy(request->ipc_client->id);
wl->ipc_id = request->ipc_id;
wl->flags = request->flags;
@@ -175,7 +170,7 @@ attrd_add_client_to_waitlist(pcmk__request_t *request)
/* And then add the key to the request XML so we can uniquely identify
* it when it comes time to issue the ACK.
*/
- crm_xml_add_int(request->xml, XML_LRM_ATTR_CALLID, waitlist_client);
+ crm_xml_add_int(request->xml, PCMK__XA_CALL_ID, waitlist_client);
}
/*!
@@ -245,7 +240,7 @@ attrd_ack_waitlist_clients(enum attrd_sync_point sync_point, const xmlNode *xml)
return;
}
- if (crm_element_value_int(xml, XML_LRM_ATTR_CALLID, &callid) == -1) {
+ if (crm_element_value_int(xml, PCMK__XA_CALL_ID, &callid) == -1) {
crm_warn("Could not get callid from request XML");
return;
}
@@ -316,7 +311,8 @@ attrd_request_sync_point(xmlNode *xml)
CRM_CHECK(xml != NULL, return NULL);
if (xml->children != NULL) {
- xmlNode *child = pcmk__xe_match(xml, XML_ATTR_OP, PCMK__XA_ATTR_SYNC_POINT, NULL);
+ xmlNode *child = pcmk__xe_first_child(xml, PCMK_XE_OP,
+ PCMK__XA_ATTR_SYNC_POINT, NULL);
if (child) {
return crm_element_value(child, PCMK__XA_ATTR_SYNC_POINT);
@@ -381,8 +377,10 @@ confirmation_timeout_cb(gpointer data)
}
crm_trace("Timed out waiting for confirmations for client %s", client->id);
- pcmk__ipc_send_ack(client, action->ipc_id, action->flags | crm_ipc_client_response,
- "ack", ATTRD_PROTOCOL_VERSION, CRM_EX_TIMEOUT);
+ pcmk__ipc_send_ack(client, action->ipc_id,
+ action->flags|crm_ipc_client_response,
+ PCMK__XE_ACK, ATTRD_PROTOCOL_VERSION,
+ CRM_EX_TIMEOUT);
g_hash_table_iter_remove(&iter);
crm_trace("%d requests now in expected confirmations table", g_hash_table_size(expected_confirmations));
@@ -486,7 +484,7 @@ attrd_expect_confirmations(pcmk__request_t *request, attrd_confirmation_action_f
expected_confirmations = pcmk__intkey_table((GDestroyNotify) free_action);
}
- if (crm_element_value_int(request->xml, XML_LRM_ATTR_CALLID, &callid) == -1) {
+ if (crm_element_value_int(request->xml, PCMK__XA_CALL_ID, &callid) == -1) {
crm_err("Could not get callid from xml");
return;
}
@@ -499,23 +497,17 @@ attrd_expect_confirmations(pcmk__request_t *request, attrd_confirmation_action_f
g_hash_table_iter_init(&iter, peer_protocol_vers);
while (g_hash_table_iter_next(&iter, &host, &ver)) {
if (ATTRD_SUPPORTS_CONFIRMATION(GPOINTER_TO_INT(ver))) {
- char *s = strdup((char *) host);
-
- CRM_ASSERT(s != NULL);
- respondents = g_list_prepend(respondents, s);
+ respondents = g_list_prepend(respondents,
+ pcmk__str_copy((char *) host));
}
}
- action = calloc(1, sizeof(struct confirmation_action));
- CRM_ASSERT(action != NULL);
+ action = pcmk__assert_alloc(1, sizeof(struct confirmation_action));
action->respondents = respondents;
action->fn = fn;
- action->xml = copy_xml(request->xml);
-
- action->client_id = strdup(request->ipc_client->id);
- CRM_ASSERT(action->client_id != NULL);
-
+ action->xml = pcmk__xml_copy(NULL, request->xml);
+ action->client_id = pcmk__str_copy(request->ipc_client->id);
action->ipc_id = request->ipc_id;
action->flags = request->flags;
diff --git a/daemons/attrd/attrd_utils.c b/daemons/attrd/attrd_utils.c
index 341ee1a..2d0bc76 100644
--- a/daemons/attrd/attrd_utils.c
+++ b/daemons/attrd/attrd_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2023 the Pacemaker project contributors
+ * Copyright 2004-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -19,7 +19,7 @@
#include <crm/crm.h>
#include <crm/common/ipc_internal.h>
#include <crm/common/mainloop.h>
-#include <crm/msg_xml.h>
+#include <crm/common/xml.h>
#include "pacemaker-attrd.h"
@@ -58,11 +58,12 @@ attrd_clear_requesting_shutdown(void)
* \internal
* \brief Check whether local attribute manager is shutting down
*
- * \param[in] if_requested Also consider presence of "shutdown" attribute
+ * \param[in] if_requested If \c true, also consider presence of
+ * \c PCMK__NODE_ATTR_SHUTDOWN attribute
*
* \return \c true if local attribute manager has begun shutdown sequence
* or (if \p if_requested is \c true) whether local node has a nonzero
- * "shutdown" attribute set, otherwise \c false
+ * \c PCMK__NODE_ATTR_SHUTDOWN attribute set, otherwise \c false
* \note Most callers should pass \c false for \p if_requested, because the
* attribute manager needs to continue performing while the controller is
* shutting down, and even needs to be eligible for election in case all
@@ -175,8 +176,8 @@ attrd_expand_value(const char *value, const char *old_value)
}
int_value += offset;
- if (int_value > INFINITY) {
- int_value = INFINITY;
+ if (int_value > PCMK_SCORE_INFINITY) {
+ int_value = PCMK_SCORE_INFINITY;
}
return int_value;
}
@@ -204,7 +205,7 @@ attrd_failure_regex(regex_t *regex, const char *rsc, const char *op,
/* Create a pattern that matches desired attributes */
if (rsc == NULL) {
- pattern = strdup(ATTRD_RE_CLEAR_ALL);
+ pattern = pcmk__str_copy(ATTRD_RE_CLEAR_ALL);
} else if (op == NULL) {
pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc);
} else {
@@ -238,7 +239,6 @@ attrd_free_attribute(gpointer data)
free(a->id);
free(a->set_id);
free(a->set_type);
- free(a->uuid);
free(a->user);
mainloop_timer_del(a->timer);
@@ -288,11 +288,9 @@ attrd_update_minimum_protocol_ver(const char *host, const char *value)
pcmk__scan_min_int(value, &ver, 0);
if (ver > 0) {
- char *host_name = strdup(host);
-
/* Record the peer attrd's protocol version. */
- CRM_ASSERT(host_name != NULL);
- g_hash_table_insert(peer_protocol_vers, host_name, GINT_TO_POINTER(ver));
+ g_hash_table_insert(peer_protocol_vers, pcmk__str_copy(host),
+ GINT_TO_POINTER(ver));
/* If the protocol version is a new minimum, record it as such. */
if (minimum_protocol_version == -1 || ver < minimum_protocol_version) {
@@ -302,24 +300,3 @@ attrd_update_minimum_protocol_ver(const char *host, const char *value)
}
}
}
-
-void
-attrd_copy_xml_attributes(xmlNode *src, xmlNode *dest)
-{
- /* Copy attributes from the wrapper parent node into the child node.
- * We can't just use copy_in_properties because we want to skip any
- * attributes that are already set on the child. For instance, if
- * we were told to use a specific node, there will already be a node
- * attribute on the child. Copying the parent's node attribute over
- * could result in the wrong value.
- */
- for (xmlAttrPtr a = pcmk__xe_first_attr(src); a != NULL; a = a->next) {
- const char *p_name = (const char *) a->name;
- const char *p_value = ((a == NULL) || (a->children == NULL)) ? NULL :
- (const char *) a->children->content;
-
- if (crm_element_value(dest, p_name) == NULL) {
- crm_xml_add(dest, p_name, p_value);
- }
- }
-}
diff --git a/daemons/attrd/pacemaker-attrd.c b/daemons/attrd/pacemaker-attrd.c
index 8091c5b..4ae5c8a 100644
--- a/daemons/attrd/pacemaker-attrd.c
+++ b/daemons/attrd/pacemaker-attrd.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the Pacemaker project contributors
+ * Copyright 2013-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -20,8 +20,6 @@
#include <fcntl.h>
#include <crm/crm.h>
-#include <crm/cib/internal.h>
-#include <crm/msg_xml.h>
#include <crm/pengine/rules.h>
#include <crm/common/cmdline_internal.h>
#include <crm/common/iso8601.h>
@@ -31,7 +29,7 @@
#include <crm/common/xml.h>
#include <crm/cluster/internal.h>
-#include <crm/common/attrd_internal.h>
+#include <crm/common/attrs_internal.h>
#include "pacemaker-attrd.h"
#define SUMMARY "daemon for managing Pacemaker node attributes"
@@ -59,7 +57,7 @@ static pcmk__supported_format_t formats[] = {
};
lrmd_t *the_lrmd = NULL;
-crm_cluster_t *attrd_cluster = NULL;
+pcmk_cluster_t *attrd_cluster = NULL;
crm_trigger_t *attrd_config_read = NULL;
crm_exit_t attrd_exit_status = CRM_EX_OK;
@@ -136,7 +134,7 @@ main(int argc, char **argv)
// Open additional log files
pcmk__add_logfiles(log_files, out);
- crm_log_init(T_ATTRD, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
+ crm_log_init(PCMK__VALUE_ATTRD, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
crm_notice("Starting Pacemaker node attribute manager%s",
stand_alone ? " in standalone mode" : "");
diff --git a/daemons/attrd/pacemaker-attrd.h b/daemons/attrd/pacemaker-attrd.h
index b8929a7..76faf04 100644
--- a/daemons/attrd/pacemaker-attrd.h
+++ b/daemons/attrd/pacemaker-attrd.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the Pacemaker project contributors
+ * Copyright 2013-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -16,7 +16,7 @@
#include <crm/cluster.h>
#include <crm/cluster/election_internal.h>
#include <crm/common/messages_internal.h>
-#include <crm/cib/internal.h>
+#include <crm/cib/cib_types.h>
/*
* Legacy attrd (all pre-1.1.11 Pacemaker versions, plus all versions when used
@@ -31,9 +31,8 @@
* -------- --------- -------------------
* 1 1.1.11 PCMK__ATTRD_CMD_UPDATE (PCMK__XA_ATTR_NAME only),
* PCMK__ATTRD_CMD_PEER_REMOVE, PCMK__ATTRD_CMD_REFRESH,
- * PCMK__ATTRD_CMD_FLUSH, PCMK__ATTRD_CMD_SYNC,
- * PCMK__ATTRD_CMD_SYNC_RESPONSE
- * 1 1.1.13 PCMK__ATTRD_CMD_UPDATE (with PCMK__XA_ATTR_PATTERN),
+ * PCMK__ATTRD_CMD_FLUSH, PCMK__ATTRD_CMD_SYNC_RESPONSE
+ * 1 1.1.13 PCMK__ATTRD_CMD_UPDATE (with PCMK__XA_ATTR_REGEX),
* PCMK__ATTRD_CMD_QUERY
* 1 1.1.15 PCMK__ATTRD_CMD_UPDATE_BOTH,
* PCMK__ATTRD_CMD_UPDATE_DELAY
@@ -42,14 +41,16 @@
* 4 2.1.5 Multiple attributes can be updated in a single IPC
* message
* 5 2.1.5 Peers can request confirmation of a sent message
+ * 6 2.1.7 PCMK__ATTRD_CMD_PEER_REMOVE supports PCMK__XA_REAP
*/
-#define ATTRD_PROTOCOL_VERSION "5"
+#define ATTRD_PROTOCOL_VERSION "6"
#define ATTRD_SUPPORTS_MULTI_MESSAGE(x) ((x) >= 4)
#define ATTRD_SUPPORTS_CONFIRMATION(x) ((x) >= 5)
-#define attrd_send_ack(client, id, flags) \
- pcmk__ipc_send_ack((client), (id), (flags), "ack", ATTRD_PROTOCOL_VERSION, CRM_EX_INDETERMINATE)
+#define attrd_send_ack(client, id, flags) \
+ pcmk__ipc_send_ack((client), (id), (flags), PCMK__XE_ACK, \
+ ATTRD_PROTOCOL_VERSION, CRM_EX_INDETERMINATE)
void attrd_init_mainloop(void);
void attrd_run_mainloop(void);
@@ -65,6 +66,7 @@ void attrd_ipc_fini(void);
int attrd_cib_connect(int max_retry);
void attrd_cib_disconnect(void);
void attrd_cib_init(void);
+void attrd_cib_erase_transient_attrs(const char *node);
bool attrd_value_needs_expansion(const char *value);
int attrd_expand_value(const char *value, const char *old_value);
@@ -116,47 +118,75 @@ void attrd_declare_winner(void);
void attrd_remove_voter(const crm_node_t *peer);
void attrd_xml_add_writer(xmlNode *xml);
-typedef struct attribute_s {
- char *uuid; /* TODO: Remove if at all possible */
- char *id;
- char *set_id;
- char *set_type;
- GHashTable *values;
- int update;
- int timeout_ms;
-
- /* TODO: refactor these three as a bitmask */
- bool changed; /* whether attribute value has changed since last write */
- bool unknown_peer_uuids; /* whether we know we're missing a peer uuid */
- gboolean is_private; /* whether to keep this attribute out of the CIB */
-
- mainloop_timer_t *timer;
-
- char *user;
-
- gboolean force_write; /* Flag for updating attribute by ignoring delay */
+enum attrd_attr_flags {
+ attrd_attr_none = 0U,
+ attrd_attr_changed = (1U << 0), // Attribute value has changed since last write
+ attrd_attr_uuid_missing = (1U << 1), // Whether we know we're missing a peer UUID
+ attrd_attr_is_private = (1U << 2), // Whether to keep this attribute out of the CIB
+ attrd_attr_force_write = (1U << 3), // Update attribute by ignoring delay
+};
+typedef struct attribute_s {
+ char *id; // Attribute name
+ char *set_type; // PCMK_XE_INSTANCE_ATTRIBUTES or PCMK_XE_UTILIZATION
+ char *set_id; // Set's XML ID to use when writing
+ char *user; // ACL user to use for CIB writes
+ int update; // Call ID of pending write
+ int timeout_ms; // How long to wait for more changes before writing
+ uint32_t flags; // Group of enum attrd_attr_flags
+ GHashTable *values; // Key: node name, value: attribute_value_t
+ mainloop_timer_t *timer; // Timer to use for timeout_ms
} attribute_t;
+#define attrd_set_attr_flags(attr, flags_to_set) do { \
+ (attr)->flags = pcmk__set_flags_as(__func__, __LINE__, \
+ LOG_TRACE, "Value for attribute", (attr)->id, \
+ (attr)->flags, (flags_to_set), #flags_to_set); \
+ } while (0)
+
+#define attrd_clear_attr_flags(attr, flags_to_clear) do { \
+ (attr)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
+ LOG_TRACE, "Value for attribute", (attr)->id, \
+ (attr)->flags, (flags_to_clear), #flags_to_clear); \
+ } while (0)
+
+enum attrd_value_flags {
+ attrd_value_none = 0U,
+ attrd_value_remote = (1U << 0), // Value is for Pacemaker Remote node
+ attrd_value_from_peer = (1U << 1), // Value is from peer sync response
+};
+
typedef struct attribute_value_s {
- uint32_t nodeid;
- gboolean is_remote;
- char *nodename;
- char *current;
- char *requested;
- gboolean seen;
+ char *nodename; // Node that this value is for
+ char *current; // Attribute value
+ char *requested; // Value specified in pending CIB write, if any
+ uint32_t nodeid; // Cluster node ID of node that this value is for
+ uint32_t flags; // Group of attrd_value_flags
} attribute_value_t;
-extern crm_cluster_t *attrd_cluster;
+#define attrd_set_value_flags(attr_value, flags_to_set) do { \
+ (attr_value)->flags = pcmk__set_flags_as(__func__, __LINE__, \
+ LOG_TRACE, "Value for node", (attr_value)->nodename, \
+ (attr_value)->flags, (flags_to_set), #flags_to_set); \
+ } while (0)
+
+#define attrd_clear_value_flags(attr_value, flags_to_clear) do { \
+ (attr_value)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
+ LOG_TRACE, "Value for node", (attr_value)->nodename, \
+ (attr_value)->flags, (flags_to_clear), #flags_to_clear); \
+ } while (0)
+
+extern pcmk_cluster_t *attrd_cluster;
extern GHashTable *attributes;
extern GHashTable *peer_protocol_vers;
#define CIB_OP_TIMEOUT_S 120
int attrd_cluster_connect(void);
+void attrd_broadcast_value(const attribute_t *a, const attribute_value_t *v);
void attrd_peer_update(const crm_node_t *peer, xmlNode *xml, const char *host,
bool filter);
-void attrd_peer_sync(crm_node_t *peer, xmlNode *xml);
+void attrd_peer_sync(crm_node_t *peer);
void attrd_peer_remove(const char *host, bool uncache, const char *source);
void attrd_peer_clear_failure(pcmk__request_t *request);
void attrd_peer_sync_response(const crm_node_t *peer, bool peer_won,
@@ -176,6 +206,8 @@ void attrd_clear_value_seen(void);
void attrd_free_attribute(gpointer data);
void attrd_free_attribute_value(gpointer data);
attribute_t *attrd_populate_attribute(xmlNode *xml, const char *attr);
+char *attrd_set_id(const attribute_t *attr, const char *node_state_id);
+char *attrd_nvpair_id(const attribute_t *attr, const char *node_state_id);
enum attrd_write_options {
attrd_write_changed = 0,
@@ -214,8 +246,6 @@ void attrd_remove_client_from_waitlist(pcmk__client_t *client);
const char *attrd_request_sync_point(xmlNode *xml);
bool attrd_request_has_sync_point(xmlNode *xml);
-void attrd_copy_xml_attributes(xmlNode *src, xmlNode *dest);
-
extern gboolean stand_alone;
#endif /* PACEMAKER_ATTRD__H */