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