summaryrefslogtreecommitdiffstats
path: root/lib/common/attrs.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common/attrs.c')
-rw-r--r--lib/common/attrs.c116
1 files changed, 105 insertions, 11 deletions
diff --git a/lib/common/attrs.c b/lib/common/attrs.c
index 2be03b4..35715df 100644
--- a/lib/common/attrs.c
+++ b/lib/common/attrs.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2022 the Pacemaker project contributors
+ * Copyright 2011-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -15,10 +15,12 @@
#include <stdio.h>
-#include <crm/msg_xml.h>
-#include <crm/common/attrd_internal.h>
+#include <crm/common/xml.h>
+#include <crm/common/scheduler.h>
+#include <crm/common/scheduler_internal.h>
-#define LRM_TARGET_ENV "OCF_RESKEY_" CRM_META "_" XML_LRM_ATTR_TARGET
+#define OCF_RESKEY_PREFIX "OCF_RESKEY_"
+#define LRM_TARGET_ENV OCF_RESKEY_PREFIX CRM_META "_" PCMK__META_ON_NODE
/*!
* \internal
@@ -27,7 +29,8 @@
* If given NULL, "auto", or "localhost" as an argument, check the environment
* to detect the node name that should be used to set node attributes. (The
* caller might not know the correct name, for example if the target is part of
- * a bundle with container-attribute-target set to "host".)
+ * a bundle with \c PCMK_META_CONTAINER_ATTRIBUTE_TARGET set to
+ * \c PCMK_VALUE_HOST.)
*
* \param[in] name NULL, "auto" or "localhost" to check environment variables,
* or anything else to return NULL
@@ -39,13 +42,22 @@ const char *
pcmk__node_attr_target(const char *name)
{
if (name == NULL || pcmk__strcase_any_of(name, "auto", "localhost", NULL)) {
- char *target_var = crm_meta_name(XML_RSC_ATTR_TARGET);
- char *phys_var = crm_meta_name(PCMK__ENV_PHYSICAL_HOST);
- const char *target = getenv(target_var);
- const char *host_physical = getenv(phys_var);
+ char buf[128] = OCF_RESKEY_PREFIX;
+ size_t offset = sizeof(OCF_RESKEY_PREFIX) - 1;
+ char *target_var = crm_meta_name(PCMK_META_CONTAINER_ATTRIBUTE_TARGET);
+ char *phys_var = crm_meta_name(PCMK__META_PHYSICAL_HOST);
+ const char *target = NULL;
+ const char *host_physical = NULL;
+
+ snprintf(buf + offset, sizeof(buf) - offset, "%s", target_var);
+ target = getenv(buf);
+
+ snprintf(buf + offset, sizeof(buf) - offset, "%s", phys_var);
+ host_physical = getenv(buf);
// It is important to use the name by which the scheduler knows us
- if (host_physical && pcmk__str_eq(target, "host", pcmk__str_casei)) {
+ if (host_physical
+ && pcmk__str_eq(target, PCMK_VALUE_HOST, pcmk__str_casei)) {
name = host_physical;
} else {
@@ -58,7 +70,7 @@ pcmk__node_attr_target(const char *name)
free(target_var);
free(phys_var);
- // TODO? Call get_local_node_name() if name == NULL
+ // TODO? Call pcmk__cluster_local_node_name() if name == NULL
// (currently would require linkage against libcrmcluster)
return name;
} else {
@@ -87,3 +99,85 @@ pcmk_promotion_score_name(const char *rsc_id)
}
return crm_strdup_printf("master-%s", rsc_id);
}
+
+/*!
+ * \internal
+ * \brief Get the value of a node attribute
+ *
+ * \param[in] node Node to get attribute for
+ * \param[in] name Name of node attribute to get
+ * \param[in] target If this is \c PCMK_VALUE_HOST and \p node is a guest
+ * (bundle) node, get the value from the guest's host,
+ * otherwise get the value from \p node itself
+ * \param[in] node_type If getting the value from \p node's host, this
+ * indicates whether to check the current or assigned host
+ *
+ * \return Value of \p name attribute for \p node
+ */
+const char *
+pcmk__node_attr(const pcmk_node_t *node, const char *name, const char *target,
+ enum pcmk__rsc_node node_type)
+{
+ const char *value = NULL; // Attribute value to return
+ const char *node_type_s = NULL; // Readable equivalent of node_type
+ const pcmk_node_t *host = NULL;
+ const pcmk_resource_t *container = NULL;
+
+ if ((node == NULL) || (name == NULL)) {
+ return NULL;
+ }
+
+ /* Check the node's own attributes unless this is a guest (bundle) node with
+ * the container host as the attribute target.
+ */
+ if (!pcmk__is_guest_or_bundle_node(node)
+ || !pcmk__str_eq(target, PCMK_VALUE_HOST, pcmk__str_casei)) {
+ value = g_hash_table_lookup(node->details->attrs, name);
+ crm_trace("%s='%s' on %s",
+ name, pcmk__s(value, ""), pcmk__node_name(node));
+ return value;
+ }
+
+ /* This resource needs attributes set for the container's host instead of
+ * for the container itself (useful when the container uses the host's
+ * storage).
+ */
+ container = node->details->remote_rsc->container;
+
+ switch (node_type) {
+ case pcmk__rsc_node_assigned:
+ host = container->allocated_to;
+ if (host == NULL) {
+ crm_trace("Skipping %s lookup for %s because "
+ "its container %s is unassigned",
+ name, pcmk__node_name(node), container->id);
+ return NULL;
+ }
+ node_type_s = "assigned";
+ break;
+
+ case pcmk__rsc_node_current:
+ if (container->running_on != NULL) {
+ host = container->running_on->data;
+ }
+ if (host == NULL) {
+ crm_trace("Skipping %s lookup for %s because "
+ "its container %s is inactive",
+ name, pcmk__node_name(node), container->id);
+ return NULL;
+ }
+ node_type_s = "current";
+ break;
+
+ default:
+ // Add support for other enum pcmk__rsc_node values if needed
+ CRM_ASSERT(false);
+ break;
+ }
+
+ value = g_hash_table_lookup(host->details->attrs, name);
+ crm_trace("%s='%s' for %s on %s container host %s",
+ name, pcmk__s(value, ""), pcmk__node_name(node), node_type_s,
+ pcmk__node_name(host));
+ return value;
+}