pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
rules.c
Go to the documentation of this file.
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 
22 #include <crm/pengine/internal.h>
24 
25 #include <sys/types.h>
26 #include <regex.h>
27 
28 CRM_TRACE_INIT_DATA(pe_rules);
29 
37 static void
38 map_rule_input(pcmk_rule_input_t *new, const pe_rule_eval_data_t *old)
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)
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)
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 
148 static GList *
149 make_pairs(const xmlNode *xml_obj, const char *set_name)
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 
184 void
185 pe_eval_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name,
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) {
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 
222 void
223 pe_unpack_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name,
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 
244 
245 gboolean
246 test_rule(xmlNode * rule, GHashTable * node_hash, enum rsc_role_e role, crm_time_t * now)
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
void pe_unpack_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now, crm_time_t *next_change)
Extract nvpair blocks contained by an XML element into a hash table.
Definition: rules.c:223
xmlNode * pcmk__xe_resolve_idref(xmlNode *xml, xmlNode *search)
Definition: xml_idref.c:85
A dumping ground.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml_element.c:42
#define PCMK_XE_NVPAIR
Definition: xml_names.h:144
int pcmk_evaluate_rule(xmlNode *rule, const pcmk_rule_input_t *rule_input, crm_time_t *next_change)
Evaluate a single rule, including all its conditions.
Definition: rules.c:1303
const char * provider
Definition: common.h:36
#define PCMK_XA_NAME
Definition: xml_names.h:330
Deprecated Pacemaker rule API.
char data[0]
Definition: cpg.c:58
Data used to evaluate a rule (any NULL items are ignored)
Definition: rules.h:57
const char * name
Definition: cib.c:26
struct crm_time_s crm_time_t
Definition: iso8601.h:32
#define pcmk__config_warn(fmt...)
pe_re_match_data_t * re
Definition: common.h:29
#define PCMK__XE_ATTRIBUTES
CRM_TRACE_INIT_DATA(pe_rules)
gint pcmk__cmp_nvpair_blocks(gconstpointer a, gconstpointer b, gpointer user_data)
Definition: nvpair.c:464
guint interval
Definition: common.h:42
pe_match_data_t * match_data
Definition: common.h:49
pe_op_eval_data_t * op_data
Definition: common.h:51
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: xml_element.c:1168
#define crm_trace(fmt, args...)
Definition: logging.h:372
const char * op_name
Definition: common.h:41
gboolean test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now)
Definition: rules.c:246
Wrappers for and extensions to libxml2.
rsc_role_e
Definition: roles.h:34
GHashTable * values
GHashTable * meta
Definition: common.h:31
#define PCMK_XA_VALUE
Definition: xml_names.h:442
pe_rsc_eval_data_t * rsc_data
Definition: common.h:50
#define PCMK_XE_RULE
Definition: xml_names.h:191
const char * agent
Definition: common.h:37
void populate_hash(xmlNode *nvpair_list, GHashTable *hash, const char **attrs, int attrs_length)
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
Definition: xml_element.c:106
GHashTable * params
Definition: common.h:30
const char * standard
Definition: common.h:35
crm_time_t * now
Definition: common.h:48
crm_time_t * next_change
GHashTable * node_hash
Definition: common.h:46
regmatch_t * pmatch
Definition: common.h:25
GHashTable * node_attrs
Definition: rules.h:77
pcmk_rule_input_t rule_input
void pe_eval_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name, const pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *next_change)
Extract nvpair blocks contained by an XML element into a hash table.
Definition: rules.c:185
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:703
char * string
Definition: common.h:23