From 4521f547457af1201442e072d426fdf89de1150e Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 9 Nov 2020 18:09:54 -0600 Subject: [PATCH 01/13] API: libpe_status: add pe_rsc_params() and new pe_resource_t member Instead of a single parameters table for a resource, this allows the possibility of a parameter table per node for the resource, since rule-based parameters may evaluate differently on different nodes. --- include/crm/pengine/complex.h | 5 +++- include/crm/pengine/pe_types.h | 8 +++++- lib/pengine/complex.c | 61 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/include/crm/pengine/complex.h b/include/crm/pengine/complex.h index effa44f..1d010f4 100644 --- a/include/crm/pengine/complex.h +++ b/include/crm/pengine/complex.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. * @@ -19,6 +19,9 @@ extern "C" { #include // pe_node_t, pe_resource_t, etc. extern resource_object_functions_t resource_class_functions[]; + +GHashTable *pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, + pe_working_set_t *data_set); void get_meta_attributes(GHashTable * meta_hash, pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set); void get_rsc_attributes(GHashTable *meta_hash, pe_resource_t *rsc, diff --git a/include/crm/pengine/pe_types.h b/include/crm/pengine/pe_types.h index 59d5ce8..5529714 100644 --- a/include/crm/pengine/pe_types.h +++ b/include/crm/pengine/pe_types.h @@ -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. * @@ -371,6 +371,12 @@ struct pe_resource_s { pe_node_t *lock_node; // Resource is shutdown-locked to this node time_t lock_time; // When shutdown lock started + /* Resource parameters may have node-attribute-based rules, which means the + * values can vary by node. This table is a cache of parameter name/value + * tables for each node (as needed). Use pe_rsc_params() to get the table + * for a given node. + */ + GHashTable *parameter_cache; // Key = node name, value = parameters table #if ENABLE_VERSIONED_ATTRS xmlNode *versioned_parameters; #endif diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c index 5f484ad..7037ca1 100644 --- a/lib/pengine/complex.c +++ b/lib/pengine/complex.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. * @@ -435,6 +435,62 @@ detect_promotable(pe_resource_t *rsc) return FALSE; } +static void +free_params_table(gpointer data) +{ + g_hash_table_destroy((GHashTable *) data); +} + +/*! + * \brief Get a table of resource parameters + * + * \param[in] rsc Resource to query + * \param[in] node Node for evaluating rules (NULL for defaults) + * \param[in] data_set Cluster working set + * + * \return Hash table containing resource parameter names and values + * (or NULL if \p rsc or \p data_set is NULL) + * \note The returned table will be destroyed when the resource is freed, so + * callers should not destroy it. + */ +GHashTable * +pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set) +{ + GHashTable *params_on_node = NULL; + + /* A NULL node is used to request the resource's default parameters + * (not evaluated for node), but we always want something non-NULL + * as a hash table key. + */ + const char *node_name = ""; + + // Sanity check + if ((rsc == NULL) || (data_set == NULL)) { + return NULL; + } + if ((node != NULL) && (node->details->uname != NULL)) { + node_name = node->details->uname; + } + + // Find the parameter table for given node + if (rsc->parameter_cache == NULL) { + rsc->parameter_cache = g_hash_table_new_full(crm_strcase_hash, + crm_strcase_equal, free, + free_params_table); + } else { + params_on_node = g_hash_table_lookup(rsc->parameter_cache, node_name); + } + + // If none exists yet, create one with parameters evaluated for node + if (params_on_node == NULL) { + params_on_node = crm_str_table_new(); + get_rsc_attributes(params_on_node, rsc, node, data_set); + g_hash_table_insert(rsc->parameter_cache, strdup(node_name), + params_on_node); + } + return params_on_node; +} + gboolean common_unpack(xmlNode * xml_obj, pe_resource_t ** rsc, pe_resource_t * parent, pe_working_set_t * data_set) @@ -869,6 +925,9 @@ common_free(pe_resource_t * rsc) if (rsc->parameters != NULL) { g_hash_table_destroy(rsc->parameters); } + if (rsc->parameter_cache != NULL) { + g_hash_table_destroy(rsc->parameter_cache); + } #if ENABLE_VERSIONED_ATTRS if (rsc->versioned_parameters != NULL) { free_xml(rsc->versioned_parameters); -- 1.8.3.1 From d5075f64c5fff1f037ee8dbca2ad6268bce15681 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Wed, 11 Nov 2020 13:03:50 -0600 Subject: [PATCH 02/13] API: libpe_status: ignore ->parameter() resource object function's create argument This uses the new resource parameter function to implement ->parameter(). That means the parameter table will always be created if not already existent. ->parameter() is not called internally. --- lib/pengine/native.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/lib/pengine/native.c b/lib/pengine/native.c index 193be17..95c3da9 100644 --- a/lib/pengine/native.c +++ b/lib/pengine/native.c @@ -312,48 +312,28 @@ native_find_rsc(pe_resource_t * rsc, const char *id, const pe_node_t *on_node, return NULL; } +// create is ignored char * native_parameter(pe_resource_t * rsc, pe_node_t * node, gboolean create, const char *name, pe_working_set_t * data_set) { char *value_copy = NULL; const char *value = NULL; - GHashTable *hash = NULL; - GHashTable *local_hash = NULL; + GHashTable *params = NULL; CRM_CHECK(rsc != NULL, return NULL); CRM_CHECK(name != NULL && strlen(name) != 0, return NULL); pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id); - - if (create || g_hash_table_size(rsc->parameters) == 0) { - if (node != NULL) { - pe_rsc_trace(rsc, "Creating hash with node %s", node->details->uname); - } else { - pe_rsc_trace(rsc, "Creating default hash"); - } - - local_hash = crm_str_table_new(); - - get_rsc_attributes(local_hash, rsc, node, data_set); - - hash = local_hash; - } else { - hash = rsc->parameters; - } - - value = g_hash_table_lookup(hash, name); + params = pe_rsc_params(rsc, node, data_set); + value = g_hash_table_lookup(params, name); if (value == NULL) { /* try meta attributes instead */ value = g_hash_table_lookup(rsc->meta, name); } - if (value != NULL) { value_copy = strdup(value); } - if (local_hash != NULL) { - g_hash_table_destroy(local_hash); - } return value_copy; } -- 1.8.3.1 From 7089c19d1a1a79dd353ade0002ba6ed3321145ca Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 9 Nov 2020 18:15:56 -0600 Subject: [PATCH 03/13] Refactor: fencer: use new resource parameters function --- daemons/fenced/pacemaker-fenced.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index 69c29a7..5390d66 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -643,6 +643,7 @@ static void cib_device_update(pe_resource_t *rsc, pe_working_set_t *data_set) /* Our node is allowed, so update the device information */ int rc; xmlNode *data; + GHashTable *rsc_params = NULL; GHashTableIter gIter; stonith_key_value_t *params = NULL; @@ -651,12 +652,12 @@ static void cib_device_update(pe_resource_t *rsc, pe_working_set_t *data_set) const char *rsc_provides = NULL; crm_debug("Device %s is allowed on %s: score=%d", rsc->id, stonith_our_uname, node->weight); - get_rsc_attributes(rsc->parameters, rsc, node, data_set); + rsc_params = pe_rsc_params(rsc, node, data_set); get_meta_attributes(rsc->meta, rsc, node, data_set); rsc_provides = g_hash_table_lookup(rsc->meta, PCMK_STONITH_PROVIDES); - g_hash_table_iter_init(&gIter, rsc->parameters); + g_hash_table_iter_init(&gIter, rsc_params); while (g_hash_table_iter_next(&gIter, (gpointer *) & name, (gpointer *) & value)) { if (!name || !value) { continue; -- 1.8.3.1 From ae0a2f26891b30a7bcf09467dac461a17d071cd9 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 9 Nov 2020 18:35:08 -0600 Subject: [PATCH 04/13] Refactor: scheduler: use new resource parameter function when getting fence action timeout This means that the fence device's active node is used to evaluate the parameters, which will be of use if we ever support rules in fence device configuration. --- lib/pengine/utils.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c index b07afbe..831f890 100644 --- a/lib/pengine/utils.c +++ b/lib/pengine/utils.c @@ -1099,12 +1099,12 @@ 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) - || is_probe) - && action->rsc->parameters) { + && (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei) + || is_probe)) { - value = g_hash_table_lookup(action->rsc->parameters, - "pcmk_monitor_timeout"); + GHashTable *params = pe_rsc_params(action->rsc, action->node, data_set); + + value = g_hash_table_lookup(params, "pcmk_monitor_timeout"); if (value) { crm_trace("\t%s: Setting timeout to pcmk_monitor_timeout '%s', " -- 1.8.3.1 From 25cf7f5e0f6e3a22000fcaa4f4492fe1c086252b Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Fri, 13 Nov 2020 09:27:43 -0600 Subject: [PATCH 05/13] Refactor: scheduler: use new resource parameter function when replacing bundle #uname --- include/crm/pengine/internal.h | 8 +++++--- lib/pacemaker/pcmk_sched_allocate.c | 2 +- lib/pacemaker/pcmk_sched_bundle.c | 14 ++++++++++++-- lib/pengine/bundle.c | 12 ++++++++---- lib/pengine/pe_digest.c | 2 +- lib/pengine/unpack.c | 2 +- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/include/crm/pengine/internal.h b/include/crm/pengine/internal.h index 1e5aee1..9f4e28a 100644 --- a/include/crm/pengine/internal.h +++ b/include/crm/pengine/internal.h @@ -545,9 +545,11 @@ int pe__common_output_text(pcmk__output_t *out, pe_resource_t * rsc, const char int pe__common_output_html(pcmk__output_t *out, pe_resource_t * rsc, const char *name, pe_node_t *node, long options); pe_resource_t *pe__find_bundle_replica(const pe_resource_t *bundle, const pe_node_t *node); -bool pe__bundle_needs_remote_name(pe_resource_t *rsc); -const char *pe__add_bundle_remote_name(pe_resource_t *rsc, xmlNode *xml, - const char *field); +bool pe__bundle_needs_remote_name(pe_resource_t *rsc, + pe_working_set_t *data_set); +const char *pe__add_bundle_remote_name(pe_resource_t *rsc, + pe_working_set_t *data_set, + xmlNode *xml, const char *field); const char *pe_node_attribute_calculated(const pe_node_t *node, const char *name, const pe_resource_t *rsc); diff --git a/lib/pacemaker/pcmk_sched_allocate.c b/lib/pacemaker/pcmk_sched_allocate.c index a0fb5ab..22f284a 100644 --- a/lib/pacemaker/pcmk_sched_allocate.c +++ b/lib/pacemaker/pcmk_sched_allocate.c @@ -470,7 +470,7 @@ check_actions_for(xmlNode * rsc_entry, pe_resource_t * rsc, pe_node_t * node, pe * has changed, clear any fail count so they can be retried fresh. */ - if (pe__bundle_needs_remote_name(rsc)) { + if (pe__bundle_needs_remote_name(rsc, data_set)) { /* We haven't allocated resources to nodes yet, so if the * REMOTE_CONTAINER_HACK is used, we may calculate the digest * based on the literal "#uname" value rather than the properly diff --git a/lib/pacemaker/pcmk_sched_bundle.c b/lib/pacemaker/pcmk_sched_bundle.c index ac9219c..4f41b70 100644 --- a/lib/pacemaker/pcmk_sched_bundle.c +++ b/lib/pacemaker/pcmk_sched_bundle.c @@ -911,7 +911,7 @@ pcmk__bundle_expand(pe_resource_t *rsc, pe_working_set_t * data_set) CRM_ASSERT(replica); if (replica->remote && replica->container - && pe__bundle_needs_remote_name(replica->remote)) { + && pe__bundle_needs_remote_name(replica->remote, data_set)) { /* REMOTE_CONTAINER_HACK: Allow remote nodes to run containers that * run pacemaker-remoted inside, without needing a separate IP for @@ -923,12 +923,22 @@ pcmk__bundle_expand(pe_resource_t *rsc, pe_working_set_t * data_set) replica->remote->xml, LOG_ERR); const char *calculated_addr = NULL; + // Replace the value in replica->remote->xml (if appropriate) calculated_addr = pe__add_bundle_remote_name(replica->remote, + data_set, nvpair, "value"); if (calculated_addr) { + /* Since this is for the bundle as a resource, and not any + * particular action, replace the value in the default + * parameters (not evaluated for node). action2xml() will grab + * it from there to replace it in node-evaluated parameters. + */ + GHashTable *params = pe_rsc_params(replica->remote, + NULL, data_set); + crm_trace("Set address for bundle connection %s to bundle host %s", replica->remote->id, calculated_addr); - g_hash_table_replace(replica->remote->parameters, + g_hash_table_replace(params, strdup(XML_RSC_ATTR_REMOTE_RA_ADDR), strdup(calculated_addr)); } else { diff --git a/lib/pengine/bundle.c b/lib/pengine/bundle.c index 7b326e9..615a35a 100644 --- a/lib/pengine/bundle.c +++ b/lib/pengine/bundle.c @@ -948,29 +948,33 @@ replica_for_remote(pe_resource_t *remote) } bool -pe__bundle_needs_remote_name(pe_resource_t *rsc) +pe__bundle_needs_remote_name(pe_resource_t *rsc, pe_working_set_t *data_set) { const char *value; + GHashTable *params = NULL; if (rsc == NULL) { return false; } - value = g_hash_table_lookup(rsc->parameters, XML_RSC_ATTR_REMOTE_RA_ADDR); + // Use NULL node since pcmk__bundle_expand() uses that to set value + params = pe_rsc_params(rsc, NULL, data_set); + value = g_hash_table_lookup(params, XML_RSC_ATTR_REMOTE_RA_ADDR); return pcmk__str_eq(value, "#uname", pcmk__str_casei) && xml_contains_remote_node(rsc->xml); } const char * -pe__add_bundle_remote_name(pe_resource_t *rsc, xmlNode *xml, const char *field) +pe__add_bundle_remote_name(pe_resource_t *rsc, pe_working_set_t *data_set, + xmlNode *xml, const char *field) { // REMOTE_CONTAINER_HACK: Allow remote nodes that start containers with pacemaker remote inside pe_node_t *node = NULL; pe__bundle_replica_t *replica = NULL; - if (!pe__bundle_needs_remote_name(rsc)) { + if (!pe__bundle_needs_remote_name(rsc, data_set)) { return NULL; } diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c index f55c896..f6e41e9 100644 --- a/lib/pengine/pe_digest.c +++ b/lib/pengine/pe_digest.c @@ -147,7 +147,7 @@ calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc, /* REMOTE_CONTAINER_HACK: Allow Pacemaker Remote nodes to run containers * that themselves are Pacemaker Remote nodes */ - if (pe__add_bundle_remote_name(rsc, data->params_all, + if (pe__add_bundle_remote_name(rsc, data_set, data->params_all, XML_RSC_ATTR_REMOTE_RA_ADDR)) { crm_trace("Set address for bundle connection %s (on %s)", rsc->id, node->details->uname); diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c index a15bb92..281bc88 100644 --- a/lib/pengine/unpack.c +++ b/lib/pengine/unpack.c @@ -3182,7 +3182,7 @@ should_clear_for_param_change(xmlNode *xml_op, const char *task, { if (!strcmp(task, "start") || !strcmp(task, "monitor")) { - if (pe__bundle_needs_remote_name(rsc)) { + if (pe__bundle_needs_remote_name(rsc, data_set)) { /* We haven't allocated resources yet, so we can't reliably * substitute addr parameters for the REMOTE_CONTAINER_HACK. * When that's needed, defer the check until later. -- 1.8.3.1 From 992b2edfe573a2bfd510090b37a8a1b355ad3c44 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 10 Nov 2020 15:32:29 -0600 Subject: [PATCH 06/13] Refactor: scheduler: use new resource parameter function when creating graph --- lib/pacemaker/pcmk_sched_graph.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/pacemaker/pcmk_sched_graph.c b/lib/pacemaker/pcmk_sched_graph.c index c012d23..f0d1f47 100644 --- a/lib/pacemaker/pcmk_sched_graph.c +++ b/lib/pacemaker/pcmk_sched_graph.c @@ -1210,11 +1210,29 @@ action2xml(pe_action_t * action, gboolean as_input, pe_working_set_t *data_set) g_hash_table_foreach(action->extra, hash2field, args_xml); if (action->rsc != NULL && action->node) { - GHashTable *p = crm_str_table_new(); + // Get the resource instance attributes, evaluated properly for node + GHashTable *params = pe_rsc_params(action->rsc, action->node, data_set); - get_rsc_attributes(p, action->rsc, action->node, data_set); - g_hash_table_foreach(p, hash2smartfield, args_xml); - g_hash_table_destroy(p); + /* REMOTE_CONTAINER_HACK: If this is a remote connection resource with + * addr="#uname", pull the actual value from the parameters evaluated + * without a node (which was put there earlier in stage8() when the + * bundle's expand() method was called). + */ + const char *remote_addr = g_hash_table_lookup(params, + XML_RSC_ATTR_REMOTE_RA_ADDR); + + if (pcmk__str_eq(remote_addr, "#uname", pcmk__str_none)) { + GHashTable *base = pe_rsc_params(action->rsc, NULL, data_set); + + remote_addr = g_hash_table_lookup(base, + XML_RSC_ATTR_REMOTE_RA_ADDR); + if (remote_addr != NULL) { + g_hash_table_insert(params, strdup(XML_RSC_ATTR_REMOTE_RA_ADDR), + strdup(remote_addr)); + } + } + + g_hash_table_foreach(params, hash2smartfield, args_xml); #if ENABLE_VERSIONED_ATTRS { @@ -1230,7 +1248,9 @@ action2xml(pe_action_t * action, gboolean as_input, pe_working_set_t *data_set) #endif } else if(action->rsc && action->rsc->variant <= pe_native) { - g_hash_table_foreach(action->rsc->parameters, hash2smartfield, args_xml); + GHashTable *params = pe_rsc_params(action->rsc, NULL, data_set); + + g_hash_table_foreach(params, hash2smartfield, args_xml); #if ENABLE_VERSIONED_ATTRS if (xml_has_children(action->rsc->versioned_parameters)) { -- 1.8.3.1 From 94316455ceead6f466e901d38e421f6116cf22d3 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 9 Nov 2020 16:04:23 -0600 Subject: [PATCH 07/13] Low: scheduler: calculate secure digest properly for node attribute rules 6830621 corrected secure digest calculation in most cases, but did not work properly when non-sensitive parameters depended on node attribute-based rules (since it used rsc->parameters, which is not evaluated for node). This fixes it by using the new resource parameters function (which is the equivalent of what calculate_main_digest() already was doing, so it is now exposed earlier for use by both digest functions). --- lib/pengine/pe_digest.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c index f6e41e9..2066a53 100644 --- a/lib/pengine/pe_digest.c +++ b/lib/pengine/pe_digest.c @@ -124,6 +124,7 @@ append_all_versioned_params(pe_resource_t *rsc, pe_node_t *node, * \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] params Resource parameters evaluated for node * \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) @@ -133,14 +134,12 @@ append_all_versioned_params(pe_resource_t *rsc, pe_node_t *node, */ static void calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc, - pe_node_t *node, const char *task, guint *interval_ms, + pe_node_t *node, GHashTable *params, + const char *task, guint *interval_ms, xmlNode *xml_op, const char *op_version, GHashTable *overrides, pe_working_set_t *data_set) { pe_action_t *action = NULL; - GHashTable *local_rsc_params = crm_str_table_new(); - - get_rsc_attributes(local_rsc_params, rsc, node, data_set); data->params_all = create_xml_node(NULL, XML_TAG_PARAMS); @@ -174,7 +173,7 @@ calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc, if (overrides != NULL) { g_hash_table_foreach(overrides, hash2field, data->params_all); } - g_hash_table_foreach(local_rsc_params, hash2field, data->params_all); + g_hash_table_foreach(params, hash2field, data->params_all); g_hash_table_foreach(action->extra, hash2field, data->params_all); g_hash_table_foreach(action->meta, hash2metafield, data->params_all); @@ -184,7 +183,6 @@ calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc, pcmk__filter_op_for_digest(data->params_all); - g_hash_table_destroy(local_rsc_params); pe_free_action(action); data->digest_all_calc = calculate_operation_digest(data->params_all, @@ -204,14 +202,15 @@ is_fence_param(xmlAttrPtr attr, void *user_data) * * \param[out] data Digest cache entry to modify * \param[in] rsc Resource that action was for + * \param[in] params Resource parameters evaluated for node * \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 */ static void calculate_secure_digest(op_digest_cache_t *data, pe_resource_t *rsc, - xmlNode *xml_op, const char *op_version, - GHashTable *overrides) + GHashTable *params, xmlNode *xml_op, + const char *op_version, GHashTable *overrides) { const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); const char *secure_list = NULL; @@ -222,16 +221,12 @@ calculate_secure_digest(op_digest_cache_t *data, pe_resource_t *rsc, secure_list = crm_element_value(xml_op, XML_LRM_ATTR_OP_SECURE); } - /* The controller doesn't create a digest of *all* non-sensitive - * parameters, only those listed in resource agent meta-data. The - * equivalent here is rsc->parameters. - */ data->params_secure = create_xml_node(NULL, XML_TAG_PARAMS); if (overrides != NULL) { g_hash_table_foreach(overrides, hash2field, data->params_secure); } - g_hash_table_foreach(rsc->parameters, hash2field, data->params_secure); + g_hash_table_foreach(params, hash2field, data->params_secure); if (secure_list != NULL) { pcmk__xe_remove_matching_attrs(data->params_secure, attr_not_in_string, (void *) secure_list); @@ -328,6 +323,7 @@ pe__calculate_digests(pe_resource_t *rsc, const char *task, guint *interval_ms, { op_digest_cache_t *data = calloc(1, sizeof(op_digest_cache_t)); const char *op_version = CRM_FEATURE_SET; + GHashTable *params = NULL; if (data == NULL) { return NULL; @@ -336,10 +332,12 @@ pe__calculate_digests(pe_resource_t *rsc, const char *task, guint *interval_ms, op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION); } - calculate_main_digest(data, rsc, node, task, interval_ms, xml_op, + params = pe_rsc_params(rsc, node, data_set); + calculate_main_digest(data, rsc, node, params, task, interval_ms, xml_op, op_version, overrides, data_set); if (calc_secure) { - calculate_secure_digest(data, rsc, xml_op, op_version, overrides); + calculate_secure_digest(data, rsc, params, xml_op, op_version, + overrides); } calculate_restart_digest(data, xml_op, op_version); return data; -- 1.8.3.1 From f546d0125b6f39fae744f43dad752089648e3f1f Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 10 Nov 2020 16:01:32 -0600 Subject: [PATCH 08/13] Fix: tools: respect rules when showing node attributes in crm_mon Previously, crm_mon checked rsc->parameters for ocf:pacemaker:ping parameter values. However that is not evaluated for node attribute rules. It also called get_rsc_attributes() for all resources unnecessarily, since that's part of common_unpack(). Now, use pe_rsc_params() to get the right values per node. --- tools/crm_mon.h | 1 - tools/crm_mon_print.c | 28 ++++++++++++++-------------- tools/crm_mon_runtime.c | 15 +-------------- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/tools/crm_mon.h b/tools/crm_mon.h index 143e8d8..f746507 100644 --- a/tools/crm_mon.h +++ b/tools/crm_mon.h @@ -109,7 +109,6 @@ int print_html_status(pcmk__output_t *out, pe_working_set_t *data_set, GList *append_attr_list(GList *attr_list, char *name); void blank_screen(void); -void crm_mon_get_parameters(pe_resource_t *rsc, pe_working_set_t *data_set); unsigned int get_resource_display_options(unsigned int mon_ops); void crm_mon_register_messages(pcmk__output_t *out); diff --git a/tools/crm_mon_print.c b/tools/crm_mon_print.c index cc3efb0..8ae11bf 100644 --- a/tools/crm_mon_print.c +++ b/tools/crm_mon_print.c @@ -38,7 +38,8 @@ static int print_rsc_history(pcmk__output_t *out, pe_working_set_t *data_set, static int print_node_history(pcmk__output_t *out, pe_working_set_t *data_set, pe_node_t *node, xmlNode *node_state, gboolean operations, unsigned int mon_ops, GListPtr only_node, GListPtr only_rsc); -static gboolean add_extra_info(pcmk__output_t *out, pe_node_t * node, GListPtr rsc_list, +static gboolean add_extra_info(pcmk__output_t *out, pe_node_t *node, + GListPtr rsc_list, pe_working_set_t *data_set, const char *attrname, int *expected_score); static void print_node_attribute(gpointer name, gpointer user_data); static int print_node_summary(pcmk__output_t *out, pe_working_set_t * data_set, @@ -330,7 +331,8 @@ print_node_history(pcmk__output_t *out, pe_working_set_t *data_set, */ static gboolean add_extra_info(pcmk__output_t *out, pe_node_t *node, GListPtr rsc_list, - const char *attrname, int *expected_score) + pe_working_set_t *data_set, const char *attrname, + int *expected_score) { GListPtr gIter = NULL; @@ -338,9 +340,11 @@ add_extra_info(pcmk__output_t *out, pe_node_t *node, GListPtr rsc_list, pe_resource_t *rsc = (pe_resource_t *) gIter->data; const char *type = g_hash_table_lookup(rsc->meta, "type"); const char *name = NULL; + GHashTable *params = NULL; if (rsc->children != NULL) { - if (add_extra_info(out, node, rsc->children, attrname, expected_score)) { + if (add_extra_info(out, node, rsc->children, data_set, attrname, + expected_score)) { return TRUE; } } @@ -349,7 +353,8 @@ add_extra_info(pcmk__output_t *out, pe_node_t *node, GListPtr rsc_list, continue; } - name = g_hash_table_lookup(rsc->parameters, "name"); + params = pe_rsc_params(rsc, node, data_set); + name = g_hash_table_lookup(params, "name"); if (name == NULL) { name = "pingd"; @@ -359,8 +364,8 @@ add_extra_info(pcmk__output_t *out, pe_node_t *node, GListPtr rsc_list, if (pcmk__str_eq(name, attrname, pcmk__str_casei)) { int host_list_num = 0; /* int value = crm_parse_int(attrvalue, "0"); */ - const char *hosts = g_hash_table_lookup(rsc->parameters, "host_list"); - const char *multiplier = g_hash_table_lookup(rsc->parameters, "multiplier"); + const char *hosts = g_hash_table_lookup(params, "host_list"); + const char *multiplier = g_hash_table_lookup(params, "multiplier"); if (hosts) { char **host_list = g_strsplit(hosts, " ", 0); @@ -381,6 +386,7 @@ add_extra_info(pcmk__output_t *out, pe_node_t *node, GListPtr rsc_list, struct mon_attr_data { pcmk__output_t *out; pe_node_t *node; + pe_working_set_t *data_set; }; static void @@ -394,7 +400,7 @@ print_node_attribute(gpointer name, gpointer user_data) value = pe_node_attribute_raw(data->node, name); add_extra = add_extra_info(data->out, data->node, data->node->details->running_rsc, - name, &expected_score); + data->data_set, name, &expected_score); /* Print attribute name and value */ data->out->message(data->out, "node-attribute", name, value, add_extra, @@ -547,19 +553,13 @@ print_node_attributes(pcmk__output_t *out, pe_working_set_t *data_set, GListPtr gIter = NULL; int rc = pcmk_rc_no_output; - /* Unpack all resource parameters (it would be more efficient to do this - * only when needed for the first time in add_extra_info()) - */ - for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) { - crm_mon_get_parameters(gIter->data, data_set); - } - /* Display each node's attributes */ for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { struct mon_attr_data data; data.out = out; data.node = (pe_node_t *) gIter->data; + data.data_set = data_set; if (data.node && data.node->details && data.node->details->online) { GList *attr_list = NULL; diff --git a/tools/crm_mon_runtime.c b/tools/crm_mon_runtime.c index ce31559..43152ce 100644 --- a/tools/crm_mon_runtime.c +++ b/tools/crm_mon_runtime.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 the Pacemaker project contributors + * Copyright 2019-2020 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -66,19 +66,6 @@ append_attr_list(GList *attr_list, char *name) return g_list_insert_sorted(attr_list, name, compare_attribute); } -void -crm_mon_get_parameters(pe_resource_t *rsc, pe_working_set_t * data_set) -{ - get_rsc_attributes(rsc->parameters, rsc, NULL, data_set); - if(rsc->children) { - GListPtr gIter = NULL; - - for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { - crm_mon_get_parameters(gIter->data, data_set); - } - } -} - /*! * \internal * \brief Return resource display options corresponding to command-line choices -- 1.8.3.1 From 397ad868d464a0ffd14ed527a97010e141ac60b3 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Wed, 11 Nov 2020 12:59:34 -0600 Subject: [PATCH 09/13] Fix: scheduler: multiple issues with value-source in location rules Delay creating rule match data for location constraints until the node is known, and evaluate the rules using that node (using the new resource parameter function). This fixes multiple issues: * Previously, match data using resource parameters was created only when rsc-pattern was specified and a resource positively matched. This meant that a node attribute rule expression with a value-source of "param" or "meta" would only work in that case, and not when rsc was specified instead, or when rsc-pattern was specified with an inverted match ("!pattern"), or when a rule was used in a constraint with a resource set. * Previously, with rsc-pattern, the match data used the resource's default parameters (not evaluated by node). This meant that a location rule that used a node attribute expression with a value-source of "param" could not be used with a resource parameter that itself was determined by a rule using a node attribute expression. --- lib/pacemaker/pcmk_sched_constraints.c | 40 ++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/pacemaker/pcmk_sched_constraints.c b/lib/pacemaker/pcmk_sched_constraints.c index 0029ad7..92b9740 100644 --- a/lib/pacemaker/pcmk_sched_constraints.c +++ b/lib/pacemaker/pcmk_sched_constraints.c @@ -47,7 +47,7 @@ static pe__location_t *generate_location_rule(pe_resource_t *rsc, const char *discovery, crm_time_t *next_change, pe_working_set_t *data_set, - pe_match_data_t *match_data); + pe_re_match_data_t *match_data); static void unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set); static void unpack_rsc_colocation(xmlNode *xml_obj, pe_working_set_t *data_set); @@ -714,7 +714,7 @@ tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set, const char * attr, 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_re_match_data_t *match_data); static void unpack_simple_location(xmlNode *xml_obj, pe_working_set_t *data_set) @@ -769,13 +769,9 @@ unpack_simple_location(xmlNode *xml_obj, pe_working_set_t *data_set) .nregs = nregs, .pmatch = pmatch }; - pe_match_data_t match_data = { - .re = &re_match_data, - .params = r->parameters, - .meta = r->meta, - }; + crm_debug("'%s' matched '%s' for %s", r->id, value, id); - unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, &match_data); + unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, &re_match_data); } else if (invert && (status != 0)) { crm_debug("'%s' is an inverted match of '%s' for %s", r->id, value, id); @@ -796,7 +792,7 @@ unpack_simple_location(xmlNode *xml_obj, pe_working_set_t *data_set) 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_re_match_data_t *re_match_data) { pe__location_t *location = NULL; const char *id_lh = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE); @@ -836,7 +832,7 @@ unpack_rsc_location(xmlNode *xml_obj, pe_resource_t *rsc_lh, const char *role, empty = FALSE; crm_trace("Unpacking %s/%s", id, ID(rule_xml)); generate_location_rule(rsc_lh, rule_xml, discovery, next_change, - data_set, match_data); + data_set, re_match_data); } if (empty) { @@ -1067,7 +1063,8 @@ get_node_score(const char *rule, const char *score, gboolean raw, pe_node_t * no static pe__location_t * generate_location_rule(pe_resource_t *rsc, xmlNode *rule_xml, const char *discovery, crm_time_t *next_change, - pe_working_set_t *data_set, pe_match_data_t *match_data) + pe_working_set_t *data_set, + pe_re_match_data_t *re_match_data) { const char *rule_id = NULL; const char *score = NULL; @@ -1113,14 +1110,14 @@ generate_location_rule(pe_resource_t *rsc, xmlNode *rule_xml, return NULL; } - if (match_data && match_data->re && match_data->re->nregs > 0 && match_data->re->pmatch[0].rm_so != -1) { - if (raw_score == FALSE) { - char *result = pe_expand_re_matches(score, match_data->re); + if ((re_match_data != NULL) && (re_match_data->nregs > 0) + && (re_match_data->pmatch[0].rm_so != -1) && !raw_score) { - if (result) { - score = (const char *) result; - score_allocated = TRUE; - } + char *result = pe_expand_re_matches(score, re_match_data); + + if (result != NULL) { + score = result; + score_allocated = TRUE; } } @@ -1148,9 +1145,14 @@ generate_location_rule(pe_resource_t *rsc, xmlNode *rule_xml, for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { int score_f = 0; pe_node_t *node = (pe_node_t *) gIter->data; + pe_match_data_t match_data = { + .re = re_match_data, + .params = pe_rsc_params(rsc, node, data_set), + .meta = rsc->meta, + }; accept = pe_test_rule(rule_xml, node->details->attrs, RSC_ROLE_UNKNOWN, - data_set->now, next_change, match_data); + data_set->now, next_change, &match_data); crm_trace("Rule %s %s on %s", ID(rule_xml), accept ? "passed" : "failed", node->details->uname); -- 1.8.3.1 From 40383ae2e2796b1bcbdb86bdd9cdc93c117eb69f Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Thu, 12 Nov 2020 15:32:47 -0600 Subject: [PATCH 10/13] Test: scheduler: add regression test for rules using value-source --- cts/cts-scheduler.in | 1 + cts/scheduler/value-source.dot | 29 +++ cts/scheduler/value-source.exp | 200 ++++++++++++++++ cts/scheduler/value-source.scores | 47 ++++ cts/scheduler/value-source.summary | 60 +++++ cts/scheduler/value-source.xml | 463 +++++++++++++++++++++++++++++++++++++ 6 files changed, 800 insertions(+) create mode 100644 cts/scheduler/value-source.dot create mode 100644 cts/scheduler/value-source.exp create mode 100644 cts/scheduler/value-source.scores create mode 100644 cts/scheduler/value-source.summary create mode 100644 cts/scheduler/value-source.xml diff --git a/cts/cts-scheduler.in b/cts/cts-scheduler.in index 23e6a91..939f8c8 100644 --- a/cts/cts-scheduler.in +++ b/cts/cts-scheduler.in @@ -145,6 +145,7 @@ TESTS = [ [ "location-date-rules-1", "Use location constraints with ineffective date-based rules" ], [ "location-date-rules-2", "Use location constraints with effective date-based rules" ], [ "nvpair-date-rules-1", "Use nvpair blocks with a variety of date-based rules" ], + [ "value-source", "Use location constraints with node attribute expressions using value-source" ], [ "rule-dbl-as-auto-number-match", "Floating-point rule values default to number comparison: match" ], [ "rule-dbl-as-auto-number-no-match", diff --git a/cts/scheduler/value-source.dot b/cts/scheduler/value-source.dot new file mode 100644 index 0000000..dfb61e9 --- /dev/null +++ b/cts/scheduler/value-source.dot @@ -0,0 +1,29 @@ + digraph "g" { +"Fencing_monitor_120000 rhel7-1" [ style=bold color="green" fontcolor="black"] +"Fencing_start_0 rhel7-1" -> "Fencing_monitor_120000 rhel7-1" [ style = bold] +"Fencing_start_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"insane-rsc_monitor_10000 rhel7-4" [ style=bold color="green" fontcolor="black"] +"insane-rsc_start_0 rhel7-4" -> "insane-rsc_monitor_10000 rhel7-4" [ style = bold] +"insane-rsc_start_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"invert-match_monitor_10000 rhel7-1" [ style=bold color="green" fontcolor="black"] +"invert-match_start_0 rhel7-1" -> "invert-match_monitor_10000 rhel7-1" [ style = bold] +"invert-match_start_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"meta-rsc_monitor_10000 rhel7-5" [ style=bold color="green" fontcolor="black"] +"meta-rsc_start_0 rhel7-5" -> "meta-rsc_monitor_10000 rhel7-5" [ style = bold] +"meta-rsc_start_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"rsc1_monitor_10000 rhel7-4" [ style=bold color="green" fontcolor="black"] +"rsc1_start_0 rhel7-4" -> "rsc1_monitor_10000 rhel7-4" [ style = bold] +"rsc1_start_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"rsc2_monitor_10000 rhel7-5" [ style=bold color="green" fontcolor="black"] +"rsc2_start_0 rhel7-5" -> "rsc2_monitor_10000 rhel7-5" [ style = bold] +"rsc2_start_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"set-rsc1_monitor_10000 rhel7-3" [ style=bold color="green" fontcolor="black"] +"set-rsc1_start_0 rhel7-3" -> "set-rsc1_monitor_10000 rhel7-3" [ style = bold] +"set-rsc1_start_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"set-rsc2_monitor_10000 rhel7-4" [ style=bold color="green" fontcolor="black"] +"set-rsc2_start_0 rhel7-4" -> "set-rsc2_monitor_10000 rhel7-4" [ style = bold] +"set-rsc2_start_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"single-rsc_monitor_10000 rhel7-2" [ style=bold color="green" fontcolor="black"] +"single-rsc_start_0 rhel7-2" -> "single-rsc_monitor_10000 rhel7-2" [ style = bold] +"single-rsc_start_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +} diff --git a/cts/scheduler/value-source.exp b/cts/scheduler/value-source.exp new file mode 100644 index 0000000..4bf469f --- /dev/null +++ b/cts/scheduler/value-source.exp @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cts/scheduler/value-source.scores b/cts/scheduler/value-source.scores new file mode 100644 index 0000000..1f781c4 --- /dev/null +++ b/cts/scheduler/value-source.scores @@ -0,0 +1,47 @@ +Allocation scores: +Using the original execution date of: 2020-11-12 21:28:08Z +pcmk__native_allocate: Fencing allocation score on rhel7-1: 0 +pcmk__native_allocate: Fencing allocation score on rhel7-2: 0 +pcmk__native_allocate: Fencing allocation score on rhel7-3: 0 +pcmk__native_allocate: Fencing allocation score on rhel7-4: 0 +pcmk__native_allocate: Fencing allocation score on rhel7-5: 0 +pcmk__native_allocate: insane-rsc allocation score on rhel7-1: 0 +pcmk__native_allocate: insane-rsc allocation score on rhel7-2: 0 +pcmk__native_allocate: insane-rsc allocation score on rhel7-3: 0 +pcmk__native_allocate: insane-rsc allocation score on rhel7-4: INFINITY +pcmk__native_allocate: insane-rsc allocation score on rhel7-5: 0 +pcmk__native_allocate: invert-match allocation score on rhel7-1: INFINITY +pcmk__native_allocate: invert-match allocation score on rhel7-2: 0 +pcmk__native_allocate: invert-match allocation score on rhel7-3: 0 +pcmk__native_allocate: invert-match allocation score on rhel7-4: 0 +pcmk__native_allocate: invert-match allocation score on rhel7-5: 0 +pcmk__native_allocate: meta-rsc allocation score on rhel7-1: 0 +pcmk__native_allocate: meta-rsc allocation score on rhel7-2: 0 +pcmk__native_allocate: meta-rsc allocation score on rhel7-3: 0 +pcmk__native_allocate: meta-rsc allocation score on rhel7-4: INFINITY +pcmk__native_allocate: meta-rsc allocation score on rhel7-5: INFINITY +pcmk__native_allocate: rsc1 allocation score on rhel7-1: 0 +pcmk__native_allocate: rsc1 allocation score on rhel7-2: 0 +pcmk__native_allocate: rsc1 allocation score on rhel7-3: 0 +pcmk__native_allocate: rsc1 allocation score on rhel7-4: INFINITY +pcmk__native_allocate: rsc1 allocation score on rhel7-5: INFINITY +pcmk__native_allocate: rsc2 allocation score on rhel7-1: 0 +pcmk__native_allocate: rsc2 allocation score on rhel7-2: 0 +pcmk__native_allocate: rsc2 allocation score on rhel7-3: 0 +pcmk__native_allocate: rsc2 allocation score on rhel7-4: 0 +pcmk__native_allocate: rsc2 allocation score on rhel7-5: INFINITY +pcmk__native_allocate: set-rsc1 allocation score on rhel7-1: 0 +pcmk__native_allocate: set-rsc1 allocation score on rhel7-2: 0 +pcmk__native_allocate: set-rsc1 allocation score on rhel7-3: INFINITY +pcmk__native_allocate: set-rsc1 allocation score on rhel7-4: 0 +pcmk__native_allocate: set-rsc1 allocation score on rhel7-5: 0 +pcmk__native_allocate: set-rsc2 allocation score on rhel7-1: 0 +pcmk__native_allocate: set-rsc2 allocation score on rhel7-2: 0 +pcmk__native_allocate: set-rsc2 allocation score on rhel7-3: 0 +pcmk__native_allocate: set-rsc2 allocation score on rhel7-4: INFINITY +pcmk__native_allocate: set-rsc2 allocation score on rhel7-5: 0 +pcmk__native_allocate: single-rsc allocation score on rhel7-1: 0 +pcmk__native_allocate: single-rsc allocation score on rhel7-2: INFINITY +pcmk__native_allocate: single-rsc allocation score on rhel7-3: 0 +pcmk__native_allocate: single-rsc allocation score on rhel7-4: 0 +pcmk__native_allocate: single-rsc allocation score on rhel7-5: 0 diff --git a/cts/scheduler/value-source.summary b/cts/scheduler/value-source.summary new file mode 100644 index 0000000..a9b0392 --- /dev/null +++ b/cts/scheduler/value-source.summary @@ -0,0 +1,60 @@ +Using the original execution date of: 2020-11-12 21:28:08Z + +Current cluster status: +Online: [ rhel7-1 rhel7-2 rhel7-3 rhel7-4 rhel7-5 ] + + Fencing (stonith:fence_xvm): Stopped + rsc1 (ocf::pacemaker:Dummy): Stopped + rsc2 (ocf::pacemaker:Dummy): Stopped + invert-match (ocf::pacemaker:Dummy): Stopped + single-rsc (ocf::pacemaker:Dummy): Stopped + set-rsc1 (ocf::pacemaker:Dummy): Stopped + set-rsc2 (ocf::pacemaker:Dummy): Stopped + meta-rsc (ocf::pacemaker:Dummy): Stopped + insane-rsc (ocf::pacemaker:Dummy): Stopped + +Transition Summary: + * Start Fencing ( rhel7-1 ) + * Start rsc1 ( rhel7-4 ) + * Start rsc2 ( rhel7-5 ) + * Start invert-match ( rhel7-1 ) + * Start single-rsc ( rhel7-2 ) + * Start set-rsc1 ( rhel7-3 ) + * Start set-rsc2 ( rhel7-4 ) + * Start meta-rsc ( rhel7-5 ) + * Start insane-rsc ( rhel7-4 ) + +Executing cluster transition: + * Resource action: Fencing start on rhel7-1 + * Resource action: rsc1 start on rhel7-4 + * Resource action: rsc2 start on rhel7-5 + * Resource action: invert-match start on rhel7-1 + * Resource action: single-rsc start on rhel7-2 + * Resource action: set-rsc1 start on rhel7-3 + * Resource action: set-rsc2 start on rhel7-4 + * Resource action: meta-rsc start on rhel7-5 + * Resource action: insane-rsc start on rhel7-4 + * Resource action: Fencing monitor=120000 on rhel7-1 + * Resource action: rsc1 monitor=10000 on rhel7-4 + * Resource action: rsc2 monitor=10000 on rhel7-5 + * Resource action: invert-match monitor=10000 on rhel7-1 + * Resource action: single-rsc monitor=10000 on rhel7-2 + * Resource action: set-rsc1 monitor=10000 on rhel7-3 + * Resource action: set-rsc2 monitor=10000 on rhel7-4 + * Resource action: meta-rsc monitor=10000 on rhel7-5 + * Resource action: insane-rsc monitor=10000 on rhel7-4 +Using the original execution date of: 2020-11-12 21:28:08Z + +Revised cluster status: +Online: [ rhel7-1 rhel7-2 rhel7-3 rhel7-4 rhel7-5 ] + + Fencing (stonith:fence_xvm): Started rhel7-1 + rsc1 (ocf::pacemaker:Dummy): Started rhel7-4 + rsc2 (ocf::pacemaker:Dummy): Started rhel7-5 + invert-match (ocf::pacemaker:Dummy): Started rhel7-1 + single-rsc (ocf::pacemaker:Dummy): Started rhel7-2 + set-rsc1 (ocf::pacemaker:Dummy): Started rhel7-3 + set-rsc2 (ocf::pacemaker:Dummy): Started rhel7-4 + meta-rsc (ocf::pacemaker:Dummy): Started rhel7-5 + insane-rsc (ocf::pacemaker:Dummy): Started rhel7-4 + diff --git a/cts/scheduler/value-source.xml b/cts/scheduler/value-source.xml new file mode 100644 index 0000000..95e7d57 --- /dev/null +++ b/cts/scheduler/value-source.xml @@ -0,0 +1,463 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 1.8.3.1 From f678813f9054e2eb80a04796b8d35214269cd352 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 9 Nov 2020 18:13:04 -0600 Subject: [PATCH 11/13] API: libpe_status: deprecate pe_resource_t parameters member Instead, pe_rsc_params() should be used. Also, define the parameters member using such a pe_rsc_params() call. --- include/crm/pengine/pe_types.h | 2 +- lib/pengine/complex.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/crm/pengine/pe_types.h b/include/crm/pengine/pe_types.h index 5529714..1416cee 100644 --- a/include/crm/pengine/pe_types.h +++ b/include/crm/pengine/pe_types.h @@ -358,7 +358,7 @@ struct pe_resource_s { enum rsc_role_e next_role; GHashTable *meta; - GHashTable *parameters; + GHashTable *parameters; //! \deprecated Use pe_rsc_params() instead GHashTable *utilization; GListPtr children; /* pe_resource_t* */ diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c index 7037ca1..60199c7 100644 --- a/lib/pengine/complex.c +++ b/lib/pengine/complex.c @@ -557,8 +557,6 @@ common_unpack(xmlNode * xml_obj, pe_resource_t ** rsc, return FALSE; } - (*rsc)->parameters = crm_str_table_new(); - #if ENABLE_VERSIONED_ATTRS (*rsc)->versioned_parameters = create_xml_node(NULL, XML_TAG_RSC_VER_ATTRS); #endif @@ -584,7 +582,7 @@ common_unpack(xmlNode * xml_obj, pe_resource_t ** rsc, pe_rsc_trace((*rsc), "Unpacking resource..."); get_meta_attributes((*rsc)->meta, *rsc, NULL, data_set); - get_rsc_attributes((*rsc)->parameters, *rsc, NULL, data_set); + (*rsc)->parameters = pe_rsc_params(*rsc, NULL, data_set); // \deprecated #if ENABLE_VERSIONED_ATTRS pe_get_versioned_attributes((*rsc)->versioned_parameters, *rsc, NULL, data_set); #endif @@ -808,7 +806,15 @@ common_unpack(xmlNode * xml_obj, pe_resource_t ** rsc, } if (remote_node) { - value = g_hash_table_lookup((*rsc)->parameters, XML_REMOTE_ATTR_RECONNECT_INTERVAL); + GHashTable *params = pe_rsc_params(*rsc, NULL, data_set); + + /* Grabbing the value now means that any rules based on node attributes + * will evaluate to false, so such rules should not be used with + * reconnect_interval. + * + * @TODO Evaluate per node before using + */ + value = g_hash_table_lookup(params, XML_REMOTE_ATTR_RECONNECT_INTERVAL); if (value) { /* reconnect delay works by setting failure_timeout and preventing the * connection from starting until the failure is cleared. */ @@ -922,9 +928,6 @@ common_free(pe_resource_t * rsc) g_list_free(rsc->rsc_tickets); g_list_free(rsc->dangling_migrations); - if (rsc->parameters != NULL) { - g_hash_table_destroy(rsc->parameters); - } if (rsc->parameter_cache != NULL) { g_hash_table_destroy(rsc->parameter_cache); } -- 1.8.3.1 From 267d0cc44e94d6963fe13974f83b2fc845b0c431 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 17 Nov 2020 15:45:35 -0600 Subject: [PATCH 12/13] Test: execd: use new resource parameter function in cts-exec-helper --- daemons/execd/cts-exec-helper.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/daemons/execd/cts-exec-helper.c b/daemons/execd/cts-exec-helper.c index 8be8e18..423b54d 100644 --- a/daemons/execd/cts-exec-helper.c +++ b/daemons/execd/cts-exec-helper.c @@ -482,13 +482,12 @@ generate_params(void) goto param_gen_bail; } - params = crm_str_table_new(); + params = pe_rsc_params(rsc, NULL, data_set); meta = crm_str_table_new(); - get_rsc_attributes(params, rsc, NULL, data_set); get_meta_attributes(meta, rsc, NULL, data_set); - if (params) { + if (params != NULL) { char *key = NULL; char *value = NULL; @@ -496,7 +495,6 @@ generate_params(void) while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { options.params = lrmd_key_value_add(options.params, key, value); } - g_hash_table_destroy(params); } if (meta) { -- 1.8.3.1 From b10c86bf785beccef147b702366607cc4ead0f79 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 17 Nov 2020 16:01:12 -0600 Subject: [PATCH 13/13] Refactor: tools: use new resource parameter function in crm_resource --- tools/crm_resource.c | 14 +++++++++----- tools/crm_resource_print.c | 10 ++++++++-- tools/crm_resource_runtime.c | 32 +++++++++++--------------------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tools/crm_resource.c b/tools/crm_resource.c index b028c40..9663e68 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -1902,6 +1902,7 @@ main(int argc, char **argv) unsigned int count = 0; GHashTable *params = NULL; pe_node_t *current = pe__find_active_on(rsc, &count, NULL); + bool free_params = true; if (count > 1) { out->err(out, "%s is active on more than one node," @@ -1909,23 +1910,26 @@ main(int argc, char **argv) current = NULL; } - params = crm_str_table_new(); + crm_debug("Looking up %s in %s", options.prop_name, rsc->id); if (pcmk__str_eq(options.attr_set_type, XML_TAG_ATTR_SETS, pcmk__str_casei)) { - get_rsc_attributes(params, rsc, current, data_set); + params = pe_rsc_params(rsc, current, data_set); + free_params = false; } else if (pcmk__str_eq(options.attr_set_type, XML_TAG_META_SETS, pcmk__str_casei)) { - /* No need to redirect to the parent */ + params = crm_str_table_new(); get_meta_attributes(params, rsc, current, data_set); } else { + params = crm_str_table_new(); pe__unpack_dataset_nvpairs(rsc->xml, XML_TAG_UTILIZATION, NULL, params, NULL, FALSE, data_set); } - crm_debug("Looking up %s in %s", options.prop_name, rsc->id); rc = out->message(out, "attribute-list", rsc, options.prop_name, params); - g_hash_table_destroy(params); + if (free_params) { + g_hash_table_destroy(params); + } break; } diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c index 89d6172..398fef0 100644 --- a/tools/crm_resource_print.c +++ b/tools/crm_resource_print.c @@ -134,8 +134,11 @@ attribute_list_default(pcmk__output_t *out, va_list args) { char *attr = va_arg(args, char *); GHashTable *params = va_arg(args, GHashTable *); - const char *value = g_hash_table_lookup(params, attr); + const char *value = NULL; + if (params != NULL) { + value = g_hash_table_lookup(params, attr); + } if (value != NULL) { out->begin_list(out, NULL, NULL, "Attributes"); out->list_item(out, attr, "%s", value); @@ -154,8 +157,11 @@ attribute_list_text(pcmk__output_t *out, va_list args) { char *attr = va_arg(args, char *); GHashTable *params = va_arg(args, GHashTable *); - const char *value = g_hash_table_lookup(params, attr); + const char *value = NULL; + if (params != NULL) { + value = g_hash_table_lookup(params, attr); + } if (value != NULL) { out->info(out, "%s", value); } else { diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c index e0804fc..9ff9e96 100644 --- a/tools/crm_resource_runtime.c +++ b/tools/crm_resource_runtime.c @@ -916,40 +916,29 @@ cli_resource_fail(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, } static GHashTable * -generate_resource_params(pe_resource_t * rsc, pe_working_set_t * data_set) +generate_resource_params(pe_resource_t *rsc, pe_node_t *node, + pe_working_set_t *data_set) { GHashTable *params = NULL; GHashTable *meta = NULL; GHashTable *combined = NULL; GHashTableIter iter; + char *key = NULL; + char *value = NULL; - if (!rsc) { - crm_err("Resource does not exist in config"); - return NULL; - } - - params = crm_str_table_new(); - meta = crm_str_table_new(); combined = crm_str_table_new(); - get_rsc_attributes(params, rsc, NULL /* TODO: Pass in local node */ , data_set); - get_meta_attributes(meta, rsc, NULL /* TODO: Pass in local node */ , data_set); - - if (params) { - char *key = NULL; - char *value = NULL; - + params = pe_rsc_params(rsc, node, data_set); + if (params != NULL) { g_hash_table_iter_init(&iter, params); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { g_hash_table_insert(combined, strdup(key), strdup(value)); } - g_hash_table_destroy(params); } - if (meta) { - char *key = NULL; - char *value = NULL; - + meta = crm_str_table_new(); + get_meta_attributes(meta, rsc, node, data_set); + if (meta != NULL) { g_hash_table_iter_init(&iter, meta); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { char *crm_name = crm_meta_name(key); @@ -1827,7 +1816,8 @@ cli_resource_execute(pcmk__output_t *out, pe_resource_t *rsc, rprov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE); - params = generate_resource_params(rsc, data_set); + params = generate_resource_params(rsc, NULL /* @TODO use local node */, + data_set); if (timeout_ms == 0) { timeout_ms = pe_get_configured_timeout(rsc, action, data_set); -- 1.8.3.1