Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/lib/lrmd/lrmd_alerts.c b/lib/lrmd/lrmd_alerts.c
index ad7eaee05e..487e48c470 100644
--- a/lib/lrmd/lrmd_alerts.c
+++ b/lib/lrmd/lrmd_alerts.c
@@ -1,379 +1,379 @@
/*
* Copyright (c) 2015 David Vossel <davidvossel@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <crm_internal.h>
#include <glib.h>
#include <unistd.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crm/services.h>
#include <crm/common/mainloop.h>
#include <crm/common/alerts_internal.h>
#include <crm/common/iso8601_internal.h>
#include <crm/lrmd_alerts_internal.h>
#include <crm/pengine/status.h>
#include <crm/cib.h>
#include <crm/lrmd.h>
static lrmd_key_value_t *
alert_key2param(lrmd_key_value_t *head, enum crm_alert_keys_e name,
const char *value)
{
const char **key;
if (value == NULL) {
value = "";
}
for (key = crm_alert_keys[name]; *key; key++) {
crm_trace("Setting alert key %s = '%s'", *key, value);
head = lrmd_key_value_add(head, *key, value);
}
return head;
}
static lrmd_key_value_t *
alert_key2param_int(lrmd_key_value_t *head, enum crm_alert_keys_e name,
int value)
{
char *value_s = crm_itoa(value);
head = alert_key2param(head, name, value_s);
free(value_s);
return head;
}
static void
set_ev_kv(gpointer key, gpointer value, gpointer user_data)
{
lrmd_key_value_t **head = (lrmd_key_value_t **) user_data;
if (value) {
crm_trace("Setting environment variable %s='%s'",
(char*)key, (char*)value);
*head = lrmd_key_value_add(*head, key, value);
}
}
static lrmd_key_value_t *
alert_envvar2params(lrmd_key_value_t *head, crm_alert_entry_t *entry)
{
if (entry->envvars) {
g_hash_table_foreach(entry->envvars, set_ev_kv, &head);
}
return head;
}
/*
* We could use g_strv_contains() instead of this function,
* but that has only been available since glib 2.43.2.
*/
static gboolean
is_target_alert(char **list, const char *value)
{
int target_list_num = 0;
gboolean rc = FALSE;
CRM_CHECK(value != NULL, return FALSE);
if (list == NULL) {
return TRUE;
}
target_list_num = g_strv_length(list);
for (int cnt = 0; cnt < target_list_num; cnt++) {
if (strcmp(list[cnt], value) == 0) {
rc = TRUE;
break;
}
}
return rc;
}
/*!
* \internal
* \brief Execute alert agents for an event
*
* \param[in] alert_list Alerts to execute
* \param[in] lrmd_connect_func Function that returns an LRMD connection
* \param[in] kind Type of event that is being alerted for
* \param[in] attr_name If crm_alert_attribute, the attribute name
* \param[in,out] params Environment variables to pass to agents
*
* \retval pcmk_ok on success
* \retval -1 if some alerts failed
* \retval -2 if all alerts failed
*/
static int
exec_alert_list(GList *alert_list, lrmd_t *(*lrmd_connect_func)(void),
enum crm_alert_flags kind, const char *attr_name,
lrmd_key_value_t *params)
{
bool any_success = FALSE, any_failure = FALSE;
const char *kind_s = crm_alert_flag2text(kind);
crm_time_hr_t *now = NULL;
params = alert_key2param(params, CRM_alert_kind, kind_s);
params = alert_key2param(params, CRM_alert_version, VERSION);
for (GList *iter = g_list_first(alert_list); iter; iter = g_list_next(iter)) {
crm_alert_entry_t *entry = (crm_alert_entry_t *)(iter->data);
lrmd_key_value_t *copy_params = NULL;
lrmd_key_value_t *head = NULL;
lrmd_t *lrmd_conn = NULL;
int rc;
if (is_not_set(entry->flags, kind)) {
crm_trace("Filtering unwanted %s alert to %s via %s",
kind_s, entry->recipient, entry->id);
continue;
}
if ((kind == crm_alert_attribute)
&& !is_target_alert(entry->select_attribute_name, attr_name)) {
crm_trace("Filtering unwanted attribute '%s' alert to %s via %s",
attr_name, entry->recipient, entry->id);
continue;
}
if (now == NULL) {
now = crm_time_hr_new(NULL);
}
crm_info("Sending %s alert via %s to %s",
kind_s, entry->id, entry->recipient);
/* Make a copy of the parameters, because each alert will be unique */
for (head = params; head != NULL; head = head->next) {
copy_params = lrmd_key_value_add(copy_params, head->key, head->value);
}
copy_params = alert_key2param(copy_params, CRM_alert_recipient,
entry->recipient);
if (now) {
char *timestamp = crm_time_format_hr(entry->tstamp_format, now);
if (timestamp) {
copy_params = alert_key2param(copy_params, CRM_alert_timestamp,
timestamp);
free(timestamp);
}
}
copy_params = alert_envvar2params(copy_params, entry);
lrmd_conn = (*lrmd_connect_func)();
if (lrmd_conn == NULL) {
crm_warn("Cannot send alerts: No LRMD connection");
any_failure = TRUE;
goto done;
}
rc = lrmd_conn->cmds->exec_alert(lrmd_conn, entry->id, entry->path,
entry->timeout, copy_params);
if (rc < 0) {
crm_err("Could not execute alert %s: %s " CRM_XS " rc=%d",
entry->id, pcmk_strerror(rc), rc);
any_failure = TRUE;
} else {
any_success = TRUE;
}
}
done:
if (now) {
free(now);
}
if (any_failure) {
return (any_success? -1 : -2);
}
return pcmk_ok;
}
/*!
* \internal
* \brief Send an alert for a node attribute change
*
* \param[in] alert_list List of alert agents to execute
* \param[in] lrmd_connect_func Function that returns an LRMD connection
* \param[in] node Name of node with attribute change
* \param[in] nodeid Node ID of node with attribute change
* \param[in] attr_name Name of attribute that changed
* \param[in] attr_value New value of attribute that changed
*
* \retval pcmk_ok on success
* \retval -1 if some alert agents failed
* \retval -2 if all alert agents failed
*/
int
lrmd_send_attribute_alert(GList *alert_list, lrmd_t *(*lrmd_connect_func)(void),
const char *node, uint32_t nodeid,
const char *attr_name, const char *attr_value)
{
int rc = pcmk_ok;
lrmd_key_value_t *params = NULL;
if (alert_list == NULL) {
return pcmk_ok;
}
params = alert_key2param(params, CRM_alert_node, node);
params = alert_key2param_int(params, CRM_alert_nodeid, nodeid);
params = alert_key2param(params, CRM_alert_attribute_name, attr_name);
params = alert_key2param(params, CRM_alert_attribute_value, attr_value);
rc = exec_alert_list(alert_list, lrmd_connect_func, crm_alert_attribute,
attr_name, params);
lrmd_key_value_freeall(params);
return rc;
}
/*!
* \internal
* \brief Send an alert for a node membership event
*
* \param[in] alert_list List of alert agents to execute
* \param[in] lrmd_connect_func Function that returns an LRMD connection
* \param[in] node Name of node with change
* \param[in] nodeid Node ID of node with change
* \param[in] state New state of node with change
*
* \retval pcmk_ok on success
* \retval -1 if some alert agents failed
* \retval -2 if all alert agents failed
*/
int
lrmd_send_node_alert(GList *alert_list, lrmd_t *(*lrmd_connect_func)(void),
const char *node, uint32_t nodeid, const char *state)
{
int rc = pcmk_ok;
lrmd_key_value_t *params = NULL;
if (alert_list == NULL) {
return pcmk_ok;
}
params = alert_key2param(params, CRM_alert_node, node);
params = alert_key2param(params, CRM_alert_desc, state);
params = alert_key2param_int(params, CRM_alert_nodeid, nodeid);
rc = exec_alert_list(alert_list, lrmd_connect_func, crm_alert_node, NULL,
params);
lrmd_key_value_freeall(params);
return rc;
}
/*!
* \internal
* \brief Send an alert for a fencing event
*
* \param[in] alert_list List of alert agents to execute
* \param[in] lrmd_connect_func Function that returns an LRMD connection
* \param[in] target Name of fence target node
* \param[in] task Type of fencing event that occurred
* \param[in] desc Readable description of event
* \param[in] op_rc Result of fence action
*
* \retval pcmk_ok on success
* \retval -1 if some alert agents failed
* \retval -2 if all alert agents failed
*/
int
lrmd_send_fencing_alert(GList *alert_list, lrmd_t *(*lrmd_connect_func)(void),
const char *target, const char *task, const char *desc,
int op_rc)
{
int rc = pcmk_ok;
lrmd_key_value_t *params = NULL;
if (alert_list == NULL) {
return pcmk_ok;
}
params = alert_key2param(params, CRM_alert_node, target);
params = alert_key2param(params, CRM_alert_task, task);
params = alert_key2param(params, CRM_alert_desc, desc);
params = alert_key2param_int(params, CRM_alert_rc, op_rc);
rc = exec_alert_list(alert_list, lrmd_connect_func, crm_alert_fencing,
NULL, params);
lrmd_key_value_freeall(params);
return rc;
}
/*!
* \internal
* \brief Send an alert for a resource operation
*
* \param[in] alert_list List of alert agents to execute
* \param[in] lrmd_connect_func Function that returns an LRMD connection
* \param[in] node Name of node that executed operation
* \param[in] op Resource operation
*
* \retval pcmk_ok on success
* \retval -1 if some alert agents failed
* \retval -2 if all alert agents failed
*/
int
lrmd_send_resource_alert(GList *alert_list, lrmd_t *(*lrmd_connect_func)(void),
const char *node, lrmd_event_data_t *op)
{
int rc = pcmk_ok;
int target_rc = pcmk_ok;
lrmd_key_value_t *params = NULL;
if (alert_list == NULL) {
return pcmk_ok;
}
target_rc = rsc_op_expected_rc(op);
if ((op->interval == 0) && (target_rc == op->rc)
&& safe_str_eq(op->op_type, RSC_STATUS)) {
/* Don't send alerts for probes with the expected result. Leave it up to
* the agent whether to alert for 'failed' probes. (Even if we find a
* resource running, it was probably because someone did a clean-up of
* the status section.)
*/
return pcmk_ok;
}
params = alert_key2param(params, CRM_alert_node, node);
params = alert_key2param(params, CRM_alert_rsc, op->rsc_id);
params = alert_key2param(params, CRM_alert_task, op->op_type);
params = alert_key2param_int(params, CRM_alert_interval, op->interval);
params = alert_key2param_int(params, CRM_alert_target_rc, target_rc);
params = alert_key2param_int(params, CRM_alert_status, op->op_status);
params = alert_key2param_int(params, CRM_alert_rc, op->rc);
if (op->op_status == PCMK_LRM_OP_DONE) {
- crm_set_alert_key(CRM_alert_desc, services_ocf_exitcode_str(op->rc));
+ params = alert_key2param(params, CRM_alert_desc, services_ocf_exitcode_str(op->rc));
} else {
- crm_set_alert_key(CRM_alert_desc, services_lrm_status_str(op->op_status));
+ params = alert_key2param(params, CRM_alert_desc, services_lrm_status_str(op->op_status));
}
rc = exec_alert_list(alert_list, lrmd_connect_func, crm_alert_resource,
NULL, params);
lrmd_key_value_freeall(params);
return rc;
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jul 20, 7:30 PM (3 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2081333
Default Alt Text
(12 KB)

Event Timeline