From 65856b5096435460685845d7e1e2fc6e3eb5f480 Mon Sep 17 00:00:00 2001 From: Andrew Beekhof Date: Thu, 17 Aug 2017 11:48:17 +1000 Subject: [PATCH] PE/attrd: Allow bundle resources to read/write attributes based on the physical host rather than the container name --- include/crm/msg_xml.h | 1 + include/crm/pengine/internal.h | 2 + include/crm_internal.h | 3 ++ lib/pengine/common.c | 52 ++++++++++++++++++++++++ lib/pengine/container.c | 5 ++- lib/pengine/unpack.c | 22 +++++----- lib/pengine/utils.c | 4 +- lib/pengine/variant.h | 1 + pengine/allocate.c | 3 +- pengine/constraints.c | 8 ++-- pengine/graph.c | 39 ++++++++++++++++++ pengine/master.c | 16 +++----- pengine/native.c | 20 ++++----- tools/attrd_updater.c | 30 ++++++++++++++ tools/crm_mon.c | 2 +- 40 files changed, 345 insertions(+), 221 deletions(-) diff --git a/include/crm/msg_xml.h b/include/crm/msg_xml.h index 0004dd6..e6bc5d0 100644 --- a/include/crm/msg_xml.h +++ b/include/crm/msg_xml.h @@ -190,6 +190,7 @@ # define XML_CIB_TAG_RSC_TEMPLATE "template" +# define XML_RSC_ATTR_TARGET "container-attribute-target" # define XML_RSC_ATTR_ISOLATION_INSTANCE "isolation-instance" # define XML_RSC_ATTR_ISOLATION_WRAPPER "isolation-wrapper" # define XML_RSC_ATTR_ISOLATION_HOST "isolation-host" diff --git a/include/crm/pengine/internal.h b/include/crm/pengine/internal.h index 4bde6b6..9cad243 100644 --- a/include/crm/pengine/internal.h +++ b/include/crm/pengine/internal.h @@ -293,5 +293,6 @@ bool remote_id_conflict(const char *remote_name, pe_working_set_t *data); void common_print(resource_t * rsc, const char *pre_text, const char *name, node_t *node, long options, void *print_data); resource_t *find_container_child(const char *stem, resource_t * rsc, node_t *node); bool fix_remote_addr(resource_t * rsc); +const char *node_attribute_calculated(pe_node_t *node, const char *name, resource_t *rsc); #endif diff --git a/include/crm_internal.h b/include/crm_internal.h index 66d91ae..b2bc0b0 100644 --- a/include/crm_internal.h +++ b/include/crm_internal.h @@ -285,6 +285,7 @@ long crm_read_pidfile(const char *filename); # define ATTRD_OP_FLUSH "flush" # define ATTRD_OP_SYNC "sync" # define ATTRD_OP_SYNC_RESPONSE "sync-response" +# define PCMK_ENV_PHYSICAL_HOST "physical_host" # if SUPPORT_COROSYNC # if CS_USES_LIBQB diff --git a/lib/pengine/common.c b/lib/pengine/common.c index cd27561..101f17e 100644 --- a/lib/pengine/common.c +++ b/lib/pengine/common.c @@ -431,3 +431,41 @@ add_hash_param(GHashTable * hash, const char *name, const char *value) g_hash_table_insert(hash, strdup(name), strdup(value)); } } + +const char * +node_attribute_calculated(pe_node_t *node, const char *name, resource_t *rsc) +{ + const char *source; + + if(node == NULL) { + return NULL; + + } else if(rsc == NULL) { + return g_hash_table_lookup(node->details->attrs, name); + } + + source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET); + if(source == NULL || safe_str_eq("host", source) == FALSE) { + return g_hash_table_lookup(node->details->attrs, name); + } + + /* Use attributes set for the containers location + * instead of for the container itself + * + * Useful when the container is using the host's local + * storage + */ + + CRM_ASSERT(node->details->remote_rsc); + CRM_ASSERT(node->details->remote_rsc->container); + + if(node->details->remote_rsc->container->running_on) { + pe_node_t *host = node->details->remote_rsc->container->running_on->data; + pe_rsc_trace(rsc, "%s: Looking for %s on the container host %s", rsc->id, name, host->details->uname); + return g_hash_table_lookup(host->details->attrs, name); + } + + pe_rsc_trace(rsc, "%s: Not looking for %s on the container host: %s is inactive", + rsc->id, name, node->details->remote_rsc->container->id); + return NULL; +} diff --git a/lib/pengine/container.c b/lib/pengine/container.c index 253f8ff..d3073cf 100644 --- a/lib/pengine/container.c +++ b/lib/pengine/container.c @@ -742,8 +742,12 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set) offset += allocate_ip(container_data, tuple, buffer+offset, max-offset); container_data->tuples = g_list_append(container_data->tuples, tuple); - } - container_data->docker_host_options = buffer; + container_data->attribute_target = g_hash_table_lookup(tuple->child->meta, XML_RSC_ATTR_TARGET); + } + container_data->docker_host_options = buffer; + if(container_data->attribute_target) { + g_hash_table_replace(rsc->meta, strdup(XML_RSC_ATTR_TARGET), strdup(container_data->attribute_target)); + } } else { // Just a naked container, no pacemaker-remote diff --git a/lib/pengine/variant.h b/lib/pengine/variant.h index c8fe159..4ceaa6b 100644 --- a/lib/pengine/variant.h +++ b/lib/pengine/variant.h @@ -100,6 +100,7 @@ typedef struct container_variant_data_s { char *docker_host_options; char *docker_run_options; char *docker_run_command; + const char *attribute_target; resource_t *child; diff --git a/pengine/constraints.c b/pengine/constraints.c index 501cb57..d7a147d 100644 --- a/pengine/constraints.c +++ b/pengine/constraints.c @@ -952,7 +952,7 @@ unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set) } static int -get_node_score(const char *rule, const char *score, gboolean raw, node_t * node) +get_node_score(const char *rule, const char *score, gboolean raw, node_t * node, resource_t *rsc) { int score_f = 0; @@ -963,7 +963,7 @@ get_node_score(const char *rule, const char *score, gboolean raw, node_t * node) score_f = char2score(score); } else { - const char *attr_score = g_hash_table_lookup(node->details->attrs, score); + const char *attr_score = node_attribute_calculated(node, score, rsc); if (attr_score == NULL) { crm_debug("Rule %s: node %s did not have a value for %s", @@ -1055,7 +1055,7 @@ generate_location_rule(resource_t * rsc, xmlNode * rule_xml, const char *discove for (gIter = match_L; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; - node->weight = get_node_score(rule_id, score, raw_score, node); + node->weight = get_node_score(rule_id, score, raw_score, node, rsc); } } @@ -1068,7 +1068,7 @@ generate_location_rule(resource_t * rsc, xmlNode * rule_xml, const char *discove crm_trace("Rule %s %s on %s", ID(rule_xml), accept ? "passed" : "failed", node->details->uname); - score_f = get_node_score(rule_id, score, raw_score, node); + score_f = get_node_score(rule_id, score, raw_score, node, rsc); /* if(accept && score_f == -INFINITY) { */ /* accept = FALSE; */ /* } */ diff --git a/pengine/graph.c b/pengine/graph.c index 1a92636..c5feea1 100644 --- a/pengine/graph.c +++ b/pengine/graph.c @@ -1135,6 +1135,45 @@ action2xml(action_t * action, gboolean as_input, pe_working_set_t *data_set) hash2smartfield((gpointer)"pcmk_external_ip", (gpointer)value, (gpointer)args_xml); } + if(is_container_remote_node(action->node)) { + pe_node_t *host = NULL; + enum action_tasks task = text2task(action->task); + + if(task == action_notify || task == action_notified) { + const char *n_task = g_hash_table_lookup(action->meta, "notify_operation"); + task = text2task(n_task); + } + + // Differentiate between up and down actions + switch (task) { + case stop_rsc: + case stopped_rsc: + case action_demote: + case action_demoted: + if(action->node->details->remote_rsc->container->running_on) { + host = action->node->details->remote_rsc->container->running_on->data; + } + break; + case start_rsc: + case started_rsc: + case monitor_rsc: + case action_promote: + case action_promoted: + if(action->node->details->remote_rsc->container->allocated_to) { + host = action->node->details->remote_rsc->container->allocated_to; + } + break; + default: + break; + } + + if(host) { + hash2metafield((gpointer)XML_RSC_ATTR_TARGET, + (gpointer)g_hash_table_lookup(action->rsc->meta, XML_RSC_ATTR_TARGET), (gpointer)args_xml); + hash2metafield((gpointer)PCMK_ENV_PHYSICAL_HOST, (gpointer)host->details->uname, (gpointer)args_xml); + } + } + } else if (safe_str_eq(action->task, CRM_OP_FENCE) && action->node) { g_hash_table_foreach(action->node->details->attrs, hash2metafield, args_xml); } diff --git a/pengine/master.c b/pengine/master.c index 8c39f49..7f60c5f 100644 --- a/pengine/master.c +++ b/pengine/master.c @@ -511,11 +511,7 @@ master_score(resource_t * rsc, node_t * node, int not_set_value) attr_name = calloc(1, len); sprintf(attr_name, "master-%s", name); - if (node) { - attr_value = g_hash_table_lookup(node->details->attrs, attr_name); - pe_rsc_trace(rsc, "%s: %s[%s] = %s", rsc->id, attr_name, node->details->uname, - crm_str(attr_value)); - } + attr_value = node_attribute_calculated(node, attr_name, rsc); if (attr_value != NULL) { score = char2score(attr_value); diff --git a/tools/attrd_updater.c b/tools/attrd_updater.c index 12135c8..250b03e 100644 --- a/tools/attrd_updater.c +++ b/tools/attrd_updater.c @@ -79,6 +79,7 @@ static int do_query(const char *attr_name, const char *attr_node, gboolean query static int do_update(char command, const char *attr_node, const char *attr_name, const char *attr_value, const char *attr_section, const char *attr_set, const char *attr_dampen, int attr_options); +static const char *get_hostname(const char *name); int main(int argc, char **argv) @@ -186,6 +187,7 @@ main(int argc, char **argv) crm_help('?', EX_USAGE); #endif } else { + attr_node = get_hostname(attr_node); crm_exit(do_update(command, attr_node, attr_name, attr_value, attr_section, attr_set, attr_dampen, attr_options)); } @@ -339,6 +341,8 @@ do_query(const char *attr_name, const char *attr_node, gboolean query_all) attr_node = "localhost"; } + attr_node = get_hostname(attr_node); + /* Build and send attrd request, and get XML reply */ rc = send_attrd_query(attr_name, attr_node, &reply); if (rc != pcmk_ok) { @@ -382,3 +386,28 @@ do_update(char command, const char *attr_node, const char *attr_name, } return rc; } + +static const char * +get_hostname(const char *name) +{ + if(name != NULL + && safe_str_neq(name, "auto") + && safe_str_neq(name, "localhost")) { + return name; + + } else { + const char *target = getenv(crm_meta_name(XML_RSC_ATTR_TARGET)); + const char *host_pyhsical = getenv(crm_meta_name(PCMK_ENV_PHYSICAL_HOST)); + const char *host_pcmk = getenv("OCF_RESKEY_" CRM_META "_" XML_LRM_ATTR_TARGET); + + /* It is important we use the names by which the PE knows us */ + if(safe_str_eq(target, "host") && host_pyhsical != NULL) { + return host_pyhsical; + + } else if(host_pcmk) { + return host_pcmk; + } + } + + return name; +}