23c78e
From df587aaec07b4a08364d4024b3d0c73e6dede562 Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Mon, 9 Nov 2020 14:55:42 -0600
23c78e
Subject: [PATCH 1/9] Refactor: scheduler: simplify XML attribute filtering
23c78e
 function
23c78e
23c78e
---
23c78e
 lib/pengine/pe_digest.c | 52 ++++++++++++++++++++++++++-----------------------
23c78e
 1 file changed, 28 insertions(+), 24 deletions(-)
23c78e
23c78e
diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c
23c78e
index 5bcd22b..1e119f9 100644
23c78e
--- a/lib/pengine/pe_digest.c
23c78e
+++ b/lib/pengine/pe_digest.c
23c78e
@@ -45,30 +45,38 @@ pe__free_digests(gpointer ptr)
23c78e
     }
23c78e
 }
23c78e
 
23c78e
+/*!
23c78e
+ * \internal
23c78e
+ * \brief Remove named attributes from an XML element
23c78e
+ *
23c78e
+ * \param[in,out] param_set     XML to be filtered
23c78e
+ * \param[in]     param_string  Space-separated list of attribute names
23c78e
+ * \param[in]     need_present  Whether to remove attributes that match,
23c78e
+ *                              or those that don't match
23c78e
+ */
23c78e
 static void
23c78e
-filter_parameters(xmlNode * param_set, const char *param_string, bool need_present)
23c78e
+filter_parameters(xmlNode *param_set, const char *param_string,
23c78e
+                  bool need_present)
23c78e
 {
23c78e
-    if (param_set && param_string) {
23c78e
-        xmlAttrPtr xIter = param_set->properties;
23c78e
-
23c78e
-        while (xIter) {
23c78e
-            const char *prop_name = (const char *)xIter->name;
23c78e
-            char *name = crm_strdup_printf(" %s ", prop_name);
23c78e
-            char *match = strstr(param_string, name);
23c78e
+    if ((param_set == NULL) || (param_string == NULL)) {
23c78e
+        return;
23c78e
+    }
23c78e
+    for (xmlAttrPtr xIter = param_set->properties; xIter; ) {
23c78e
+        const char *prop_name = (const char *) xIter->name;
23c78e
+        char *name = crm_strdup_printf(" %s ", prop_name);
23c78e
+        char *match = strstr(param_string, name);
23c78e
 
23c78e
-            free(name);
23c78e
+        free(name);
23c78e
 
23c78e
-            //  Do now, because current entry might get removed below
23c78e
-            xIter = xIter->next;
23c78e
+        //  Do now, because current entry might get removed below
23c78e
+        xIter = xIter->next;
23c78e
 
23c78e
-            if (need_present && match == NULL) {
23c78e
-                crm_trace("%s not found in %s", prop_name, param_string);
23c78e
-                xml_remove_prop(param_set, prop_name);
23c78e
+        if ((need_present && (match == NULL))
23c78e
+            || (!need_present && (match != NULL))) {
23c78e
 
23c78e
-            } else if (need_present == FALSE && match) {
23c78e
-                crm_trace("%s found in %s", prop_name, param_string);
23c78e
-                xml_remove_prop(param_set, prop_name);
23c78e
-            }
23c78e
+            crm_trace("Filtering %s (%sfound in '%s')",
23c78e
+                      prop_name, (need_present? "not " : ""), param_string);
23c78e
+            xml_remove_prop(param_set, prop_name);
23c78e
         }
23c78e
     }
23c78e
 }
23c78e
@@ -203,9 +211,7 @@ calculate_secure_digest(op_digest_cache_t *data, pe_resource_t *rsc,
23c78e
         g_hash_table_foreach(overrides, hash2field, data->params_secure);
23c78e
     }
23c78e
     g_hash_table_foreach(rsc->parameters, hash2field, data->params_secure);
23c78e
-    if (secure_list != NULL) {
23c78e
-        filter_parameters(data->params_secure, secure_list, FALSE);
23c78e
-    }
23c78e
+    filter_parameters(data->params_secure, secure_list, FALSE);
23c78e
     if (pcmk_is_set(pcmk_get_ra_caps(class),
23c78e
                     pcmk_ra_cap_fence_params)) {
23c78e
         /* For stonith resources, Pacemaker adds special parameters,
23c78e
@@ -259,9 +265,7 @@ calculate_restart_digest(op_digest_cache_t *data, xmlNode *xml_op,
23c78e
 
23c78e
     // Then filter out reloadable parameters, if any
23c78e
     value = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART);
23c78e
-    if (value != NULL) {
23c78e
-        filter_parameters(data->params_restart, value, TRUE);
23c78e
-    }
23c78e
+    filter_parameters(data->params_restart, value, TRUE);
23c78e
 
23c78e
     value = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
23c78e
     data->digest_restart_calc = calculate_operation_digest(data->params_restart,
23c78e
-- 
23c78e
1.8.3.1
23c78e
23c78e
23c78e
From f030af8771601d46947ac9276538c46c6c296504 Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Mon, 9 Nov 2020 18:37:37 -0600
23c78e
Subject: [PATCH 2/9] Refactor: scheduler: remember whether action is probe
23c78e
 when unpacking
23c78e
23c78e
... to reduce code duplication and improve readability
23c78e
---
23c78e
 lib/pengine/utils.c | 8 ++++----
23c78e
 1 file changed, 4 insertions(+), 4 deletions(-)
23c78e
23c78e
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
23c78e
index 04110be..b0922fa 100644
23c78e
--- a/lib/pengine/utils.c
23c78e
+++ b/lib/pengine/utils.c
23c78e
@@ -995,6 +995,8 @@ unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * contai
23c78e
 {
23c78e
     int timeout_ms = 0;
23c78e
     const char *value = NULL;
23c78e
+    bool is_probe = pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)
23c78e
+                    && (interval_ms == 0);
23c78e
 #if ENABLE_VERSIONED_ATTRS
23c78e
     pe_rsc_action_details_t *rsc_details = NULL;
23c78e
 #endif
23c78e
@@ -1026,8 +1028,7 @@ unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * contai
23c78e
                                action->meta, NULL, FALSE, data_set);
23c78e
 
23c78e
     // Determine probe default timeout differently
23c78e
-    if (pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)
23c78e
-            && (interval_ms == 0)) {
23c78e
+    if (is_probe) {
23c78e
         xmlNode *min_interval_mon = find_min_interval_mon(action->rsc, FALSE);
23c78e
 
23c78e
         if (min_interval_mon) {
23c78e
@@ -1099,8 +1100,7 @@ unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * contai
23c78e
     if (pcmk_is_set(pcmk_get_ra_caps(rsc_rule_data.standard),
23c78e
                     pcmk_ra_cap_fence_params)
23c78e
             && (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)
23c78e
-                    || (pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)
23c78e
-                            && (interval_ms == 0)))
23c78e
+                || is_probe)
23c78e
             && action->rsc->parameters) {
23c78e
 
23c78e
         value = g_hash_table_lookup(action->rsc->parameters,
23c78e
-- 
23c78e
1.8.3.1
23c78e
23c78e
23c78e
From 9de547849697cd6a3581db3f83b04f68d0405d9d Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Tue, 10 Nov 2020 15:15:01 -0600
23c78e
Subject: [PATCH 3/9] Refactor: scheduler: don't include originally unpacked
23c78e
 resource parameters in digest
23c78e
23c78e
Previously, when calculating an operation digest, calculate_main_digest() would
23c78e
grab the following, in order of highest to lowest precedence:
23c78e
23c78e
* instance attributes evaluated for the appropriate node
23c78e
* instance attributes specified with the operation
23c78e
* instance attributes as originally unpacked (without evaluating for any node)
23c78e
* resource meta-attributes
23c78e
23c78e
Adding the originally unpacked instance attributes was redundant, since
23c78e
node-evaluated instance attributes would always be a superset of those and
23c78e
would take precedence.
23c78e
---
23c78e
 lib/pengine/pe_digest.c | 1 -
23c78e
 1 file changed, 1 deletion(-)
23c78e
23c78e
diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c
23c78e
index 1e119f9..dd6b753 100644
23c78e
--- a/lib/pengine/pe_digest.c
23c78e
+++ b/lib/pengine/pe_digest.c
23c78e
@@ -162,7 +162,6 @@ calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc,
23c78e
     }
23c78e
     g_hash_table_foreach(local_rsc_params, hash2field, data->params_all);
23c78e
     g_hash_table_foreach(action->extra, hash2field, data->params_all);
23c78e
-    g_hash_table_foreach(rsc->parameters, hash2field, data->params_all);
23c78e
     g_hash_table_foreach(action->meta, hash2metafield, data->params_all);
23c78e
 
23c78e
 #if ENABLE_VERSIONED_ATTRS
23c78e
-- 
23c78e
1.8.3.1
23c78e
23c78e
23c78e
From e9921b2ab3e9eeab6227d97cc12b85fa04dfd187 Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Fri, 13 Nov 2020 09:27:12 -0600
23c78e
Subject: [PATCH 4/9] Refactor: scheduler: reuse existing function to check for
23c78e
 remote in XML
23c78e
23c78e
... to reduce code duplication and improve readability
23c78e
---
23c78e
 lib/pengine/bundle.c | 21 +++------------------
23c78e
 1 file changed, 3 insertions(+), 18 deletions(-)
23c78e
23c78e
diff --git a/lib/pengine/bundle.c b/lib/pengine/bundle.c
23c78e
index 76730c7..4f6eac3 100644
23c78e
--- a/lib/pengine/bundle.c
23c78e
+++ b/lib/pengine/bundle.c
23c78e
@@ -959,28 +959,13 @@ pe__bundle_needs_remote_name(pe_resource_t *rsc)
23c78e
     const char *value;
23c78e
 
23c78e
     if (rsc == NULL) {
23c78e
-        return FALSE;
23c78e
+        return false;
23c78e
     }
23c78e
 
23c78e
     value = g_hash_table_lookup(rsc->parameters, XML_RSC_ATTR_REMOTE_RA_ADDR);
23c78e
-    if (!pcmk__str_eq(value, "#uname", pcmk__str_casei)) {
23c78e
-        return FALSE;
23c78e
 
23c78e
-    } else {
23c78e
-        const char *match[3][2] = {
23c78e
-            { XML_ATTR_TYPE,           "remote"                },
23c78e
-            { XML_AGENT_ATTR_CLASS,    PCMK_RESOURCE_CLASS_OCF },
23c78e
-            { XML_AGENT_ATTR_PROVIDER, "pacemaker"             },
23c78e
-        };
23c78e
-
23c78e
-        for (int m = 0; m < 3; m++) {
23c78e
-            value = crm_element_value(rsc->xml, match[m][0]);
23c78e
-            if (!pcmk__str_eq(value, match[m][1], pcmk__str_casei)) {
23c78e
-                return FALSE;
23c78e
-            }
23c78e
-        }
23c78e
-    }
23c78e
-    return TRUE;
23c78e
+    return pcmk__str_eq(value, "#uname", pcmk__str_casei)
23c78e
+           && xml_contains_remote_node(rsc->xml);
23c78e
 }
23c78e
 
23c78e
 const char *
23c78e
-- 
23c78e
1.8.3.1
23c78e
23c78e
23c78e
From 0f220e1cd25ec095492ac4b346452520f4b71cf1 Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Wed, 11 Nov 2020 15:29:46 -0600
23c78e
Subject: [PATCH 5/9] Refactor: scheduler: remove dead code
23c78e
23c78e
Several internal expression-testing functions were unused. While they might
23c78e
have had some potential future value, the abundance of similarly named
23c78e
functions made debugging difficult. Comment blocks were added to the functions
23c78e
they wrapped, which should add similar value.
23c78e
23c78e
Also, we had an internal wrapper for pe__eval_date_expr() that was used
23c78e
only in crm_rule, so it was moved there.
23c78e
---
23c78e
 include/crm/pengine/rules_internal.h |  10 +--
23c78e
 lib/pengine/rules.c                  | 130 +++++++++++------------------------
23c78e
 tools/crm_rule.c                     |  27 +++++++-
23c78e
 3 files changed, 66 insertions(+), 101 deletions(-)
23c78e
23c78e
diff --git a/include/crm/pengine/rules_internal.h b/include/crm/pengine/rules_internal.h
23c78e
index f60263a..7380826 100644
23c78e
--- a/include/crm/pengine/rules_internal.h
23c78e
+++ b/include/crm/pengine/rules_internal.h
23c78e
@@ -1,5 +1,5 @@
23c78e
 /*
23c78e
- * Copyright 2015-2019 the Pacemaker project contributors
23c78e
+ * Copyright 2015-2020 the Pacemaker project contributors
23c78e
  *
23c78e
  * The version control history for this file may have further details.
23c78e
  *
23c78e
@@ -28,14 +28,6 @@ gboolean pe__eval_op_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data);
23c78e
 gboolean pe__eval_role_expr(xmlNode *expr, pe_rule_eval_data_t *rule_data);
23c78e
 gboolean pe__eval_rsc_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data);
23c78e
 
23c78e
-int pe_eval_date_expression(xmlNode *time_expr,
23c78e
-                            crm_time_t *now,
23c78e
-                            crm_time_t *next_change);
23c78e
-gboolean pe_test_date_expression(xmlNode *time_expr, crm_time_t *now,
23c78e
-                                 crm_time_t *next_change);
23c78e
 int pe_cron_range_satisfied(crm_time_t * now, xmlNode * cron_spec);
23c78e
-gboolean pe_test_attr_expression(xmlNode *expr, GHashTable *hash, crm_time_t *now,
23c78e
-                                 pe_match_data_t *match_data);
23c78e
-gboolean pe_test_role_expression(xmlNode * expr, enum rsc_role_e role, crm_time_t * now);
23c78e
 
23c78e
 #endif
23c78e
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
23c78e
index 28562aa..be30e67 100644
23c78e
--- a/lib/pengine/rules.c
23c78e
+++ b/lib/pengine/rules.c
23c78e
@@ -140,37 +140,6 @@ find_expression_type(xmlNode * expr)
23c78e
     return attr_expr;
23c78e
 }
23c78e
 
23c78e
-gboolean
23c78e
-pe_test_role_expression(xmlNode *expr, enum rsc_role_e role, crm_time_t *now)
23c78e
-{
23c78e
-    pe_rule_eval_data_t rule_data = {
23c78e
-        .node_hash = NULL,
23c78e
-        .role = role,
23c78e
-        .now = now,
23c78e
-        .match_data = NULL,
23c78e
-        .rsc_data = NULL,
23c78e
-        .op_data = NULL
23c78e
-    };
23c78e
-
23c78e
-    return pe__eval_role_expr(expr, &rule_data);
23c78e
-}
23c78e
-
23c78e
-gboolean
23c78e
-pe_test_attr_expression(xmlNode *expr, GHashTable *hash, crm_time_t *now,
23c78e
-                        pe_match_data_t *match_data)
23c78e
-{
23c78e
-    pe_rule_eval_data_t rule_data = {
23c78e
-        .node_hash = hash,
23c78e
-        .role = RSC_ROLE_UNKNOWN,
23c78e
-        .now = now,
23c78e
-        .match_data = match_data,
23c78e
-        .rsc_data = NULL,
23c78e
-        .op_data = NULL
23c78e
-    };
23c78e
-
23c78e
-    return pe__eval_attr_expr(expr, &rule_data);
23c78e
-}
23c78e
-
23c78e
 /* As per the nethack rules:
23c78e
  *
23c78e
  * moon period = 29.53058 days ~= 30, year = 365.2422 days
23c78e
@@ -331,38 +300,6 @@ pe_parse_xml_duration(crm_time_t * start, xmlNode * duration_spec)
23c78e
     return end;
23c78e
 }
23c78e
 
23c78e
-/*!
23c78e
- * \internal
23c78e
- * \brief Test a date expression (pass/fail) for a specific time
23c78e
- *
23c78e
- * \param[in]  time_expr    date_expression XML
23c78e
- * \param[in]  now          Time for which to evaluate expression
23c78e
- * \param[out] next_change  If not NULL, set to when evaluation will change
23c78e
- *
23c78e
- * \return TRUE if date expression is in effect at given time, FALSE otherwise
23c78e
- */
23c78e
-gboolean
23c78e
-pe_test_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
23c78e
-{
23c78e
-    pe_rule_eval_data_t rule_data = {
23c78e
-        .node_hash = NULL,
23c78e
-        .role = RSC_ROLE_UNKNOWN,
23c78e
-        .now = now,
23c78e
-        .match_data = NULL,
23c78e
-        .rsc_data = NULL,
23c78e
-        .op_data = NULL
23c78e
-    };
23c78e
-
23c78e
-    switch (pe__eval_date_expr(expr, &rule_data, next_change)) {
23c78e
-        case pcmk_rc_within_range:
23c78e
-        case pcmk_rc_ok:
23c78e
-            return TRUE;
23c78e
-
23c78e
-        default:
23c78e
-            return FALSE;
23c78e
-    }
23c78e
-}
23c78e
-
23c78e
 // Set next_change to t if t is earlier
23c78e
 static void
23c78e
 crm_time_set_if_earlier(crm_time_t *next_change, crm_time_t *t)
23c78e
@@ -375,31 +312,6 @@ crm_time_set_if_earlier(crm_time_t *next_change, crm_time_t *t)
23c78e
     }
23c78e
 }
23c78e
 
23c78e
-/*!
23c78e
- * \internal
23c78e
- * \brief Evaluate a date expression for a specific time
23c78e
- *
23c78e
- * \param[in]  time_expr    date_expression XML
23c78e
- * \param[in]  now          Time for which to evaluate expression
23c78e
- * \param[out] next_change  If not NULL, set to when evaluation will change
23c78e
- *
23c78e
- * \return Standard Pacemaker return code
23c78e
- */
23c78e
-int
23c78e
-pe_eval_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
23c78e
-{
23c78e
-    pe_rule_eval_data_t rule_data = {
23c78e
-        .node_hash = NULL,
23c78e
-        .role = RSC_ROLE_UNKNOWN,
23c78e
-        .now = now,
23c78e
-        .match_data = NULL,
23c78e
-        .rsc_data = NULL,
23c78e
-        .op_data = NULL
23c78e
-    };
23c78e
-
23c78e
-    return pe__eval_date_expr(expr, &rule_data, next_change);
23c78e
-}
23c78e
-
23c78e
 // Information about a block of nvpair elements
23c78e
 typedef struct sorted_set_s {
23c78e
     int score;                  // This block's score for sorting
23c78e
@@ -908,7 +820,16 @@ pe_eval_subexpr(xmlNode *expr, pe_rule_eval_data_t *rule_data, crm_time_t *next_
23c78e
             break;
23c78e
 
23c78e
         case time_expr:
23c78e
-            accept = pe_test_date_expression(expr, rule_data->now, next_change);
23c78e
+            switch (pe__eval_date_expr(expr, rule_data, next_change)) {
23c78e
+                case pcmk_rc_within_range:
23c78e
+                case pcmk_rc_ok:
23c78e
+                    accept = TRUE;
23c78e
+                    break;
23c78e
+
23c78e
+                default:
23c78e
+                    accept = FALSE;
23c78e
+                    break;
23c78e
+            }
23c78e
             break;
23c78e
 
23c78e
         case role_expr:
23c78e
@@ -1104,6 +1025,16 @@ accept_attr_expr(const char *l_val, const char *r_val, const char *type,
23c78e
     return false;   // Should never reach this point
23c78e
 }
23c78e
 
23c78e
+/*!
23c78e
+ * \internal
23c78e
+ * \brief Evaluate a node attribute expression based on #uname, #id, #kind,
23c78e
+ *        or a generic node attribute
23c78e
+ *
23c78e
+ * \param[in] expr       XML of rule expression
23c78e
+ * \param[in] rule_data  The match_data and node_hash members are used
23c78e
+ *
23c78e
+ * \return TRUE if rule_data satisfies the expression, FALSE otherwise
23c78e
+ */
23c78e
 gboolean
23c78e
 pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
23c78e
 {
23c78e
@@ -1169,8 +1100,16 @@ pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
23c78e
     return accept_attr_expr(h_val, value, type, op);
23c78e
 }
23c78e
 
23c78e
-
23c78e
-
23c78e
+/*!
23c78e
+ * \internal
23c78e
+ * \brief Evaluate a date_expression
23c78e
+ *
23c78e
+ * \param[in]  expr         XML of rule expression
23c78e
+ * \param[in]  rule_data    Only the now member is used
23c78e
+ * \param[out] next_change  If not NULL, set to when evaluation will change
23c78e
+ *
23c78e
+ * \return Standard Pacemaker return code
23c78e
+ */
23c78e
 int
23c78e
 pe__eval_date_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
23c78e
 {
23c78e
@@ -1285,6 +1224,15 @@ pe__eval_op_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data) {
23c78e
     return TRUE;
23c78e
 }
23c78e
 
23c78e
+/*!
23c78e
+ * \internal
23c78e
+ * \brief Evaluate a node attribute expression based on #role
23c78e
+ *
23c78e
+ * \param[in] expr       XML of rule expression
23c78e
+ * \param[in] rule_data  Only the role member is used
23c78e
+ *
23c78e
+ * \return TRUE if rule_data->role satisfies the expression, FALSE otherwise
23c78e
+ */
23c78e
 gboolean
23c78e
 pe__eval_role_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
23c78e
 {
23c78e
diff --git a/tools/crm_rule.c b/tools/crm_rule.c
23c78e
index 0e44828..2871f3d 100644
23c78e
--- a/tools/crm_rule.c
23c78e
+++ b/tools/crm_rule.c
23c78e
@@ -75,6 +75,31 @@ mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **e
23c78e
     return TRUE;
23c78e
 }
23c78e
 
23c78e
+/*!
23c78e
+ * \internal
23c78e
+ * \brief Evaluate a date expression for a specific time
23c78e
+ *
23c78e
+ * \param[in]  time_expr    date_expression XML
23c78e
+ * \param[in]  now          Time for which to evaluate expression
23c78e
+ * \param[out] next_change  If not NULL, set to when evaluation will change
23c78e
+ *
23c78e
+ * \return Standard Pacemaker return code
23c78e
+ */
23c78e
+static int
23c78e
+eval_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
23c78e
+{
23c78e
+    pe_rule_eval_data_t rule_data = {
23c78e
+        .node_hash = NULL,
23c78e
+        .role = RSC_ROLE_UNKNOWN,
23c78e
+        .now = now,
23c78e
+        .match_data = NULL,
23c78e
+        .rsc_data = NULL,
23c78e
+        .op_data = NULL
23c78e
+    };
23c78e
+
23c78e
+    return pe__eval_date_expr(expr, &rule_data, next_change);
23c78e
+}
23c78e
+
23c78e
 static int
23c78e
 crm_rule_check(pe_working_set_t *data_set, const char *rule_id, crm_time_t *effective_date)
23c78e
 {
23c78e
@@ -156,7 +181,7 @@ crm_rule_check(pe_working_set_t *data_set, const char *rule_id, crm_time_t *effe
23c78e
     CRM_ASSERT(match != NULL);
23c78e
     CRM_ASSERT(find_expression_type(match) == time_expr);
23c78e
 
23c78e
-    rc = pe_eval_date_expression(match, effective_date, NULL);
23c78e
+    rc = eval_date_expression(match, effective_date, NULL);
23c78e
 
23c78e
     if (rc == pcmk_rc_within_range) {
23c78e
         printf("Rule %s is still in effect\n", rule_id);
23c78e
-- 
23c78e
1.8.3.1
23c78e
23c78e
23c78e
From 91a6ec4bec86de7389fcd64cb27e315da760f0dd Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Wed, 11 Nov 2020 16:44:57 -0600
23c78e
Subject: [PATCH 6/9] Refactor: scheduler: make constraint unpacking function
23c78e
 static
23c78e
23c78e
... for linker efficiency and readability. Also change the return type to void
23c78e
since it was ignored (and the same for some related functions).
23c78e
---
23c78e
 include/pcmki/pcmki_sched_allocate.h   |  4 +--
23c78e
 lib/pacemaker/pcmk_sched_constraints.c | 46 ++++++++++++++++------------------
23c78e
 2 files changed, 23 insertions(+), 27 deletions(-)
23c78e
23c78e
diff --git a/include/pcmki/pcmki_sched_allocate.h b/include/pcmki/pcmki_sched_allocate.h
23c78e
index efc0da6..a7f8c11 100644
23c78e
--- a/include/pcmki/pcmki_sched_allocate.h
23c78e
+++ b/include/pcmki/pcmki_sched_allocate.h
23c78e
@@ -1,5 +1,5 @@
23c78e
 /*
23c78e
- * Copyright 2004-2019 the Pacemaker project contributors
23c78e
+ * Copyright 2004-2020 the Pacemaker project contributors
23c78e
  *
23c78e
  * The version control history for this file may have further details.
23c78e
  *
23c78e
@@ -143,8 +143,6 @@ extern gboolean unpack_rsc_order(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
 
23c78e
 extern gboolean unpack_rsc_colocation(xmlNode * xml_obj, pe_working_set_t * data_set);
23c78e
 
23c78e
-extern gboolean unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set);
23c78e
-
23c78e
 extern gboolean unpack_rsc_ticket(xmlNode * xml_obj, pe_working_set_t * data_set);
23c78e
 
23c78e
 void LogNodeActions(pe_working_set_t * data_set, gboolean terminal);
23c78e
diff --git a/lib/pacemaker/pcmk_sched_constraints.c b/lib/pacemaker/pcmk_sched_constraints.c
23c78e
index 6ed2d8c..121754d 100644
23c78e
--- a/lib/pacemaker/pcmk_sched_constraints.c
23c78e
+++ b/lib/pacemaker/pcmk_sched_constraints.c
23c78e
@@ -48,6 +48,7 @@ static pe__location_t *generate_location_rule(pe_resource_t *rsc,
23c78e
                                               crm_time_t *next_change,
23c78e
                                               pe_working_set_t *data_set,
23c78e
                                               pe_match_data_t *match_data);
23c78e
+static void unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set);
23c78e
 
23c78e
 static bool
23c78e
 evaluate_lifetime(xmlNode *lifetime, pe_working_set_t *data_set)
23c78e
@@ -709,11 +710,13 @@ tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set, const char * attr,
23c78e
     return TRUE;
23c78e
 }
23c78e
 
23c78e
-static gboolean unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role,
23c78e
-                             const char * score, pe_working_set_t * data_set, pe_match_data_t * match_data);
23c78e
+static void unpack_rsc_location(xmlNode *xml_obj, pe_resource_t *rsc_lh,
23c78e
+                                const char *role, const char *score,
23c78e
+                                pe_working_set_t *data_set,
23c78e
+                                pe_match_data_t *match_data);
23c78e
 
23c78e
-static gboolean
23c78e
-unpack_simple_location(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
+static void
23c78e
+unpack_simple_location(xmlNode *xml_obj, pe_working_set_t *data_set)
23c78e
 {
23c78e
     const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
23c78e
     const char *value = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE);
23c78e
@@ -721,7 +724,7 @@ unpack_simple_location(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
     if(value) {
23c78e
         pe_resource_t *rsc_lh = pe_find_constraint_resource(data_set->resources, value);
23c78e
 
23c78e
-        return unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
23c78e
+        unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
23c78e
     }
23c78e
 
23c78e
     value = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE_PATTERN);
23c78e
@@ -741,7 +744,7 @@ unpack_simple_location(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
                              " has invalid value '%s'", id, value);
23c78e
             regfree(r_patt);
23c78e
             free(r_patt);
23c78e
-            return FALSE;
23c78e
+            return;
23c78e
         }
23c78e
 
23c78e
         for (rIter = data_set->resources; rIter; rIter = rIter->next) {
23c78e
@@ -787,13 +790,12 @@ unpack_simple_location(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
         regfree(r_patt);
23c78e
         free(r_patt);
23c78e
     }
23c78e
-
23c78e
-    return FALSE;
23c78e
 }
23c78e
 
23c78e
-static gboolean
23c78e
-unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role,
23c78e
-                    const char * score, pe_working_set_t * data_set, pe_match_data_t * match_data)
23c78e
+static void
23c78e
+unpack_rsc_location(xmlNode *xml_obj, pe_resource_t *rsc_lh, const char *role,
23c78e
+                    const char *score, pe_working_set_t *data_set,
23c78e
+                    pe_match_data_t *match_data)
23c78e
 {
23c78e
     pe__location_t *location = NULL;
23c78e
     const char *id_lh = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE);
23c78e
@@ -804,7 +806,7 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
23c78e
     if (rsc_lh == NULL) {
23c78e
         pcmk__config_warn("Ignoring constraint '%s' because resource '%s' "
23c78e
                           "does not exist", id, id_lh);
23c78e
-        return FALSE;
23c78e
+        return;
23c78e
     }
23c78e
 
23c78e
     if (score == NULL) {
23c78e
@@ -816,7 +818,7 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
23c78e
         pe_node_t *match = pe_find_node(data_set->nodes, node);
23c78e
 
23c78e
         if (!match) {
23c78e
-            return FALSE;
23c78e
+            return;
23c78e
         }
23c78e
         location = rsc2node_new(id, rsc_lh, score_i, discovery, match, data_set);
23c78e
 
23c78e
@@ -850,7 +852,7 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
23c78e
             pe__update_recheck_time(t, data_set);
23c78e
         }
23c78e
         crm_time_free(next_change);
23c78e
-        return TRUE;
23c78e
+        return;
23c78e
     }
23c78e
 
23c78e
     if (role == NULL) {
23c78e
@@ -860,7 +862,7 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
23c78e
     if (location && role) {
23c78e
         if (text2role(role) == RSC_ROLE_UNKNOWN) {
23c78e
             pe_err("Invalid constraint %s: Bad role %s", id, role);
23c78e
-            return FALSE;
23c78e
+            return;
23c78e
 
23c78e
         } else {
23c78e
             enum rsc_role_e r = text2role(role);
23c78e
@@ -877,8 +879,6 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
23c78e
             }
23c78e
         }
23c78e
     }
23c78e
-
23c78e
-    return TRUE;
23c78e
 }
23c78e
 
23c78e
 static gboolean
23c78e
@@ -992,8 +992,8 @@ unpack_location_set(xmlNode * location, xmlNode * set, pe_working_set_t * data_s
23c78e
     return TRUE;
23c78e
 }
23c78e
 
23c78e
-gboolean
23c78e
-unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
+static void
23c78e
+unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set)
23c78e
 {
23c78e
     xmlNode *set = NULL;
23c78e
     gboolean any_sets = FALSE;
23c78e
@@ -1002,7 +1002,7 @@ unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
     xmlNode *expanded_xml = NULL;
23c78e
 
23c78e
     if (unpack_location_tags(xml_obj, &expanded_xml, data_set) == FALSE) {
23c78e
-        return FALSE;
23c78e
+        return;
23c78e
     }
23c78e
 
23c78e
     if (expanded_xml) {
23c78e
@@ -1020,7 +1020,7 @@ unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
                 if (expanded_xml) {
23c78e
                     free_xml(expanded_xml);
23c78e
                 }
23c78e
-                return FALSE;
23c78e
+                return;
23c78e
             }
23c78e
         }
23c78e
     }
23c78e
@@ -1031,10 +1031,8 @@ unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set)
23c78e
     }
23c78e
 
23c78e
     if (any_sets == FALSE) {
23c78e
-        return unpack_simple_location(xml_obj, data_set);
23c78e
+        unpack_simple_location(xml_obj, data_set);
23c78e
     }
23c78e
-
23c78e
-    return TRUE;
23c78e
 }
23c78e
 
23c78e
 static int
23c78e
-- 
23c78e
1.8.3.1
23c78e
23c78e
23c78e
From df842adafca8ba56ddb5b448490ffef54ea785d4 Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Fri, 13 Nov 2020 09:19:51 -0600
23c78e
Subject: [PATCH 7/9] Refactor: scheduler: trivial refactoring of nvpair
23c78e
 evaluation
23c78e
23c78e
... for readability
23c78e
---
23c78e
 lib/pengine/rules.c | 15 +++++++--------
23c78e
 1 file changed, 7 insertions(+), 8 deletions(-)
23c78e
23c78e
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
23c78e
index be30e67..86e7899 100644
23c78e
--- a/lib/pengine/rules.c
23c78e
+++ b/lib/pengine/rules.c
23c78e
@@ -529,20 +529,19 @@ static GList *
23c78e
 make_pairs(xmlNode *top, xmlNode *xml_obj, const char *set_name,
23c78e
            const char *always_first)
23c78e
 {
23c78e
-    GListPtr unsorted = NULL;
23c78e
-    const char *score = NULL;
23c78e
-    sorted_set_t *pair = NULL;
23c78e
-    xmlNode *attr_set = NULL;
23c78e
+    GList *unsorted = NULL;
23c78e
 
23c78e
     if (xml_obj == NULL) {
23c78e
         return NULL;
23c78e
     }
23c78e
-    for (attr_set = pcmk__xe_first_child(xml_obj); attr_set != NULL;
23c78e
+    for (xmlNode *attr_set = pcmk__xe_first_child(xml_obj); attr_set != NULL;
23c78e
          attr_set = pcmk__xe_next(attr_set)) {
23c78e
 
23c78e
-        /* Uncertain if set_name == NULL check is strictly necessary here */
23c78e
-        if (pcmk__str_eq(set_name, (const char *)attr_set->name, pcmk__str_null_matches)) {
23c78e
-            pair = NULL;
23c78e
+        if (pcmk__str_eq(set_name, (const char *) attr_set->name,
23c78e
+                         pcmk__str_null_matches)) {
23c78e
+            const char *score = NULL;
23c78e
+            sorted_set_t *pair = NULL;
23c78e
+
23c78e
             attr_set = expand_idref(attr_set, top);
23c78e
             if (attr_set == NULL) {
23c78e
                 continue;
23c78e
-- 
23c78e
1.8.3.1
23c78e
23c78e
23c78e
From 373c224ac1c41bd47a928a7523744c6c678a6543 Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Fri, 13 Nov 2020 09:21:35 -0600
23c78e
Subject: [PATCH 8/9] Low: scheduler: correctly skip dangling id-ref
23c78e
23c78e
When evaluating XML nvpair blocks, make_pairs() previously reused the
23c78e
"for" loop variable when expanding id-ref's. However if the id-ref was dangling
23c78e
(only possible if schema enforcement is turned off), this would make it NULL
23c78e
and thus exiting the loop instead of continuing.
23c78e
---
23c78e
 lib/pengine/rules.c | 11 ++++++-----
23c78e
 1 file changed, 6 insertions(+), 5 deletions(-)
23c78e
23c78e
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
23c78e
index 86e7899..1bd807f 100644
23c78e
--- a/lib/pengine/rules.c
23c78e
+++ b/lib/pengine/rules.c
23c78e
@@ -541,18 +541,19 @@ make_pairs(xmlNode *top, xmlNode *xml_obj, const char *set_name,
23c78e
                          pcmk__str_null_matches)) {
23c78e
             const char *score = NULL;
23c78e
             sorted_set_t *pair = NULL;
23c78e
+            xmlNode *expanded_attr_set = expand_idref(attr_set, top);
23c78e
 
23c78e
-            attr_set = expand_idref(attr_set, top);
23c78e
-            if (attr_set == NULL) {
23c78e
+            if (expanded_attr_set == NULL) {
23c78e
+                // Schema (if not "none") prevents this
23c78e
                 continue;
23c78e
             }
23c78e
 
23c78e
             pair = calloc(1, sizeof(sorted_set_t));
23c78e
-            pair->name = ID(attr_set);
23c78e
+            pair->name = ID(expanded_attr_set);
23c78e
             pair->special_name = always_first;
23c78e
-            pair->attr_set = attr_set;
23c78e
+            pair->attr_set = expanded_attr_set;
23c78e
 
23c78e
-            score = crm_element_value(attr_set, XML_RULE_ATTR_SCORE);
23c78e
+            score = crm_element_value(expanded_attr_set, XML_RULE_ATTR_SCORE);
23c78e
             pair->score = char2score(score);
23c78e
 
23c78e
             unsorted = g_list_prepend(unsorted, pair);
23c78e
-- 
23c78e
1.8.3.1
23c78e
23c78e
23c78e
From b59717751c168ec745bedbcc5696bee11036d931 Mon Sep 17 00:00:00 2001
23c78e
From: Ken Gaillot <kgaillot@redhat.com>
23c78e
Date: Thu, 12 Nov 2020 14:37:27 -0600
23c78e
Subject: [PATCH 9/9] Low: scheduler: treat missing parameter as NULL in rules
23c78e
 with value-source
23c78e
23c78e
Previously, if value-source were set to "param" or "meta", and an affected
23c78e
resource did not have the specified parameter, the parameter name would wrongly
23c78e
be used as the value to compare against. Now, use NULL as the value to compare
23c78e
against.
23c78e
---
23c78e
 lib/pengine/rules.c | 11 ++++++++---
23c78e
 1 file changed, 8 insertions(+), 3 deletions(-)
23c78e
23c78e
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
23c78e
index 1bd807f..e5d452f 100644
23c78e
--- a/lib/pengine/rules.c
23c78e
+++ b/lib/pengine/rules.c
23c78e
@@ -1041,6 +1041,7 @@ pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
23c78e
     gboolean attr_allocated = FALSE;
23c78e
     const char *h_val = NULL;
23c78e
     GHashTable *table = NULL;
23c78e
+    bool literal = true;
23c78e
 
23c78e
     const char *op = NULL;
23c78e
     const char *type = NULL;
23c78e
@@ -1071,18 +1072,22 @@ pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
23c78e
         }
23c78e
 
23c78e
         if (pcmk__str_eq(value_source, "param", pcmk__str_casei)) {
23c78e
+            literal = false;
23c78e
             table = rule_data->match_data->params;
23c78e
         } else if (pcmk__str_eq(value_source, "meta", pcmk__str_casei)) {
23c78e
+            literal = false;
23c78e
             table = rule_data->match_data->meta;
23c78e
         }
23c78e
     }
23c78e
 
23c78e
-    if (table) {
23c78e
+    if (!literal) {
23c78e
         const char *param_name = value;
23c78e
         const char *param_value = NULL;
23c78e
 
23c78e
-        if (param_name && param_name[0]) {
23c78e
-            if ((param_value = (const char *)g_hash_table_lookup(table, param_name))) {
23c78e
+        value = NULL;
23c78e
+        if ((table != NULL) && !pcmk__str_empty(param_name)) {
23c78e
+            param_value = (const char *)g_hash_table_lookup(table, param_name);
23c78e
+            if (param_value != NULL) {
23c78e
                 value = param_value;
23c78e
             }
23c78e
         }
23c78e
-- 
23c78e
1.8.3.1
23c78e