Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F1841719
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/include/crm/common/xml_idref_internal.h b/include/crm/common/xml_idref_internal.h
index 58f1c1b9e3..29313f1353 100644
--- a/include/crm/common/xml_idref_internal.h
+++ b/include/crm/common/xml_idref_internal.h
@@ -1,26 +1,28 @@
/*
* Copyright 2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef PCMK__CRM_COMMON_XML_IDREF_INTERNAL__H
#define PCMK__CRM_COMMON_XML_IDREF_INTERNAL__H
#include <glib.h> // gboolean, gpointer, GList, GHashTable
#include <libxml/tree.h> // xmlNode
// An XML ID and references to it (used for tags and templates)
typedef struct {
char *id; // XML ID of primary element
GList *refs; // XML IDs of elements that reference the primary element
} pcmk__idref_t;
void pcmk__add_idref(GHashTable *table, const char *id, const char *referrer);
void pcmk__free_idref(gpointer data);
xmlNode *pcmk__xe_resolve_idref(xmlNode *xml, xmlNode *search);
+GList *pcmk__xe_dereference_children(const xmlNode *xml_obj,
+ const char *set_name);
#endif // PCMK__CRM_COMMON_XML_IDREF_INTERNAL__H
diff --git a/lib/common/xml_idref.c b/lib/common/xml_idref.c
index 2721b8bf7e..583018ceed 100644
--- a/lib/common/xml_idref.c
+++ b/lib/common/xml_idref.c
@@ -1,115 +1,147 @@
/*
* Copyright 2004-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <stdio.h> // NULL
#include <stdlib.h> // free()
#include <glib.h> // GList, GHashTable, etc.
#include <libxml/tree.h> // xmlNode
#include <crm/crm.h>
#include <crm/common/xml.h> // get_xpath_object(), PCMK_XA_ID_REF
/*!
* \internal
* \brief Add an XML ID reference to a table
*
* \param[in,out] table Table of ID references to add to
* \param[in] id ID of primary element being referred to
* \param[in] referrer ID of element referring to \p id
*
* \note This refers to an ID reference in general, not necessarily connected to
* an id-ref attribute.
*/
void
pcmk__add_idref(GHashTable *table, const char *id, const char *referrer)
{
pcmk__idref_t *idref = NULL;
pcmk__assert((table != NULL) && (id != NULL) && (referrer != NULL));
idref = g_hash_table_lookup(table, id);
if (idref == NULL) {
idref = pcmk__assert_alloc(1, sizeof(pcmk__idref_t));
idref->id = pcmk__str_copy(id);
g_hash_table_insert(table, pcmk__str_copy(id), idref);
}
for (GList *iter = idref->refs; iter != NULL; iter = iter->next) {
if (pcmk__str_eq(referrer, (const char *) iter->data,
pcmk__str_none)) {
return; // Already present
}
}
idref->refs = g_list_append(idref->refs, pcmk__str_copy(referrer));
crm_trace("Added ID %s referrer %s", id, referrer);
}
/*!
* \internal
* \brief Free a pcmk__idref_t
*
* \param[in,out] data pcmk__idref_t to free
*/
void
pcmk__free_idref(gpointer data)
{
pcmk__idref_t *idref = data;
if (idref != NULL) {
free(idref->id);
g_list_free_full(idref->refs, free);
free(idref);
}
}
/*!
* \internal
* \brief Get the XML element whose \c PCMK_XA_ID matches an \c PCMK_XA_ID_REF
*
* \param[in] xml Element whose \c PCMK_XA_ID_REF attribute to check
* \param[in] search Node whose document to search for node with matching
* \c PCMK_XA_ID (\c NULL to use \p xml)
*
* \return If \p xml has a \c PCMK_XA_ID_REF attribute, node in
* <tt>search</tt>'s document whose \c PCMK_XA_ID attribute matches;
* otherwise, \p xml
*/
xmlNode *
pcmk__xe_resolve_idref(xmlNode *xml, xmlNode *search)
{
char *xpath = NULL;
const char *ref = NULL;
xmlNode *result = NULL;
if (xml == NULL) {
return NULL;
}
ref = crm_element_value(xml, PCMK_XA_ID_REF);
if (ref == NULL) {
return xml;
}
if (search == NULL) {
search = xml;
}
xpath = crm_strdup_printf("//%s[@" PCMK_XA_ID "='%s']", xml->name, ref);
result = get_xpath_object(xpath, search, LOG_DEBUG);
if (result == NULL) {
// Not possible with schema validation enabled
pcmk__config_err("Ignoring invalid %s configuration: "
PCMK_XA_ID_REF " '%s' does not reference "
"a valid object " QB_XS " xpath=%s",
xml->name, ref, xpath);
}
free(xpath);
return result;
}
+
+/*!
+ * \internal
+ * \brief Get list of resolved ID references for child elements of given element
+ *
+ * \param[in] xml_obj XML element containing blocks of nvpair elements
+ * \param[in] set_name If not NULL, only get blocks of this element
+ *
+ * \return List of XML blocks of name/value pairs
+ */
+GList *
+pcmk__xe_dereference_children(const xmlNode *xml_obj, const char *set_name)
+{
+ GList *unsorted = NULL;
+
+ if (xml_obj == NULL) {
+ return NULL;
+ }
+ for (xmlNode *attr_set = pcmk__xe_first_child(xml_obj, NULL, NULL, NULL);
+ attr_set != NULL; attr_set = pcmk__xe_next(attr_set, NULL)) {
+
+ if ((set_name == NULL) || pcmk__xe_is(attr_set, set_name)) {
+ xmlNode *expanded_attr_set = pcmk__xe_resolve_idref(attr_set, NULL);
+
+ if (expanded_attr_set == NULL) {
+ continue; // Not possible with schema validation enabled
+ }
+ unsorted = g_list_prepend(unsorted, expanded_attr_set);
+ }
+ }
+ return unsorted;
+}
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
index a01d42f9c9..6a46c1c032 100644
--- a/lib/pengine/rules.c
+++ b/lib/pengine/rules.c
@@ -1,257 +1,225 @@
/*
* Copyright 2004-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <glib.h>
#include <crm/crm.h>
#include <crm/common/xml.h>
#include <crm/pengine/rules.h>
#include <crm/common/iso8601_internal.h>
#include <crm/common/nvpair_internal.h>
#include <crm/common/rules_internal.h>
#include <crm/common/xml_internal.h>
#include <crm/pengine/internal.h>
#include <crm/pengine/rules_internal.h>
#include <sys/types.h>
#include <regex.h>
CRM_TRACE_INIT_DATA(pe_rules);
/*!
* \internal
* \brief Map pe_rule_eval_data_t to pcmk_rule_input_t
*
* \param[out] new New data struct
* \param[in] old Old data struct
*/
static void
map_rule_input(pcmk_rule_input_t *new, const pe_rule_eval_data_t *old)
{
if (old == NULL) {
return;
}
new->now = old->now;
new->node_attrs = old->node_hash;
if (old->rsc_data != NULL) {
new->rsc_standard = old->rsc_data->standard;
new->rsc_provider = old->rsc_data->provider;
new->rsc_agent = old->rsc_data->agent;
}
if (old->match_data != NULL) {
new->rsc_params = old->match_data->params;
new->rsc_meta = old->match_data->meta;
if (old->match_data->re != NULL) {
new->rsc_id = old->match_data->re->string;
new->rsc_id_submatches = old->match_data->re->pmatch;
new->rsc_id_nmatches = old->match_data->re->nregs;
}
}
if (old->op_data != NULL) {
new->op_name = old->op_data->op_name;
new->op_interval_ms = old->op_data->interval;
}
}
static void
populate_hash(xmlNode *nvpair_list, GHashTable *hash, bool overwrite)
{
if (pcmk__xe_is(nvpair_list->children, PCMK__XE_ATTRIBUTES)) {
nvpair_list = nvpair_list->children;
}
for (xmlNode *nvpair = pcmk__xe_first_child(nvpair_list, PCMK_XE_NVPAIR,
NULL, NULL);
nvpair != NULL; nvpair = pcmk__xe_next(nvpair, PCMK_XE_NVPAIR)) {
xmlNode *ref_nvpair = pcmk__xe_resolve_idref(nvpair, NULL);
const char *name = NULL;
const char *value = NULL;
const char *old_value = NULL;
if (ref_nvpair == NULL) {
/* Not possible with schema validation enabled (error already
* logged)
*/
continue;
}
name = crm_element_value(ref_nvpair, PCMK_XA_NAME);
value = crm_element_value(ref_nvpair, PCMK_XA_VALUE);
if ((name == NULL) || (value == NULL)) {
continue;
}
old_value = g_hash_table_lookup(hash, name);
if (pcmk__str_eq(value, "#default", pcmk__str_casei)) {
// @COMPAT Deprecated since 2.1.8
pcmk__config_warn("Support for setting meta-attributes (such as "
"%s) to the explicit value '#default' is "
"deprecated and will be removed in a future "
"release", name);
if (old_value != NULL) {
crm_trace("Letting %s default (removing explicit value \"%s\")",
name, value);
g_hash_table_remove(hash, name);
}
} else if (old_value == NULL) {
crm_trace("Setting %s=\"%s\"", name, value);
pcmk__insert_dup(hash, name, value);
} else if (overwrite) {
crm_trace("Setting %s=\"%s\" (overwriting old value \"%s\")",
name, value, old_value);
pcmk__insert_dup(hash, name, value);
}
}
}
static void
unpack_attr_set(gpointer data, gpointer user_data)
{
xmlNode *pair = data;
pcmk__nvpair_unpack_t *unpack_data = user_data;
xmlNode *rule_xml = pcmk__xe_first_child(pair, PCMK_XE_RULE, NULL, NULL);
if ((rule_xml != NULL)
&& (pcmk_evaluate_rule(rule_xml, &(unpack_data->rule_input),
unpack_data->next_change) != pcmk_rc_ok)) {
return;
}
crm_trace("Adding name/value pairs from %s %s overwrite",
pcmk__xe_id(pair), (unpack_data->overwrite? "with" : "without"));
populate_hash(pair, unpack_data->values, unpack_data->overwrite);
}
-/*!
- * \internal
- * \brief Create a sorted list of nvpair blocks
- *
- * \param[in] xml_obj XML element containing blocks of nvpair elements
- * \param[in] set_name If not NULL, only get blocks of this element
- *
- * \return List of XML blocks of name/value pairs
- */
-static GList *
-make_pairs(const xmlNode *xml_obj, const char *set_name)
-{
- GList *unsorted = NULL;
-
- if (xml_obj == NULL) {
- return NULL;
- }
- for (xmlNode *attr_set = pcmk__xe_first_child(xml_obj, NULL, NULL, NULL);
- attr_set != NULL; attr_set = pcmk__xe_next(attr_set, NULL)) {
-
- if ((set_name == NULL) || pcmk__xe_is(attr_set, set_name)) {
- xmlNode *expanded_attr_set = pcmk__xe_resolve_idref(attr_set, NULL);
-
- if (expanded_attr_set == NULL) {
- continue; // Not possible with schema validation enabled
- }
- unsorted = g_list_prepend(unsorted, expanded_attr_set);
- }
- }
- return unsorted;
-}
-
/*!
* \brief Extract nvpair blocks contained by an XML element into a hash table
*
* \param[in,out] top Ignored
* \param[in] xml_obj XML element containing blocks of nvpair elements
* \param[in] set_name If not NULL, only use blocks of this element
* \param[in] rule_data Matching parameters to use when unpacking
* \param[out] hash Where to store extracted name/value pairs
* \param[in] always_first If not NULL, process block with this ID first
* \param[in] overwrite Whether to replace existing values with same
* name (all internal callers pass \c FALSE)
* \param[out] next_change If not NULL, set to when evaluation will change
*/
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)
{
- GList *pairs = make_pairs(xml_obj, set_name);
+ GList *pairs = pcmk__xe_dereference_children(xml_obj, set_name);
if (pairs) {
pcmk__nvpair_unpack_t data = {
.values = hash,
.first_id = always_first,
.overwrite = overwrite,
.next_change = next_change,
};
map_rule_input(&(data.rule_input), rule_data);
pairs = g_list_sort_with_data(pairs, pcmk__cmp_nvpair_blocks, &data);
g_list_foreach(pairs, unpack_attr_set, &data);
g_list_free(pairs);
}
}
/*!
* \brief Extract nvpair blocks contained by an XML element into a hash table
*
* \param[in,out] top Ignored
* \param[in] xml_obj XML element containing blocks of nvpair elements
* \param[in] set_name Element name to identify nvpair blocks
* \param[in] node_hash Node attributes to use when evaluating rules
* \param[out] hash Where to store extracted name/value pairs
* \param[in] always_first If not NULL, process block with this ID first
* \param[in] overwrite Whether to replace existing values with same
* name (all internal callers pass \c FALSE)
* \param[in] now Time to use when evaluating rules
* \param[out] next_change If not NULL, set to when evaluation will change
*/
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)
{
pe_rule_eval_data_t rule_data = {
.node_hash = node_hash,
.now = now,
.match_data = NULL,
.rsc_data = NULL,
.op_data = NULL
};
pe_eval_nvpairs(NULL, xml_obj, set_name, &rule_data, hash,
always_first, overwrite, next_change);
}
// Deprecated functions kept only for backward API compatibility
// LCOV_EXCL_START
#include <crm/pengine/rules_compat.h>
gboolean
test_rule(xmlNode * rule, GHashTable * node_hash, enum rsc_role_e role, crm_time_t * now)
{
pcmk_rule_input_t rule_input = {
.node_attrs = node_hash,
.now = now,
};
return pcmk_evaluate_rule(rule, &rule_input, NULL) == pcmk_rc_ok;
}
// LCOV_EXCL_STOP
// End deprecated API
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 23, 7:23 AM (16 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018395
Default Alt Text
(14 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment