pacemaker  2.0.2-debe490
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rules_alerts.c
Go to the documentation of this file.
1 /*
2  * Copyright 2015-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 #include <crm/crm.h>
10 #include <crm/msg_xml.h>
11 #include <crm/pengine/rules.h>
14 
15 static void
16 get_meta_attrs_from_cib(xmlNode *basenode, crm_alert_entry_t *entry,
17  guint *max_timeout)
18 {
19  GHashTable *config_hash = crm_str_table_new();
20  crm_time_t *now = crm_time_new(NULL);
21  const char *value = NULL;
22 
23  unpack_instance_attributes(basenode, basenode, XML_TAG_META_SETS, NULL,
24  config_hash, NULL, FALSE, now);
25  crm_time_free(now);
26 
27  value = g_hash_table_lookup(config_hash, XML_ALERT_ATTR_TIMEOUT);
28  if (value) {
29  entry->timeout = crm_get_msec(value);
30  if (entry->timeout <= 0) {
31  if (entry->timeout == 0) {
32  crm_trace("Alert %s uses default timeout of %dmsec",
34  } else {
35  crm_warn("Alert %s has invalid timeout value '%s', using default %dmsec",
36  entry->id, (char*)value, CRM_ALERT_DEFAULT_TIMEOUT_MS);
37  }
39  } else {
40  crm_trace("Alert %s uses timeout of %dmsec",
41  entry->id, entry->timeout);
42  }
43  if (entry->timeout > *max_timeout) {
44  *max_timeout = entry->timeout;
45  }
46  }
47  value = g_hash_table_lookup(config_hash, XML_ALERT_ATTR_TSTAMP_FORMAT);
48  if (value) {
49  /* hard to do any checks here as merely anything can
50  * can be a valid time-format-string
51  */
52  entry->tstamp_format = strdup(value);
53  crm_trace("Alert %s uses timestamp format '%s'",
54  entry->id, entry->tstamp_format);
55  }
56 
57  g_hash_table_destroy(config_hash);
58 }
59 
60 static void
61 get_envvars_from_cib(xmlNode *basenode, crm_alert_entry_t *entry)
62 {
63  xmlNode *child;
64 
65  if ((basenode == NULL) || (entry == NULL)) {
66  return;
67  }
68 
69  child = first_named_child(basenode, XML_TAG_ATTR_SETS);
70  if (child == NULL) {
71  return;
72  }
73 
74  if (entry->envvars == NULL) {
75  entry->envvars = crm_str_table_new();
76  }
77 
78  for (child = first_named_child(child, XML_CIB_TAG_NVPAIR); child != NULL;
79  child = crm_next_same_xml(child)) {
80 
81  const char *name = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
82  const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);
83 
84  if (value == NULL) {
85  value = "";
86  }
87  g_hash_table_insert(entry->envvars, strdup(name), strdup(value));
88  crm_trace("Alert %s: added environment variable %s='%s'",
89  entry->id, name, value);
90  }
91 }
92 
93 static void
94 unpack_alert_filter(xmlNode *basenode, crm_alert_entry_t *entry)
95 {
96  xmlNode *select = first_named_child(basenode, XML_CIB_TAG_ALERT_SELECT);
97  xmlNode *event_type = NULL;
98  uint32_t flags = crm_alert_none;
99 
100  for (event_type = __xml_first_child(select); event_type != NULL;
101  event_type = __xml_next(event_type)) {
102 
103  const char *tagname = crm_element_name(event_type);
104 
105  if (tagname == NULL) {
106  continue;
107 
108  } else if (!strcmp(tagname, XML_CIB_TAG_ALERT_FENCING)) {
109  flags |= crm_alert_fencing;
110 
111  } else if (!strcmp(tagname, XML_CIB_TAG_ALERT_NODES)) {
112  flags |= crm_alert_node;
113 
114  } else if (!strcmp(tagname, XML_CIB_TAG_ALERT_RESOURCES)) {
115  flags |= crm_alert_resource;
116 
117  } else if (!strcmp(tagname, XML_CIB_TAG_ALERT_ATTRIBUTES)) {
118  xmlNode *attr;
119  const char *attr_name;
120  int nattrs = 0;
121 
122  flags |= crm_alert_attribute;
123  for (attr = first_named_child(event_type, XML_CIB_TAG_ALERT_ATTR);
124  attr != NULL;
125  attr = crm_next_same_xml(attr)) {
126 
127  attr_name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME);
128  if (attr_name) {
129  if (nattrs == 0) {
130  g_strfreev(entry->select_attribute_name);
131  entry->select_attribute_name = NULL;
132  }
133  ++nattrs;
134  entry->select_attribute_name = realloc_safe(entry->select_attribute_name,
135  (nattrs + 1) * sizeof(char*));
136  entry->select_attribute_name[nattrs - 1] = strdup(attr_name);
137  entry->select_attribute_name[nattrs] = NULL;
138  }
139  }
140  }
141  }
142 
143  if (flags != crm_alert_none) {
144  entry->flags = flags;
145  crm_debug("Alert %s receives events: attributes:%s, fencing:%s, nodes:%s, resources:%s",
146  entry->id,
147  (flags & crm_alert_attribute)?
148  (entry->select_attribute_name? "some" : "all") : "no",
149  (flags & crm_alert_fencing)? "yes" : "no",
150  (flags & crm_alert_node)? "yes" : "no",
151  (flags & crm_alert_resource)? "yes" : "no");
152  }
153 }
154 
155 static void
156 unpack_alert(xmlNode *alert, crm_alert_entry_t *entry, guint *max_timeout)
157 {
158  get_envvars_from_cib(alert, entry);
159  get_meta_attrs_from_cib(alert, entry, max_timeout);
160  unpack_alert_filter(alert, entry);
161 }
162 
174 GListPtr
175 pe_unpack_alerts(xmlNode *alerts)
176 {
177  xmlNode *alert;
178  crm_alert_entry_t *entry;
179  guint max_timeout = 0;
180  GListPtr alert_list = NULL;
181 
182  if (alerts == NULL) {
183  return alert_list;
184  }
185 
186  for (alert = first_named_child(alerts, XML_CIB_TAG_ALERT);
187  alert != NULL; alert = crm_next_same_xml(alert)) {
188 
189  xmlNode *recipient;
190  int recipients = 0;
191  const char *alert_id = ID(alert);
192  const char *alert_path = crm_element_value(alert, XML_ALERT_ATTR_PATH);
193 
194  /* The schema should enforce this, but to be safe ... */
195  if ((alert_id == NULL) || (alert_path == NULL)) {
196  crm_warn("Ignoring invalid alert without id and path");
197  continue;
198  }
199 
200  entry = crm_alert_entry_new(alert_id, alert_path);
201 
202  unpack_alert(alert, entry, &max_timeout);
203 
204  if (entry->tstamp_format == NULL) {
206  }
207 
208  crm_debug("Alert %s: path=%s timeout=%dms tstamp-format='%s' %u vars",
209  entry->id, entry->path, entry->timeout, entry->tstamp_format,
210  (entry->envvars? g_hash_table_size(entry->envvars) : 0));
211 
212  for (recipient = first_named_child(alert, XML_CIB_TAG_ALERT_RECIPIENT);
213  recipient != NULL; recipient = crm_next_same_xml(recipient)) {
214 
215  crm_alert_entry_t *recipient_entry = crm_dup_alert_entry(entry);
216 
217  recipients++;
218  recipient_entry->recipient = strdup(crm_element_value(recipient,
220  unpack_alert(recipient, recipient_entry, &max_timeout);
221  alert_list = g_list_prepend(alert_list, recipient_entry);
222  crm_debug("Alert %s has recipient %s with value %s and %d envvars",
223  entry->id, ID(recipient), recipient_entry->recipient,
224  (recipient_entry->envvars?
225  g_hash_table_size(recipient_entry->envvars) : 0));
226  }
227 
228  if (recipients == 0) {
229  alert_list = g_list_prepend(alert_list, entry);
230  } else {
231  crm_free_alert_entry(entry);
232  }
233  }
234  return alert_list;
235 }
236 
243 void
245 {
246  if (alert_list) {
247  g_list_free_full(alert_list, (GDestroyNotify) crm_free_alert_entry);
248  }
249 }
A dumping ground.
#define CRM_ALERT_DEFAULT_TSTAMP_FORMAT
void pe_free_alert_list(GListPtr alert_list)
Definition: rules_alerts.c:244
struct crm_time_s crm_time_t
Definition: iso8601.h:32
#define CRM_ALERT_DEFAULT_TIMEOUT_MS
GHashTable * envvars
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:4155
char * recipient
#define XML_CIB_TAG_ALERT_RESOURCES
Definition: msg_xml.h:155
long long crm_get_msec(const char *input)
Definition: utils.c:567
#define XML_NVPAIR_ATTR_NAME
Definition: msg_xml.h:339
#define XML_CIB_TAG_ALERT_ATTRIBUTES
Definition: msg_xml.h:152
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:160
#define XML_ALERT_ATTR_REC_VALUE
Definition: msg_xml.h:352
crm_alert_entry_t * crm_dup_alert_entry(crm_alert_entry_t *entry)
Definition: alerts.c:92
uint32_t flags
GListPtr pe_unpack_alerts(xmlNode *alerts)
Definition: rules_alerts.c:175
char * tstamp_format
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:163
#define crm_warn(fmt, args...)
Definition: logging.h:241
char * id
#define crm_debug(fmt, args...)
Definition: logging.h:245
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:423
#define XML_CIB_TAG_ALERT_NODES
Definition: msg_xml.h:154
#define crm_trace(fmt, args...)
Definition: logging.h:246
#define XML_TAG_META_SETS
Definition: msg_xml.h:164
#define XML_ALERT_ATTR_TIMEOUT
Definition: msg_xml.h:350
#define XML_ALERT_ATTR_TSTAMP_FORMAT
Definition: msg_xml.h:351
#define XML_CIB_TAG_ALERT
Definition: msg_xml.h:149
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:84
crm_alert_entry_t * crm_alert_entry_new(const char *id, const char *path)
Create a new alert entry structure.
Definition: alerts.c:54
char ** select_attribute_name
#define XML_CIB_TAG_ALERT_FENCING
Definition: msg_xml.h:153
int timeout
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:340
char * path
void unpack_instance_attributes(xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now)
Definition: rules.c:904
#define XML_CIB_TAG_ALERT_SELECT
Definition: msg_xml.h:151
#define XML_ALERT_ATTR_PATH
Definition: msg_xml.h:349
#define XML_CIB_TAG_ALERT_ATTR
Definition: msg_xml.h:156
#define ID(x)
Definition: msg_xml.h:414
#define XML_CIB_TAG_ALERT_RECIPIENT
Definition: msg_xml.h:150
void crm_free_alert_entry(crm_alert_entry_t *entry)
Definition: alerts.c:67
GList * GListPtr
Definition: crm.h:192
uint64_t flags
Definition: remote.c:148
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:4180
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:101