pacemaker  2.0.2-debe490
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 2015-2019 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/lrmd.h>
11 #include <crm/msg_xml.h>
13 #include <crm/cib/internal.h> /* for F_CIB_UPDATE_RESULT */
14 
15 /*
16  * to allow script compatibility we can have more than one
17  * set of environment variables
18  */
20 {
21  [CRM_alert_recipient] = {"CRM_notify_recipient", "CRM_alert_recipient", NULL},
22  [CRM_alert_node] = {"CRM_notify_node", "CRM_alert_node", NULL},
23  [CRM_alert_nodeid] = {"CRM_notify_nodeid", "CRM_alert_nodeid", NULL},
24  [CRM_alert_rsc] = {"CRM_notify_rsc", "CRM_alert_rsc", NULL},
25  [CRM_alert_task] = {"CRM_notify_task", "CRM_alert_task", NULL},
26  [CRM_alert_interval] = {"CRM_notify_interval", "CRM_alert_interval", NULL},
27  [CRM_alert_desc] = {"CRM_notify_desc", "CRM_alert_desc", NULL},
28  [CRM_alert_status] = {"CRM_notify_status", "CRM_alert_status", NULL},
29  [CRM_alert_target_rc] = {"CRM_notify_target_rc", "CRM_alert_target_rc", NULL},
30  [CRM_alert_rc] = {"CRM_notify_rc", "CRM_alert_rc", NULL},
31  [CRM_alert_kind] = {"CRM_notify_kind", "CRM_alert_kind", NULL},
32  [CRM_alert_version] = {"CRM_notify_version", "CRM_alert_version", NULL},
33  [CRM_alert_node_sequence] = {"CRM_notify_node_sequence", CRM_ALERT_NODE_SEQUENCE, NULL},
34  [CRM_alert_timestamp] = {"CRM_notify_timestamp", "CRM_alert_timestamp", NULL},
35  [CRM_alert_attribute_name] = {"CRM_notify_attribute_name", "CRM_alert_attribute_name", NULL},
36  [CRM_alert_attribute_value] = {"CRM_notify_attribute_value", "CRM_alert_attribute_value", NULL},
37  [CRM_alert_timestamp_epoch] = {"CRM_notify_timestamp_epoch", "CRM_alert_timestamp_epoch", NULL},
38  [CRM_alert_timestamp_usec] = {"CRM_notify_timestamp_usec", "CRM_alert_timestamp_usec", NULL},
39  [CRM_alert_exec_time] = {"CRM_notify_exec_time", "CRM_alert_exec_time", NULL}
40 };
41 
54 crm_alert_entry_new(const char *id, const char *path)
55 {
56  crm_alert_entry_t *entry = calloc(1, sizeof(crm_alert_entry_t));
57 
58  CRM_ASSERT(entry && id && path);
59  entry->id = strdup(id);
60  entry->path = strdup(path);
62  entry->flags = crm_alert_default;
63  return entry;
64 }
65 
66 void
68 {
69  if (entry) {
70  free(entry->id);
71  free(entry->path);
72  free(entry->tstamp_format);
73  free(entry->recipient);
74 
75  g_strfreev(entry->select_attribute_name);
76  if (entry->envvars) {
77  g_hash_table_destroy(entry->envvars);
78  }
79  free(entry);
80  }
81 }
82 
93 {
94  crm_alert_entry_t *new_entry = crm_alert_entry_new(entry->id, entry->path);
95 
96  new_entry->timeout = entry->timeout;
97  new_entry->flags = entry->flags;
98  new_entry->envvars = crm_str_table_dup(entry->envvars);
99  if (entry->tstamp_format) {
100  new_entry->tstamp_format = strdup(entry->tstamp_format);
101  }
102  if (entry->recipient) {
103  new_entry->recipient = strdup(entry->recipient);
104  }
105  if (entry->select_attribute_name) {
106  new_entry->select_attribute_name = g_strdupv(entry->select_attribute_name);
107  }
108  return new_entry;
109 }
110 
111 void
113 {
114  const char **key;
115  enum crm_alert_keys_e name;
116 
117  for(name = 0; name < DIMOF(crm_alert_keys); name++) {
118  for(key = crm_alert_keys[name]; *key; key++) {
119  crm_trace("Unsetting alert key %s", *key);
120  unsetenv(*key);
121  }
122  }
123 }
124 
125 void
126 crm_insert_alert_key(GHashTable *table, enum crm_alert_keys_e name,
127  const char *value)
128 {
129  for (const char **key = crm_alert_keys[name]; *key; key++) {
130  crm_trace("Inserting alert key %s = '%s'", *key, value);
131  if (value) {
132  g_hash_table_insert(table, strdup(*key), strdup(value));
133  } else {
134  g_hash_table_remove(table, *key);
135  }
136  }
137 }
138 
139 void
140 crm_insert_alert_key_int(GHashTable *table, enum crm_alert_keys_e name,
141  int value)
142 {
143  for (const char **key = crm_alert_keys[name]; *key; key++) {
144  crm_trace("Inserting alert key %s = %d", *key, value);
145  g_hash_table_insert(table, strdup(*key), crm_itoa(value));
146  }
147 }
148 
149 static void
150 set_envvar(gpointer key, gpointer value, gpointer user_data)
151 {
152  gboolean always_unset = GPOINTER_TO_INT(user_data);
153 
154  crm_trace("%s environment variable %s='%s'",
155  (value? "Setting" : "Unsetting"),
156  (char*)key, (value? (char*)value : ""));
157  if (value && !always_unset) {
158  setenv(key, value, 1);
159  } else {
160  unsetenv(key);
161  }
162 }
163 
164 void
166 {
167  if (entry->envvars) {
168  g_hash_table_foreach(entry->envvars, set_envvar, GINT_TO_POINTER(FALSE));
169  }
170 }
171 
172 /*
173  * \note We have no way of restoring a previous value if one was set.
174  */
175 void
177 {
178  if (entry->envvars) {
179  g_hash_table_foreach(entry->envvars, set_envvar, GINT_TO_POINTER(TRUE));
180  }
181 }
182 
183 #define XPATH_PATCHSET1_DIFF "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED
184 
185 #define XPATH_PATCHSET1_CRMCONFIG XPATH_PATCHSET1_DIFF "//" XML_CIB_TAG_CRMCONFIG
186 #define XPATH_PATCHSET1_ALERTS XPATH_PATCHSET1_DIFF "//" XML_CIB_TAG_ALERTS
187 
188 #define XPATH_PATCHSET1_EITHER \
189  XPATH_PATCHSET1_CRMCONFIG " | " XPATH_PATCHSET1_ALERTS
190 
191 #define XPATH_CONFIG "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION
192 
193 #define XPATH_CRMCONFIG XPATH_CONFIG "/" XML_CIB_TAG_CRMCONFIG "/"
194 #define XPATH_ALERTS XPATH_CONFIG "/" XML_CIB_TAG_ALERTS
195 
205 bool
206 crm_patchset_contains_alert(xmlNode *msg, bool config)
207 {
208  int rc = -1;
209  int format= 1;
210  xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
211  xmlNode *change = NULL;
212  xmlXPathObject *xpathObj = NULL;
213 
214  CRM_CHECK(msg != NULL, return FALSE);
215 
216  crm_element_value_int(msg, F_CIB_RC, &rc);
217  if (rc < pcmk_ok) {
218  crm_trace("Ignore failed CIB update: %s (%d)", pcmk_strerror(rc), rc);
219  return FALSE;
220  }
221 
222  crm_element_value_int(patchset, "format", &format);
223  if (format == 1) {
224  const char *diff = (config? XPATH_PATCHSET1_EITHER : XPATH_PATCHSET1_ALERTS);
225 
226  if ((xpathObj = xpath_search(msg, diff)) != NULL) {
227  freeXpathObject(xpathObj);
228  return TRUE;
229  }
230  } else if (format == 2) {
231  for (change = __xml_first_child(patchset); change != NULL; change = __xml_next(change)) {
232  const char *xpath = crm_element_value(change, XML_DIFF_PATH);
233 
234  if (xpath == NULL) {
235  continue;
236  }
237 
238  if ((!config || !strstr(xpath, XPATH_CRMCONFIG))
239  && !strstr(xpath, XPATH_ALERTS)) {
240 
241  /* this is not a change to an existing section ... */
242 
243  xmlNode *section = NULL;
244  const char *name = NULL;
245 
246  if ((strcmp(xpath, XPATH_CONFIG) != 0) ||
247  ((section = __xml_first_child(change)) == NULL) ||
248  ((name = crm_element_name(section)) == NULL) ||
249  (strcmp(name, XML_CIB_TAG_ALERTS) != 0)) {
250 
251  /* ... nor is it a newly added alerts section */
252  continue;
253  }
254  }
255 
256  return TRUE;
257  }
258 
259  } else {
260  crm_warn("Unknown patch format: %d", format);
261  }
262  return FALSE;
263 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:156
A dumping ground.
const char * crm_alert_keys[CRM_ALERT_INTERNAL_KEY_MAX][3]
Definition: alerts.c:19
xmlNode * get_message_xml(xmlNode *msg, const char *field)
Definition: xml.c:2504
const char * pcmk_strerror(int rc)
Definition: results.c:188
#define XPATH_ALERTS
Definition: alerts.c:194
#define CRM_ALERT_DEFAULT_TIMEOUT_MS
GHashTable * envvars
char * recipient
Resource agent executor.
void crm_unset_envvar_list(crm_alert_entry_t *entry)
Definition: alerts.c:176
void crm_set_envvar_list(crm_alert_entry_t *entry)
Definition: alerts.c:165
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:459
crm_alert_entry_t * crm_dup_alert_entry(crm_alert_entry_t *entry)
Definition: alerts.c:92
#define XPATH_CRMCONFIG
Definition: alerts.c:193
uint32_t flags
char * tstamp_format
#define XPATH_PATCHSET1_EITHER
Definition: alerts.c:188
#define crm_warn(fmt, args...)
Definition: logging.h:241
char * id
#define XPATH_PATCHSET1_ALERTS
Definition: alerts.c:186
#define F_CIB_RC
Definition: internal.h:40
void crm_unset_alert_keys(void)
Definition: alerts.c:112
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:423
#define XPATH_CONFIG
Definition: alerts.c:191
#define crm_trace(fmt, args...)
Definition: logging.h:246
int setenv(const char *name, const char *value, int why)
#define CRM_ALERT_NODE_SEQUENCE
#define F_CIB_UPDATE_RESULT
Definition: internal.h:51
void crm_insert_alert_key_int(GHashTable *table, enum crm_alert_keys_e name, int value)
Definition: alerts.c:140
#define XML_DIFF_PATH
Definition: msg_xml.h:409
bool crm_patchset_contains_alert(xmlNode *msg, bool config)
Definition: alerts.c:206
#define CRM_ASSERT(expr)
Definition: results.h:42
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:145
GHashTable * crm_str_table_dup(GHashTable *old_table)
Definition: strings.c:396
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
int timeout
#define DIMOF(a)
Definition: crm.h:35
crm_alert_keys_e
char * path
#define pcmk_ok
Definition: results.h:57
void crm_insert_alert_key(GHashTable *table, enum crm_alert_keys_e name, const char *value)
Definition: alerts.c:126
#define XML_CIB_TAG_ALERTS
Definition: msg_xml.h:148
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:45
void crm_free_alert_entry(crm_alert_entry_t *entry)
Definition: alerts.c:67
#define CRM_ALERT_INTERNAL_KEY_MAX