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