root/lib/pengine/rules_alerts.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_meta_attrs_from_cib
  2. get_envvars_from_cib
  3. unpack_alert_filter
  4. unpack_alert
  5. pe_unpack_alerts
  6. pe_free_alert_list

   1 /*
   2  * Copyright 2015-2021 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/msg_xml.h>
  13 #include <crm/pengine/rules.h>
  14 #include <crm/common/alerts_internal.h>
  15 #include <crm/common/xml_internal.h>
  16 #include <crm/pengine/rules_internal.h>
  17 
  18 static void
  19 get_meta_attrs_from_cib(xmlNode *basenode, pcmk__alert_t *entry,
     /* [previous][next][first][last][top][bottom][index][help] */
  20                         guint *max_timeout)
  21 {
  22     GHashTable *config_hash = pcmk__strkey_table(free, free);
  23     crm_time_t *now = crm_time_new(NULL);
  24     const char *value = NULL;
  25 
  26     pe_unpack_nvpairs(basenode, basenode, XML_TAG_META_SETS, NULL, config_hash,
  27                       NULL, FALSE, now, NULL);
  28     crm_time_free(now);
  29 
  30     value = g_hash_table_lookup(config_hash, XML_ALERT_ATTR_TIMEOUT);
  31     if (value) {
  32         entry->timeout = crm_get_msec(value);
  33         if (entry->timeout <= 0) {
  34             if (entry->timeout == 0) {
  35                 crm_trace("Alert %s uses default timeout of %dmsec",
  36                           entry->id, PCMK__ALERT_DEFAULT_TIMEOUT_MS);
  37             } else {
  38                 crm_warn("Alert %s has invalid timeout value '%s', using default %dmsec",
  39                          entry->id, (char*)value, PCMK__ALERT_DEFAULT_TIMEOUT_MS);
  40             }
  41             entry->timeout = PCMK__ALERT_DEFAULT_TIMEOUT_MS;
  42         } else {
  43             crm_trace("Alert %s uses timeout of %dmsec",
  44                       entry->id, entry->timeout);
  45         }
  46         if (entry->timeout > *max_timeout) {
  47             *max_timeout = entry->timeout;
  48         }
  49     }
  50     value = g_hash_table_lookup(config_hash, XML_ALERT_ATTR_TSTAMP_FORMAT);
  51     if (value) {
  52         /* hard to do any checks here as merely anything can
  53          * can be a valid time-format-string
  54          */
  55         entry->tstamp_format = strdup(value);
  56         crm_trace("Alert %s uses timestamp format '%s'",
  57                   entry->id, entry->tstamp_format);
  58     }
  59 
  60     g_hash_table_destroy(config_hash);
  61 }
  62 
  63 static void
  64 get_envvars_from_cib(xmlNode *basenode, pcmk__alert_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66     xmlNode *child;
  67 
  68     if ((basenode == NULL) || (entry == NULL)) {
  69         return;
  70     }
  71 
  72     child = first_named_child(basenode, XML_TAG_ATTR_SETS);
  73     if (child == NULL) {
  74         return;
  75     }
  76 
  77     if (entry->envvars == NULL) {
  78         entry->envvars = pcmk__strkey_table(free, free);
  79     }
  80 
  81     for (child = first_named_child(child, XML_CIB_TAG_NVPAIR); child != NULL;
  82          child = crm_next_same_xml(child)) {
  83 
  84         const char *name = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
  85         const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);
  86 
  87         if (value == NULL) {
  88             value = "";
  89         }
  90         g_hash_table_insert(entry->envvars, strdup(name), strdup(value));
  91         crm_trace("Alert %s: added environment variable %s='%s'",
  92                   entry->id, name, value);
  93     }
  94 }
  95 
  96 static void
  97 unpack_alert_filter(xmlNode *basenode, pcmk__alert_t *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99     xmlNode *select = first_named_child(basenode, XML_CIB_TAG_ALERT_SELECT);
 100     xmlNode *event_type = NULL;
 101     uint32_t flags = pcmk__alert_none;
 102 
 103     for (event_type = pcmk__xe_first_child(select); event_type != NULL;
 104          event_type = pcmk__xe_next(event_type)) {
 105 
 106         const char *tagname = crm_element_name(event_type);
 107 
 108         if (tagname == NULL) {
 109             continue;
 110 
 111         } else if (!strcmp(tagname, XML_CIB_TAG_ALERT_FENCING)) {
 112             flags |= pcmk__alert_fencing;
 113 
 114         } else if (!strcmp(tagname, XML_CIB_TAG_ALERT_NODES)) {
 115             flags |= pcmk__alert_node;
 116 
 117         } else if (!strcmp(tagname, XML_CIB_TAG_ALERT_RESOURCES)) {
 118             flags |= pcmk__alert_resource;
 119 
 120         } else if (!strcmp(tagname, XML_CIB_TAG_ALERT_ATTRIBUTES)) {
 121             xmlNode *attr;
 122             const char *attr_name;
 123             int nattrs = 0;
 124 
 125             flags |= pcmk__alert_attribute;
 126             for (attr = first_named_child(event_type, XML_CIB_TAG_ALERT_ATTR);
 127                  attr != NULL;
 128                  attr = crm_next_same_xml(attr)) {
 129 
 130                 attr_name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME);
 131                 if (attr_name) {
 132                     if (nattrs == 0) {
 133                         g_strfreev(entry->select_attribute_name);
 134                         entry->select_attribute_name = NULL;
 135                     }
 136                     ++nattrs;
 137                     entry->select_attribute_name = pcmk__realloc(entry->select_attribute_name,
 138                                                                  (nattrs + 1) * sizeof(char*));
 139                     entry->select_attribute_name[nattrs - 1] = strdup(attr_name);
 140                     entry->select_attribute_name[nattrs] = NULL;
 141                 }
 142             }
 143         }
 144     }
 145 
 146     if (flags != pcmk__alert_none) {
 147         entry->flags = flags;
 148         crm_debug("Alert %s receives events: attributes:%s%s%s%s",
 149                   entry->id,
 150                   (pcmk_is_set(flags, pcmk__alert_attribute)?
 151                    (entry->select_attribute_name? "some" : "all") : "none"),
 152                   (pcmk_is_set(flags, pcmk__alert_fencing)? " fencing" : ""),
 153                   (pcmk_is_set(flags, pcmk__alert_node)? " nodes" : ""),
 154                   (pcmk_is_set(flags, pcmk__alert_resource)? " resources" : ""));
 155     }
 156 }
 157 
 158 static void
 159 unpack_alert(xmlNode *alert, pcmk__alert_t *entry, guint *max_timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161     get_envvars_from_cib(alert, entry);
 162     get_meta_attrs_from_cib(alert, entry, max_timeout);
 163     unpack_alert_filter(alert, entry);
 164 }
 165 
 166 /*!
 167  * \internal
 168  * \brief Unpack a CIB alerts section
 169  *
 170  * \param[in] alerts  XML of alerts section
 171  *
 172  * \return  List of unpacked alert entries
 173  *
 174  * \note Unlike most unpack functions, this is not used by the scheduler itself,
 175  *       but is supplied for use by daemons that need to send alerts.
 176  */
 177 GList *
 178 pe_unpack_alerts(xmlNode *alerts)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180     xmlNode *alert;
 181     pcmk__alert_t *entry;
 182     guint max_timeout = 0;
 183     GList *alert_list = NULL;
 184 
 185     if (alerts == NULL) {
 186         return alert_list;
 187     }
 188 
 189     for (alert = first_named_child(alerts, XML_CIB_TAG_ALERT);
 190          alert != NULL; alert = crm_next_same_xml(alert)) {
 191 
 192         xmlNode *recipient;
 193         int recipients = 0;
 194         const char *alert_id = ID(alert);
 195         const char *alert_path = crm_element_value(alert, XML_ALERT_ATTR_PATH);
 196 
 197         /* The schema should enforce this, but to be safe ... */
 198         if ((alert_id == NULL) || (alert_path == NULL)) {
 199             crm_warn("Ignoring invalid alert without id and path");
 200             continue;
 201         }
 202 
 203         entry = pcmk__alert_new(alert_id, alert_path);
 204 
 205         unpack_alert(alert, entry, &max_timeout);
 206 
 207         if (entry->tstamp_format == NULL) {
 208             entry->tstamp_format = strdup(PCMK__ALERT_DEFAULT_TSTAMP_FORMAT);
 209         }
 210 
 211         crm_debug("Alert %s: path=%s timeout=%dms tstamp-format='%s' %u vars",
 212                   entry->id, entry->path, entry->timeout, entry->tstamp_format,
 213                   (entry->envvars? g_hash_table_size(entry->envvars) : 0));
 214 
 215         for (recipient = first_named_child(alert, XML_CIB_TAG_ALERT_RECIPIENT);
 216              recipient != NULL; recipient = crm_next_same_xml(recipient)) {
 217 
 218             pcmk__alert_t *recipient_entry = pcmk__dup_alert(entry);
 219 
 220             recipients++;
 221             recipient_entry->recipient = strdup(crm_element_value(recipient,
 222                                                 XML_ALERT_ATTR_REC_VALUE));
 223             unpack_alert(recipient, recipient_entry, &max_timeout);
 224             alert_list = g_list_prepend(alert_list, recipient_entry);
 225             crm_debug("Alert %s has recipient %s with value %s and %d envvars",
 226                       entry->id, ID(recipient), recipient_entry->recipient,
 227                       (recipient_entry->envvars?
 228                        g_hash_table_size(recipient_entry->envvars) : 0));
 229         }
 230 
 231         if (recipients == 0) {
 232             alert_list = g_list_prepend(alert_list, entry);
 233         } else {
 234             pcmk__free_alert(entry);
 235         }
 236     }
 237     return alert_list;
 238 }
 239 
 240 /*!
 241  * \internal
 242  * \brief Free an alert list generated by pe_unpack_alerts()
 243  *
 244  * \param[in] alert_list  Alert list to free
 245  */
 246 void
 247 pe_free_alert_list(GList *alert_list)
     /* [previous][next][first][last][top][bottom][index][help] */
 248 {
 249     if (alert_list) {
 250         g_list_free_full(alert_list, (GDestroyNotify) pcmk__free_alert);
 251     }
 252 }

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