pacemaker  1.1.18-7fdfbbe
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
alerts.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This software 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  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU 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 #include <crm_internal.h>
20 #include <crm/crm.h>
21 #include <crm/lrmd.h>
22 #include <crm/msg_xml.h>
24 #include <crm/cib/internal.h> /* for F_CIB_UPDATE_RESULT */
25 
26 /*
27  * to allow script compatibility we can have more than one
28  * set of environment variables
29  */
31 {
32  [CRM_alert_recipient] = {"CRM_notify_recipient", "CRM_alert_recipient", NULL},
33  [CRM_alert_node] = {"CRM_notify_node", "CRM_alert_node", NULL},
34  [CRM_alert_nodeid] = {"CRM_notify_nodeid", "CRM_alert_nodeid", NULL},
35  [CRM_alert_rsc] = {"CRM_notify_rsc", "CRM_alert_rsc", NULL},
36  [CRM_alert_task] = {"CRM_notify_task", "CRM_alert_task", NULL},
37  [CRM_alert_interval] = {"CRM_notify_interval", "CRM_alert_interval", NULL},
38  [CRM_alert_desc] = {"CRM_notify_desc", "CRM_alert_desc", NULL},
39  [CRM_alert_status] = {"CRM_notify_status", "CRM_alert_status", NULL},
40  [CRM_alert_target_rc] = {"CRM_notify_target_rc", "CRM_alert_target_rc", NULL},
41  [CRM_alert_rc] = {"CRM_notify_rc", "CRM_alert_rc", NULL},
42  [CRM_alert_kind] = {"CRM_notify_kind", "CRM_alert_kind", NULL},
43  [CRM_alert_version] = {"CRM_notify_version", "CRM_alert_version", NULL},
44  [CRM_alert_node_sequence] = {"CRM_notify_node_sequence", CRM_ALERT_NODE_SEQUENCE, NULL},
45  [CRM_alert_timestamp] = {"CRM_notify_timestamp", "CRM_alert_timestamp", NULL},
46  [CRM_alert_attribute_name] = {"CRM_notify_attribute_name", "CRM_alert_attribute_name", NULL},
47  [CRM_alert_attribute_value] = {"CRM_notify_attribute_value", "CRM_alert_attribute_value", NULL}
48 };
49 
50 void
52 {
53  free(entry->name);
54  free(entry->value);
55  free(entry);
56 }
57 
70 crm_alert_entry_new(const char *id, const char *path)
71 {
72  crm_alert_entry_t *entry = calloc(1, sizeof(crm_alert_entry_t));
73 
74  CRM_ASSERT(entry && id && path);
75  entry->id = strdup(id);
76  entry->path = strdup(path);
78  entry->flags = crm_alert_default;
79  return entry;
80 }
81 
82 void
84 {
85  if (entry) {
86  free(entry->id);
87  free(entry->path);
88  free(entry->tstamp_format);
89  free(entry->recipient);
90 
91  g_strfreev(entry->select_attribute_name);
92  if (entry->envvars) {
93  g_hash_table_destroy(entry->envvars);
94  }
95  free(entry);
96  }
97 }
98 
101 {
102  crm_alert_envvar_t *dst = calloc(1, sizeof(crm_alert_envvar_t));
103 
104  CRM_ASSERT(dst);
105  dst->name = strdup(src->name);
106  dst->value = src->value?strdup(src->value):NULL;
107  return dst;
108 }
109 
120 {
121  crm_alert_entry_t *new_entry = crm_alert_entry_new(entry->id, entry->path);
122 
123  new_entry->timeout = entry->timeout;
124  new_entry->flags = entry->flags;
125  new_entry->envvars = crm_str_table_dup(entry->envvars);
126  if (entry->tstamp_format) {
127  new_entry->tstamp_format = strdup(entry->tstamp_format);
128  }
129  if (entry->recipient) {
130  new_entry->recipient = strdup(entry->recipient);
131  }
132  if (entry->select_attribute_name) {
133  new_entry->select_attribute_name = g_strdupv(entry->select_attribute_name);
134  }
135  return new_entry;
136 }
137 
138 void
140 {
141  const char **key;
142  enum crm_alert_keys_e name;
143 
144  for(name = 0; name < DIMOF(crm_alert_keys); name++) {
145  for(key = crm_alert_keys[name]; *key; key++) {
146  crm_trace("Unsetting alert key %s", *key);
147  unsetenv(*key);
148  }
149  }
150 }
151 
152 void
153 crm_insert_alert_key(GHashTable *table, enum crm_alert_keys_e name,
154  const char *value)
155 {
156  for (const char **key = crm_alert_keys[name]; *key; key++) {
157  crm_trace("Inserting alert key %s = '%s'", *key, value);
158  if (value) {
159  g_hash_table_insert(table, strdup(*key), strdup(value));
160  } else {
161  g_hash_table_remove(table, *key);
162  }
163  }
164 }
165 
166 void
167 crm_insert_alert_key_int(GHashTable *table, enum crm_alert_keys_e name,
168  int value)
169 {
170  for (const char **key = crm_alert_keys[name]; *key; key++) {
171  crm_trace("Inserting alert key %s = %d", *key, value);
172  g_hash_table_insert(table, strdup(*key), crm_itoa(value));
173  }
174 }
175 
176 static void
177 set_envvar(gpointer key, gpointer value, gpointer user_data)
178 {
179  gboolean always_unset = GPOINTER_TO_INT(user_data);
180 
181  crm_trace("%s environment variable %s='%s'",
182  (value? "Setting" : "Unsetting"),
183  (char*)key, (value? (char*)value : ""));
184  if (value && !always_unset) {
185  setenv(key, value, 1);
186  } else {
187  unsetenv(key);
188  }
189 }
190 
191 void
193 {
194  if (entry->envvars) {
195  g_hash_table_foreach(entry->envvars, set_envvar, GINT_TO_POINTER(FALSE));
196  }
197 }
198 
199 /*
200  * \note We have no way of restoring a previous value if one was set.
201  */
202 void
204 {
205  if (entry->envvars) {
206  g_hash_table_foreach(entry->envvars, set_envvar, GINT_TO_POINTER(TRUE));
207  }
208 }
209 
210 #define XPATH_PATCHSET1_DIFF "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED
211 
212 #define XPATH_PATCHSET1_CRMCONFIG XPATH_PATCHSET1_DIFF "//" XML_CIB_TAG_CRMCONFIG
213 #define XPATH_PATCHSET1_ALERTS XPATH_PATCHSET1_DIFF "//" XML_CIB_TAG_ALERTS
214 
215 #define XPATH_PATCHSET1_EITHER \
216  XPATH_PATCHSET1_CRMCONFIG " | " XPATH_PATCHSET1_ALERTS
217 
218 #define XPATH_CONFIG "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION
219 
220 #define XPATH_CRMCONFIG XPATH_CONFIG "/" XML_CIB_TAG_CRMCONFIG "/"
221 #define XPATH_ALERTS XPATH_CONFIG "/" XML_CIB_TAG_ALERTS
222 
232 bool
233 crm_patchset_contains_alert(xmlNode *msg, bool config)
234 {
235  int rc = -1;
236  int format= 1;
237  xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
238  xmlNode *change = NULL;
239  xmlXPathObject *xpathObj = NULL;
240 
241  CRM_CHECK(msg != NULL, return FALSE);
242 
243  crm_element_value_int(msg, F_CIB_RC, &rc);
244  if (rc < pcmk_ok) {
245  crm_trace("Ignore failed CIB update: %s (%d)", pcmk_strerror(rc), rc);
246  return FALSE;
247  }
248 
249  crm_element_value_int(patchset, "format", &format);
250  if (format == 1) {
251  const char *diff = (config? XPATH_PATCHSET1_EITHER : XPATH_PATCHSET1_ALERTS);
252 
253  if ((xpathObj = xpath_search(msg, diff)) != NULL) {
254  freeXpathObject(xpathObj);
255  return TRUE;
256  }
257  } else if (format == 2) {
258  for (change = __xml_first_child(patchset); change != NULL; change = __xml_next(change)) {
259  const char *xpath = crm_element_value(change, XML_DIFF_PATH);
260 
261  if (xpath == NULL) {
262  continue;
263  }
264 
265  if ((!config || !strstr(xpath, XPATH_CRMCONFIG))
266  && !strstr(xpath, XPATH_ALERTS)) {
267 
268  /* this is not a change to an existing section ... */
269 
270  xmlNode *section = NULL;
271  const char *name = NULL;
272 
273  if ((strcmp(xpath, XPATH_CONFIG) != 0) ||
274  ((section = __xml_first_child(change)) == NULL) ||
275  ((name = crm_element_name(section)) == NULL) ||
276  (strcmp(name, XML_CIB_TAG_ALERTS) != 0)) {
277 
278  /* ... nor is it a newly added alerts section */
279  continue;
280  }
281  }
282 
283  return TRUE;
284  }
285 
286  } else {
287  crm_warn("Unknown patch format: %d", format);
288  }
289  return FALSE;
290 }
#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
xmlNode * get_message_xml(xmlNode *msg, const char *field)
Definition: xml.c:3163
#define XPATH_ALERTS
Definition: alerts.c:221
#define CRM_ALERT_DEFAULT_TIMEOUT_MS
const char * pcmk_strerror(int rc)
Definition: logging.c:1135
GHashTable * envvars
crm_alert_envvar_t * crm_dup_alert_envvar(crm_alert_envvar_t *src)
Definition: alerts.c:100
char * recipient
#define pcmk_ok
Definition: error.h:42
Local Resource Manager.
void crm_unset_envvar_list(crm_alert_entry_t *entry)
Definition: alerts.c:203
void crm_set_envvar_list(crm_alert_entry_t *entry)
Definition: alerts.c:192
crm_alert_entry_t * crm_dup_alert_entry(crm_alert_entry_t *entry)
Definition: alerts.c:119
#define XPATH_CRMCONFIG
Definition: alerts.c:220
uint32_t flags
char * tstamp_format
#define XPATH_PATCHSET1_EITHER
Definition: alerts.c:215
#define crm_warn(fmt, args...)
Definition: logging.h:249
char * id
#define XPATH_PATCHSET1_ALERTS
Definition: alerts.c:213
#define F_CIB_RC
Definition: internal.h:51
void crm_unset_alert_keys(void)
Definition: alerts.c:139
#define XPATH_CONFIG
Definition: alerts.c:218
#define crm_trace(fmt, args...)
Definition: logging.h:254
int setenv(const char *name, const char *value, int why)
#define CRM_ALERT_NODE_SEQUENCE
#define F_CIB_UPDATE_RESULT
Definition: internal.h:61
int crm_element_value_int(xmlNode *data, const char *name, int *dest)
Definition: xml.c:3844
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5165
void crm_insert_alert_key_int(GHashTable *table, enum crm_alert_keys_e name, int value)
Definition: alerts.c:167
#define XML_DIFF_PATH
Definition: msg_xml.h:438
bool crm_patchset_contains_alert(xmlNode *msg, bool config)
Definition: alerts.c:233
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:145
GHashTable * crm_str_table_dup(GHashTable *old_table)
Definition: strings.c:382
crm_alert_entry_t * crm_alert_entry_new(const char *id, const char *path)
Create a new alert entry structure.
Definition: alerts.c:70
char ** select_attribute_name
int timeout
void crm_free_alert_envvar(crm_alert_envvar_t *entry)
Definition: alerts.c:51
#define DIMOF(a)
Definition: crm.h:39
crm_alert_keys_e
char * path
#define CRM_ASSERT(expr)
Definition: error.h:35
void crm_insert_alert_key(GHashTable *table, enum crm_alert_keys_e name, const char *value)
Definition: alerts.c:153
#define XML_CIB_TAG_ALERTS
Definition: msg_xml.h:167
char * crm_itoa(int an_int)
Definition: strings.c:60
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:45
void crm_free_alert_entry(crm_alert_entry_t *entry)
Definition: alerts.c:83
#define CRM_ALERT_INTERNAL_KEY_MAX