root/lib/pengine/rules.c

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

DEFINITIONS

This source file includes following definitions.
  1. map_rule_input
  2. populate_hash
  3. unpack_attr_set
  4. make_pairs
  5. pe_eval_nvpairs
  6. pe_unpack_nvpairs
  7. test_rule

   1 /*
   2  * Copyright 2004-2024 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 
  12 #include <glib.h>
  13 
  14 #include <crm/crm.h>
  15 #include <crm/common/xml.h>
  16 #include <crm/pengine/rules.h>
  17 
  18 #include <crm/common/iso8601_internal.h>
  19 #include <crm/common/nvpair_internal.h>
  20 #include <crm/common/rules_internal.h>
  21 #include <crm/common/xml_internal.h>
  22 #include <crm/pengine/internal.h>
  23 #include <crm/pengine/rules_internal.h>
  24 
  25 #include <sys/types.h>
  26 #include <regex.h>
  27 
  28 CRM_TRACE_INIT_DATA(pe_rules);
  29 
  30 /*!
  31  * \internal
  32  * \brief Map pe_rule_eval_data_t to pcmk_rule_input_t
  33  *
  34  * \param[out] new  New data struct
  35  * \param[in]  old  Old data struct
  36  */
  37 static void
  38 map_rule_input(pcmk_rule_input_t *new, const pe_rule_eval_data_t *old)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40     if (old == NULL) {
  41         return;
  42     }
  43     new->now = old->now;
  44     new->node_attrs = old->node_hash;
  45     if (old->rsc_data != NULL) {
  46         new->rsc_standard = old->rsc_data->standard;
  47         new->rsc_provider = old->rsc_data->provider;
  48         new->rsc_agent = old->rsc_data->agent;
  49     }
  50     if (old->match_data != NULL) {
  51         new->rsc_params = old->match_data->params;
  52         new->rsc_meta = old->match_data->meta;
  53         if (old->match_data->re != NULL) {
  54             new->rsc_id = old->match_data->re->string;
  55             new->rsc_id_submatches = old->match_data->re->pmatch;
  56             new->rsc_id_nmatches = old->match_data->re->nregs;
  57         }
  58     }
  59     if (old->op_data != NULL) {
  60         new->op_name = old->op_data->op_name;
  61         new->op_interval_ms = old->op_data->interval;
  62     }
  63 }
  64 
  65 static void
  66 populate_hash(xmlNode *nvpair_list, GHashTable *hash, bool overwrite)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68     if (pcmk__xe_is(nvpair_list->children, PCMK__XE_ATTRIBUTES)) {
  69         nvpair_list = nvpair_list->children;
  70     }
  71 
  72     for (xmlNode *nvpair = pcmk__xe_first_child(nvpair_list, PCMK_XE_NVPAIR,
  73                                                 NULL, NULL);
  74          nvpair != NULL; nvpair = pcmk__xe_next(nvpair, PCMK_XE_NVPAIR)) {
  75 
  76         xmlNode *ref_nvpair = pcmk__xe_resolve_idref(nvpair, NULL);
  77         const char *name = NULL;
  78         const char *value = NULL;
  79         const char *old_value = NULL;
  80 
  81         if (ref_nvpair == NULL) {
  82             /* Not possible with schema validation enabled (error already
  83              * logged)
  84              */
  85             continue;
  86         }
  87 
  88         name = crm_element_value(ref_nvpair, PCMK_XA_NAME);
  89         value = crm_element_value(ref_nvpair, PCMK_XA_VALUE);
  90         if ((name == NULL) || (value == NULL)) {
  91             continue;
  92         }
  93 
  94         old_value = g_hash_table_lookup(hash, name);
  95 
  96         if (pcmk__str_eq(value, "#default", pcmk__str_casei)) {
  97             // @COMPAT Deprecated since 2.1.8
  98             pcmk__config_warn("Support for setting meta-attributes (such as "
  99                               "%s) to the explicit value '#default' is "
 100                               "deprecated and will be removed in a future "
 101                               "release", name);
 102             if (old_value != NULL) {
 103                 crm_trace("Letting %s default (removing explicit value \"%s\")",
 104                           name, value);
 105                 g_hash_table_remove(hash, name);
 106             }
 107 
 108         } else if (old_value == NULL) {
 109             crm_trace("Setting %s=\"%s\"", name, value);
 110             pcmk__insert_dup(hash, name, value);
 111 
 112         } else if (overwrite) {
 113             crm_trace("Setting %s=\"%s\" (overwriting old value \"%s\")",
 114                       name, value, old_value);
 115             pcmk__insert_dup(hash, name, value);
 116         }
 117     }
 118 }
 119 
 120 static void
 121 unpack_attr_set(gpointer data, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123     xmlNode *pair = data;
 124     pcmk__nvpair_unpack_t *unpack_data = user_data;
 125 
 126     xmlNode *rule_xml = pcmk__xe_first_child(pair, PCMK_XE_RULE, NULL, NULL);
 127 
 128     if ((rule_xml != NULL)
 129         && (pcmk_evaluate_rule(rule_xml, &(unpack_data->rule_input),
 130                                unpack_data->next_change) != pcmk_rc_ok)) {
 131         return;
 132     }
 133 
 134     crm_trace("Adding name/value pairs from %s %s overwrite",
 135               pcmk__xe_id(pair), (unpack_data->overwrite? "with" : "without"));
 136     populate_hash(pair, unpack_data->values, unpack_data->overwrite);
 137 }
 138 
 139 /*!
 140  * \internal
 141  * \brief Create a sorted list of nvpair blocks
 142  *
 143  * \param[in]     xml_obj       XML element containing blocks of nvpair elements
 144  * \param[in]     set_name      If not NULL, only get blocks of this element
 145  *
 146  * \return List of XML blocks of name/value pairs
 147  */
 148 static GList *
 149 make_pairs(const xmlNode *xml_obj, const char *set_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151     GList *unsorted = NULL;
 152 
 153     if (xml_obj == NULL) {
 154         return NULL;
 155     }
 156     for (xmlNode *attr_set = pcmk__xe_first_child(xml_obj, NULL, NULL, NULL);
 157          attr_set != NULL; attr_set = pcmk__xe_next(attr_set, NULL)) {
 158 
 159         if ((set_name == NULL) || pcmk__xe_is(attr_set, set_name)) {
 160             xmlNode *expanded_attr_set = pcmk__xe_resolve_idref(attr_set, NULL);
 161 
 162             if (expanded_attr_set == NULL) {
 163                 continue; // Not possible with schema validation enabled
 164             }
 165             unsorted = g_list_prepend(unsorted, expanded_attr_set);
 166         }
 167     }
 168     return unsorted;
 169 }
 170 
 171 /*!
 172  * \brief Extract nvpair blocks contained by an XML element into a hash table
 173  *
 174  * \param[in,out] top           Ignored
 175  * \param[in]     xml_obj       XML element containing blocks of nvpair elements
 176  * \param[in]     set_name      If not NULL, only use blocks of this element
 177  * \param[in]     rule_data     Matching parameters to use when unpacking
 178  * \param[out]    hash          Where to store extracted name/value pairs
 179  * \param[in]     always_first  If not NULL, process block with this ID first
 180  * \param[in]     overwrite     Whether to replace existing values with same
 181  *                              name (all internal callers pass \c FALSE)
 182  * \param[out]    next_change   If not NULL, set to when evaluation will change
 183  */
 184 void
 185 pe_eval_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 186                 const pe_rule_eval_data_t *rule_data, GHashTable *hash,
 187                 const char *always_first, gboolean overwrite,
 188                 crm_time_t *next_change)
 189 {
 190     GList *pairs = make_pairs(xml_obj, set_name);
 191 
 192     if (pairs) {
 193         pcmk__nvpair_unpack_t data = {
 194             .values = hash,
 195             .first_id = always_first,
 196             .overwrite = overwrite,
 197             .next_change = next_change,
 198         };
 199 
 200         map_rule_input(&(data.rule_input), rule_data);
 201 
 202         pairs = g_list_sort_with_data(pairs, pcmk__cmp_nvpair_blocks, &data);
 203         g_list_foreach(pairs, unpack_attr_set, &data);
 204         g_list_free(pairs);
 205     }
 206 }
 207 
 208 /*!
 209  * \brief Extract nvpair blocks contained by an XML element into a hash table
 210  *
 211  * \param[in,out] top           Ignored
 212  * \param[in]     xml_obj       XML element containing blocks of nvpair elements
 213  * \param[in]     set_name      Element name to identify nvpair blocks
 214  * \param[in]     node_hash     Node attributes to use when evaluating rules
 215  * \param[out]    hash          Where to store extracted name/value pairs
 216  * \param[in]     always_first  If not NULL, process block with this ID first
 217  * \param[in]     overwrite     Whether to replace existing values with same
 218  *                              name (all internal callers pass \c FALSE)
 219  * \param[in]     now           Time to use when evaluating rules
 220  * \param[out]    next_change   If not NULL, set to when evaluation will change
 221  */
 222 void
 223 pe_unpack_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 224                   GHashTable *node_hash, GHashTable *hash,
 225                   const char *always_first, gboolean overwrite,
 226                   crm_time_t *now, crm_time_t *next_change)
 227 {
 228     pe_rule_eval_data_t rule_data = {
 229         .node_hash = node_hash,
 230         .now = now,
 231         .match_data = NULL,
 232         .rsc_data = NULL,
 233         .op_data = NULL
 234     };
 235 
 236     pe_eval_nvpairs(NULL, xml_obj, set_name, &rule_data, hash,
 237                     always_first, overwrite, next_change);
 238 }
 239 
 240 // Deprecated functions kept only for backward API compatibility
 241 // LCOV_EXCL_START
 242 
 243 #include <crm/pengine/rules_compat.h>
 244 
 245 gboolean
 246 test_rule(xmlNode * rule, GHashTable * node_hash, enum rsc_role_e role, crm_time_t * now)
     /* [previous][next][first][last][top][bottom][index][help] */
 247 {
 248     pcmk_rule_input_t rule_input = {
 249         .node_attrs = node_hash,
 250         .now = now,
 251     };
 252 
 253     return pcmk_evaluate_rule(rule, &rule_input, NULL) == pcmk_rc_ok;
 254 }
 255 
 256 // LCOV_EXCL_STOP
 257 // End deprecated API

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