Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3687153
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/include/crm/pengine/rules_compat.h b/include/crm/pengine/rules_compat.h
index c329c84313..4630e8cdb7 100644
--- a/include/crm/pengine/rules_compat.h
+++ b/include/crm/pengine/rules_compat.h
@@ -1,103 +1,100 @@
/*
* 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.
*/
#ifndef PCMK__CRM_PENGINE_RULES_COMPAT__H
# define PCMK__CRM_PENGINE_RULES_COMPAT__H
#include <glib.h>
#include <libxml/tree.h> // xmlNode
#include <crm/common/iso8601.h> // crm_time_t
#include <crm/pengine/pe_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file
* \brief Deprecated Pacemaker rule API
* \ingroup pengine
* \deprecated Do not include this header directly. The rule APIs in this
* header, and the header itself, will be removed in a future
* release.
*/
//! \deprecated Use pcmk_evaluate_rule() on each rule instead
gboolean pe_evaluate_rules(xmlNode *ruleset, GHashTable *node_hash,
crm_time_t *now, crm_time_t *next_change);
//! \deprecated Use pcmk_evaluate_rule() on each rule instead
gboolean pe_eval_rules(xmlNode *ruleset, const pe_rule_eval_data_t *rule_data,
crm_time_t *next_change);
//! \deprecated Use pcmk_evaluate_rule() on each rule instead
gboolean test_ruleset(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now);
// @COMPAT sbd's configure script checks for this (as of at least 1.5.2)
//! \deprecated Use pcmk_evaluate_rule() instead
gboolean test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role,
crm_time_t *now);
//! \deprecated Use pcmk_evaluate_rule() instead
gboolean pe_test_rule(xmlNode *rule, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now,
crm_time_t *next_change, pe_match_data_t *match_data);
//! \deprecated Use pcmk_evaluate_rule() instead
gboolean pe_test_rule_re(xmlNode *rule, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now,
pe_re_match_data_t *re_match_data);
//! \deprecated Use pcmk_evaluate_rule() instead
gboolean pe_test_rule_full(xmlNode *rule, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now,
pe_match_data_t *match_data);
//! \deprecated Use pcmk_evaluate_rule() on parent rule instead
gboolean pe_test_expression(xmlNode *expr, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now,
crm_time_t *next_change,
pe_match_data_t *match_data);
//! \deprecated Use pcmk_evaluate_rule() on parent rule instead
gboolean test_expression(xmlNode *expr, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now);
//! \deprecated Use pcmk_evaluate_rule() on parent rule instead
gboolean pe_test_expression_re(xmlNode *expr, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now,
pe_re_match_data_t *re_match_data);
//! \deprecated Use pcmk_evaluate_rule() on parent rule instead
gboolean pe_test_expression_full(xmlNode *expr, GHashTable *node_hash,
enum rsc_role_e role,
crm_time_t *now, pe_match_data_t *match_data);
//! \deprecated Use pcmk_evaluate_rule() on parent rule instead
gboolean pe_eval_expr(xmlNode *rule, const pe_rule_eval_data_t *rule_data,
crm_time_t *next_change);
//! \deprecated Use pcmk_evaluate_rule() on parent rule instead
gboolean pe_eval_subexpr(xmlNode *expr, const pe_rule_eval_data_t *rule_data,
crm_time_t *next_change);
//! \deprecated Use pe_unpack_nvpairs() instead
void unpack_instance_attributes(xmlNode *top, xmlNode *xml_obj,
const char *set_name, GHashTable *node_hash,
GHashTable *hash, const char *always_first,
gboolean overwrite, crm_time_t *now);
-//! \deprecated Do not use
-enum expression_type find_expression_type(xmlNode *expr);
-
#ifdef __cplusplus
}
#endif
#endif // PCMK__CRM_PENGINE_RULES_COMPAT__H
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
index 2ba9a8fe46..f542d438d1 100644
--- a/lib/pengine/rules.c
+++ b/lib/pengine/rules.c
@@ -1,461 +1,455 @@
/*
* 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 gint
sort_pairs(gconstpointer a, gconstpointer b, gpointer user_data)
{
const xmlNode *pair_a = a;
const xmlNode *pair_b = b;
pcmk__nvpair_unpack_t *unpack_data = user_data;
const char *score = NULL;
int score_a = 0;
int score_b = 0;
if (a == NULL && b == NULL) {
return 0;
} else if (a == NULL) {
return 1;
} else if (b == NULL) {
return -1;
}
if (pcmk__str_eq(pcmk__xe_id(pair_a), unpack_data->first_id,
pcmk__str_none)) {
return -1;
} else if (pcmk__str_eq(pcmk__xe_id(pair_b), unpack_data->first_id,
pcmk__str_none)) {
return 1;
}
score = crm_element_value(pair_a, PCMK_XA_SCORE);
score_a = char2score(score);
score = crm_element_value(pair_b, PCMK_XA_SCORE);
score_b = char2score(score);
/* If we're overwriting values, we want lowest score first, so the highest
* score is processed last; if we're not overwriting values, we want highest
* score first, so nothing else overwrites it.
*/
if (score_a < score_b) {
return unpack_data->overwrite? -1 : 1;
} else if (score_a > score_b) {
return unpack_data->overwrite? 1 : -1;
}
return 0;
}
static void
populate_hash(xmlNode *nvpair_list, GHashTable *hash, bool overwrite)
{
const char *name = NULL;
const char *value = NULL;
const char *old_value = NULL;
xmlNode *list = nvpair_list;
xmlNode *an_attr = NULL;
if (pcmk__xe_is(list->children, PCMK__XE_ATTRIBUTES)) {
list = list->children;
}
for (an_attr = pcmk__xe_first_child(list, NULL, NULL, NULL);
an_attr != NULL; an_attr = pcmk__xe_next(an_attr)) {
if (pcmk__xe_is(an_attr, PCMK_XE_NVPAIR)) {
xmlNode *ref_nvpair = expand_idref(an_attr, NULL);
name = crm_element_value(an_attr, PCMK_XA_NAME);
if ((name == NULL) && (ref_nvpair != NULL)) {
name = crm_element_value(ref_nvpair, PCMK_XA_NAME);
}
value = crm_element_value(an_attr, PCMK_XA_VALUE);
if ((value == NULL) && (ref_nvpair != NULL)) {
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) {
crm_trace("Letting %s default (removing explicit value \"%s\")",
name, value);
g_hash_table_remove(hash, name);
}
continue;
} 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;
if (pcmk__evaluate_rules(pair, &(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)) {
if ((set_name == NULL) || pcmk__xe_is(attr_set, set_name)) {
xmlNode *expanded_attr_set = expand_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
* \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);
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, sort_pairs, &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
* \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
pe_eval_rules(xmlNode *ruleset, const pe_rule_eval_data_t *rule_data,
crm_time_t *next_change)
{
pcmk_rule_input_t rule_input = { NULL, };
map_rule_input(&rule_input, rule_data);
return pcmk__evaluate_rules(ruleset, &rule_input,
next_change) == pcmk_rc_ok;
}
gboolean
pe_evaluate_rules(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now,
crm_time_t *next_change)
{
pcmk_rule_input_t rule_input = {
.node_attrs = node_hash,
.now = now,
};
return pcmk__evaluate_rules(ruleset, &rule_input, next_change);
}
gboolean
pe_test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role,
crm_time_t *now, crm_time_t *next_change,
pe_match_data_t *match_data)
{
pcmk_rule_input_t rule_input = {
.node_attrs = node_hash,
.now = now,
};
if (match_data != NULL) {
rule_input.rsc_params = match_data->params;
rule_input.rsc_meta = match_data->meta;
if (match_data->re != NULL) {
rule_input.rsc_id = match_data->re->string;
rule_input.rsc_id_submatches = match_data->re->pmatch;
rule_input.rsc_id_nmatches = match_data->re->nregs;
}
}
return pcmk_evaluate_rule(rule, &rule_input, next_change) == pcmk_rc_ok;
}
gboolean
test_ruleset(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now)
{
return pe_evaluate_rules(ruleset, node_hash, now, NULL);
}
gboolean
test_rule(xmlNode * rule, GHashTable * node_hash, enum rsc_role_e role, crm_time_t * now)
{
return pe_test_rule(rule, node_hash, role, now, NULL, NULL);
}
gboolean
pe_test_rule_re(xmlNode * rule, GHashTable * node_hash, enum rsc_role_e role, crm_time_t * now, pe_re_match_data_t * re_match_data)
{
pe_match_data_t match_data = {
.re = re_match_data,
.params = NULL,
.meta = NULL,
};
return pe_test_rule(rule, node_hash, role, now, NULL, &match_data);
}
gboolean
pe_test_rule_full(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role,
crm_time_t *now, pe_match_data_t *match_data)
{
return pe_test_rule(rule, node_hash, role, now, NULL, match_data);
}
gboolean
pe_test_expression(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role,
crm_time_t *now, crm_time_t *next_change,
pe_match_data_t *match_data)
{
pcmk_rule_input_t rule_input = {
.now = now,
.node_attrs = node_hash,
};
if (match_data != NULL) {
rule_input.rsc_params = match_data->params;
rule_input.rsc_meta = match_data->meta;
if (match_data->re != NULL) {
rule_input.rsc_id = match_data->re->string;
rule_input.rsc_id_submatches = match_data->re->pmatch;
rule_input.rsc_id_nmatches = match_data->re->nregs;
}
}
return pcmk__evaluate_condition(expr, &rule_input,
next_change) == pcmk_rc_ok;
}
gboolean
test_expression(xmlNode * expr, GHashTable * node_hash, enum rsc_role_e role, crm_time_t * now)
{
return pe_test_expression(expr, node_hash, role, now, NULL, NULL);
}
gboolean
pe_test_expression_re(xmlNode * expr, GHashTable * node_hash, enum rsc_role_e role, crm_time_t * now, pe_re_match_data_t * re_match_data)
{
pe_match_data_t match_data = {
.re = re_match_data,
.params = NULL,
.meta = NULL,
};
return pe_test_expression(expr, node_hash, role, now, NULL, &match_data);
}
gboolean
pe_test_expression_full(xmlNode *expr, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now,
pe_match_data_t *match_data)
{
return pe_test_expression(expr, node_hash, role, now, NULL, match_data);
}
gboolean
pe_eval_expr(xmlNode *rule, const pe_rule_eval_data_t *rule_data,
crm_time_t *next_change)
{
pcmk_rule_input_t rule_input = { NULL, };
map_rule_input(&rule_input, rule_data);
return pcmk_evaluate_rule(rule, &rule_input, next_change) == pcmk_rc_ok;
}
gboolean
pe_eval_subexpr(xmlNode *expr, const pe_rule_eval_data_t *rule_data,
crm_time_t *next_change)
{
pcmk_rule_input_t rule_input = { NULL, };
map_rule_input(&rule_input, rule_data);
return pcmk__evaluate_condition(expr, &rule_input,
next_change) == pcmk_rc_ok;
}
void
unpack_instance_attributes(xmlNode *top, xmlNode *xml_obj, const char *set_name,
GHashTable *node_hash, GHashTable *hash,
const char *always_first, gboolean overwrite,
crm_time_t *now)
{
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, NULL);
}
-enum expression_type
-find_expression_type(xmlNode *expr)
-{
- return pcmk__condition_type(expr);
-}
-
// LCOV_EXCL_STOP
// End deprecated API
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Apr 21, 7:02 PM (20 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1665304
Default Alt Text
(19 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment