1530 lines
59 KiB
Diff
1530 lines
59 KiB
Diff
|
From 08ce507927ff497b0e8f125050f67d59c74d674c Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 19 Nov 2020 15:52:14 -0600
|
||
|
Subject: [PATCH 01/12] Refactor: libpe_rules: functionize value-source
|
||
|
expansion
|
||
|
|
||
|
... for readability
|
||
|
---
|
||
|
lib/pengine/rules.c | 61 +++++++++++++++++++++++++++++++----------------------
|
||
|
1 file changed, 36 insertions(+), 25 deletions(-)
|
||
|
|
||
|
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
|
||
|
index e5d452f..aa5d6ab 100644
|
||
|
--- a/lib/pengine/rules.c
|
||
|
+++ b/lib/pengine/rules.c
|
||
|
@@ -1027,6 +1027,36 @@ accept_attr_expr(const char *l_val, const char *r_val, const char *type,
|
||
|
|
||
|
/*!
|
||
|
* \internal
|
||
|
+ * \brief Get correct value according to value-source
|
||
|
+ *
|
||
|
+ * \param[in] value value given in rule expression
|
||
|
+ * \param[in] value_source value-source given in rule expressions
|
||
|
+ * \param[in] match_data If not NULL, resource back-references and params
|
||
|
+ */
|
||
|
+static const char *
|
||
|
+expand_value_source(const char *value, const char *value_source,
|
||
|
+ pe_match_data_t *match_data)
|
||
|
+{
|
||
|
+ GHashTable *table = NULL;
|
||
|
+
|
||
|
+ if (pcmk__str_eq(value_source, "param", pcmk__str_casei)) {
|
||
|
+ table = match_data->params;
|
||
|
+
|
||
|
+ } else if (pcmk__str_eq(value_source, "meta", pcmk__str_casei)) {
|
||
|
+ table = match_data->meta;
|
||
|
+
|
||
|
+ } else { // literal
|
||
|
+ return value;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ((table == NULL) || pcmk__str_empty(value)) {
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ return (const char *) g_hash_table_lookup(table, value);
|
||
|
+}
|
||
|
+
|
||
|
+/*!
|
||
|
+ * \internal
|
||
|
* \brief Evaluate a node attribute expression based on #uname, #id, #kind,
|
||
|
* or a generic node attribute
|
||
|
*
|
||
|
@@ -1040,8 +1070,6 @@ pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
|
||
|
{
|
||
|
gboolean attr_allocated = FALSE;
|
||
|
const char *h_val = NULL;
|
||
|
- GHashTable *table = NULL;
|
||
|
- bool literal = true;
|
||
|
|
||
|
const char *op = NULL;
|
||
|
const char *type = NULL;
|
||
|
@@ -1061,36 +1089,19 @@ pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
- if (rule_data->match_data) {
|
||
|
- if (rule_data->match_data->re) {
|
||
|
+ if (rule_data->match_data != NULL) {
|
||
|
+ // Expand any regular expression submatches (%0-%9) in attribute name
|
||
|
+ if (rule_data->match_data->re != NULL) {
|
||
|
char *resolved_attr = pe_expand_re_matches(attr, rule_data->match_data->re);
|
||
|
|
||
|
- if (resolved_attr) {
|
||
|
+ if (resolved_attr != NULL) {
|
||
|
attr = (const char *) resolved_attr;
|
||
|
attr_allocated = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- if (pcmk__str_eq(value_source, "param", pcmk__str_casei)) {
|
||
|
- literal = false;
|
||
|
- table = rule_data->match_data->params;
|
||
|
- } else if (pcmk__str_eq(value_source, "meta", pcmk__str_casei)) {
|
||
|
- literal = false;
|
||
|
- table = rule_data->match_data->meta;
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- if (!literal) {
|
||
|
- const char *param_name = value;
|
||
|
- const char *param_value = NULL;
|
||
|
-
|
||
|
- value = NULL;
|
||
|
- if ((table != NULL) && !pcmk__str_empty(param_name)) {
|
||
|
- param_value = (const char *)g_hash_table_lookup(table, param_name);
|
||
|
- if (param_value != NULL) {
|
||
|
- value = param_value;
|
||
|
- }
|
||
|
- }
|
||
|
+ // Get value appropriate to value-source
|
||
|
+ value = expand_value_source(value, value_source, rule_data->match_data);
|
||
|
}
|
||
|
|
||
|
if (rule_data->node_hash != NULL) {
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From 8864e8596cc44fa275f68d58fea9b7d3d5236106 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 19 Nov 2020 11:59:05 -0600
|
||
|
Subject: [PATCH 02/12] Refactor: libcrmcommon: expose "first XML attribute"
|
||
|
function
|
||
|
|
||
|
... for future reuse. Also, rename to reflect that only XML element nodes may
|
||
|
have attributes.
|
||
|
---
|
||
|
include/crm/common/xml_internal.h | 14 +++++++
|
||
|
lib/common/crmcommon_private.h | 6 ---
|
||
|
lib/common/nvpair.c | 4 +-
|
||
|
lib/common/patchset.c | 20 +++++-----
|
||
|
lib/common/xml.c | 81 +++++++++++++++++----------------------
|
||
|
5 files changed, 61 insertions(+), 64 deletions(-)
|
||
|
|
||
|
diff --git a/include/crm/common/xml_internal.h b/include/crm/common/xml_internal.h
|
||
|
index 13157c6..b2ff529 100644
|
||
|
--- a/include/crm/common/xml_internal.h
|
||
|
+++ b/include/crm/common/xml_internal.h
|
||
|
@@ -255,4 +255,18 @@ void
|
||
|
pcmk__xe_set_props(xmlNodePtr node, ...)
|
||
|
G_GNUC_NULL_TERMINATED;
|
||
|
|
||
|
+/*!
|
||
|
+ * \internal
|
||
|
+ * \brief Get first attribute of an XML element
|
||
|
+ *
|
||
|
+ * \param[in] xe XML element to check
|
||
|
+ *
|
||
|
+ * \return First attribute of \p xe (or NULL if \p xe is NULL or has none)
|
||
|
+ */
|
||
|
+static inline xmlAttr *
|
||
|
+pcmk__xe_first_attr(const xmlNode *xe)
|
||
|
+{
|
||
|
+ return (xe == NULL)? NULL : xe->properties;
|
||
|
+}
|
||
|
+
|
||
|
#endif // PCMK__XML_INTERNAL__H
|
||
|
diff --git a/lib/common/crmcommon_private.h b/lib/common/crmcommon_private.h
|
||
|
index 1654cba..c2f334d 100644
|
||
|
--- a/lib/common/crmcommon_private.h
|
||
|
+++ b/lib/common/crmcommon_private.h
|
||
|
@@ -141,12 +141,6 @@ void pcmk__mark_xml_attr_dirty(xmlAttr *a);
|
||
|
G_GNUC_INTERNAL
|
||
|
bool pcmk__xa_filterable(const char *name);
|
||
|
|
||
|
-static inline xmlAttr *
|
||
|
-pcmk__first_xml_attr(const xmlNode *xml)
|
||
|
-{
|
||
|
- return xml? xml->properties : NULL;
|
||
|
-}
|
||
|
-
|
||
|
static inline const char *
|
||
|
pcmk__xml_attr_value(const xmlAttr *attr)
|
||
|
{
|
||
|
diff --git a/lib/common/nvpair.c b/lib/common/nvpair.c
|
||
|
index 0ed7a7d..9bd87af 100644
|
||
|
--- a/lib/common/nvpair.c
|
||
|
+++ b/lib/common/nvpair.c
|
||
|
@@ -163,7 +163,7 @@ pcmk_xml_attrs2nvpairs(xmlNode *xml)
|
||
|
{
|
||
|
GSList *result = NULL;
|
||
|
|
||
|
- for (xmlAttrPtr iter = pcmk__first_xml_attr(xml); iter != NULL;
|
||
|
+ for (xmlAttrPtr iter = pcmk__xe_first_attr(xml); iter != NULL;
|
||
|
iter = iter->next) {
|
||
|
|
||
|
result = pcmk_prepend_nvpair(result,
|
||
|
@@ -925,7 +925,7 @@ xml2list(xmlNode *parent)
|
||
|
|
||
|
crm_log_xml_trace(nvpair_list, "Unpacking");
|
||
|
|
||
|
- for (pIter = pcmk__first_xml_attr(nvpair_list); pIter != NULL;
|
||
|
+ for (pIter = pcmk__xe_first_attr(nvpair_list); pIter != NULL;
|
||
|
pIter = pIter->next) {
|
||
|
|
||
|
const char *p_name = (const char *)pIter->name;
|
||
|
diff --git a/lib/common/patchset.c b/lib/common/patchset.c
|
||
|
index f3dab03..15cbe07 100644
|
||
|
--- a/lib/common/patchset.c
|
||
|
+++ b/lib/common/patchset.c
|
||
|
@@ -112,7 +112,7 @@ add_xml_changes_to_patchset(xmlNode *xml, xmlNode *patchset)
|
||
|
}
|
||
|
|
||
|
// Check each of the XML node's attributes for changes
|
||
|
- for (pIter = pcmk__first_xml_attr(xml); pIter != NULL;
|
||
|
+ for (pIter = pcmk__xe_first_attr(xml); pIter != NULL;
|
||
|
pIter = pIter->next) {
|
||
|
xmlNode *attr = NULL;
|
||
|
|
||
|
@@ -156,7 +156,7 @@ add_xml_changes_to_patchset(xmlNode *xml, xmlNode *patchset)
|
||
|
change = create_xml_node(change->parent, XML_DIFF_RESULT);
|
||
|
result = create_xml_node(change, (const char *)xml->name);
|
||
|
|
||
|
- for (pIter = pcmk__first_xml_attr(xml); pIter != NULL;
|
||
|
+ for (pIter = pcmk__xe_first_attr(xml); pIter != NULL;
|
||
|
pIter = pIter->next) {
|
||
|
p = pIter->_private;
|
||
|
if (!pcmk_is_set(p->flags, xpf_deleted)) {
|
||
|
@@ -677,7 +677,7 @@ process_v1_removals(xmlNode *target, xmlNode *patch)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- for (xIter = pcmk__first_xml_attr(patch); xIter != NULL;
|
||
|
+ for (xIter = pcmk__xe_first_attr(patch); xIter != NULL;
|
||
|
xIter = xIter->next) {
|
||
|
const char *p_name = (const char *)xIter->name;
|
||
|
|
||
|
@@ -745,7 +745,7 @@ process_v1_additions(xmlNode *parent, xmlNode *target, xmlNode *patch)
|
||
|
return);
|
||
|
CRM_CHECK(pcmk__str_eq(ID(target), ID(patch), pcmk__str_casei), return);
|
||
|
|
||
|
- for (xIter = pcmk__first_xml_attr(patch); xIter != NULL;
|
||
|
+ for (xIter = pcmk__xe_first_attr(patch); xIter != NULL;
|
||
|
xIter = xIter->next) {
|
||
|
const char *p_name = (const char *) xIter->name;
|
||
|
const char *p_value = crm_element_value(patch, p_name);
|
||
|
@@ -1204,7 +1204,7 @@ apply_v2_patchset(xmlNode *xml, xmlNode *patchset)
|
||
|
free_xml(match);
|
||
|
|
||
|
} else if (strcmp(op, "modify") == 0) {
|
||
|
- xmlAttr *pIter = pcmk__first_xml_attr(match);
|
||
|
+ xmlAttr *pIter = pcmk__xe_first_attr(match);
|
||
|
xmlNode *attrs = NULL;
|
||
|
|
||
|
attrs = pcmk__xml_first_child(first_named_child(change,
|
||
|
@@ -1220,7 +1220,7 @@ apply_v2_patchset(xmlNode *xml, xmlNode *patchset)
|
||
|
xml_remove_prop(match, name);
|
||
|
}
|
||
|
|
||
|
- for (pIter = pcmk__first_xml_attr(attrs); pIter != NULL;
|
||
|
+ for (pIter = pcmk__xe_first_attr(attrs); pIter != NULL;
|
||
|
pIter = pIter->next) {
|
||
|
const char *name = (const char *) pIter->name;
|
||
|
const char *value = crm_element_value(attrs, name);
|
||
|
@@ -1553,7 +1553,7 @@ subtract_xml_object(xmlNode *parent, xmlNode *left, xmlNode *right,
|
||
|
} else if (full) {
|
||
|
xmlAttrPtr pIter = NULL;
|
||
|
|
||
|
- for (pIter = pcmk__first_xml_attr(left); pIter != NULL;
|
||
|
+ for (pIter = pcmk__xe_first_attr(left); pIter != NULL;
|
||
|
pIter = pIter->next) {
|
||
|
const char *p_name = (const char *)pIter->name;
|
||
|
const char *p_value = pcmk__xml_attr_value(pIter);
|
||
|
@@ -1566,7 +1566,7 @@ subtract_xml_object(xmlNode *parent, xmlNode *left, xmlNode *right,
|
||
|
}
|
||
|
|
||
|
// Changes to name/value pairs
|
||
|
- for (xIter = pcmk__first_xml_attr(left); xIter != NULL;
|
||
|
+ for (xIter = pcmk__xe_first_attr(left); xIter != NULL;
|
||
|
xIter = xIter->next) {
|
||
|
const char *prop_name = (const char *) xIter->name;
|
||
|
xmlAttrPtr right_attr = NULL;
|
||
|
@@ -1594,7 +1594,7 @@ subtract_xml_object(xmlNode *parent, xmlNode *left, xmlNode *right,
|
||
|
if (full) {
|
||
|
xmlAttrPtr pIter = NULL;
|
||
|
|
||
|
- for (pIter = pcmk__first_xml_attr(left); pIter != NULL;
|
||
|
+ for (pIter = pcmk__xe_first_attr(left); pIter != NULL;
|
||
|
pIter = pIter->next) {
|
||
|
const char *p_name = (const char *) pIter->name;
|
||
|
const char *p_value = pcmk__xml_attr_value(pIter);
|
||
|
@@ -1624,7 +1624,7 @@ subtract_xml_object(xmlNode *parent, xmlNode *left, xmlNode *right,
|
||
|
|
||
|
crm_trace("Changes detected to %s in <%s id=%s>", prop_name,
|
||
|
crm_element_name(left), id);
|
||
|
- for (pIter = pcmk__first_xml_attr(left); pIter != NULL;
|
||
|
+ for (pIter = pcmk__xe_first_attr(left); pIter != NULL;
|
||
|
pIter = pIter->next) {
|
||
|
const char *p_name = (const char *) pIter->name;
|
||
|
const char *p_value = pcmk__xml_attr_value(pIter);
|
||
|
diff --git a/lib/common/xml.c b/lib/common/xml.c
|
||
|
index abb120c..f2f48e9 100644
|
||
|
--- a/lib/common/xml.c
|
||
|
+++ b/lib/common/xml.c
|
||
|
@@ -337,7 +337,7 @@ accept_attr_deletions(xmlNode *xml)
|
||
|
xml_private_t *p = xml->_private;
|
||
|
|
||
|
p->flags = xpf_none;
|
||
|
- pIter = pcmk__first_xml_attr(xml);
|
||
|
+ pIter = pcmk__xe_first_attr(xml);
|
||
|
|
||
|
while (pIter != NULL) {
|
||
|
const xmlChar *name = pIter->name;
|
||
|
@@ -528,11 +528,9 @@ copy_in_properties(xmlNode * target, xmlNode * src)
|
||
|
crm_err("No node to copy properties into");
|
||
|
|
||
|
} else {
|
||
|
- xmlAttrPtr pIter = NULL;
|
||
|
-
|
||
|
- for (pIter = pcmk__first_xml_attr(src); pIter != NULL; pIter = pIter->next) {
|
||
|
- const char *p_name = (const char *)pIter->name;
|
||
|
- const char *p_value = pcmk__xml_attr_value(pIter);
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(src); a != NULL; a = a->next) {
|
||
|
+ const char *p_name = (const char *) a->name;
|
||
|
+ const char *p_value = pcmk__xml_attr_value(a);
|
||
|
|
||
|
expand_plus_plus(target, p_name, p_value);
|
||
|
}
|
||
|
@@ -546,11 +544,10 @@ fix_plus_plus_recursive(xmlNode * target)
|
||
|
{
|
||
|
/* TODO: Remove recursion and use xpath searches for value++ */
|
||
|
xmlNode *child = NULL;
|
||
|
- xmlAttrPtr pIter = NULL;
|
||
|
|
||
|
- for (pIter = pcmk__first_xml_attr(target); pIter != NULL; pIter = pIter->next) {
|
||
|
- const char *p_name = (const char *)pIter->name;
|
||
|
- const char *p_value = pcmk__xml_attr_value(pIter);
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(target); a != NULL; a = a->next) {
|
||
|
+ const char *p_name = (const char *) a->name;
|
||
|
+ const char *p_value = pcmk__xml_attr_value(a);
|
||
|
|
||
|
expand_plus_plus(target, p_name, p_value);
|
||
|
}
|
||
|
@@ -1429,7 +1426,6 @@ pcmk__xe_log(int log_level, const char *file, const char *function, int line,
|
||
|
const char *hidden = NULL;
|
||
|
|
||
|
xmlNode *child = NULL;
|
||
|
- xmlAttrPtr pIter = NULL;
|
||
|
|
||
|
if ((data == NULL) || (log_level == LOG_NEVER)) {
|
||
|
return;
|
||
|
@@ -1449,10 +1445,12 @@ pcmk__xe_log(int log_level, const char *file, const char *function, int line,
|
||
|
buffer_print(buffer, max, offset, "<%s", name);
|
||
|
|
||
|
hidden = crm_element_value(data, "hidden");
|
||
|
- for (pIter = pcmk__first_xml_attr(data); pIter != NULL; pIter = pIter->next) {
|
||
|
- xml_private_t *p = pIter->_private;
|
||
|
- const char *p_name = (const char *)pIter->name;
|
||
|
- const char *p_value = pcmk__xml_attr_value(pIter);
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(data); a != NULL;
|
||
|
+ a = a->next) {
|
||
|
+
|
||
|
+ xml_private_t *p = a->_private;
|
||
|
+ const char *p_name = (const char *) a->name;
|
||
|
+ const char *p_value = pcmk__xml_attr_value(a);
|
||
|
char *p_copy = NULL;
|
||
|
|
||
|
if (pcmk_is_set(p->flags, xpf_deleted)) {
|
||
|
@@ -1526,7 +1524,6 @@ log_xml_changes(int log_level, const char *file, const char *function, int line,
|
||
|
xml_private_t *p;
|
||
|
char *prefix_m = NULL;
|
||
|
xmlNode *child = NULL;
|
||
|
- xmlAttrPtr pIter = NULL;
|
||
|
|
||
|
if ((data == NULL) || (log_level == LOG_NEVER)) {
|
||
|
return;
|
||
|
@@ -1566,10 +1563,10 @@ log_xml_changes(int log_level, const char *file, const char *function, int line,
|
||
|
pcmk__xe_log(log_level, file, function, line, flags, data, depth,
|
||
|
options|xml_log_option_open);
|
||
|
|
||
|
- for (pIter = pcmk__first_xml_attr(data); pIter != NULL; pIter = pIter->next) {
|
||
|
- const char *aname = (const char*)pIter->name;
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(data); a != NULL; a = a->next) {
|
||
|
+ const char *aname = (const char*) a->name;
|
||
|
|
||
|
- p = pIter->_private;
|
||
|
+ p = a->_private;
|
||
|
if (pcmk_is_set(p->flags, xpf_deleted)) {
|
||
|
const char *value = crm_element_value(data, aname);
|
||
|
flags = prefix_del;
|
||
|
@@ -1684,11 +1681,9 @@ log_data_element(int log_level, const char *file, const char *function, int line
|
||
|
static void
|
||
|
dump_filtered_xml(xmlNode * data, int options, char **buffer, int *offset, int *max)
|
||
|
{
|
||
|
- xmlAttrPtr xIter = NULL;
|
||
|
-
|
||
|
- for (xIter = pcmk__first_xml_attr(data); xIter != NULL; xIter = xIter->next) {
|
||
|
- if (!pcmk__xa_filterable((const char *) (xIter->name))) {
|
||
|
- dump_xml_attr(xIter, options, buffer, offset, max);
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(data); a != NULL; a = a->next) {
|
||
|
+ if (!pcmk__xa_filterable((const char *) (a->name))) {
|
||
|
+ dump_xml_attr(a, options, buffer, offset, max);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
@@ -1722,10 +1717,8 @@ dump_xml_element(xmlNode * data, int options, char **buffer, int *offset, int *m
|
||
|
dump_filtered_xml(data, options, buffer, offset, max);
|
||
|
|
||
|
} else {
|
||
|
- xmlAttrPtr xIter = NULL;
|
||
|
-
|
||
|
- for (xIter = pcmk__first_xml_attr(data); xIter != NULL; xIter = xIter->next) {
|
||
|
- dump_xml_attr(xIter, options, buffer, offset, max);
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(data); a != NULL; a = a->next) {
|
||
|
+ dump_xml_attr(a, options, buffer, offset, max);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -2062,7 +2055,7 @@ save_xml_to_file(xmlNode * xml, const char *desc, const char *filename)
|
||
|
static void
|
||
|
set_attrs_flag(xmlNode *xml, enum xml_private_flags flag)
|
||
|
{
|
||
|
- for (xmlAttr *attr = pcmk__first_xml_attr(xml); attr; attr = attr->next) {
|
||
|
+ for (xmlAttr *attr = pcmk__xe_first_attr(xml); attr; attr = attr->next) {
|
||
|
pcmk__set_xml_flags((xml_private_t *) (attr->_private), flag);
|
||
|
}
|
||
|
}
|
||
|
@@ -2152,7 +2145,7 @@ mark_attr_moved(xmlNode *new_xml, const char *element, xmlAttr *old_attr,
|
||
|
static void
|
||
|
xml_diff_old_attrs(xmlNode *old_xml, xmlNode *new_xml)
|
||
|
{
|
||
|
- xmlAttr *attr_iter = pcmk__first_xml_attr(old_xml);
|
||
|
+ xmlAttr *attr_iter = pcmk__xe_first_attr(old_xml);
|
||
|
|
||
|
while (attr_iter != NULL) {
|
||
|
xmlAttr *old_attr = attr_iter;
|
||
|
@@ -2194,7 +2187,7 @@ xml_diff_old_attrs(xmlNode *old_xml, xmlNode *new_xml)
|
||
|
static void
|
||
|
mark_created_attrs(xmlNode *new_xml)
|
||
|
{
|
||
|
- xmlAttr *attr_iter = pcmk__first_xml_attr(new_xml);
|
||
|
+ xmlAttr *attr_iter = pcmk__xe_first_attr(new_xml);
|
||
|
|
||
|
while (attr_iter != NULL) {
|
||
|
xmlAttr *new_attr = attr_iter;
|
||
|
@@ -2371,7 +2364,6 @@ gboolean
|
||
|
can_prune_leaf(xmlNode * xml_node)
|
||
|
{
|
||
|
xmlNode *cIter = NULL;
|
||
|
- xmlAttrPtr pIter = NULL;
|
||
|
gboolean can_prune = TRUE;
|
||
|
const char *name = crm_element_name(xml_node);
|
||
|
|
||
|
@@ -2380,8 +2372,8 @@ can_prune_leaf(xmlNode * xml_node)
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
- for (pIter = pcmk__first_xml_attr(xml_node); pIter != NULL; pIter = pIter->next) {
|
||
|
- const char *p_name = (const char *)pIter->name;
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(xml_node); a != NULL; a = a->next) {
|
||
|
+ const char *p_name = (const char *) a->name;
|
||
|
|
||
|
if (strcmp(p_name, XML_ATTR_ID) == 0) {
|
||
|
continue;
|
||
|
@@ -2558,15 +2550,13 @@ pcmk__xml_update(xmlNode *parent, xmlNode *target, xmlNode *update,
|
||
|
|
||
|
} else {
|
||
|
/* No need for expand_plus_plus(), just raw speed */
|
||
|
- xmlAttrPtr pIter = NULL;
|
||
|
-
|
||
|
- for (pIter = pcmk__first_xml_attr(update); pIter != NULL; pIter = pIter->next) {
|
||
|
- const char *p_name = (const char *)pIter->name;
|
||
|
- const char *p_value = pcmk__xml_attr_value(pIter);
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(update); a != NULL;
|
||
|
+ a = a->next) {
|
||
|
+ const char *p_value = pcmk__xml_attr_value(a);
|
||
|
|
||
|
/* Remove it first so the ordering of the update is preserved */
|
||
|
- xmlUnsetProp(target, (pcmkXmlStr) p_name);
|
||
|
- xmlSetProp(target, (pcmkXmlStr) p_name, (pcmkXmlStr) p_value);
|
||
|
+ xmlUnsetProp(target, a->name);
|
||
|
+ xmlSetProp(target, a->name, (pcmkXmlStr) p_value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -2681,11 +2671,10 @@ replace_xml_child(xmlNode * parent, xmlNode * child, xmlNode * update, gboolean
|
||
|
can_delete = FALSE;
|
||
|
}
|
||
|
if (can_delete && delete_only) {
|
||
|
- xmlAttrPtr pIter = NULL;
|
||
|
-
|
||
|
- for (pIter = pcmk__first_xml_attr(update); pIter != NULL; pIter = pIter->next) {
|
||
|
- const char *p_name = (const char *)pIter->name;
|
||
|
- const char *p_value = pcmk__xml_attr_value(pIter);
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(update); a != NULL;
|
||
|
+ a = a->next) {
|
||
|
+ const char *p_name = (const char *) a->name;
|
||
|
+ const char *p_value = pcmk__xml_attr_value(a);
|
||
|
|
||
|
right_val = crm_element_value(child, p_name);
|
||
|
if (!pcmk__str_eq(p_value, right_val, pcmk__str_casei)) {
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From 68e35a6f715f26a8a3b033cc91875f6f7001f106 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 19 Nov 2020 10:31:36 -0600
|
||
|
Subject: [PATCH 03/12] Refactor: libcrmcommon: new internal function for
|
||
|
removing XML attributes
|
||
|
|
||
|
---
|
||
|
include/crm/common/xml_internal.h | 4 ++++
|
||
|
lib/common/xml.c | 34 ++++++++++++++++++++++++++++++++++
|
||
|
2 files changed, 38 insertions(+)
|
||
|
|
||
|
diff --git a/include/crm/common/xml_internal.h b/include/crm/common/xml_internal.h
|
||
|
index b2ff529..1e80bc6 100644
|
||
|
--- a/include/crm/common/xml_internal.h
|
||
|
+++ b/include/crm/common/xml_internal.h
|
||
|
@@ -136,6 +136,10 @@ const char *pcmk__xe_add_last_written(xmlNode *xe);
|
||
|
xmlNode *pcmk__xe_match(xmlNode *parent, const char *node_name,
|
||
|
const char *attr_n, const char *attr_v);
|
||
|
|
||
|
+void pcmk__xe_remove_matching_attrs(xmlNode *element,
|
||
|
+ bool (*match)(xmlAttrPtr, void *),
|
||
|
+ void *user_data);
|
||
|
+
|
||
|
/*!
|
||
|
* \internal
|
||
|
* \brief Get the root directory to scan XML artefacts of given kind for
|
||
|
diff --git a/lib/common/xml.c b/lib/common/xml.c
|
||
|
index f2f48e9..39c5e53 100644
|
||
|
--- a/lib/common/xml.c
|
||
|
+++ b/lib/common/xml.c
|
||
|
@@ -618,6 +618,40 @@ expand_plus_plus(xmlNode * target, const char *name, const char *value)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
+/*!
|
||
|
+ * \internal
|
||
|
+ * \brief Remove an XML element's attributes that match some criteria
|
||
|
+ *
|
||
|
+ * \param[in,out] element XML element to modify
|
||
|
+ * \param[in] match If not NULL, only remove attributes for which
|
||
|
+ * this function returns true
|
||
|
+ * \param[in] user_data Data to pass to \p match
|
||
|
+ */
|
||
|
+void
|
||
|
+pcmk__xe_remove_matching_attrs(xmlNode *element,
|
||
|
+ bool (*match)(xmlAttrPtr, void *),
|
||
|
+ void *user_data)
|
||
|
+{
|
||
|
+ xmlAttrPtr next = NULL;
|
||
|
+
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(element); a != NULL; a = next) {
|
||
|
+ next = a->next; // Grab now because attribute might get removed
|
||
|
+ if ((match == NULL) || match(a, user_data)) {
|
||
|
+ if (!pcmk__check_acl(element, NULL, xpf_acl_write)) {
|
||
|
+ crm_trace("ACLs prevent removal of %s attribute from %s element",
|
||
|
+ (const char *) a->name, (const char *) element->name);
|
||
|
+
|
||
|
+ } else if (pcmk__tracking_xml_changes(element, false)) {
|
||
|
+ // Leave (marked for removal) until after diff is calculated
|
||
|
+ set_parent_flag(element, xpf_dirty);
|
||
|
+ pcmk__set_xml_flags((xml_private_t *) a->_private, xpf_deleted);
|
||
|
+ } else {
|
||
|
+ xmlRemoveProp(a);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
xmlDoc *
|
||
|
getDocPtr(xmlNode * node)
|
||
|
{
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From a6e1804156dfd1f6c3bc1ffbf888fbd6421aa464 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 19 Nov 2020 11:10:52 -0600
|
||
|
Subject: [PATCH 04/12] Refactor: libcrmcommon,libpe_status: use new attribute
|
||
|
removing function
|
||
|
|
||
|
... where appropriate, for readability and efficiency
|
||
|
---
|
||
|
lib/common/operations.c | 64 ++++++++++++++++++-------------------
|
||
|
lib/common/patchset.c | 29 +++++++----------
|
||
|
lib/common/xml.c | 39 +++++++++++------------
|
||
|
lib/pengine/pe_digest.c | 84 ++++++++++++++++++++++++++-----------------------
|
||
|
4 files changed, 105 insertions(+), 111 deletions(-)
|
||
|
|
||
|
diff --git a/lib/common/operations.c b/lib/common/operations.c
|
||
|
index 7e6bf5a..f3a11be 100644
|
||
|
--- a/lib/common/operations.c
|
||
|
+++ b/lib/common/operations.c
|
||
|
@@ -24,6 +24,7 @@
|
||
|
#include <crm/lrmd.h>
|
||
|
#include <crm/msg_xml.h>
|
||
|
#include <crm/common/xml.h>
|
||
|
+#include <crm/common/xml_internal.h>
|
||
|
#include <crm/common/util.h>
|
||
|
|
||
|
static regex_t *notify_migrate_re = NULL;
|
||
|
@@ -361,6 +362,24 @@ decode_transition_key(const char *key, char **uuid, int *transition_id, int *act
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
+#define CRM_META_LEN (sizeof(CRM_META) - 1)
|
||
|
+
|
||
|
+// Return true if a is an attribute that should be filtered
|
||
|
+static bool
|
||
|
+should_filter_for_digest(xmlAttrPtr a, void *user_data)
|
||
|
+{
|
||
|
+ // @TODO CRM_META check should be case-sensitive
|
||
|
+ return (strncasecmp((const char *) a->name, CRM_META, CRM_META_LEN) == 0)
|
||
|
+ || pcmk__str_any_of((const char *) a->name,
|
||
|
+ XML_ATTR_ID,
|
||
|
+ XML_ATTR_CRM_VERSION,
|
||
|
+ XML_LRM_ATTR_OP_DIGEST,
|
||
|
+ XML_LRM_ATTR_TARGET,
|
||
|
+ XML_LRM_ATTR_TARGET_UUID,
|
||
|
+ "pcmk_external_ip",
|
||
|
+ NULL);
|
||
|
+}
|
||
|
+
|
||
|
/*!
|
||
|
* \internal
|
||
|
* \brief Remove XML attributes not needed for operation digest
|
||
|
@@ -374,52 +393,31 @@ pcmk__filter_op_for_digest(xmlNode *param_set)
|
||
|
char *timeout = NULL;
|
||
|
guint interval_ms = 0;
|
||
|
|
||
|
- const char *attr_filter[] = {
|
||
|
- XML_ATTR_ID,
|
||
|
- XML_ATTR_CRM_VERSION,
|
||
|
- XML_LRM_ATTR_OP_DIGEST,
|
||
|
- XML_LRM_ATTR_TARGET,
|
||
|
- XML_LRM_ATTR_TARGET_UUID,
|
||
|
- "pcmk_external_ip"
|
||
|
- };
|
||
|
-
|
||
|
- const int meta_len = strlen(CRM_META);
|
||
|
-
|
||
|
if (param_set == NULL) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- // Remove the specific attributes listed in attr_filter
|
||
|
- for (int lpc = 0; lpc < DIMOF(attr_filter); lpc++) {
|
||
|
- xml_remove_prop(param_set, attr_filter[lpc]);
|
||
|
- }
|
||
|
-
|
||
|
+ /* Timeout is useful for recurring operation digests, so grab it before
|
||
|
+ * removing meta-attributes
|
||
|
+ */
|
||
|
key = crm_meta_name(XML_LRM_ATTR_INTERVAL_MS);
|
||
|
if (crm_element_value_ms(param_set, key, &interval_ms) != pcmk_ok) {
|
||
|
interval_ms = 0;
|
||
|
}
|
||
|
free(key);
|
||
|
-
|
||
|
- key = crm_meta_name(XML_ATTR_TIMEOUT);
|
||
|
- timeout = crm_element_value_copy(param_set, key);
|
||
|
-
|
||
|
- // Remove all CRM_meta_* attributes
|
||
|
- for (xmlAttrPtr xIter = param_set->properties; xIter != NULL; ) {
|
||
|
- const char *prop_name = (const char *) (xIter->name);
|
||
|
-
|
||
|
- xIter = xIter->next;
|
||
|
-
|
||
|
- // @TODO Why is this case-insensitive?
|
||
|
- if (strncasecmp(prop_name, CRM_META, meta_len) == 0) {
|
||
|
- xml_remove_prop(param_set, prop_name);
|
||
|
- }
|
||
|
+ key = NULL;
|
||
|
+ if (interval_ms != 0) {
|
||
|
+ key = crm_meta_name(XML_ATTR_TIMEOUT);
|
||
|
+ timeout = crm_element_value_copy(param_set, key);
|
||
|
}
|
||
|
|
||
|
- if ((interval_ms != 0) && (timeout != NULL)) {
|
||
|
- // Add the timeout back, it's useful for recurring operation digests
|
||
|
+ // Remove all CRM_meta_* attributes and certain other attributes
|
||
|
+ pcmk__xe_remove_matching_attrs(param_set, should_filter_for_digest, NULL);
|
||
|
+
|
||
|
+ // Add timeout back for recurring operation digests
|
||
|
+ if (timeout != NULL) {
|
||
|
crm_xml_add(param_set, key, timeout);
|
||
|
}
|
||
|
-
|
||
|
free(timeout);
|
||
|
free(key);
|
||
|
}
|
||
|
diff --git a/lib/common/patchset.c b/lib/common/patchset.c
|
||
|
index 15cbe07..fae7046 100644
|
||
|
--- a/lib/common/patchset.c
|
||
|
+++ b/lib/common/patchset.c
|
||
|
@@ -638,13 +638,19 @@ xml_log_patchset(uint8_t log_level, const char *function, xmlNode *patchset)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+// Return true if attribute name is not "id"
|
||
|
+static bool
|
||
|
+not_id(xmlAttrPtr attr, void *user_data)
|
||
|
+{
|
||
|
+ return strcmp((const char *) attr->name, XML_ATTR_ID) != 0;
|
||
|
+}
|
||
|
+
|
||
|
// Apply the removals section of an v1 patchset to an XML node
|
||
|
static void
|
||
|
process_v1_removals(xmlNode *target, xmlNode *patch)
|
||
|
{
|
||
|
xmlNode *patch_child = NULL;
|
||
|
xmlNode *cIter = NULL;
|
||
|
- xmlAttrPtr xIter = NULL;
|
||
|
|
||
|
char *id = NULL;
|
||
|
const char *name = NULL;
|
||
|
@@ -677,15 +683,8 @@ process_v1_removals(xmlNode *target, xmlNode *patch)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- for (xIter = pcmk__xe_first_attr(patch); xIter != NULL;
|
||
|
- xIter = xIter->next) {
|
||
|
- const char *p_name = (const char *)xIter->name;
|
||
|
-
|
||
|
- // Removing then restoring id would change ordering of properties
|
||
|
- if (!pcmk__str_eq(p_name, XML_ATTR_ID, pcmk__str_casei)) {
|
||
|
- xml_remove_prop(target, p_name);
|
||
|
- }
|
||
|
- }
|
||
|
+ // Removing then restoring id would change ordering of properties
|
||
|
+ pcmk__xe_remove_matching_attrs(patch, not_id, NULL);
|
||
|
|
||
|
// Changes to child objects
|
||
|
cIter = pcmk__xml_first_child(target);
|
||
|
@@ -1204,7 +1203,6 @@ apply_v2_patchset(xmlNode *xml, xmlNode *patchset)
|
||
|
free_xml(match);
|
||
|
|
||
|
} else if (strcmp(op, "modify") == 0) {
|
||
|
- xmlAttr *pIter = pcmk__xe_first_attr(match);
|
||
|
xmlNode *attrs = NULL;
|
||
|
|
||
|
attrs = pcmk__xml_first_child(first_named_child(change,
|
||
|
@@ -1213,14 +1211,9 @@ apply_v2_patchset(xmlNode *xml, xmlNode *patchset)
|
||
|
rc = ENOMSG;
|
||
|
continue;
|
||
|
}
|
||
|
- while (pIter != NULL) {
|
||
|
- const char *name = (const char *)pIter->name;
|
||
|
-
|
||
|
- pIter = pIter->next;
|
||
|
- xml_remove_prop(match, name);
|
||
|
- }
|
||
|
+ pcmk__xe_remove_matching_attrs(match, NULL, NULL); // Remove all
|
||
|
|
||
|
- for (pIter = pcmk__xe_first_attr(attrs); pIter != NULL;
|
||
|
+ for (xmlAttrPtr pIter = pcmk__xe_first_attr(attrs); pIter != NULL;
|
||
|
pIter = pIter->next) {
|
||
|
const char *name = (const char *) pIter->name;
|
||
|
const char *value = crm_element_value(attrs, name);
|
||
|
diff --git a/lib/common/xml.c b/lib/common/xml.c
|
||
|
index 39c5e53..869ed51 100644
|
||
|
--- a/lib/common/xml.c
|
||
|
+++ b/lib/common/xml.c
|
||
|
@@ -328,32 +328,31 @@ pcmk__xml_position(xmlNode *xml, enum xml_private_flags ignore_if_set)
|
||
|
return position;
|
||
|
}
|
||
|
|
||
|
-// Remove all attributes marked as deleted from an XML node
|
||
|
-static void
|
||
|
-accept_attr_deletions(xmlNode *xml)
|
||
|
+// This also clears attribute's flags if not marked as deleted
|
||
|
+static bool
|
||
|
+marked_as_deleted(xmlAttrPtr a, void *user_data)
|
||
|
{
|
||
|
- xmlNode *cIter = NULL;
|
||
|
- xmlAttr *pIter = NULL;
|
||
|
- xml_private_t *p = xml->_private;
|
||
|
+ xml_private_t *p = a->_private;
|
||
|
|
||
|
+ if (pcmk_is_set(p->flags, xpf_deleted)) {
|
||
|
+ return true;
|
||
|
+ }
|
||
|
p->flags = xpf_none;
|
||
|
- pIter = pcmk__xe_first_attr(xml);
|
||
|
-
|
||
|
- while (pIter != NULL) {
|
||
|
- const xmlChar *name = pIter->name;
|
||
|
-
|
||
|
- p = pIter->_private;
|
||
|
- pIter = pIter->next;
|
||
|
+ return false;
|
||
|
+}
|
||
|
|
||
|
- if(p->flags & xpf_deleted) {
|
||
|
- xml_remove_prop(xml, (const char *)name);
|
||
|
+// Remove all attributes marked as deleted from an XML node
|
||
|
+static void
|
||
|
+accept_attr_deletions(xmlNode *xml)
|
||
|
+{
|
||
|
+ // Clear XML node's flags
|
||
|
+ ((xml_private_t *) xml->_private)->flags = xpf_none;
|
||
|
|
||
|
- } else {
|
||
|
- p->flags = xpf_none;
|
||
|
- }
|
||
|
- }
|
||
|
+ // Remove this XML node's attributes that were marked as deleted
|
||
|
+ pcmk__xe_remove_matching_attrs(xml, marked_as_deleted, NULL);
|
||
|
|
||
|
- for (cIter = pcmk__xml_first_child(xml); cIter != NULL;
|
||
|
+ // Recursively do the same for this XML node's children
|
||
|
+ for (xmlNodePtr cIter = pcmk__xml_first_child(xml); cIter != NULL;
|
||
|
cIter = pcmk__xml_next(cIter)) {
|
||
|
accept_attr_deletions(cIter);
|
||
|
}
|
||
|
diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c
|
||
|
index dd6b753..e8cb108 100644
|
||
|
--- a/lib/pengine/pe_digest.c
|
||
|
+++ b/lib/pengine/pe_digest.c
|
||
|
@@ -15,6 +15,7 @@
|
||
|
#include <crm/crm.h>
|
||
|
#include <crm/msg_xml.h>
|
||
|
#include <crm/common/xml.h>
|
||
|
+#include <crm/common/xml_internal.h>
|
||
|
#include <crm/pengine/internal.h>
|
||
|
#include "pe_status_private.h"
|
||
|
|
||
|
@@ -45,40 +46,36 @@ pe__free_digests(gpointer ptr)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-/*!
|
||
|
- * \internal
|
||
|
- * \brief Remove named attributes from an XML element
|
||
|
- *
|
||
|
- * \param[in,out] param_set XML to be filtered
|
||
|
- * \param[in] param_string Space-separated list of attribute names
|
||
|
- * \param[in] need_present Whether to remove attributes that match,
|
||
|
- * or those that don't match
|
||
|
- */
|
||
|
-static void
|
||
|
-filter_parameters(xmlNode *param_set, const char *param_string,
|
||
|
- bool need_present)
|
||
|
+// Return true if XML attribute name is substring of a given string
|
||
|
+static bool
|
||
|
+attr_in_string(xmlAttrPtr a, void *user_data)
|
||
|
{
|
||
|
- if ((param_set == NULL) || (param_string == NULL)) {
|
||
|
- return;
|
||
|
- }
|
||
|
- for (xmlAttrPtr xIter = param_set->properties; xIter; ) {
|
||
|
- const char *prop_name = (const char *) xIter->name;
|
||
|
- char *name = crm_strdup_printf(" %s ", prop_name);
|
||
|
- char *match = strstr(param_string, name);
|
||
|
-
|
||
|
- free(name);
|
||
|
+ bool filter = false;
|
||
|
+ char *name = crm_strdup_printf(" %s ", (const char *) a->name);
|
||
|
|
||
|
- // Do now, because current entry might get removed below
|
||
|
- xIter = xIter->next;
|
||
|
+ if (strstr((const char *) user_data, name) == NULL) {
|
||
|
+ crm_trace("Filtering %s (not found in '%s')",
|
||
|
+ (const char *) a->name, (const char *) user_data);
|
||
|
+ filter = true;
|
||
|
+ }
|
||
|
+ free(name);
|
||
|
+ return filter;
|
||
|
+}
|
||
|
|
||
|
- if ((need_present && (match == NULL))
|
||
|
- || (!need_present && (match != NULL))) {
|
||
|
+// Return true if XML attribute name is not substring of a given string
|
||
|
+static bool
|
||
|
+attr_not_in_string(xmlAttrPtr a, void *user_data)
|
||
|
+{
|
||
|
+ bool filter = false;
|
||
|
+ char *name = crm_strdup_printf(" %s ", (const char *) a->name);
|
||
|
|
||
|
- crm_trace("Filtering %s (%sfound in '%s')",
|
||
|
- prop_name, (need_present? "not " : ""), param_string);
|
||
|
- xml_remove_prop(param_set, prop_name);
|
||
|
- }
|
||
|
+ if (strstr((const char *) user_data, name) != NULL) {
|
||
|
+ crm_trace("Filtering %s (found in '%s')",
|
||
|
+ (const char *) a->name, (const char *) user_data);
|
||
|
+ filter = true;
|
||
|
}
|
||
|
+ free(name);
|
||
|
+ return filter;
|
||
|
}
|
||
|
|
||
|
#if ENABLE_VERSIONED_ATTRS
|
||
|
@@ -177,6 +174,13 @@ calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc,
|
||
|
op_version);
|
||
|
}
|
||
|
|
||
|
+// Return true if XML attribute name is a Pacemaker-defined fencing parameter
|
||
|
+static bool
|
||
|
+is_fence_param(xmlAttrPtr attr, void *user_data)
|
||
|
+{
|
||
|
+ return pcmk_stonith_param((const char *) attr->name);
|
||
|
+}
|
||
|
+
|
||
|
/*!
|
||
|
* \internal
|
||
|
* \brief Add secure digest to a digest cache entry
|
||
|
@@ -209,8 +213,12 @@ calculate_secure_digest(op_digest_cache_t *data, pe_resource_t *rsc,
|
||
|
if (overrides != NULL) {
|
||
|
g_hash_table_foreach(overrides, hash2field, data->params_secure);
|
||
|
}
|
||
|
+
|
||
|
g_hash_table_foreach(rsc->parameters, hash2field, data->params_secure);
|
||
|
- filter_parameters(data->params_secure, secure_list, FALSE);
|
||
|
+ if (secure_list != NULL) {
|
||
|
+ pcmk__xe_remove_matching_attrs(data->params_secure, attr_not_in_string,
|
||
|
+ (void *) secure_list);
|
||
|
+ }
|
||
|
if (pcmk_is_set(pcmk_get_ra_caps(class),
|
||
|
pcmk_ra_cap_fence_params)) {
|
||
|
/* For stonith resources, Pacemaker adds special parameters,
|
||
|
@@ -218,15 +226,8 @@ calculate_secure_digest(op_digest_cache_t *data, pe_resource_t *rsc,
|
||
|
* controller will not hash them. That means we have to filter
|
||
|
* them out before calculating our hash for comparison.
|
||
|
*/
|
||
|
- for (xmlAttrPtr iter = data->params_secure->properties;
|
||
|
- iter != NULL; ) {
|
||
|
- const char *prop_name = (const char *) iter->name;
|
||
|
-
|
||
|
- iter = iter->next; // Grab next now in case we remove current
|
||
|
- if (pcmk_stonith_param(prop_name)) {
|
||
|
- xml_remove_prop(data->params_secure, prop_name);
|
||
|
- }
|
||
|
- }
|
||
|
+ pcmk__xe_remove_matching_attrs(data->params_secure, is_fence_param,
|
||
|
+ NULL);
|
||
|
}
|
||
|
data->digest_secure_calc = calculate_operation_digest(data->params_secure,
|
||
|
op_version);
|
||
|
@@ -264,7 +265,10 @@ calculate_restart_digest(op_digest_cache_t *data, xmlNode *xml_op,
|
||
|
|
||
|
// Then filter out reloadable parameters, if any
|
||
|
value = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART);
|
||
|
- filter_parameters(data->params_restart, value, TRUE);
|
||
|
+ if (value != NULL) {
|
||
|
+ pcmk__xe_remove_matching_attrs(data->params_restart, attr_in_string,
|
||
|
+ (void *) value);
|
||
|
+ }
|
||
|
|
||
|
value = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
|
||
|
data->digest_restart_calc = calculate_operation_digest(data->params_restart,
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From 579875b70c2399f6cbf15d7afd210a2d4e2ed9df Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 19 Nov 2020 11:47:20 -0600
|
||
|
Subject: [PATCH 05/12] Refactor: libcrmcommon,libpe_status: use "first XML
|
||
|
attribute" function
|
||
|
|
||
|
... where appropriate. It checks for NULL, so that doesn't need to be
|
||
|
duplicated.
|
||
|
---
|
||
|
lib/common/patchset.c | 11 +++--------
|
||
|
lib/pengine/complex.c | 12 ++++--------
|
||
|
2 files changed, 7 insertions(+), 16 deletions(-)
|
||
|
|
||
|
diff --git a/lib/common/patchset.c b/lib/common/patchset.c
|
||
|
index fae7046..46d136a 100644
|
||
|
--- a/lib/common/patchset.c
|
||
|
+++ b/lib/common/patchset.c
|
||
|
@@ -279,15 +279,10 @@ xml_repair_v1_diff(xmlNode *last, xmlNode *next, xmlNode *local_diff,
|
||
|
crm_xml_add(diff_child, vfields[lpc], value);
|
||
|
}
|
||
|
|
||
|
- if (next) {
|
||
|
- xmlAttrPtr xIter = NULL;
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(next); a != NULL; a = a->next) {
|
||
|
+ const char *p_value = crm_element_value(next, (const char *) a->name);
|
||
|
|
||
|
- for (xIter = next->properties; xIter; xIter = xIter->next) {
|
||
|
- const char *p_name = (const char *) xIter->name;
|
||
|
- const char *p_value = crm_element_value(next, p_name);
|
||
|
-
|
||
|
- xmlSetProp(cib, (pcmkXmlStr) p_name, (pcmkXmlStr) p_value);
|
||
|
- }
|
||
|
+ xmlSetProp(cib, a->name, (pcmkXmlStr) p_value);
|
||
|
}
|
||
|
|
||
|
crm_log_xml_explicit(local_diff, "Repaired-diff");
|
||
|
diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c
|
||
|
index a087e5e..5f484ad 100644
|
||
|
--- a/lib/pengine/complex.c
|
||
|
+++ b/lib/pengine/complex.c
|
||
|
@@ -159,15 +159,11 @@ get_meta_attributes(GHashTable * meta_hash, pe_resource_t * rsc,
|
||
|
rule_data.node_hash = node->details->attrs;
|
||
|
}
|
||
|
|
||
|
- if (rsc->xml) {
|
||
|
- xmlAttrPtr xIter = NULL;
|
||
|
+ for (xmlAttrPtr a = pcmk__xe_first_attr(rsc->xml); a != NULL; a = a->next) {
|
||
|
+ const char *prop_name = (const char *) a->name;
|
||
|
+ const char *prop_value = crm_element_value(rsc->xml, prop_name);
|
||
|
|
||
|
- for (xIter = rsc->xml->properties; xIter; xIter = xIter->next) {
|
||
|
- const char *prop_name = (const char *)xIter->name;
|
||
|
- const char *prop_value = crm_element_value(rsc->xml, prop_name);
|
||
|
-
|
||
|
- add_hash_param(meta_hash, prop_name, prop_value);
|
||
|
- }
|
||
|
+ add_hash_param(meta_hash, prop_name, prop_value);
|
||
|
}
|
||
|
|
||
|
pe__unpack_dataset_nvpairs(rsc->xml, XML_TAG_META_SETS, &rule_data,
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From a30d60e6344129e03fcab9cd8c9523bf24951a92 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 19 Nov 2020 13:37:37 -0600
|
||
|
Subject: [PATCH 06/12] Low: libcrmcommon: compare CRM_meta_ properly
|
||
|
|
||
|
Previously, when filtering XML attributes for digests, we would filter
|
||
|
attributes starting with "CRM_meta" case-insensitively. Now, compare
|
||
|
against "CRM_meta_" case-sensitively.
|
||
|
|
||
|
This could potentially cause resource restarts after upgrading to a version
|
||
|
with this commit, for any resource that has instance attributes that start with
|
||
|
something like "crm_meta" -- a highly unlikely scenario.
|
||
|
---
|
||
|
lib/common/operations.c | 6 +++---
|
||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/lib/common/operations.c b/lib/common/operations.c
|
||
|
index f3a11be..421aaac 100644
|
||
|
--- a/lib/common/operations.c
|
||
|
+++ b/lib/common/operations.c
|
||
|
@@ -362,14 +362,14 @@ decode_transition_key(const char *key, char **uuid, int *transition_id, int *act
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
-#define CRM_META_LEN (sizeof(CRM_META) - 1)
|
||
|
+// String length of CRM_META"_"
|
||
|
+#define CRM_META_LEN sizeof(CRM_META)
|
||
|
|
||
|
// Return true if a is an attribute that should be filtered
|
||
|
static bool
|
||
|
should_filter_for_digest(xmlAttrPtr a, void *user_data)
|
||
|
{
|
||
|
- // @TODO CRM_META check should be case-sensitive
|
||
|
- return (strncasecmp((const char *) a->name, CRM_META, CRM_META_LEN) == 0)
|
||
|
+ return (strncmp((const char *) a->name, CRM_META "_", CRM_META_LEN) == 0)
|
||
|
|| pcmk__str_any_of((const char *) a->name,
|
||
|
XML_ATTR_ID,
|
||
|
XML_ATTR_CRM_VERSION,
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From cb81616eaf53e7029a0c196ffab6203d60389386 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Mon, 23 Nov 2020 11:04:08 -0600
|
||
|
Subject: [PATCH 07/12] Low: scheduler: filter non-private parameters properly
|
||
|
for digest
|
||
|
|
||
|
Do the same filtering for non-private parameter digests as for all-parameter
|
||
|
digests. This matters when a filterable parameter is specified in overrides.
|
||
|
---
|
||
|
lib/pengine/pe_digest.c | 1 +
|
||
|
1 file changed, 1 insertion(+)
|
||
|
|
||
|
diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c
|
||
|
index e8cb108..03aa3bc 100644
|
||
|
--- a/lib/pengine/pe_digest.c
|
||
|
+++ b/lib/pengine/pe_digest.c
|
||
|
@@ -229,6 +229,7 @@ calculate_secure_digest(op_digest_cache_t *data, pe_resource_t *rsc,
|
||
|
pcmk__xe_remove_matching_attrs(data->params_secure, is_fence_param,
|
||
|
NULL);
|
||
|
}
|
||
|
+ pcmk__filter_op_for_digest(data->params_secure);
|
||
|
data->digest_secure_calc = calculate_operation_digest(data->params_secure,
|
||
|
op_version);
|
||
|
}
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From fe4aee37ceca64fd8a512e7cae57bae0745c7ace Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Mon, 23 Nov 2020 17:17:59 -0600
|
||
|
Subject: [PATCH 08/12] Refactor: scheduler: pull interval from digest
|
||
|
overrides if appropriate
|
||
|
|
||
|
When calculating an operation digest, we previously used an operation key
|
||
|
provided by the caller, along with a table of parameter overrides. However, if
|
||
|
CRM_meta_interval is one of the overrides, that should be used in the operation
|
||
|
key instead of the caller-provided key.
|
||
|
|
||
|
Now, the caller passes in a pointer to the interval, and if it's overridden,
|
||
|
pe__calculate_digests() will use the overridden value and reset the caller's
|
||
|
interval to it.
|
||
|
|
||
|
As of this commit, no caller passes overrides, so it has no effect, but it will
|
||
|
be useful for an upcoming feature.
|
||
|
---
|
||
|
include/crm/pengine/internal.h | 2 +-
|
||
|
lib/pengine/pe_digest.c | 117 +++++++++++++++++++++++++----------------
|
||
|
2 files changed, 73 insertions(+), 46 deletions(-)
|
||
|
|
||
|
diff --git a/include/crm/pengine/internal.h b/include/crm/pengine/internal.h
|
||
|
index a4f8086..1e5aee1 100644
|
||
|
--- a/include/crm/pengine/internal.h
|
||
|
+++ b/include/crm/pengine/internal.h
|
||
|
@@ -503,7 +503,7 @@ typedef struct op_digest_cache_s {
|
||
|
} op_digest_cache_t;
|
||
|
|
||
|
op_digest_cache_t *pe__calculate_digests(pe_resource_t *rsc, const char *task,
|
||
|
- const char *key, pe_node_t *node,
|
||
|
+ guint *interval_ms, pe_node_t *node,
|
||
|
xmlNode *xml_op, GHashTable *overrides,
|
||
|
bool calc_secure,
|
||
|
pe_working_set_t *data_set);
|
||
|
diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c
|
||
|
index 03aa3bc..b608f22 100644
|
||
|
--- a/lib/pengine/pe_digest.c
|
||
|
+++ b/lib/pengine/pe_digest.c
|
||
|
@@ -121,19 +121,19 @@ append_all_versioned_params(pe_resource_t *rsc, pe_node_t *node,
|
||
|
* \internal
|
||
|
* \brief Add digest of all parameters to a digest cache entry
|
||
|
*
|
||
|
- * \param[out] data Digest cache entry to modify
|
||
|
- * \param[in] rsc Resource that action was for
|
||
|
- * \param[in] node Node action was performed on
|
||
|
- * \param[in] task Name of action performed
|
||
|
- * \param[in] key Action's task key
|
||
|
- * \param[in] xml_op XML of operation in CIB status (if available)
|
||
|
- * \param[in] op_version CRM feature set to use for digest calculation
|
||
|
- * \param[in] overrides Key/value hash table to override resource parameters
|
||
|
- * \param[in] data_set Cluster working set
|
||
|
+ * \param[out] data Digest cache entry to modify
|
||
|
+ * \param[in] rsc Resource that action was for
|
||
|
+ * \param[in] node Node action was performed on
|
||
|
+ * \param[in] task Name of action performed
|
||
|
+ * \param[in,out] interval_ms Action's interval (will be reset if in overrides)
|
||
|
+ * \param[in] xml_op XML of operation in CIB status (if available)
|
||
|
+ * \param[in] op_version CRM feature set to use for digest calculation
|
||
|
+ * \param[in] overrides Key/value table to override resource parameters
|
||
|
+ * \param[in] data_set Cluster working set
|
||
|
*/
|
||
|
static void
|
||
|
calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc,
|
||
|
- pe_node_t *node, const char *task, const char *key,
|
||
|
+ pe_node_t *node, const char *task, guint *interval_ms,
|
||
|
xmlNode *xml_op, const char *op_version,
|
||
|
GHashTable *overrides, pe_working_set_t *data_set)
|
||
|
{
|
||
|
@@ -153,7 +153,24 @@ calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc,
|
||
|
rsc->id, node->details->uname);
|
||
|
}
|
||
|
|
||
|
- action = custom_action(rsc, strdup(key), task, node, TRUE, FALSE, data_set);
|
||
|
+ // If interval was overridden, reset it
|
||
|
+ if (overrides != NULL) {
|
||
|
+ const char *interval_s = g_hash_table_lookup(overrides, CRM_META "_"
|
||
|
+ XML_LRM_ATTR_INTERVAL);
|
||
|
+
|
||
|
+ if (interval_s != NULL) {
|
||
|
+ long long value_ll;
|
||
|
+
|
||
|
+ errno = 0;
|
||
|
+ value_ll = crm_parse_ll(interval_s, NULL);
|
||
|
+ if ((errno == 0) && (value_ll >= 0) && (value_ll <= G_MAXUINT)) {
|
||
|
+ *interval_ms = (guint) value_ll;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ action = custom_action(rsc, pcmk__op_key(rsc->id, task, *interval_ms),
|
||
|
+ task, node, TRUE, FALSE, data_set);
|
||
|
if (overrides != NULL) {
|
||
|
g_hash_table_foreach(overrides, hash2field, data->params_all);
|
||
|
}
|
||
|
@@ -280,21 +297,21 @@ calculate_restart_digest(op_digest_cache_t *data, xmlNode *xml_op,
|
||
|
* \internal
|
||
|
* \brief Create a new digest cache entry with calculated digests
|
||
|
*
|
||
|
- * \param[in] rsc Resource that action was for
|
||
|
- * \param[in] task Name of action performed
|
||
|
- * \param[in] key Action's task key
|
||
|
- * \param[in] node Node action was performed on
|
||
|
- * \param[in] xml_op XML of operation in CIB status (if available)
|
||
|
- * \param[in] overrides Key/value hash table to override resource parameters
|
||
|
- * \param[in] calc_secure Whether to calculate secure digest
|
||
|
- * \param[in] data_set Cluster working set
|
||
|
+ * \param[in] rsc Resource that action was for
|
||
|
+ * \param[in] task Name of action performed
|
||
|
+ * \param[in,out] interval_ms Action's interval (will be reset if in overrides)
|
||
|
+ * \param[in] node Node action was performed on
|
||
|
+ * \param[in] xml_op XML of operation in CIB status (if available)
|
||
|
+ * \param[in] overrides Key/value table to override resource parameters
|
||
|
+ * \param[in] calc_secure Whether to calculate secure digest
|
||
|
+ * \param[in] data_set Cluster working set
|
||
|
*
|
||
|
* \return Pointer to new digest cache entry (or NULL on memory error)
|
||
|
* \note It is the caller's responsibility to free the result using
|
||
|
* pe__free_digests().
|
||
|
*/
|
||
|
op_digest_cache_t *
|
||
|
-pe__calculate_digests(pe_resource_t *rsc, const char *task, const char *key,
|
||
|
+pe__calculate_digests(pe_resource_t *rsc, const char *task, guint *interval_ms,
|
||
|
pe_node_t *node, xmlNode *xml_op, GHashTable *overrides,
|
||
|
bool calc_secure, pe_working_set_t *data_set)
|
||
|
{
|
||
|
@@ -307,8 +324,9 @@ pe__calculate_digests(pe_resource_t *rsc, const char *task, const char *key,
|
||
|
if (xml_op != NULL) {
|
||
|
op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
|
||
|
}
|
||
|
- calculate_main_digest(data, rsc, node, task, key, xml_op, op_version,
|
||
|
- overrides, data_set);
|
||
|
+
|
||
|
+ calculate_main_digest(data, rsc, node, task, interval_ms, xml_op,
|
||
|
+ op_version, overrides, data_set);
|
||
|
if (calc_secure) {
|
||
|
calculate_secure_digest(data, rsc, xml_op, op_version, overrides);
|
||
|
}
|
||
|
@@ -322,7 +340,7 @@ pe__calculate_digests(pe_resource_t *rsc, const char *task, const char *key,
|
||
|
*
|
||
|
* \param[in] rsc Resource that action was for
|
||
|
* \param[in] task Name of action performed
|
||
|
- * \param[in] key Action's task key
|
||
|
+ * \param[in] interval_ms Action's interval
|
||
|
* \param[in] node Node action was performed on
|
||
|
* \param[in] xml_op XML of operation in CIB status (if available)
|
||
|
* \param[in] calc_secure Whether to calculate secure digest
|
||
|
@@ -331,29 +349,40 @@ pe__calculate_digests(pe_resource_t *rsc, const char *task, const char *key,
|
||
|
* \return Pointer to node's digest cache entry
|
||
|
*/
|
||
|
static op_digest_cache_t *
|
||
|
-rsc_action_digest(pe_resource_t *rsc, const char *task, const char *key,
|
||
|
+rsc_action_digest(pe_resource_t *rsc, const char *task, guint interval_ms,
|
||
|
pe_node_t *node, xmlNode *xml_op, bool calc_secure,
|
||
|
pe_working_set_t *data_set)
|
||
|
{
|
||
|
op_digest_cache_t *data = NULL;
|
||
|
+ char *key = pcmk__op_key(rsc->id, task, interval_ms);
|
||
|
|
||
|
data = g_hash_table_lookup(node->details->digest_cache, key);
|
||
|
if (data == NULL) {
|
||
|
- data = pe__calculate_digests(rsc, task, key, node, xml_op, NULL,
|
||
|
- calc_secure, data_set);
|
||
|
+ data = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
|
||
|
+ NULL, calc_secure, data_set);
|
||
|
CRM_ASSERT(data != NULL);
|
||
|
g_hash_table_insert(node->details->digest_cache, strdup(key), data);
|
||
|
}
|
||
|
+ free(key);
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
+/*!
|
||
|
+ * \internal
|
||
|
+ * \brief Calculate operation digests and compare against an XML history entry
|
||
|
+ *
|
||
|
+ * \param[in] rsc Resource to check
|
||
|
+ * \param[in] xml_op Resource history XML
|
||
|
+ * \param[in] node Node to use for digest calculation
|
||
|
+ * \param[in] data_set Cluster working set
|
||
|
+ *
|
||
|
+ * \return Pointer to node's digest cache entry, with comparison result set
|
||
|
+ */
|
||
|
op_digest_cache_t *
|
||
|
rsc_action_digest_cmp(pe_resource_t * rsc, xmlNode * xml_op, pe_node_t * node,
|
||
|
pe_working_set_t * data_set)
|
||
|
{
|
||
|
op_digest_cache_t *data = NULL;
|
||
|
-
|
||
|
- char *key = NULL;
|
||
|
guint interval_ms = 0;
|
||
|
|
||
|
const char *op_version;
|
||
|
@@ -368,17 +397,18 @@ rsc_action_digest_cmp(pe_resource_t * rsc, xmlNode * xml_op, pe_node_t * node,
|
||
|
digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
|
||
|
|
||
|
crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
|
||
|
- key = pcmk__op_key(rsc->id, task, interval_ms);
|
||
|
- data = rsc_action_digest(rsc, task, key, node, xml_op,
|
||
|
+ data = rsc_action_digest(rsc, task, interval_ms, node, xml_op,
|
||
|
pcmk_is_set(data_set->flags, pe_flag_sanitized),
|
||
|
data_set);
|
||
|
|
||
|
data->rc = RSC_DIGEST_MATCH;
|
||
|
if (digest_restart && data->digest_restart_calc && strcmp(data->digest_restart_calc, digest_restart) != 0) {
|
||
|
- pe_rsc_info(rsc, "Parameters to %s on %s changed: was %s vs. now %s (restart:%s) %s",
|
||
|
- key, node->details->uname,
|
||
|
- crm_str(digest_restart), data->digest_restart_calc,
|
||
|
- op_version, crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
|
||
|
+ pe_rsc_info(rsc, "Parameters to %ums-interval %s action for %s on %s "
|
||
|
+ "changed: hash was %s vs. now %s (restart:%s) %s",
|
||
|
+ interval_ms, task, rsc->id, node->details->uname,
|
||
|
+ crm_str(digest_restart), data->digest_restart_calc,
|
||
|
+ op_version,
|
||
|
+ crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
|
||
|
data->rc = RSC_DIGEST_RESTART;
|
||
|
|
||
|
} else if (digest_all == NULL) {
|
||
|
@@ -386,15 +416,15 @@ rsc_action_digest_cmp(pe_resource_t * rsc, xmlNode * xml_op, pe_node_t * node,
|
||
|
data->rc = RSC_DIGEST_UNKNOWN;
|
||
|
|
||
|
} else if (strcmp(digest_all, data->digest_all_calc) != 0) {
|
||
|
- pe_rsc_info(rsc, "Parameters to %s on %s changed: was %s vs. now %s (%s:%s) %s",
|
||
|
- key, node->details->uname,
|
||
|
- crm_str(digest_all), data->digest_all_calc,
|
||
|
- (interval_ms > 0)? "reschedule" : "reload",
|
||
|
- op_version, crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
|
||
|
+ pe_rsc_info(rsc, "Parameters to %ums-interval %s action for %s on %s "
|
||
|
+ "changed: hash was %s vs. now %s (%s:%s) %s",
|
||
|
+ interval_ms, task, rsc->id, node->details->uname,
|
||
|
+ crm_str(digest_all), data->digest_all_calc,
|
||
|
+ (interval_ms > 0)? "reschedule" : "reload",
|
||
|
+ op_version,
|
||
|
+ crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
|
||
|
data->rc = RSC_DIGEST_ALL;
|
||
|
}
|
||
|
-
|
||
|
- free(key);
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
@@ -483,12 +513,9 @@ pe__compare_fencing_digest(pe_resource_t *rsc, const char *agent,
|
||
|
const char *node_summary = NULL;
|
||
|
|
||
|
// Calculate device's current parameter digests
|
||
|
- char *key = pcmk__op_key(rsc->id, STONITH_DIGEST_TASK, 0);
|
||
|
- op_digest_cache_t *data = rsc_action_digest(rsc, STONITH_DIGEST_TASK, key,
|
||
|
+ op_digest_cache_t *data = rsc_action_digest(rsc, STONITH_DIGEST_TASK, 0U,
|
||
|
node, NULL, TRUE, data_set);
|
||
|
|
||
|
- free(key);
|
||
|
-
|
||
|
// Check whether node has special unfencing summary node attribute
|
||
|
node_summary = pe_node_attribute_raw(node, CRM_ATTR_DIGESTS_ALL);
|
||
|
if (node_summary == NULL) {
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From bf20b166b6e7dcf87edd398f2edfc384cb640886 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Mon, 23 Nov 2020 17:48:34 -0600
|
||
|
Subject: [PATCH 09/12] Low: scheduler: don't include timeout in secure digests
|
||
|
|
||
|
... to match what the controller does
|
||
|
---
|
||
|
lib/pengine/pe_digest.c | 11 +++++++++++
|
||
|
1 file changed, 11 insertions(+)
|
||
|
|
||
|
diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c
|
||
|
index b608f22..f55c896 100644
|
||
|
--- a/lib/pengine/pe_digest.c
|
||
|
+++ b/lib/pengine/pe_digest.c
|
||
|
@@ -247,6 +247,17 @@ calculate_secure_digest(op_digest_cache_t *data, pe_resource_t *rsc,
|
||
|
NULL);
|
||
|
}
|
||
|
pcmk__filter_op_for_digest(data->params_secure);
|
||
|
+
|
||
|
+ /* CRM_meta_timeout *should* be part of a digest for recurring operations.
|
||
|
+ * However, currently the controller does not add timeout to secure digests,
|
||
|
+ * because it only includes parameters declared by the resource agent.
|
||
|
+ * Remove any timeout that made it this far, to match.
|
||
|
+ *
|
||
|
+ * @TODO Update the controller to add the timeout (which will require
|
||
|
+ * bumping the feature set and checking that here).
|
||
|
+ */
|
||
|
+ xml_remove_prop(data->params_secure, CRM_META "_" XML_ATTR_TIMEOUT);
|
||
|
+
|
||
|
data->digest_secure_calc = calculate_operation_digest(data->params_secure,
|
||
|
op_version);
|
||
|
}
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From a956e32a536942b0fc1f2f058e441b3faf2abdd3 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 7 Jan 2021 12:08:56 -0600
|
||
|
Subject: [PATCH 10/12] Low: scheduler: treat NULL and empty string the same in
|
||
|
literal attribute comparisons
|
||
|
|
||
|
Previously, expand_value_source() returned NULL if the value was the empty
|
||
|
string ("") only when value-source was "param" or "meta". If value-source was
|
||
|
literal, it would return the empty string.
|
||
|
|
||
|
This behavior shouldn't depend on value-source, so it now returns NULL when a
|
||
|
literal value is the empty string.
|
||
|
|
||
|
This could change the behavior for "defined"/"not_defined" checks, and
|
||
|
comparisons against another NULL or empty string value (NULL compares less than
|
||
|
empty strings). But the consistency seems worth it.
|
||
|
|
||
|
(Another question not addressed here is whether NULL and empty string should
|
||
|
compare as equal.)
|
||
|
---
|
||
|
lib/pengine/rules.c | 9 ++++++---
|
||
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
|
||
|
index aa5d6ab..d69f449 100644
|
||
|
--- a/lib/pengine/rules.c
|
||
|
+++ b/lib/pengine/rules.c
|
||
|
@@ -1,5 +1,5 @@
|
||
|
/*
|
||
|
- * Copyright 2004-2020 the Pacemaker project contributors
|
||
|
+ * Copyright 2004-2021 the Pacemaker project contributors
|
||
|
*
|
||
|
* The version control history for this file may have further details.
|
||
|
*
|
||
|
@@ -1039,7 +1039,10 @@ expand_value_source(const char *value, const char *value_source,
|
||
|
{
|
||
|
GHashTable *table = NULL;
|
||
|
|
||
|
- if (pcmk__str_eq(value_source, "param", pcmk__str_casei)) {
|
||
|
+ if (pcmk__str_empty(value)) {
|
||
|
+ return NULL; // value_source is irrelevant
|
||
|
+
|
||
|
+ } else if (pcmk__str_eq(value_source, "param", pcmk__str_casei)) {
|
||
|
table = match_data->params;
|
||
|
|
||
|
} else if (pcmk__str_eq(value_source, "meta", pcmk__str_casei)) {
|
||
|
@@ -1049,7 +1052,7 @@ expand_value_source(const char *value, const char *value_source,
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
- if ((table == NULL) || pcmk__str_empty(value)) {
|
||
|
+ if (table == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
return (const char *) g_hash_table_lookup(table, value);
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From 2d7cd78340b47045b5987002c9b2d221ccb01ee9 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 7 Jan 2021 13:01:29 -0600
|
||
|
Subject: [PATCH 11/12] Refactor: libcrmcommon: bail early if ACLs block
|
||
|
attribute removal
|
||
|
|
||
|
... for efficiency and fewer trace messages
|
||
|
---
|
||
|
lib/common/xml.c | 9 ++++++---
|
||
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/lib/common/xml.c b/lib/common/xml.c
|
||
|
index 869ed51..8b71911 100644
|
||
|
--- a/lib/common/xml.c
|
||
|
+++ b/lib/common/xml.c
|
||
|
@@ -1,5 +1,5 @@
|
||
|
/*
|
||
|
- * Copyright 2004-2020 the Pacemaker project contributors
|
||
|
+ * Copyright 2004-2021 the Pacemaker project contributors
|
||
|
*
|
||
|
* The version control history for this file may have further details.
|
||
|
*
|
||
|
@@ -637,10 +637,13 @@ pcmk__xe_remove_matching_attrs(xmlNode *element,
|
||
|
next = a->next; // Grab now because attribute might get removed
|
||
|
if ((match == NULL) || match(a, user_data)) {
|
||
|
if (!pcmk__check_acl(element, NULL, xpf_acl_write)) {
|
||
|
- crm_trace("ACLs prevent removal of %s attribute from %s element",
|
||
|
+ crm_trace("ACLs prevent removal of attributes (%s and "
|
||
|
+ "possibly others) from %s element",
|
||
|
(const char *) a->name, (const char *) element->name);
|
||
|
+ return; // ACLs apply to element, not particular attributes
|
||
|
+ }
|
||
|
|
||
|
- } else if (pcmk__tracking_xml_changes(element, false)) {
|
||
|
+ if (pcmk__tracking_xml_changes(element, false)) {
|
||
|
// Leave (marked for removal) until after diff is calculated
|
||
|
set_parent_flag(element, xpf_dirty);
|
||
|
pcmk__set_xml_flags((xml_private_t *) a->_private, xpf_deleted);
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|
||
|
|
||
|
From 459f7a58424b05b7c586906d904129a6408d6206 Mon Sep 17 00:00:00 2001
|
||
|
From: Ken Gaillot <kgaillot@redhat.com>
|
||
|
Date: Thu, 7 Jan 2021 13:30:40 -0600
|
||
|
Subject: [PATCH 12/12] Refactor: libcrmcommon: drop a constant
|
||
|
|
||
|
It was only used once, and the code is actually more readable without it
|
||
|
---
|
||
|
lib/common/operations.c | 26 +++++++++++++-------------
|
||
|
1 file changed, 13 insertions(+), 13 deletions(-)
|
||
|
|
||
|
diff --git a/lib/common/operations.c b/lib/common/operations.c
|
||
|
index 421aaac..420f078 100644
|
||
|
--- a/lib/common/operations.c
|
||
|
+++ b/lib/common/operations.c
|
||
|
@@ -1,5 +1,5 @@
|
||
|
/*
|
||
|
- * Copyright 2004-2020 the Pacemaker project contributors
|
||
|
+ * Copyright 2004-2021 the Pacemaker project contributors
|
||
|
*
|
||
|
* The version control history for this file may have further details.
|
||
|
*
|
||
|
@@ -362,22 +362,22 @@ decode_transition_key(const char *key, char **uuid, int *transition_id, int *act
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
-// String length of CRM_META"_"
|
||
|
-#define CRM_META_LEN sizeof(CRM_META)
|
||
|
-
|
||
|
// Return true if a is an attribute that should be filtered
|
||
|
static bool
|
||
|
should_filter_for_digest(xmlAttrPtr a, void *user_data)
|
||
|
{
|
||
|
- return (strncmp((const char *) a->name, CRM_META "_", CRM_META_LEN) == 0)
|
||
|
- || pcmk__str_any_of((const char *) a->name,
|
||
|
- XML_ATTR_ID,
|
||
|
- XML_ATTR_CRM_VERSION,
|
||
|
- XML_LRM_ATTR_OP_DIGEST,
|
||
|
- XML_LRM_ATTR_TARGET,
|
||
|
- XML_LRM_ATTR_TARGET_UUID,
|
||
|
- "pcmk_external_ip",
|
||
|
- NULL);
|
||
|
+ if (strncmp((const char *) a->name, CRM_META "_",
|
||
|
+ sizeof(CRM_META " ") - 1) == 0) {
|
||
|
+ return true;
|
||
|
+ }
|
||
|
+ return pcmk__str_any_of((const char *) a->name,
|
||
|
+ XML_ATTR_ID,
|
||
|
+ XML_ATTR_CRM_VERSION,
|
||
|
+ XML_LRM_ATTR_OP_DIGEST,
|
||
|
+ XML_LRM_ATTR_TARGET,
|
||
|
+ XML_LRM_ATTR_TARGET_UUID,
|
||
|
+ "pcmk_external_ip",
|
||
|
+ NULL);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|