blob: 658ba62c6b0042676f3e5caaf604d3bd5f6888f7 [file] [edit]
/*
* Copyright (C) 2006-2017 Andrew Beekhof <andrew@beekhof.net>
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <crm/crm.h>
#include <crm/attrd.h>
#include <crm/msg_xml.h>
#include <crmd_fsa.h>
#include <crmd_utils.h>
#include <crmd_messages.h>
crm_ipc_t *attrd_ipc = NULL;
static void
log_attrd_error(const char *host, const char *name, const char *value,
gboolean is_remote, char command, int rc)
{
const char *display_command; /* for commands without name/value */
const char *node_type = (is_remote? "Pacemaker Remote" : "cluster");
gboolean shutting_down = is_set(fsa_input_register, R_SHUTDOWN);
const char *when = (shutting_down? " at shutdown" : "");
switch (command) {
case 'R':
display_command = "refresh";
break;
case 'C':
display_command = "purge";
break;
default:
display_command = NULL;
}
if (display_command) {
crm_err("Could not request %s of %s node %s%s: %s (%d)",
display_command, node_type, host, when, pcmk_strerror(rc), rc);
} else {
crm_err("Could not request update of %s=%s for %s node %s%s: %s (%d)",
name, value, node_type, host, when, pcmk_strerror(rc), rc);
}
/* If we can't request shutdown via attribute, fast-track it */
if ((command == 'U') && shutting_down) {
register_fsa_input(C_FSA_INTERNAL, I_FAIL, NULL);
}
}
static void
update_attrd_helper(const char *host, const char *name, const char *value,
const char *interval, const char *user_name,
gboolean is_remote_node, char command)
{
int rc;
int attrd_opts = attrd_opt_none;
if (is_remote_node) {
attrd_opts |= attrd_opt_remote;
}
if (attrd_ipc == NULL) {
attrd_ipc = crm_ipc_new(T_ATTRD, 0);
}
for (int attempt = 1; attempt <= 4; ++attempt) {
rc = pcmk_ok;
// If we're not already connected, try to connect
if (crm_ipc_connected(attrd_ipc) == FALSE) {
if (attempt == 1) {
// Start with a clean slate
crm_ipc_close(attrd_ipc);
}
if (crm_ipc_connect(attrd_ipc) == FALSE) {
rc = errno;
}
crm_debug("Attribute manager connection attempt %d of 4: %s (%d)",
attempt, pcmk_strerror(rc), rc);
}
if (rc == pcmk_ok) {
rc = command?
attrd_update_delegate(attrd_ipc, command, host, name, value,
XML_CIB_TAG_STATUS, NULL, NULL,
user_name, attrd_opts)
/* No command means clear fail count (name/value is really
* resource/operation)
*/
: attrd_clear_delegate(attrd_ipc, host, name, value,
interval, user_name, attrd_opts);
crm_debug("Attribute manager request attempt %d of 4: %s (%d)",
attempt, pcmk_strerror(rc), rc);
}
if (rc == pcmk_ok) {
// Success, we're done
break;
} else if ((rc != EAGAIN) && (rc != EALREADY)) {
/* EAGAIN or EALREADY indicates a temporary block, so just try
* again. Otherwise, close the connection for a clean slate.
*/
crm_ipc_close(attrd_ipc);
}
/* @TODO If the attribute manager remains unavailable the entire time,
* this function takes more than 6 seconds. Maybe set a timer for
* retries, to let the main loop do other work.
*/
if (attempt < 4) {
sleep(attempt);
}
}
if (rc != pcmk_ok) {
log_attrd_error(host, name, value, is_remote_node, command, rc);
}
}
void
update_attrd(const char *host, const char *name, const char *value,
const char *user_name, gboolean is_remote_node)
{
update_attrd_helper(host, name, value, NULL, user_name, is_remote_node,
'U');
}
void
update_attrd_remote_node_removed(const char *host, const char *user_name)
{
crm_trace("Asking attrd to purge Pacemaker Remote node %s", host);
update_attrd_helper(host, NULL, NULL, NULL, user_name, TRUE, 'C');
}
void
update_attrd_clear_failures(const char *host, const char *rsc, const char *op,
const char *interval, gboolean is_remote_node)
{
crm_info("Asking attrd to clear failure of %s %s for %s on %s node %s",
(op? op : "all operations"),
(interval? interval : "at all intervals"),
rsc, (is_remote_node? "Pacemaker Remote" : "cluster"), host);
update_attrd_helper(host, rsc, op, interval, NULL, is_remote_node, 0);
}