root/lib/common/alerts.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. crm_free_alert_envvar
  2. crm_alert_entry_new
  3. crm_free_alert_entry
  4. crm_dup_alert_envvar
  5. crm_dup_alert_entry
  6. crm_unset_alert_keys
  7. crm_insert_alert_key
  8. crm_insert_alert_key_int
  9. set_envvar
  10. crm_set_envvar_list
  11. crm_unset_envvar_list
  12. crm_patchset_contains_alert

   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>
  23 #include <crm/common/alerts_internal.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  */
  30 const char *crm_alert_keys[CRM_ALERT_INTERNAL_KEY_MAX][3] =             
  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
  51 crm_free_alert_envvar(crm_alert_envvar_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {               
  53     free(entry->name);          
  54     free(entry->value);         
  55     free(entry);                
  56 }               
  57 
  58 /*!
  59  * \brief Create a new alert entry structure
  60  *
  61  * \param[in] id  ID to use
  62  * \param[in] path  Path to alert agent executable
  63  *
  64  * \return Pointer to newly allocated alert entry
  65  * \note Non-string fields will be filled in with defaults.
  66  *       It is the caller's responsibility to free the result,
  67  *       using crm_free_alert_entry().
  68  */
  69 crm_alert_entry_t *
  70 crm_alert_entry_new(const char *id, const char *path)
     /* [previous][next][first][last][top][bottom][index][help] */
  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);
  77     entry->timeout = CRM_ALERT_DEFAULT_TIMEOUT_MS;
  78     entry->flags = crm_alert_default;
  79     return entry;
  80 }
  81 
  82 void
  83 crm_free_alert_entry(crm_alert_entry_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
  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 
  99 crm_alert_envvar_t *
 100 crm_dup_alert_envvar(crm_alert_envvar_t *src)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 110 /*!
 111  * \internal
 112  * \brief Duplicate an alert entry
 113  *
 114  * \param[in] entry  Alert entry to duplicate
 115  *
 116  * \return Duplicate of alert entry
 117  */
 118 crm_alert_entry_t *
 119 crm_dup_alert_entry(crm_alert_entry_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 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
 139 crm_unset_alert_keys()
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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
 192 crm_set_envvar_list(crm_alert_entry_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 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
 203 crm_unset_envvar_list(crm_alert_entry_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 223 /*!
 224  * \internal
 225  * \brief Check whether a CIB update affects alerts
 226  *
 227  * \param[in] msg     XML containing CIB update
 228  * \param[in] config  Whether to check for crmconfig change as well
 229  *
 230  * \return TRUE if update affects alerts, FALSE otherwise
 231  */
 232 bool
 233 crm_patchset_contains_alert(xmlNode *msg, bool config)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }

/* [previous][next][first][last][top][bottom][index][help] */