root/lib/common/attrs.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pcmk__node_attr_target
  2. pcmk_promotion_score_name
  3. pcmk__node_attr

   1 /*
   2  * Copyright 2011-2024 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <stdio.h>
  13 
  14 #include <crm/common/xml.h>
  15 #include <crm/common/scheduler.h>
  16 #include <crm/common/scheduler_internal.h>
  17 
  18 #define OCF_RESKEY_PREFIX "OCF_RESKEY_"
  19 #define LRM_TARGET_ENV OCF_RESKEY_PREFIX CRM_META "_" PCMK__META_ON_NODE
  20 
  21 /*!
  22  * \internal
  23  * \brief Get the node name that should be used to set node attributes
  24  *
  25  * If given NULL, "auto", or "localhost" as an argument, check the environment
  26  * to detect the node name that should be used to set node attributes. (The
  27  * caller might not know the correct name, for example if the target is part of
  28  * a bundle with \c PCMK_META_CONTAINER_ATTRIBUTE_TARGET set to
  29  * \c PCMK_VALUE_HOST.)
  30  *
  31  * \param[in] name  NULL, "auto" or "localhost" to check environment variables,
  32  *                  or anything else to return NULL
  33  *
  34  * \return Node name that should be used for node attributes based on the
  35  *         environment if known, otherwise NULL
  36  */
  37 const char *
  38 pcmk__node_attr_target(const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40     if (name == NULL || pcmk__strcase_any_of(name, "auto", "localhost", NULL)) {
  41         char buf[128] = OCF_RESKEY_PREFIX;
  42         size_t offset = sizeof(OCF_RESKEY_PREFIX) - 1;
  43         char *target_var = crm_meta_name(PCMK_META_CONTAINER_ATTRIBUTE_TARGET);
  44         char *phys_var = crm_meta_name(PCMK__META_PHYSICAL_HOST);
  45         const char *target = NULL;
  46         const char *host_physical = NULL;
  47 
  48         snprintf(buf + offset, sizeof(buf) - offset, "%s", target_var);
  49         target = getenv(buf);
  50 
  51         snprintf(buf + offset, sizeof(buf) - offset, "%s", phys_var);
  52         host_physical = getenv(buf);
  53 
  54         // It is important to use the name by which the scheduler knows us
  55         if (host_physical
  56             && pcmk__str_eq(target, PCMK_VALUE_HOST, pcmk__str_casei)) {
  57             name = host_physical;
  58 
  59         } else {
  60             const char *host_pcmk = getenv(LRM_TARGET_ENV);
  61 
  62             if (host_pcmk) {
  63                 name = host_pcmk;
  64             }
  65         }
  66         free(target_var);
  67         free(phys_var);
  68 
  69         // TODO? Call pcmk__cluster_local_node_name() if name == NULL
  70         // (currently would require linkage against libcrmcluster)
  71         return name;
  72     } else {
  73         return NULL;
  74     }
  75 }
  76 
  77 /*!
  78  * \brief Return the name of the node attribute used as a promotion score
  79  *
  80  * \param[in] rsc_id  Resource ID that promotion score is for (or NULL to
  81  *                    check the OCF_RESOURCE_INSTANCE environment variable)
  82  *
  83  * \return Newly allocated string with the node attribute name (or NULL on
  84  *         error, including no ID or environment variable specified)
  85  * \note It is the caller's responsibility to free() the result.
  86  */
  87 char *
  88 pcmk_promotion_score_name(const char *rsc_id)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90     if (pcmk__str_empty(rsc_id)) {
  91         rsc_id = getenv("OCF_RESOURCE_INSTANCE");
  92         if (pcmk__str_empty(rsc_id)) {
  93             return NULL;
  94         }
  95     }
  96     return crm_strdup_printf("master-%s", rsc_id);
  97 }
  98 
  99 /*!
 100  * \internal
 101  * \brief Get the value of a node attribute
 102  *
 103  * \param[in] node       Node to get attribute for
 104  * \param[in] name       Name of node attribute to get
 105  * \param[in] target     If this is \c PCMK_VALUE_HOST and \p node is a guest
 106  *                       (bundle) node, get the value from the guest's host,
 107  *                       otherwise get the value from \p node itself
 108  * \param[in] node_type  If getting the value from \p node's host, this
 109  *                       indicates whether to check the current or assigned host
 110  *
 111  * \return Value of \p name attribute for \p node
 112  */
 113 const char *
 114 pcmk__node_attr(const pcmk_node_t *node, const char *name, const char *target,
     /* [previous][next][first][last][top][bottom][index][help] */
 115                 enum pcmk__rsc_node node_type)
 116 {
 117     // @TODO accept a group of enum pcmk__rsc_node flags as node_type
 118     const char *value = NULL;       // Attribute value to return
 119     const char *node_type_s = NULL; // Readable equivalent of node_type
 120     const pcmk_node_t *host = NULL;
 121     const pcmk_resource_t *container = NULL;
 122 
 123     if ((node == NULL) || (name == NULL)) {
 124         return NULL;
 125     }
 126 
 127     /* Check the node's own attributes unless this is a guest (bundle) node with
 128      * the container host as the attribute target.
 129      */
 130     if (!pcmk__is_guest_or_bundle_node(node)
 131         || !pcmk__str_eq(target, PCMK_VALUE_HOST, pcmk__str_casei)) {
 132         value = g_hash_table_lookup(node->priv->attrs, name);
 133         crm_trace("%s='%s' on %s",
 134                   name, pcmk__s(value, ""), pcmk__node_name(node));
 135         return value;
 136     }
 137 
 138     /* This resource needs attributes set for the container's host instead of
 139      * for the container itself (useful when the container uses the host's
 140      * storage).
 141      */
 142     container = node->priv->remote->priv->launcher;
 143 
 144     switch (node_type) {
 145         case pcmk__rsc_node_assigned:
 146             host = container->priv->assigned_node;
 147             if (host == NULL) {
 148                 crm_trace("Skipping %s lookup for %s because "
 149                           "its container %s is unassigned",
 150                           name, pcmk__node_name(node), container->id);
 151                 return NULL;
 152             }
 153             node_type_s = "assigned";
 154             break;
 155 
 156         case pcmk__rsc_node_current:
 157             if (container->priv->active_nodes != NULL) {
 158                 host = container->priv->active_nodes->data;
 159             }
 160             if (host == NULL) {
 161                 crm_trace("Skipping %s lookup for %s because "
 162                           "its container %s is inactive",
 163                           name, pcmk__node_name(node), container->id);
 164                 return NULL;
 165             }
 166             node_type_s = "current";
 167             break;
 168 
 169         default:
 170             // Add support for other enum pcmk__rsc_node values if needed
 171             pcmk__assert(false);
 172             break;
 173     }
 174 
 175     value = g_hash_table_lookup(host->priv->attrs, name);
 176     crm_trace("%s='%s' for %s on %s container host %s",
 177               name, pcmk__s(value, ""), pcmk__node_name(node), node_type_s,
 178               pcmk__node_name(host));
 179     return value;
 180 }

/* [previous][next][first][last][top][bottom][index][help] */