Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/include/crm/common/ipc_attrd_internal.h b/include/crm/common/ipc_attrd_internal.h
index f90c2e566a..48d62f0da2 100644
--- a/include/crm/common/ipc_attrd_internal.h
+++ b/include/crm/common/ipc_attrd_internal.h
@@ -1,143 +1,148 @@
/*
* Copyright 2022 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef PCMK__CRM_COMMON_IPC_ATTRD_INTERNAL__H
# define PCMK__CRM_COMMON_IPC_ATTRD_INTERNAL__H
#include <glib.h> // GList
#include <crm/common/ipc.h> // pcmk_ipc_api_t
#ifdef __cplusplus
extern "C" {
#endif
//! Possible types of attribute manager replies
enum pcmk__attrd_api_reply {
pcmk__attrd_reply_unknown,
pcmk__attrd_reply_query,
};
// Information passed with pcmk__attrd_reply_query
typedef struct {
const char *node;
const char *name;
const char *value;
} pcmk__attrd_query_pair_t;
/*!
* Attribute manager reply passed to event callback
*
* \note The pointers in the reply are only guaranteed to be meaningful for the
* execution of the callback; if the values are needed for later, the
* callback should copy them.
*/
typedef struct {
enum pcmk__attrd_api_reply reply_type;
union {
// pcmk__attrd_reply_query
GList *pairs;
} data;
} pcmk__attrd_api_reply_t;
/*!
* \internal
* \brief Send a request to pacemaker-attrd to clear resource failure
*
- * \param[in] api Connection to pacemaker-attrd
+ * \param[in] api Connection to pacemaker-attrd (or NULL to use
+ * a temporary new connection)
* \param[in] node Affect only this node (or NULL for all nodes)
* \param[in] resource Name of resource to clear (or NULL for all)
* \param[in] operation Name of operation to clear (or NULL for all)
* \param[in] interval_spec If operation is not NULL, its interval
* \param[in] user_name ACL user to pass to pacemaker-attrd
* \param[in] options Bitmask of pcmk__node_attr_opts
*
* \return Standard Pacemaker return code
*/
int pcmk__attrd_api_clear_failures(pcmk_ipc_api_t *api, const char *node,
const char *resource, const char *operation,
const char *interval_spec, const char *user_name,
uint32_t options);
/*!
* \internal
*
* \brief Delete a previously set attribute by setting its value to NULL
*
- * \param[in] api Connection to pacemaker-attrd
+ * \param[in] api Connection to pacemaker-attrd (or NULL to use
+ * a temporary new connection)
* \param[in] node Delete attribute for this node (or NULL for current node)
* \param[in] name Attribute name
* \param[in] options Bitmask of pcmk__node_attr_opts
*
* \return Standard Pacemaker return code
*/
int pcmk__attrd_api_delete(pcmk_ipc_api_t *api, const char *node, const char *name,
uint32_t options);
/*!
* \internal
* \brief Purge a node from pacemaker-attrd
*
- * \param[in] api Connection to pacemaker-attrd
+ * \param[in] api Connection to pacemaker-attrd (or NULL to use
+ * a temporary new connection)
* \param[in] node Node to remove
*
* \return Standard Pacemaker return code
*/
int pcmk__attrd_api_purge(pcmk_ipc_api_t *api, const char *node);
/*!
* \internal
* \brief Get the value of an attribute from pacemaker-attrd
*
* \param[in] api Connection to pacemaker-attrd
* \param[in] node Look up the attribute for this node
* (or NULL for all nodes)
* \param[in] name Attribute name
* \param[in] options Bitmask of pcmk__node_attr_opts
*
* \return Standard Pacemaker return code
*/
int pcmk__attrd_api_query(pcmk_ipc_api_t *api, const char *node, const char *name,
uint32_t options);
/*!
* \internal
* \brief Tell pacemaker-attrd to update the CIB with current values
*
- * \param[in] api Connection to pacemaker-attrd
+ * \param[in] api Connection to pacemaker-attrd (or NULL to use
+ * a temporary new connection)
* \param[in] node Affect only this node (or NULL for all nodes)
*
* \return Standard Pacemaker return code
*/
int pcmk__attrd_api_refresh(pcmk_ipc_api_t *api, const char *node);
/*!
* \internal
* \brief Update an attribute's value, time to wait, or both
*
- * \param[in] api Connection to pacemaker-attrd
+ * \param[in] api Connection to pacemaker-attrd (or NULL to use
+ * a temporary new connection)
* \param[in] node Affect only this node (or NULL for current node)
* \param[in] name Attribute name
* \param[in] value The attribute's new value, or NULL to unset
* \param[in] dampen The new time to wait value, or NULL to unset
* \param[in] set ID of attribute set to use (or NULL to choose first)
* \param[in] user_name ACL user to pass to pacemaker-attrd
* \param[in] options Bitmask of pcmk__node_attr_opts
*
* \return Standard Pacemaker return code
*/
int pcmk__attrd_api_update(pcmk_ipc_api_t *api, const char *node, const char *name,
const char *value, const char *dampen, const char *set,
const char *user_name, uint32_t options);
#ifdef __cplusplus
}
#endif
#endif // PCMK__CRM_COMMON_IPC_ATTRD_INTERNAL__H
diff --git a/lib/common/ipc_attrd.c b/lib/common/ipc_attrd.c
index ecb9df9f31..3c77609ce7 100644
--- a/lib/common/ipc_attrd.c
+++ b/lib/common/ipc_attrd.c
@@ -1,359 +1,414 @@
/*
* Copyright 2011-2022 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <crm_internal.h>
#include <stdio.h>
#include <crm/crm.h>
#include <crm/common/ipc.h>
#include <crm/common/ipc_attrd_internal.h>
#include <crm/common/attrd_internal.h>
#include <crm/msg_xml.h>
#include "crmcommon_private.h"
static void
set_pairs_data(pcmk__attrd_api_reply_t *data, xmlNode *msg_data)
{
const char *name = NULL;
pcmk__attrd_query_pair_t *pair;
name = crm_element_value(msg_data, PCMK__XA_ATTR_NAME);
for (xmlNode *node = first_named_child(msg_data, XML_CIB_TAG_NODE);
node != NULL; node = crm_next_same_xml(node)) {
pair = calloc(1, sizeof(pcmk__attrd_query_pair_t));
CRM_ASSERT(pair != NULL);
pair->node = crm_element_value(node, PCMK__XA_ATTR_NODE_NAME);
pair->name = name;
pair->value = crm_element_value(node, PCMK__XA_ATTR_VALUE);
data->data.pairs = g_list_prepend(data->data.pairs, pair);
}
}
static bool
reply_expected(pcmk_ipc_api_t *api, xmlNode *request)
{
const char *command = crm_element_value(request, PCMK__XA_TASK);
/* Only the query command gets a reply. */
return pcmk__str_any_of(command, PCMK__ATTRD_CMD_QUERY, NULL);
}
static bool
dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
{
const char *value = NULL;
crm_exit_t status = CRM_EX_OK;
pcmk__attrd_api_reply_t reply_data = {
pcmk__attrd_reply_unknown
};
if (pcmk__str_eq((const char *) reply->name, "ack", pcmk__str_none)) {
return false;
}
/* Do some basic validation of the reply */
value = crm_element_value(reply, F_TYPE);
if (value == NULL || !pcmk__str_eq(value, T_ATTRD, pcmk__str_none)) {
crm_debug("Unrecognizable attrd message: invalid message type '%s'",
crm_str(value));
status = CRM_EX_PROTOCOL;
goto done;
}
/* Only the query command gets a reply for now. */
value = crm_element_value(reply, F_SUBTYPE);
if (pcmk__str_eq(value, PCMK__ATTRD_CMD_QUERY, pcmk__str_null_matches)) {
/* This likely means the client gave us an attribute name that doesn't
* exist.
*/
if (!xmlHasProp(reply, (pcmkXmlStr) PCMK__XA_ATTR_NAME)) {
crm_debug("Empty attrd message: no attribute name");
status = ENXIO;
goto done;
}
reply_data.reply_type = pcmk__attrd_reply_query;
set_pairs_data(&reply_data, reply);
} else {
crm_debug("Cannot handle a reply from message type '%s'",
crm_str(value));
status = CRM_EX_PROTOCOL;
goto done;
}
done:
pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
/* Free any reply data that was allocated */
if (reply_data.data.pairs) {
g_list_free_full(reply_data.data.pairs, free);
}
return false;
}
pcmk__ipc_methods_t *
pcmk__attrd_api_methods()
{
pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
if (cmds != NULL) {
cmds->new_data = NULL;
cmds->free_data = NULL;
cmds->post_connect = NULL;
cmds->reply_expected = reply_expected;
cmds->dispatch = dispatch;
}
return cmds;
}
/*!
* \internal
* \brief Create a generic pacemaker-attrd operation
*
* \param[in] user_name If not NULL, ACL user to set for operation
*
* \return XML of pacemaker-attrd operation
*/
static xmlNode *
create_attrd_op(const char *user_name)
{
xmlNode *attrd_op = create_xml_node(NULL, __func__);
crm_xml_add(attrd_op, F_TYPE, T_ATTRD);
crm_xml_add(attrd_op, F_ORIG, (crm_system_name? crm_system_name: "unknown"));
crm_xml_add(attrd_op, PCMK__XA_ATTR_USER, user_name);
return attrd_op;
}
+static int
+connect_and_send_attrd_request(xmlNode *request)
+{
+ pcmk_ipc_api_t *api = NULL;
+ int rc = pcmk_rc_ok;
+ int max = 5;
+
+ rc = pcmk_new_ipc_api(&api, pcmk_ipc_attrd);
+ if (rc != pcmk_rc_ok) {
+ crm_err("error: Could not connect to attrd: %s", pcmk_rc_str(rc));
+ return ENOTCONN;
+ }
+
+ while (max > 0) {
+ crm_info("Connecting to cluster... %d retries remaining", max);
+ rc = pcmk_connect_ipc(api, pcmk_ipc_dispatch_sync);
+
+ if (rc == pcmk_rc_ok) {
+ rc = pcmk__send_ipc_request(api, request);
+ pcmk_disconnect_ipc(api);
+ pcmk_free_ipc_api(api);
+ api = NULL;
+ break;
+ } else if (rc == EAGAIN || rc == EALREADY) {
+ sleep(5 - max);
+ max--;
+ } else {
+ crm_err("error: Could not connect to attrd: %s", pcmk_rc_str(rc));
+ break;
+ }
+ }
+
+ return rc;
+}
+
static int
send_attrd_request(pcmk_ipc_api_t *api, xmlNode *request)
{
return pcmk__send_ipc_request(api, request);
}
int
pcmk__attrd_api_clear_failures(pcmk_ipc_api_t *api, const char *node,
const char *resource, const char *operation,
const char *interval_spec, const char *user_name,
uint32_t options)
{
int rc = pcmk_rc_ok;
xmlNode *request = create_attrd_op(user_name);
const char *interval_desc = NULL;
const char *op_desc = NULL;
const char *target = pcmk__node_attr_target(node);
if (target != NULL) {
node = target;
}
crm_xml_add(request, PCMK__XA_TASK, PCMK__ATTRD_CMD_CLEAR_FAILURE);
crm_xml_add(request, PCMK__XA_ATTR_NODE_NAME, node);
crm_xml_add(request, PCMK__XA_ATTR_RESOURCE, resource);
crm_xml_add(request, PCMK__XA_ATTR_OPERATION, operation);
crm_xml_add(request, PCMK__XA_ATTR_INTERVAL, interval_spec);
crm_xml_add_int(request, PCMK__XA_ATTR_IS_REMOTE,
pcmk_is_set(options, pcmk__node_attr_remote));
- rc = send_attrd_request(api, request);
+ if (api == NULL) {
+ rc = connect_and_send_attrd_request(request);
+ } else {
+ rc = send_attrd_request(api, request);
+ }
+
free_xml(request);
if (operation) {
interval_desc = interval_spec? interval_spec : "nonrecurring";
op_desc = operation;
} else {
interval_desc = "all";
op_desc = "operations";
}
crm_debug("Asked pacemaker-attrd to clear failure of %s %s for %s on %s: %s (%d)",
interval_desc, op_desc, (resource? resource : "all resources"),
(node? node : "all nodes"), pcmk_rc_str(rc), rc);
return rc;
}
int
pcmk__attrd_api_delete(pcmk_ipc_api_t *api, const char *node, const char *name,
uint32_t options)
{
const char *target = NULL;
if (name == NULL) {
return EINVAL;
}
target = pcmk__node_attr_target(node);
if (target != NULL) {
node = target;
}
/* Make sure the right update option is set. */
options &= ~pcmk__node_attr_delay;
options |= pcmk__node_attr_value;
return pcmk__attrd_api_update(api, node, name, NULL, NULL, NULL, NULL, options);
}
int
pcmk__attrd_api_purge(pcmk_ipc_api_t *api, const char *node)
{
int rc = pcmk_rc_ok;
xmlNode *request = NULL;
const char *display_host = (node ? node : "localhost");
const char *target = pcmk__node_attr_target(node);
if (target != NULL) {
node = target;
}
request = create_attrd_op(NULL);
crm_xml_add(request, PCMK__XA_TASK, PCMK__ATTRD_CMD_PEER_REMOVE);
crm_xml_add(request, PCMK__XA_ATTR_NODE_NAME, node);
- rc = send_attrd_request(api, request);
+ if (api == NULL) {
+ rc = connect_and_send_attrd_request(request);
+ } else {
+ rc = send_attrd_request(api, request);
+ }
+
free_xml(request);
crm_debug("Asked pacemaker-attrd to purge %s: %s (%d)",
display_host, pcmk_rc_str(rc), rc);
return rc;
}
int
pcmk__attrd_api_query(pcmk_ipc_api_t *api, const char *node, const char *name,
uint32_t options)
{
int rc = pcmk_rc_ok;
xmlNode *request = NULL;
const char *target = NULL;
if (name == NULL) {
return EINVAL;
}
target = pcmk__node_attr_target(node);
if (target != NULL) {
node = target;
}
request = create_attrd_op(NULL);
crm_xml_add(request, PCMK__XA_ATTR_NAME, name);
crm_xml_add(request, PCMK__XA_TASK, PCMK__ATTRD_CMD_QUERY);
crm_xml_add(request, PCMK__XA_ATTR_NODE_NAME, node);
rc = send_attrd_request(api, request);
free_xml(request);
if (node) {
crm_debug("Queried pacemaker-attrd for %s on %s: %s (%d)",
name, node, pcmk_rc_str(rc), rc);
} else {
crm_debug("Queried pacemaker-attrd for %s: %s (%d)",
name, pcmk_rc_str(rc), rc);
}
return rc;
}
int
pcmk__attrd_api_refresh(pcmk_ipc_api_t *api, const char *node)
{
int rc = pcmk_rc_ok;
xmlNode *request = NULL;
const char *display_host = (node ? node : "localhost");
const char *target = pcmk__node_attr_target(node);
if (target != NULL) {
node = target;
}
request = create_attrd_op(NULL);
crm_xml_add(request, PCMK__XA_TASK, PCMK__ATTRD_CMD_REFRESH);
crm_xml_add(request, PCMK__XA_ATTR_NODE_NAME, node);
- rc = send_attrd_request(api, request);
+ if (api == NULL) {
+ rc = connect_and_send_attrd_request(request);
+ } else {
+ rc = send_attrd_request(api, request);
+ }
+
free_xml(request);
crm_debug("Asked pacemaker-attrd to refresh %s: %s (%d)",
display_host, pcmk_rc_str(rc), rc);
return rc;
}
int
pcmk__attrd_api_update(pcmk_ipc_api_t *api, const char *node, const char *name,
const char *value, const char *dampen, const char *set,
const char *user_name, uint32_t options)
{
int rc = pcmk_rc_ok;
xmlNode *request = NULL;
const char *display_host = (node ? node : "localhost");
const char *target = NULL;
if (name == NULL) {
return EINVAL;
}
target = pcmk__node_attr_target(node);
if (target != NULL) {
node = target;
}
request = create_attrd_op(user_name);
if (pcmk_is_set(options, pcmk__node_attr_pattern)) {
crm_xml_add(request, PCMK__XA_ATTR_PATTERN, name);
} else {
crm_xml_add(request, PCMK__XA_ATTR_NAME, name);
}
if (pcmk_all_flags_set(options, pcmk__node_attr_value | pcmk__node_attr_delay)) {
crm_xml_add(request, PCMK__XA_TASK, PCMK__ATTRD_CMD_UPDATE_BOTH);
} else if (pcmk_is_set(options, pcmk__node_attr_value)) {
crm_xml_add(request, PCMK__XA_TASK, PCMK__ATTRD_CMD_UPDATE);
} else if (pcmk_is_set(options, pcmk__node_attr_delay)) {
crm_xml_add(request, PCMK__XA_TASK, PCMK__ATTRD_CMD_UPDATE_DELAY);
}
crm_xml_add(request, PCMK__XA_ATTR_VALUE, value);
crm_xml_add(request, PCMK__XA_ATTR_DAMPENING, dampen);
crm_xml_add(request, PCMK__XA_ATTR_NODE_NAME, node);
crm_xml_add(request, PCMK__XA_ATTR_SET, set);
crm_xml_add_int(request, PCMK__XA_ATTR_IS_REMOTE,
pcmk_is_set(options, pcmk__node_attr_remote));
crm_xml_add_int(request, PCMK__XA_ATTR_IS_PRIVATE,
pcmk_is_set(options, pcmk__node_attr_private));
- rc = send_attrd_request(api, request);
+ if (api == NULL) {
+ rc = connect_and_send_attrd_request(request);
+ } else {
+ rc = send_attrd_request(api, request);
+ }
+
free_xml(request);
crm_debug("Asked pacemaker-attrd to update %s on %s: %s (%d)",
name, display_host, pcmk_rc_str(rc), rc);
return rc;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 10, 2:32 AM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2009744
Default Alt Text
(17 KB)

Event Timeline