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