1 /* 2 * Copyright 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 #ifndef PCMK__CRM_COMMON_NODES_INTERNAL__H 11 #define PCMK__CRM_COMMON_NODES_INTERNAL__H 12 13 #include <stdio.h> // NULL 14 #include <stdbool.h> // bool 15 #include <stdint.h> // uint32_t, UINT32_C() 16 17 #include <glib.h> 18 #include <crm/common/nodes.h> 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /* 25 * Special node attributes 26 */ 27 28 #define PCMK__NODE_ATTR_SHUTDOWN "shutdown" 29 30 /* @COMPAT Deprecated since 2.1.8. Use a location constraint with 31 * PCMK_XA_RSC_PATTERN=".*" and PCMK_XA_RESOURCE_DISCOVERY="never" instead of 32 * PCMK__NODE_ATTR_RESOURCE_DISCOVERY_ENABLED="false". 33 */ 34 #define PCMK__NODE_ATTR_RESOURCE_DISCOVERY_ENABLED "resource-discovery-enabled" 35 36 enum pcmk__node_variant { // Possible node types 37 pcmk__node_variant_cluster = 1, // Cluster layer node 38 pcmk__node_variant_remote = 2, // Pacemaker Remote node 39 }; 40 41 enum pcmk__node_flags { 42 pcmk__node_none = UINT32_C(0), 43 44 // Whether node is in standby mode 45 pcmk__node_standby = (UINT32_C(1) << 0), 46 47 // Whether node is in standby mode due to PCMK_META_ON_FAIL 48 pcmk__node_fail_standby = (UINT32_C(1) << 1), 49 50 // Whether node has ever joined cluster (and thus has node state in CIB) 51 pcmk__node_seen = (UINT32_C(1) << 2), 52 53 // Whether expected join state is member 54 pcmk__node_expected_up = (UINT32_C(1) << 3), 55 56 // Whether probes are allowed on node 57 pcmk__node_probes_allowed = (UINT32_C(1) << 4), 58 59 /* Whether this either is a guest node whose guest resource must be 60 * recovered or a remote node that must be fenced 61 */ 62 pcmk__node_remote_reset = (UINT32_C(1) << 5), 63 64 /* Whether this is a Pacemaker Remote node that was fenced since it was last 65 * connected by the cluster 66 */ 67 pcmk__node_remote_fenced = (UINT32_C(1) << 6), 68 69 /* 70 * Whether this is a Pacemaker Remote node previously marked in its 71 * node state as being in maintenance mode 72 */ 73 pcmk__node_remote_maint = (UINT32_C(1) << 7), 74 75 // Whether node history has been unpacked 76 pcmk__node_unpacked = (UINT32_C(1) << 8), 77 }; 78 79 // When to probe a resource on a node (as specified in location constraints) 80 enum pcmk__probe_mode { 81 pcmk__probe_always = 0, // Always probe resource on node 82 pcmk__probe_never = 1, // Never probe resource on node 83 pcmk__probe_exclusive = 2, // Probe only on designated nodes 84 }; 85 86 /* Per-node data used in resource assignment 87 * 88 * @COMPAT When we can make the pcmk_node_t implementation internal, move these 89 * there and drop this struct. 90 */ 91 struct pcmk__node_assignment { 92 int score; // Node's score for relevant resource 93 int count; // Counter reused by assignment and promotion code 94 enum pcmk__probe_mode probe_mode; // When to probe resource on this node 95 }; 96 97 /* Implementation of pcmk__node_private_t (pcmk_node_t objects are shallow 98 * copies, so all pcmk_node_t objects for the same node will share the same 99 * private data) 100 */ 101 struct pcmk__node_private { 102 /* Node's XML ID in the CIB (the cluster layer ID for cluster nodes, 103 * the node name for Pacemaker Remote nodes) 104 */ 105 const char *id; 106 107 /* 108 * Sum of priorities of all resources active on node and on any guest nodes 109 * connected to this node, with +1 for promoted instances (used to compare 110 * nodes for PCMK_OPT_PRIORITY_FENCING_DELAY) 111 */ 112 int priority; 113 114 const char *name; // Node name in cluster 115 enum pcmk__node_variant variant; // Node variant 116 uint32_t flags; // Group of enum pcmk__node_flags 117 GHashTable *attrs; // Node attributes 118 GHashTable *utilization; // Node utilization attributes 119 int num_resources; // Number of active resources on node 120 GList *assigned_resources; // List of resources assigned to node 121 GHashTable *digest_cache; // Cache of calculated resource digests 122 pcmk_resource_t *remote; // Pacemaker Remote connection (if any) 123 pcmk_scheduler_t *scheduler; // Scheduler data that node is part of 124 }; 125 126 void pcmk__free_node_copy(void *data); 127 pcmk_node_t *pcmk__find_node_in_list(const GList *nodes, const char *node_name); 128 129 /*! 130 * \internal 131 * \brief Set node flags 132 * 133 * \param[in,out] node Node to set flags for 134 * \param[in] flags_to_set Group of enum pcmk_node_flags to set 135 */ 136 #define pcmk__set_node_flags(node, flags_to_set) do { \ 137 (node)->priv->flags = pcmk__set_flags_as(__func__, __LINE__, \ 138 LOG_TRACE, "Node", pcmk__node_name(node), \ 139 (node)->priv->flags, (flags_to_set), #flags_to_set); \ 140 } while (0) 141 142 /*! 143 * \internal 144 * \brief Clear node flags 145 * 146 * \param[in,out] node Node to clear flags for 147 * \param[in] flags_to_clear Group of enum pcmk_node_flags to clear 148 */ 149 #define pcmk__clear_node_flags(node, flags_to_clear) do { \ 150 (node)->priv->flags = pcmk__clear_flags_as(__func__, __LINE__, \ 151 LOG_TRACE, "Node", pcmk__node_name(node), \ 152 (node)->priv->flags, (flags_to_clear), #flags_to_clear); \ 153 } while (0) 154 155 /*! 156 * \internal 157 * \brief Return a string suitable for logging as a node name 158 * 159 * \param[in] node Node to return a node name string for 160 * 161 * \return Node name if available, otherwise node ID if available, 162 * otherwise "unspecified node" if node is NULL or "unidentified node" 163 * if node has neither a name nor ID. 164 */ 165 static inline const char * 166 pcmk__node_name(const pcmk_node_t *node) /**/ 167 { 168 if (node == NULL) { 169 return "unspecified node"; 170 171 } else if (node->priv->name != NULL) { 172 return node->priv->name; 173 174 } else if (node->priv->id != NULL) { 175 return node->priv->id; 176 177 } else { 178 return "unidentified node"; 179 } 180 } 181 182 /*! 183 * \internal 184 * \brief Check whether two node objects refer to the same node 185 * 186 * \param[in] node1 First node object to compare 187 * \param[in] node2 Second node object to compare 188 * 189 * \return true if \p node1 and \p node2 refer to the same node 190 */ 191 static inline bool 192 pcmk__same_node(const pcmk_node_t *node1, const pcmk_node_t *node2) /*
*/ 193 { 194 return (node1 != NULL) && (node2 != NULL) 195 && (node1->priv == node2->priv); 196 } 197 198 #ifdef __cplusplus 199 } 200 #endif 201 202 #endif // PCMK__CRM_COMMON_NODES_INTERNAL__H