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-2022 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(const 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 = pcmk__str_table_dup(entry->envvars);
 140     pcmk__str_update(&new_entry->tstamp_format, entry->tstamp_format);
 141     pcmk__str_update(&new_entry->recipient, entry->recipient);
 142     if (entry->select_attribute_name) {
 143         new_entry->select_attribute_name = g_strdupv(entry->select_attribute_name);
 144     }
 145     return new_entry;
 146 }
 147 
 148 void
 149 pcmk__add_alert_key(GHashTable *table, enum pcmk__alert_keys_e name,
     /* [previous][next][first][last][top][bottom][index][help] */
 150                     const char *value)
 151 {
 152     for (const char **key = pcmk__alert_keys[name]; *key; key++) {
 153         crm_trace("Inserting alert key %s = '%s'", *key, value);
 154         if (value) {
 155             g_hash_table_insert(table, strdup(*key), strdup(value));
 156         } else {
 157             g_hash_table_remove(table, *key);
 158         }
 159     }
 160 }
 161 
 162 void
 163 pcmk__add_alert_key_int(GHashTable *table, enum pcmk__alert_keys_e name,
     /* [previous][next][first][last][top][bottom][index][help] */
 164                         int value)
 165 {
 166     for (const char **key = pcmk__alert_keys[name]; *key; key++) {
 167         crm_trace("Inserting alert key %s = %d", *key, value);
 168         g_hash_table_insert(table, strdup(*key), pcmk__itoa(value));
 169     }
 170 }
 171 
 172 #define XPATH_PATCHSET1_DIFF "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED
 173 
 174 #define XPATH_PATCHSET1_CRMCONFIG XPATH_PATCHSET1_DIFF "//" XML_CIB_TAG_CRMCONFIG
 175 #define XPATH_PATCHSET1_ALERTS    XPATH_PATCHSET1_DIFF "//" XML_CIB_TAG_ALERTS
 176 
 177 #define XPATH_PATCHSET1_EITHER \
 178     XPATH_PATCHSET1_CRMCONFIG " | " XPATH_PATCHSET1_ALERTS
 179 
 180 #define XPATH_CONFIG "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION
 181 
 182 #define XPATH_CRMCONFIG XPATH_CONFIG "/" XML_CIB_TAG_CRMCONFIG "/"
 183 #define XPATH_ALERTS    XPATH_CONFIG "/" XML_CIB_TAG_ALERTS
 184 
 185 /*!
 186  * \internal
 187  * \brief Check whether a CIB update affects alerts
 188  *
 189  * \param[in] msg     XML containing CIB update
 190  * \param[in] config  Whether to check for crmconfig change as well
 191  *
 192  * \return TRUE if update affects alerts, FALSE otherwise
 193  */
 194 bool
 195 pcmk__alert_in_patchset(xmlNode *msg, bool config)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197     int rc = -1;
 198     int format= 1;
 199     xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 200     xmlNode *change = NULL;
 201     xmlXPathObject *xpathObj = NULL;
 202 
 203     CRM_CHECK(msg != NULL, return FALSE);
 204 
 205     crm_element_value_int(msg, F_CIB_RC, &rc);
 206     if (rc < pcmk_ok) {
 207         crm_trace("Ignore failed CIB update: %s (%d)", pcmk_strerror(rc), rc);
 208         return FALSE;
 209     }
 210 
 211     crm_element_value_int(patchset, "format", &format);
 212     if (format == 1) {
 213         const char *diff = (config? XPATH_PATCHSET1_EITHER : XPATH_PATCHSET1_ALERTS);
 214 
 215         if ((xpathObj = xpath_search(msg, diff)) != NULL) {
 216             freeXpathObject(xpathObj);
 217             return TRUE;
 218         }
 219     } else if (format == 2) {
 220         for (change = pcmk__xml_first_child(patchset); change != NULL;
 221              change = pcmk__xml_next(change)) {
 222             const char *xpath = crm_element_value(change, XML_DIFF_PATH);
 223 
 224             if (xpath == NULL) {
 225                 continue;
 226             }
 227 
 228             if ((!config || !strstr(xpath, XPATH_CRMCONFIG))
 229                 && !strstr(xpath, XPATH_ALERTS)) {
 230 
 231                 /* this is not a change to an existing section ... */
 232 
 233                 xmlNode *section = NULL;
 234                 const char *name = NULL;
 235 
 236                 if ((strcmp(xpath, XPATH_CONFIG) != 0) ||
 237                     ((section = pcmk__xml_first_child(change)) == NULL) ||
 238                     ((name = crm_element_name(section)) == NULL) ||
 239                     (strcmp(name, XML_CIB_TAG_ALERTS) != 0)) {
 240 
 241                     /* ... nor is it a newly added alerts section */
 242                     continue;
 243                 }
 244             }
 245 
 246             return TRUE;
 247         }
 248 
 249     } else {
 250         crm_warn("Unknown patch format: %d", format);
 251     }
 252     return FALSE;
 253 }

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