root/lib/common/alerts.c

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

DEFINITIONS

This source file includes following definitions.
  1. pcmk__alert_new
  2. pcmk__free_alert
  3. pcmk__dup_alert
  4. pcmk__add_alert_key
  5. pcmk__add_alert_key_int
  6. pcmk__alert_in_patchset

   1 /*
   2  * Copyright 2015-2020 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/lrmd.h>
  13 #include <crm/msg_xml.h>
  14 #include <crm/common/alerts_internal.h>
  15 #include <crm/common/xml_internal.h>
  16 #include <crm/cib/internal.h> /* for F_CIB_UPDATE_RESULT */
  17 
  18 /*
  19  * to allow script compatibility we can have more than one
  20  * set of environment variables
  21  */
  22 const char *pcmk__alert_keys[PCMK__ALERT_INTERNAL_KEY_MAX][3] =
  23 {
  24     [PCMK__alert_key_recipient] = {
  25         "CRM_notify_recipient",         "CRM_alert_recipient",          NULL
  26     },
  27     [PCMK__alert_key_node] = {
  28         "CRM_notify_node",              "CRM_alert_node",               NULL
  29     },
  30     [PCMK__alert_key_nodeid] = {
  31         "CRM_notify_nodeid",            "CRM_alert_nodeid",             NULL
  32     },
  33     [PCMK__alert_key_rsc] = {
  34         "CRM_notify_rsc",               "CRM_alert_rsc",                NULL
  35     },
  36     [PCMK__alert_key_task] = {
  37         "CRM_notify_task",              "CRM_alert_task",               NULL
  38     },
  39     [PCMK__alert_key_interval] = {
  40         "CRM_notify_interval",          "CRM_alert_interval",           NULL
  41     },
  42     [PCMK__alert_key_desc] = {
  43         "CRM_notify_desc",              "CRM_alert_desc",               NULL
  44     },
  45     [PCMK__alert_key_status] = {
  46         "CRM_notify_status",            "CRM_alert_status",             NULL
  47     },
  48     [PCMK__alert_key_target_rc] = {
  49         "CRM_notify_target_rc",         "CRM_alert_target_rc",          NULL
  50     },
  51     [PCMK__alert_key_rc] = {
  52         "CRM_notify_rc",                "CRM_alert_rc",                 NULL
  53     },
  54     [PCMK__alert_key_kind] = {
  55         "CRM_notify_kind",              "CRM_alert_kind",               NULL
  56     },
  57     [PCMK__alert_key_version] = {
  58         "CRM_notify_version",           "CRM_alert_version",            NULL
  59     },
  60     [PCMK__alert_key_node_sequence] = {
  61         "CRM_notify_node_sequence",     PCMK__ALERT_NODE_SEQUENCE,      NULL
  62     },
  63     [PCMK__alert_key_timestamp] = {
  64         "CRM_notify_timestamp",         "CRM_alert_timestamp",          NULL
  65     },
  66     [PCMK__alert_key_attribute_name] = {
  67         "CRM_notify_attribute_name",    "CRM_alert_attribute_name",     NULL
  68     },
  69     [PCMK__alert_key_attribute_value] = {
  70         "CRM_notify_attribute_value",   "CRM_alert_attribute_value",    NULL
  71     },
  72     [PCMK__alert_key_timestamp_epoch] = {
  73         "CRM_notify_timestamp_epoch",   "CRM_alert_timestamp_epoch",    NULL
  74     },
  75     [PCMK__alert_key_timestamp_usec] = {
  76         "CRM_notify_timestamp_usec",    "CRM_alert_timestamp_usec",     NULL
  77     },
  78     [PCMK__alert_key_exec_time] = {
  79         "CRM_notify_exec_time",         "CRM_alert_exec_time",          NULL
  80     }
  81 };
  82 
  83 /*!
  84  * \brief Create a new alert entry structure
  85  *
  86  * \param[in] id  ID to use
  87  * \param[in] path  Path to alert agent executable
  88  *
  89  * \return Pointer to newly allocated alert entry
  90  * \note Non-string fields will be filled in with defaults.
  91  *       It is the caller's responsibility to free the result,
  92  *       using pcmk__free_alert().
  93  */
  94 pcmk__alert_t *
  95 pcmk__alert_new(const char *id, const char *path)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97     pcmk__alert_t *entry = calloc(1, sizeof(pcmk__alert_t));
  98 
  99     CRM_ASSERT(entry && id && path);
 100     entry->id = strdup(id);
 101     entry->path = strdup(path);
 102     entry->timeout = PCMK__ALERT_DEFAULT_TIMEOUT_MS;
 103     entry->flags = pcmk__alert_default;
 104     return entry;
 105 }
 106 
 107 void
 108 pcmk__free_alert(pcmk__alert_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110     if (entry) {
 111         free(entry->id);
 112         free(entry->path);
 113         free(entry->tstamp_format);
 114         free(entry->recipient);
 115 
 116         g_strfreev(entry->select_attribute_name);
 117         if (entry->envvars) {
 118             g_hash_table_destroy(entry->envvars);
 119         }
 120         free(entry);
 121     }
 122 }
 123 
 124 /*!
 125  * \internal
 126  * \brief Duplicate an alert entry
 127  *
 128  * \param[in] entry  Alert entry to duplicate
 129  *
 130  * \return Duplicate of alert entry
 131  */
 132 pcmk__alert_t *
 133 pcmk__dup_alert(pcmk__alert_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135     pcmk__alert_t *new_entry = pcmk__alert_new(entry->id, entry->path);
 136 
 137     new_entry->timeout = entry->timeout;
 138     new_entry->flags = entry->flags;
 139     new_entry->envvars = crm_str_table_dup(entry->envvars);
 140     if (entry->tstamp_format) {
 141         new_entry->tstamp_format = strdup(entry->tstamp_format);
 142     }
 143     if (entry->recipient) {
 144         new_entry->recipient = strdup(entry->recipient);
 145     }
 146     if (entry->select_attribute_name) {
 147         new_entry->select_attribute_name = g_strdupv(entry->select_attribute_name);
 148     }
 149     return new_entry;
 150 }
 151 
 152 void
 153 pcmk__add_alert_key(GHashTable *table, enum pcmk__alert_keys_e name,
     /* [previous][next][first][last][top][bottom][index][help] */
 154                     const char *value)
 155 {
 156     for (const char **key = pcmk__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 pcmk__add_alert_key_int(GHashTable *table, enum pcmk__alert_keys_e name,
     /* [previous][next][first][last][top][bottom][index][help] */
 168                         int value)
 169 {
 170     for (const char **key = pcmk__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 #define XPATH_PATCHSET1_DIFF "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED
 177 
 178 #define XPATH_PATCHSET1_CRMCONFIG XPATH_PATCHSET1_DIFF "//" XML_CIB_TAG_CRMCONFIG
 179 #define XPATH_PATCHSET1_ALERTS    XPATH_PATCHSET1_DIFF "//" XML_CIB_TAG_ALERTS
 180 
 181 #define XPATH_PATCHSET1_EITHER \
 182     XPATH_PATCHSET1_CRMCONFIG " | " XPATH_PATCHSET1_ALERTS
 183 
 184 #define XPATH_CONFIG "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION
 185 
 186 #define XPATH_CRMCONFIG XPATH_CONFIG "/" XML_CIB_TAG_CRMCONFIG "/"
 187 #define XPATH_ALERTS    XPATH_CONFIG "/" XML_CIB_TAG_ALERTS
 188 
 189 /*!
 190  * \internal
 191  * \brief Check whether a CIB update affects alerts
 192  *
 193  * \param[in] msg     XML containing CIB update
 194  * \param[in] config  Whether to check for crmconfig change as well
 195  *
 196  * \return TRUE if update affects alerts, FALSE otherwise
 197  */
 198 bool
 199 pcmk__alert_in_patchset(xmlNode *msg, bool config)
     /* [previous][next][first][last][top][bottom][index][help] */
 200 {
 201     int rc = -1;
 202     int format= 1;
 203     xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 204     xmlNode *change = NULL;
 205     xmlXPathObject *xpathObj = NULL;
 206 
 207     CRM_CHECK(msg != NULL, return FALSE);
 208 
 209     crm_element_value_int(msg, F_CIB_RC, &rc);
 210     if (rc < pcmk_ok) {
 211         crm_trace("Ignore failed CIB update: %s (%d)", pcmk_strerror(rc), rc);
 212         return FALSE;
 213     }
 214 
 215     crm_element_value_int(patchset, "format", &format);
 216     if (format == 1) {
 217         const char *diff = (config? XPATH_PATCHSET1_EITHER : XPATH_PATCHSET1_ALERTS);
 218 
 219         if ((xpathObj = xpath_search(msg, diff)) != NULL) {
 220             freeXpathObject(xpathObj);
 221             return TRUE;
 222         }
 223     } else if (format == 2) {
 224         for (change = pcmk__xml_first_child(patchset); change != NULL;
 225              change = pcmk__xml_next(change)) {
 226             const char *xpath = crm_element_value(change, XML_DIFF_PATH);
 227 
 228             if (xpath == NULL) {
 229                 continue;
 230             }
 231 
 232             if ((!config || !strstr(xpath, XPATH_CRMCONFIG))
 233                 && !strstr(xpath, XPATH_ALERTS)) {
 234 
 235                 /* this is not a change to an existing section ... */
 236 
 237                 xmlNode *section = NULL;
 238                 const char *name = NULL;
 239 
 240                 if ((strcmp(xpath, XPATH_CONFIG) != 0) ||
 241                     ((section = pcmk__xml_first_child(change)) == NULL) ||
 242                     ((name = crm_element_name(section)) == NULL) ||
 243                     (strcmp(name, XML_CIB_TAG_ALERTS) != 0)) {
 244 
 245                     /* ... nor is it a newly added alerts section */
 246                     continue;
 247                 }
 248             }
 249 
 250             return TRUE;
 251         }
 252 
 253     } else {
 254         crm_warn("Unknown patch format: %d", format);
 255     }
 256     return FALSE;
 257 }

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