root/include/crm/cluster/internal.h

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. crm_get_cluster_proc
  2. pcmk__cs_err_str

   1 /*
   2  * Copyright 2004-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 #ifndef PCMK__CRM_CLUSTER_INTERNAL__H
  11 #define PCMK__CRM_CLUSTER_INTERNAL__H
  12 
  13 #include <stdbool.h>
  14 #include <stdint.h>         // uint32_t, uint64_t
  15 
  16 #include <glib.h>           // gboolean
  17 #include <libxml/tree.h>    // xmlNode
  18 
  19 #include <crm/common/ipc.h> // enum crm_ipc_server
  20 #include <crm/cluster.h>
  21 
  22 #if SUPPORT_COROSYNC
  23 #include <corosync/cpg.h>   // cpg_name, cpg_handle_t
  24 #endif
  25 
  26 #ifdef __cplusplus
  27 extern "C" {
  28 #endif
  29 
  30 // @TODO Replace this with a pcmk__node_status_flags value
  31 enum crm_proc_flag {
  32     crm_proc_none       = 0x00000001,
  33 
  34     // Cluster layers
  35     crm_proc_cpg        = 0x04000000,
  36 };
  37 
  38 /*!
  39  * \internal
  40  * \brief Boolean flags for a \c pcmk__node_status_t object
  41  *
  42  * Some flags may not be related to status specifically. However, we keep these
  43  * separate from <tt>enum pcmk__node_flags</tt> because they're used with
  44  * different object types.
  45  */
  46 enum pcmk__node_status_flags {
  47     /*!
  48      * Node is a Pacemaker Remote node and should not be considered for cluster
  49      * membership
  50      */
  51     pcmk__node_status_remote = (UINT32_C(1) << 0),
  52 
  53     //! Node's cache entry is dirty
  54     pcmk__node_status_dirty  = (UINT32_C(1) << 1),
  55 };
  56 
  57 // Used with node cache search functions
  58 enum pcmk__node_search_flags {
  59     //! Does not affect search
  60     pcmk__node_search_none              = 0,
  61 
  62     //! Search for cluster nodes from membership cache
  63     pcmk__node_search_cluster_member    = (1 << 0),
  64 
  65     //! Search for remote nodes
  66     pcmk__node_search_remote            = (1 << 1),
  67 
  68     //! Search for cluster member nodes and remote nodes
  69     pcmk__node_search_any               = pcmk__node_search_cluster_member
  70                                           |pcmk__node_search_remote,
  71 
  72     //! Search for cluster nodes from CIB (as of last cache refresh)
  73     pcmk__node_search_cluster_cib       = (1 << 2),
  74 };
  75 
  76 /*!
  77  * \internal
  78  * \brief Type of update to a \c pcmk__node_status_t object
  79  */
  80 enum pcmk__node_update {
  81     pcmk__node_update_name,         //!< Node name updated
  82     pcmk__node_update_state,        //!< Node connection state updated
  83     pcmk__node_update_processes,    //!< Node process group membership updated
  84 };
  85 
  86 typedef struct pcmk__election pcmk__election_t;
  87 
  88 //! Implementation of pcmk__cluster_private_t
  89 struct pcmk__cluster_private {
  90     enum pcmk_ipc_server server;    //!< Server this connection is for (if any)
  91     char *node_name;                //!< Local node name at cluster layer
  92     char *node_xml_id;              //!< Local node XML ID in CIB
  93     pcmk__election_t *election;     //!< Election state (if election is needed)
  94 
  95     /* @TODO Corosync uses an integer node ID, but cluster layers in the
  96      * abstract do not necessarily need to
  97      */
  98     uint32_t node_id;               //!< Local node ID at cluster layer
  99 
 100 #if SUPPORT_COROSYNC
 101     /* @TODO Make these members a separate struct and use void *cluster_data
 102      * here instead, to abstract the cluster layer further.
 103      */
 104     struct cpg_name group;          //!< Corosync CPG name
 105 
 106     cpg_handle_t cpg_handle;        //!< Corosync CPG handle
 107 #endif  // SUPPORT_COROSYNC
 108 };
 109 
 110 //! Node status data (may be a cluster node or a Pacemaker Remote node)
 111 typedef struct pcmk__node_status {
 112     //! Node name as known to cluster layer, or Pacemaker Remote node name
 113     char *name;
 114 
 115     /* @COMPAT This is less than ideal since the value is not a valid XML ID
 116      * (for Corosync, it's the string equivalent of the node's numeric node ID,
 117      * but XML IDs can't start with a number) and the three elements should have
 118      * different IDs.
 119      *
 120      * Ideally, we would use something like node-NODEID, node_state-NODEID, and
 121      * transient_attributes-NODEID as the element IDs. Unfortunately changing it
 122      * would be impractical due to backward compatibility; older nodes in a
 123      * rolling upgrade will always write and expect the value in the old format.
 124      */
 125 
 126     /*!
 127      * Value of the PCMK_XA_ID XML attribute to use with the node's
 128      * PCMK_XE_NODE, PCMK_XE_NODE_STATE, and PCMK_XE_TRANSIENT_ATTRIBUTES
 129      * XML elements in the CIB
 130      */
 131     char *xml_id;
 132 
 133     char *state;                // @TODO change to enum
 134 
 135     //! Group of <tt>enum pcmk__node_status_flags</tt>
 136     uint32_t flags;
 137 
 138     /*!
 139      * Most recent cluster membership in which node was seen (0 for Pacemaker
 140      * Remote nodes)
 141      */
 142     uint64_t membership_id;
 143 
 144     uint32_t processes;         // @TODO most not needed, merge into flags
 145 
 146     /* @TODO When we can break public API compatibility, we can make the rest of
 147      * these members separate structs and use void *cluster_data and
 148      * void *user_data here instead, to abstract the cluster layer further.
 149      */
 150 
 151     //! Arbitrary data (must be freeable by \c free())
 152     void *user_data;
 153 
 154     char *expected;
 155 
 156     time_t peer_lost;
 157     char *conn_host;
 158 
 159     time_t when_member;         // Since when node has been a cluster member
 160     time_t when_online;         // Since when peer has been online in CPG
 161 
 162     /* @TODO The following are currently needed only by the Corosync stack.
 163      * Eventually consider moving them to a cluster-layer-specific data object.
 164      */
 165     uint32_t cluster_layer_id;  //!< Cluster-layer numeric node ID
 166     time_t when_lost;           //!< When CPG membership was last lost
 167 } pcmk__node_status_t;
 168 
 169 /*!
 170  * \internal
 171  * \brief Return the process bit corresponding to the current cluster stack
 172  *
 173  * \return Process flag if detectable, otherwise 0
 174  */
 175 static inline uint32_t
 176 crm_get_cluster_proc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 177 {
 178     switch (pcmk_get_cluster_layer()) {
 179         case pcmk_cluster_layer_corosync:
 180             return crm_proc_cpg;
 181 
 182         default:
 183             break;
 184     }
 185     return crm_proc_none;
 186 }
 187 
 188 /*!
 189  * \internal
 190  * \brief Get log-friendly string description of a Corosync return code
 191  *
 192  * \param[in] error  Corosync return code
 193  *
 194  * \return Log-friendly string description corresponding to \p error
 195  */
 196 static inline const char *
 197 pcmk__cs_err_str(int error)
     /* [previous][next][first][last][top][bottom][index][help] */
 198 {
 199 #  if SUPPORT_COROSYNC
 200     switch (error) {
 201         case CS_OK:                         return "OK";
 202         case CS_ERR_LIBRARY:                return "Library error";
 203         case CS_ERR_VERSION:                return "Version error";
 204         case CS_ERR_INIT:                   return "Initialization error";
 205         case CS_ERR_TIMEOUT:                return "Timeout";
 206         case CS_ERR_TRY_AGAIN:              return "Try again";
 207         case CS_ERR_INVALID_PARAM:          return "Invalid parameter";
 208         case CS_ERR_NO_MEMORY:              return "No memory";
 209         case CS_ERR_BAD_HANDLE:             return "Bad handle";
 210         case CS_ERR_BUSY:                   return "Busy";
 211         case CS_ERR_ACCESS:                 return "Access error";
 212         case CS_ERR_NOT_EXIST:              return "Doesn't exist";
 213         case CS_ERR_NAME_TOO_LONG:          return "Name too long";
 214         case CS_ERR_EXIST:                  return "Exists";
 215         case CS_ERR_NO_SPACE:               return "No space";
 216         case CS_ERR_INTERRUPT:              return "Interrupt";
 217         case CS_ERR_NAME_NOT_FOUND:         return "Name not found";
 218         case CS_ERR_NO_RESOURCES:           return "No resources";
 219         case CS_ERR_NOT_SUPPORTED:          return "Not supported";
 220         case CS_ERR_BAD_OPERATION:          return "Bad operation";
 221         case CS_ERR_FAILED_OPERATION:       return "Failed operation";
 222         case CS_ERR_MESSAGE_ERROR:          return "Message error";
 223         case CS_ERR_QUEUE_FULL:             return "Queue full";
 224         case CS_ERR_QUEUE_NOT_AVAILABLE:    return "Queue not available";
 225         case CS_ERR_BAD_FLAGS:              return "Bad flags";
 226         case CS_ERR_TOO_BIG:                return "Too big";
 227         case CS_ERR_NO_SECTIONS:            return "No sections";
 228     }
 229 #  endif
 230     return "Corosync error";
 231 }
 232 
 233 #  if SUPPORT_COROSYNC
 234 
 235 #if 0
 236 /* This is the new way to do it, but we still support all Corosync 2 versions,
 237  * and this isn't always available. A better alternative here would be to check
 238  * for support in the configure script and enable this conditionally.
 239  */
 240 #define pcmk__init_cmap(handle) cmap_initialize_map((handle), CMAP_MAP_ICMAP)
 241 #else
 242 #define pcmk__init_cmap(handle) cmap_initialize(handle)
 243 #endif
 244 
 245 char *pcmk__corosync_cluster_name(void);
 246 bool pcmk__corosync_add_nodes(xmlNode *xml_parent);
 247 
 248 void pcmk__cpg_confchg_cb(cpg_handle_t handle,
 249                           const struct cpg_name *group_name,
 250                           const struct cpg_address *member_list,
 251                           size_t member_list_entries,
 252                           const struct cpg_address *left_list,
 253                           size_t left_list_entries,
 254                           const struct cpg_address *joined_list,
 255                           size_t joined_list_entries);
 256 
 257 char *pcmk__cpg_message_data(cpg_handle_t handle, uint32_t sender_id,
 258                              uint32_t pid, void *content, const char **from);
 259 
 260 #  endif
 261 
 262 const char *pcmk__cluster_get_xml_id(pcmk__node_status_t *node);
 263 char *pcmk__cluster_node_name(uint32_t nodeid);
 264 const char *pcmk__cluster_local_node_name(void);
 265 const char *pcmk__node_name_from_uuid(const char *uuid);
 266 
 267 pcmk__node_status_t *crm_update_peer_proc(const char *source,
 268                                           pcmk__node_status_t *peer,
 269                                           uint32_t flag, const char *status);
 270 pcmk__node_status_t *pcmk__update_peer_state(const char *source,
 271                                              pcmk__node_status_t *node,
 272                                              const char *state,
 273                                              uint64_t membership);
 274 
 275 void pcmk__update_peer_expected(const char *source, pcmk__node_status_t *node,
 276                                 const char *expected);
 277 void pcmk__reap_unseen_nodes(uint64_t ring_id);
 278 
 279 void pcmk__corosync_quorum_connect(gboolean (*dispatch)(unsigned long long,
 280                                                         gboolean),
 281                                    void (*destroy) (gpointer));
 282 
 283 bool pcmk__cluster_send_message(const pcmk__node_status_t *node,
 284                                 enum pcmk_ipc_server service,
 285                                 const xmlNode *data);
 286 
 287 // Membership
 288 
 289 extern GHashTable *pcmk__peer_cache;
 290 extern GHashTable *pcmk__remote_peer_cache;
 291 
 292 bool pcmk__cluster_has_quorum(void);
 293 
 294 void pcmk__cluster_init_node_caches(void);
 295 void pcmk__cluster_destroy_node_caches(void);
 296 
 297 void pcmk__cluster_set_autoreap(bool enable);
 298 void pcmk__cluster_set_status_callback(void (*dispatch)(enum pcmk__node_update,
 299                                                         pcmk__node_status_t *,
 300                                                         const void *));
 301 
 302 bool pcmk__cluster_is_node_active(const pcmk__node_status_t *node);
 303 unsigned int pcmk__cluster_num_active_nodes(void);
 304 unsigned int pcmk__cluster_num_remote_nodes(void);
 305 
 306 pcmk__node_status_t *pcmk__cluster_lookup_remote_node(const char *node_name);
 307 void pcmk__cluster_forget_cluster_node(uint32_t id, const char *node_name);
 308 void pcmk__cluster_forget_remote_node(const char *node_name);
 309 pcmk__node_status_t *pcmk__search_node_caches(unsigned int id,
 310                                               const char *uname,
 311                                               const char *xml_id,
 312                                               uint32_t flags);
 313 void pcmk__purge_node_from_cache(const char *node_name, uint32_t node_id);
 314 
 315 void pcmk__refresh_node_caches_from_cib(xmlNode *cib);
 316 
 317 pcmk__node_status_t *pcmk__get_node(unsigned int id, const char *uname,
 318                                     const char *xml_id, uint32_t flags);
 319 
 320 #ifdef __cplusplus
 321 }
 322 #endif
 323 
 324 #endif // PCMK__CRM_CLUSTER_INTERNAL__H

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