root/lib/common/nodes.c

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

DEFINITIONS

This source file includes following definitions.
  1. pcmk__free_node
  2. pcmk__free_node_copy
  3. pcmk_node_is_online
  4. pcmk_node_is_pending
  5. pcmk_node_is_clean
  6. pcmk_node_is_shutting_down
  7. pcmk_node_is_in_maintenance
  8. pcmk_foreach_active_resource
  9. pcmk__find_node_in_list
  10. pcmk_cib_node_shutdown

   1 /*
   2  * Copyright 2022-2025 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 <libxml/tree.h>        // xmlNode
  13 #include <crm/common/nvpair.h>
  14 
  15 /*!
  16  * \internal
  17  * \brief Free a node object
  18  *
  19  * \param[in,out] user_data  Node object to free
  20  */
  21 void
  22 pcmk__free_node(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  23 {
  24     pcmk_node_t *node = user_data;
  25 
  26     if (node == NULL) {
  27         return;
  28     }
  29     if (node->details == NULL) {
  30         free(node);
  31         return;
  32     }
  33 
  34     /* This may be called after freeing resources, which means that we can't
  35      * use node->private->name for Pacemaker Remote nodes.
  36      */
  37     crm_trace("Freeing node %s", (pcmk__is_pacemaker_remote_node(node)?
  38               "(guest or remote)" : pcmk__node_name(node)));
  39 
  40     if (node->priv->attrs != NULL) {
  41         g_hash_table_destroy(node->priv->attrs);
  42     }
  43     if (node->priv->utilization != NULL) {
  44         g_hash_table_destroy(node->priv->utilization);
  45     }
  46     if (node->priv->digest_cache != NULL) {
  47         g_hash_table_destroy(node->priv->digest_cache);
  48     }
  49     g_list_free(node->details->running_rsc);
  50     g_list_free(node->priv->assigned_resources);
  51     free(node->priv);
  52     free(node->details);
  53     free(node->assign);
  54     free(node);
  55 }
  56 
  57 /*!
  58  * \internal
  59  * \brief Free a copy of a node object
  60  *
  61  * \param[in] data  Node copy (created by pe__copy_node()) to free
  62  */
  63 void
  64 pcmk__free_node_copy(void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66     if (data != NULL) {
  67         pcmk_node_t *node = data;
  68 
  69         if (node->assign != NULL) {
  70             // This is the only member allocated separately for a node copy
  71             free(node->assign);
  72         }
  73         free(node);
  74     }
  75 }
  76 
  77 /*!
  78  * \internal
  79  * \brief Check whether a node is online
  80  *
  81  * \param[in] node  Node to check
  82  *
  83  * \return true if \p node is online, otherwise false
  84  */
  85 bool
  86 pcmk_node_is_online(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88     return (node != NULL) && node->details->online;
  89 }
  90 
  91 /*!
  92  * \internal
  93  * \brief Check whether a node is pending
  94  *
  95  * Check whether a node is pending. A node is pending if it is a member of the
  96  * cluster but not the controller group, which means it is in the process of
  97  * either joining or leaving the cluster.
  98  *
  99  * \param[in] node  Node to check
 100  *
 101  * \return true if \p node is pending, otherwise false
 102  */
 103 bool
 104 pcmk_node_is_pending(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 105 {
 106     return (node != NULL) && node->details->pending;
 107 }
 108 
 109 /*!
 110  * \internal
 111  * \brief Check whether a node is clean
 112  *
 113  * Check whether a node is clean. A node is clean if it is a cluster node or
 114  * remote node that has been seen by the cluster at least once, or the
 115  * startup-fencing cluster option is false; and the node, and its host if a
 116  * guest or bundle node, are not scheduled to be fenced.
 117  *
 118  * \param[in] node  Node to check
 119  *
 120  * \return true if \p node is clean, otherwise false
 121  */
 122 bool
 123 pcmk_node_is_clean(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125     return (node != NULL) && !(node->details->unclean);
 126 }
 127 
 128 /*!
 129  * \internal
 130  * \brief Check whether a node is shutting down
 131  *
 132  * \param[in] node  Node to check
 133  *
 134  * \return true if \p node is shutting down, otherwise false
 135  */
 136 bool
 137 pcmk_node_is_shutting_down(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139     return (node != NULL) && node->details->shutdown;
 140 }
 141 
 142 /*!
 143  * \internal
 144  * \brief Check whether a node is in maintenance mode
 145  *
 146  * \param[in] node  Node to check
 147  *
 148  * \return true if \p node is in maintenance mode, otherwise false
 149  */
 150 bool
 151 pcmk_node_is_in_maintenance(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153     return (node != NULL) && node->details->maintenance;
 154 }
 155 
 156 /*!
 157  * \internal
 158  * \brief Call a function for each resource active on a node
 159  *
 160  * Call a caller-supplied function with a caller-supplied argument for each
 161  * resource that is active on a given node. If the function returns false, this
 162  * function will return immediately without processing any remaining resources.
 163  *
 164  * \param[in] node  Node to check
 165  *
 166  * \return Result of last call of \p fn (or false if none)
 167  */
 168 bool
 169 pcmk_foreach_active_resource(pcmk_node_t *node,
     /* [previous][next][first][last][top][bottom][index][help] */
 170                              bool (*fn)(pcmk_resource_t *, void *),
 171                              void *user_data)
 172 {
 173     bool result = false;
 174 
 175     if ((node != NULL) && (fn != NULL)) {
 176         for (GList *item = node->details->running_rsc; item != NULL;
 177              item = item->next) {
 178 
 179             result = fn((pcmk_resource_t *) item->data, user_data);
 180             if (!result) {
 181                 break;
 182             }
 183         }
 184     }
 185     return result;
 186 }
 187 
 188 /*!
 189  * \internal
 190  * \brief Find a node by name in a list of nodes
 191  *
 192  * \param[in] nodes      List of nodes (as pcmk_node_t*)
 193  * \param[in] node_name  Name of node to find
 194  *
 195  * \return Node from \p nodes that matches \p node_name if any, otherwise NULL
 196  */
 197 pcmk_node_t *
 198 pcmk__find_node_in_list(const GList *nodes, const char *node_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 199 {
 200     if (node_name != NULL) {
 201         for (const GList *iter = nodes; iter != NULL; iter = iter->next) {
 202             pcmk_node_t *node = (pcmk_node_t *) iter->data;
 203 
 204             if (pcmk__str_eq(node->priv->name, node_name, pcmk__str_casei)) {
 205                 return node;
 206             }
 207         }
 208     }
 209     return NULL;
 210 }
 211 
 212 #define XP_SHUTDOWN "//" PCMK__XE_NODE_STATE "[@" PCMK_XA_UNAME "='%s']/"   \
 213     PCMK__XE_TRANSIENT_ATTRIBUTES "/" PCMK_XE_INSTANCE_ATTRIBUTES "/"       \
 214     PCMK_XE_NVPAIR "[@" PCMK_XA_NAME "='" PCMK__NODE_ATTR_SHUTDOWN "']"
 215 
 216 /*!
 217  * \brief Get value of a node's shutdown attribute from CIB, if present
 218  *
 219  * \param[in] cib   CIB to check
 220  * \param[in] node  Name of node to check
 221  *
 222  * \return Value of shutdown attribute for \p node in \p cib if any,
 223  *         otherwise NULL
 224  * \note The return value is a pointer into \p cib and so is valid only for the
 225  *       lifetime of that object.
 226  */
 227 const char *
 228 pcmk_cib_node_shutdown(xmlNode *cib, const char *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230     if ((cib != NULL) && (node != NULL)) {
 231         char *xpath = crm_strdup_printf(XP_SHUTDOWN, node);
 232         xmlNode *match = pcmk__xpath_find_one(cib->doc, xpath, LOG_TRACE);
 233 
 234         free(xpath);
 235         if (match != NULL) {
 236             return crm_element_value(match, PCMK_XA_VALUE);
 237         }
 238     }
 239     return NULL;
 240 }

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