pacemaker  1.1.18-7fdfbbe
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lrmd_alerts.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 David Vossel <davidvossel@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  */
19 
20 #include <crm_internal.h>
21 
22 #include <glib.h>
23 #include <unistd.h>
24 
25 #include <crm/crm.h>
26 #include <crm/msg_xml.h>
27 #include <crm/services.h>
28 #include <crm/common/mainloop.h>
32 
33 #include <crm/pengine/status.h>
34 #include <crm/cib.h>
35 #include <crm/lrmd.h>
36 
37 static lrmd_key_value_t *
38 alert_key2param(lrmd_key_value_t *head, enum crm_alert_keys_e name,
39  const char *value)
40 {
41  const char **key;
42 
43  if (value == NULL) {
44  value = "";
45  }
46  for (key = crm_alert_keys[name]; *key; key++) {
47  crm_trace("Setting alert key %s = '%s'", *key, value);
48  head = lrmd_key_value_add(head, *key, value);
49  }
50  return head;
51 }
52 
53 static lrmd_key_value_t *
54 alert_key2param_int(lrmd_key_value_t *head, enum crm_alert_keys_e name,
55  int value)
56 {
57  char *value_s = crm_itoa(value);
58 
59  head = alert_key2param(head, name, value_s);
60  free(value_s);
61  return head;
62 }
63 
64 static void
65 set_ev_kv(gpointer key, gpointer value, gpointer user_data)
66 {
67  lrmd_key_value_t **head = (lrmd_key_value_t **) user_data;
68 
69  if (value) {
70  crm_trace("Setting environment variable %s='%s'",
71  (char*)key, (char*)value);
72  *head = lrmd_key_value_add(*head, key, value);
73  }
74 }
75 
76 static lrmd_key_value_t *
77 alert_envvar2params(lrmd_key_value_t *head, crm_alert_entry_t *entry)
78 {
79  if (entry->envvars) {
80  g_hash_table_foreach(entry->envvars, set_ev_kv, &head);
81  }
82  return head;
83 }
84 
85 /*
86  * We could use g_strv_contains() instead of this function,
87  * but that has only been available since glib 2.43.2.
88  */
89 static gboolean
90 is_target_alert(char **list, const char *value)
91 {
92  int target_list_num = 0;
93  gboolean rc = FALSE;
94 
95  CRM_CHECK(value != NULL, return FALSE);
96 
97  if (list == NULL) {
98  return TRUE;
99  }
100 
101  target_list_num = g_strv_length(list);
102 
103  for (int cnt = 0; cnt < target_list_num; cnt++) {
104  if (strcmp(list[cnt], value) == 0) {
105  rc = TRUE;
106  break;
107  }
108  }
109  return rc;
110 }
111 
126 static int
127 exec_alert_list(lrmd_t *lrmd, GList *alert_list, enum crm_alert_flags kind,
128  const char *attr_name, lrmd_key_value_t *params)
129 {
130  bool any_success = FALSE, any_failure = FALSE;
131  const char *kind_s = crm_alert_flag2text(kind);
132  crm_time_hr_t *now = NULL;
133 
134  params = alert_key2param(params, CRM_alert_kind, kind_s);
135  params = alert_key2param(params, CRM_alert_version, VERSION);
136 
137  for (GList *iter = g_list_first(alert_list); iter; iter = g_list_next(iter)) {
138  crm_alert_entry_t *entry = (crm_alert_entry_t *)(iter->data);
139  lrmd_key_value_t *copy_params = NULL;
140  lrmd_key_value_t *head = NULL;
141  int rc;
142 
143  if (is_not_set(entry->flags, kind)) {
144  crm_trace("Filtering unwanted %s alert to %s via %s",
145  kind_s, entry->recipient, entry->id);
146  continue;
147  }
148 
149  if ((kind == crm_alert_attribute)
150  && !is_target_alert(entry->select_attribute_name, attr_name)) {
151 
152  crm_trace("Filtering unwanted attribute '%s' alert to %s via %s",
153  attr_name, entry->recipient, entry->id);
154  continue;
155  }
156 
157  if (now == NULL) {
158  now = crm_time_hr_new(NULL);
159  }
160  crm_info("Sending %s alert via %s to %s",
161  kind_s, entry->id, entry->recipient);
162 
163  /* Make a copy of the parameters, because each alert will be unique */
164  for (head = params; head != NULL; head = head->next) {
165  copy_params = lrmd_key_value_add(copy_params, head->key, head->value);
166  }
167 
168  copy_params = alert_key2param(copy_params, CRM_alert_recipient,
169  entry->recipient);
170 
171  if (now) {
172  char *timestamp = crm_time_format_hr(entry->tstamp_format, now);
173 
174  if (timestamp) {
175  copy_params = alert_key2param(copy_params, CRM_alert_timestamp,
176  timestamp);
177  free(timestamp);
178  }
179  }
180 
181  copy_params = alert_envvar2params(copy_params, entry);
182 
183  rc = lrmd->cmds->exec_alert(lrmd, entry->id, entry->path,
184  entry->timeout, copy_params);
185  if (rc < 0) {
186  crm_err("Could not execute alert %s: %s " CRM_XS " rc=%d",
187  entry->id, pcmk_strerror(rc), rc);
188  any_failure = TRUE;
189  } else {
190  any_success = TRUE;
191  }
192  }
193 
194  if (now) {
195  free(now);
196  }
197 
198  if (any_failure) {
199  return (any_success? -1 : -2);
200  }
201  return pcmk_ok;
202 }
203 
219 int
220 lrmd_send_attribute_alert(lrmd_t *lrmd, GList *alert_list,
221  const char *node, uint32_t nodeid,
222  const char *attr_name, const char *attr_value)
223 {
224  int rc = pcmk_ok;
225  lrmd_key_value_t *params = NULL;
226 
227  if (lrmd == NULL) {
228  return -2;
229  }
230 
231  params = alert_key2param(params, CRM_alert_node, node);
232  params = alert_key2param_int(params, CRM_alert_nodeid, nodeid);
233  params = alert_key2param(params, CRM_alert_attribute_name, attr_name);
234  params = alert_key2param(params, CRM_alert_attribute_value, attr_value);
235 
236  rc = exec_alert_list(lrmd, alert_list, crm_alert_attribute, attr_name,
237  params);
238  lrmd_key_value_freeall(params);
239  return rc;
240 }
241 
256 int
257 lrmd_send_node_alert(lrmd_t *lrmd, GList *alert_list,
258  const char *node, uint32_t nodeid, const char *state)
259 {
260  int rc = pcmk_ok;
261  lrmd_key_value_t *params = NULL;
262 
263  if (lrmd == NULL) {
264  return -2;
265  }
266 
267  params = alert_key2param(params, CRM_alert_node, node);
268  params = alert_key2param(params, CRM_alert_desc, state);
269  params = alert_key2param_int(params, CRM_alert_nodeid, nodeid);
270 
271  rc = exec_alert_list(lrmd, alert_list, crm_alert_node, NULL, params);
272  lrmd_key_value_freeall(params);
273  return rc;
274 }
275 
291 int
292 lrmd_send_fencing_alert(lrmd_t *lrmd, GList *alert_list,
293  const char *target, const char *task, const char *desc,
294  int op_rc)
295 {
296  int rc = pcmk_ok;
297  lrmd_key_value_t *params = NULL;
298 
299  if (lrmd == NULL) {
300  return -2;
301  }
302 
303  params = alert_key2param(params, CRM_alert_node, target);
304  params = alert_key2param(params, CRM_alert_task, task);
305  params = alert_key2param(params, CRM_alert_desc, desc);
306  params = alert_key2param_int(params, CRM_alert_rc, op_rc);
307 
308  rc = exec_alert_list(lrmd, alert_list, crm_alert_fencing, NULL, params);
309  lrmd_key_value_freeall(params);
310  return rc;
311 }
312 
326 int
327 lrmd_send_resource_alert(lrmd_t *lrmd, GList *alert_list,
328  const char *node, lrmd_event_data_t *op)
329 {
330  int rc = pcmk_ok;
331  int target_rc = pcmk_ok;
332  lrmd_key_value_t *params = NULL;
333 
334  if (lrmd == NULL) {
335  return -2;
336  }
337 
338  target_rc = rsc_op_expected_rc(op);
339  if ((op->interval == 0) && (target_rc == op->rc)
340  && safe_str_eq(op->op_type, RSC_STATUS)) {
341 
342  /* Don't send alerts for probes with the expected result. Leave it up to
343  * the agent whether to alert for 'failed' probes. (Even if we find a
344  * resource running, it was probably because someone did a clean-up of
345  * the status section.)
346  */
347  return pcmk_ok;
348  }
349 
350  params = alert_key2param(params, CRM_alert_node, node);
351  params = alert_key2param(params, CRM_alert_rsc, op->rsc_id);
352  params = alert_key2param(params, CRM_alert_task, op->op_type);
353  params = alert_key2param_int(params, CRM_alert_interval, op->interval);
354  params = alert_key2param_int(params, CRM_alert_target_rc, target_rc);
355  params = alert_key2param_int(params, CRM_alert_status, op->op_status);
356  params = alert_key2param_int(params, CRM_alert_rc, op->rc);
357 
358  if (op->op_status == PCMK_LRM_OP_DONE) {
359  params = alert_key2param(params, CRM_alert_desc, services_ocf_exitcode_str(op->rc));
360  } else {
361  params = alert_key2param(params, CRM_alert_desc, services_lrm_status_str(op->op_status));
362  }
363 
364  rc = exec_alert_list(lrmd, alert_list, crm_alert_resource, NULL, params);
365  lrmd_key_value_freeall(params);
366  return rc;
367 }
Services API.
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:164
A dumping ground.
const char * crm_alert_keys[CRM_ALERT_INTERNAL_KEY_MAX][3]
Definition: alerts.c:30
const char * rsc_id
Definition: lrmd.h:209
int lrmd_send_resource_alert(lrmd_t *lrmd, GList *alert_list, const char *node, lrmd_event_data_t *op)
Definition: lrmd_alerts.c:327
const char * pcmk_strerror(int rc)
Definition: logging.c:1135
GHashTable * envvars
int rsc_op_expected_rc(lrmd_event_data_t *event)
Definition: operations.c:389
char * recipient
#define pcmk_ok
Definition: error.h:42
#define VERSION
Definition: config.h:763
char * crm_time_format_hr(const char *format, crm_time_hr_t *hr_dt)
Definition: iso8601.c:1383
Local Resource Manager.
enum ocf_exitcode rc
Definition: lrmd.h:227
Wrappers for and extensions to glib mainloop.
int(* exec_alert)(lrmd_t *lrmd, const char *alert_id, const char *alert_path, int timeout, lrmd_key_value_t *params)
Execute an alert agent.
Definition: lrmd.h:492
crm_time_hr_t * crm_time_hr_new(const char *date_time)
Definition: iso8601.c:1357
uint32_t flags
int lrmd_send_node_alert(lrmd_t *lrmd, GList *alert_list, const char *node, uint32_t nodeid, const char *state)
Definition: lrmd_alerts.c:257
char * tstamp_format
char * id
char * key
Definition: lrmd.h:33
#define crm_trace(fmt, args...)
Definition: logging.h:254
lrmd_key_value_t * lrmd_key_value_add(lrmd_key_value_t *kvp, const char *key, const char *value)
Definition: lrmd_client.c:153
struct lrmd_key_value_s * next
Definition: lrmd.h:35
const char * op_type
Definition: lrmd.h:211
void lrmd_key_value_freeall(lrmd_key_value_t *head)
Definition: lrmd_client.c:176
#define CRM_XS
Definition: logging.h:42
lrmd_api_operations_t * cmds
Definition: lrmd.h:499
int lrmd_send_fencing_alert(lrmd_t *lrmd, GList *alert_list, const char *target, const char *task, const char *desc, int op_rc)
Definition: lrmd_alerts.c:292
#define crm_err(fmt, args...)
Definition: logging.h:248
#define RSC_STATUS
Definition: crm.h:214
Cluster Configuration.
char ** select_attribute_name
int timeout
crm_alert_keys_e
#define uint32_t
Definition: stdint.in.h:158
char * path
Definition: lrmd.h:498
char * crm_itoa(int an_int)
Definition: strings.c:60
#define safe_str_eq(a, b)
Definition: util.h:72
int lrmd_send_attribute_alert(lrmd_t *lrmd, GList *alert_list, const char *node, uint32_t nodeid, const char *attr_name, const char *attr_value)
Definition: lrmd_alerts.c:220
crm_alert_flags
char * value
Definition: lrmd.h:34
#define crm_info(fmt, args...)
Definition: logging.h:251