Coverage Report

Created: 2025-11-26 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pacemaker/include/crm/cluster/internal.h
Line
Count
Source
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
/*!
58
 * \internal
59
 * \brief Used with node cache search functions
60
 */
61
enum pcmk__node_search_flags {
62
    //! Does not affect search
63
    pcmk__node_search_none              = 0,
64
65
    //! Search for cluster nodes from membership cache
66
    pcmk__node_search_cluster_member    = (UINT32_C(1) << 0),
67
68
    //! Search for remote nodes
69
    pcmk__node_search_remote            = (UINT32_C(1) << 1),
70
71
    //! Search for cluster member nodes and remote nodes
72
    pcmk__node_search_any               = pcmk__node_search_cluster_member
73
                                          |pcmk__node_search_remote,
74
75
    //! Search for cluster nodes from CIB (as of last cache refresh)
76
    pcmk__node_search_cluster_cib       = (UINT32_C(1) << 2),
77
};
78
79
/*!
80
 * \internal
81
 * \brief Type of update to a \c pcmk__node_status_t object
82
 */
83
enum pcmk__node_update {
84
    pcmk__node_update_name,         //!< Node name updated
85
    pcmk__node_update_state,        //!< Node connection state updated
86
    pcmk__node_update_processes,    //!< Node process group membership updated
87
};
88
89
typedef struct pcmk__election pcmk__election_t;
90
91
//! Implementation of pcmk__cluster_private_t
92
struct pcmk__cluster_private {
93
    enum pcmk_ipc_server server;    //!< Server this connection is for (if any)
94
    char *node_name;                //!< Local node name at cluster layer
95
    char *node_xml_id;              //!< Local node XML ID in CIB
96
    pcmk__election_t *election;     //!< Election state (if election is needed)
97
98
    /* @TODO Corosync uses an integer node ID, but cluster layers in the
99
     * abstract do not necessarily need to
100
     */
101
    uint32_t node_id;               //!< Local node ID at cluster layer
102
103
#if SUPPORT_COROSYNC
104
    /* @TODO Make these members a separate struct and use void *cluster_data
105
     * here instead, to abstract the cluster layer further.
106
     */
107
    struct cpg_name group;          //!< Corosync CPG name
108
109
    cpg_handle_t cpg_handle;        //!< Corosync CPG handle
110
#endif  // SUPPORT_COROSYNC
111
};
112
113
//! Node status data (may be a cluster node or a Pacemaker Remote node)
114
typedef struct pcmk__node_status {
115
    //! Node name as known to cluster layer, or Pacemaker Remote node name
116
    char *name;
117
118
    /* @COMPAT This is less than ideal since the value is not a valid XML ID
119
     * (for Corosync, it's the string equivalent of the node's numeric node ID,
120
     * but XML IDs can't start with a number) and the three elements should have
121
     * different IDs.
122
     *
123
     * Ideally, we would use something like node-NODEID, node_state-NODEID, and
124
     * transient_attributes-NODEID as the element IDs. Unfortunately changing it
125
     * would be impractical due to backward compatibility; older nodes in a
126
     * rolling upgrade will always write and expect the value in the old format.
127
     */
128
129
    /*!
130
     * Value of the PCMK_XA_ID XML attribute to use with the node's
131
     * PCMK_XE_NODE, PCMK_XE_NODE_STATE, and PCMK_XE_TRANSIENT_ATTRIBUTES
132
     * XML elements in the CIB
133
     */
134
    char *xml_id;
135
136
    char *state;                // @TODO change to enum
137
138
    //! Group of <tt>enum pcmk__node_status_flags</tt>
139
    uint32_t flags;
140
141
    /*!
142
     * Most recent cluster membership in which node was seen (0 for Pacemaker
143
     * Remote nodes)
144
     */
145
    uint64_t membership_id;
146
147
    uint32_t processes;         // @TODO most not needed, merge into flags
148
149
    /* @TODO When we can break public API compatibility, we can make the rest of
150
     * these members separate structs and use void *cluster_data and
151
     * void *user_data here instead, to abstract the cluster layer further.
152
     */
153
154
    //! Arbitrary data (must be freeable by \c free())
155
    void *user_data;
156
157
    char *expected;
158
159
    time_t peer_lost;
160
    char *conn_host;
161
162
    time_t when_member;         // Since when node has been a cluster member
163
    time_t when_online;         // Since when peer has been online in CPG
164
165
    /* @TODO The following are currently needed only by the Corosync stack.
166
     * Eventually consider moving them to a cluster-layer-specific data object.
167
     */
168
    uint32_t cluster_layer_id;  //!< Cluster-layer numeric node ID
169
    time_t when_lost;           //!< When CPG membership was last lost
170
} pcmk__node_status_t;
171
172
/*!
173
 * \internal
174
 * \brief Return the process bit corresponding to the current cluster stack
175
 *
176
 * \return Process flag if detectable, otherwise 0
177
 */
178
static inline uint32_t
179
crm_get_cluster_proc(void)
180
0
{
181
0
    switch (pcmk_get_cluster_layer()) {
182
0
        case pcmk_cluster_layer_corosync:
183
0
            return crm_proc_cpg;
184
0
185
0
        default:
186
0
            break;
187
0
    }
188
0
    return crm_proc_none;
189
0
}
Unexecuted instantiation: results.c:crm_get_cluster_proc
Unexecuted instantiation: scores.c:crm_get_cluster_proc
Unexecuted instantiation: strings.c:crm_get_cluster_proc
Unexecuted instantiation: utils.c:crm_get_cluster_proc
Unexecuted instantiation: iso8601.c:crm_get_cluster_proc
Unexecuted instantiation: logging.c:crm_get_cluster_proc
Unexecuted instantiation: mainloop.c:crm_get_cluster_proc
Unexecuted instantiation: options.c:crm_get_cluster_proc
Unexecuted instantiation: output.c:crm_get_cluster_proc
Unexecuted instantiation: output_log.c:crm_get_cluster_proc
Unexecuted instantiation: output_text.c:crm_get_cluster_proc
Unexecuted instantiation: output_xml.c:crm_get_cluster_proc
Unexecuted instantiation: patchset_display.c:crm_get_cluster_proc
Unexecuted instantiation: schemas.c:crm_get_cluster_proc
Unexecuted instantiation: xml.c:crm_get_cluster_proc
Unexecuted instantiation: xml_attr.c:crm_get_cluster_proc
Unexecuted instantiation: xml_comment.c:crm_get_cluster_proc
Unexecuted instantiation: xml_display.c:crm_get_cluster_proc
Unexecuted instantiation: xml_element.c:crm_get_cluster_proc
Unexecuted instantiation: xml_idref.c:crm_get_cluster_proc
Unexecuted instantiation: xml_io.c:crm_get_cluster_proc
Unexecuted instantiation: xpath.c:crm_get_cluster_proc
Unexecuted instantiation: acl.c:crm_get_cluster_proc
Unexecuted instantiation: actions.c:crm_get_cluster_proc
Unexecuted instantiation: agents.c:crm_get_cluster_proc
Unexecuted instantiation: cmdline.c:crm_get_cluster_proc
Unexecuted instantiation: digest.c:crm_get_cluster_proc
Unexecuted instantiation: health.c:crm_get_cluster_proc
Unexecuted instantiation: io.c:crm_get_cluster_proc
Unexecuted instantiation: ipc_client.c:crm_get_cluster_proc
Unexecuted instantiation: ipc_common.c:crm_get_cluster_proc
Unexecuted instantiation: ipc_controld.c:crm_get_cluster_proc
Unexecuted instantiation: ipc_pacemakerd.c:crm_get_cluster_proc
Unexecuted instantiation: ipc_schedulerd.c:crm_get_cluster_proc
Unexecuted instantiation: ipc_server.c:crm_get_cluster_proc
Unexecuted instantiation: messages.c:crm_get_cluster_proc
Unexecuted instantiation: nodes.c:crm_get_cluster_proc
Unexecuted instantiation: nvpair.c:crm_get_cluster_proc
Unexecuted instantiation: options_display.c:crm_get_cluster_proc
Unexecuted instantiation: patchset.c:crm_get_cluster_proc
Unexecuted instantiation: procfs.c:crm_get_cluster_proc
Unexecuted instantiation: rules.c:crm_get_cluster_proc
Unexecuted instantiation: servers.c:crm_get_cluster_proc
Unexecuted instantiation: cib.c:crm_get_cluster_proc
Unexecuted instantiation: ipc_attrd.c:crm_get_cluster_proc
Unexecuted instantiation: pid.c:crm_get_cluster_proc
Unexecuted instantiation: attrs.c:crm_get_cluster_proc
Unexecuted instantiation: strings_fuzzer.c:crm_get_cluster_proc
Unexecuted instantiation: cib_file_fuzzer.c:crm_get_cluster_proc
Unexecuted instantiation: cib_client.c:crm_get_cluster_proc
Unexecuted instantiation: cib_file.c:crm_get_cluster_proc
Unexecuted instantiation: cib_native.c:crm_get_cluster_proc
Unexecuted instantiation: cib_ops.c:crm_get_cluster_proc
Unexecuted instantiation: cib_remote.c:crm_get_cluster_proc
Unexecuted instantiation: cib_utils.c:crm_get_cluster_proc
Unexecuted instantiation: remote.c:crm_get_cluster_proc
Unexecuted instantiation: tls.c:crm_get_cluster_proc
Unexecuted instantiation: watchdog.c:crm_get_cluster_proc
190
191
#  if SUPPORT_COROSYNC
192
193
#if 0
194
/* This is the new way to do it, but we still support all Corosync 2 versions,
195
 * and this isn't always available. A better alternative here would be to check
196
 * for support in the configure script and enable this conditionally.
197
 */
198
#define pcmk__init_cmap(handle) cmap_initialize_map((handle), CMAP_MAP_ICMAP)
199
#else
200
#define pcmk__init_cmap(handle) cmap_initialize(handle)
201
#endif
202
203
char *pcmk__corosync_cluster_name(void);
204
bool pcmk__corosync_add_nodes(xmlNode *xml_parent);
205
206
void pcmk__cpg_confchg_cb(cpg_handle_t handle,
207
                          const struct cpg_name *group_name,
208
                          const struct cpg_address *member_list,
209
                          size_t member_list_entries,
210
                          const struct cpg_address *left_list,
211
                          size_t left_list_entries,
212
                          const struct cpg_address *joined_list,
213
                          size_t joined_list_entries);
214
215
char *pcmk__cpg_message_data(cpg_handle_t handle, uint32_t sender_id,
216
                             uint32_t pid, void *content, const char **from);
217
218
#  endif
219
220
const char *pcmk__cluster_get_xml_id(pcmk__node_status_t *node);
221
char *pcmk__cluster_node_name(uint32_t nodeid);
222
const char *pcmk__cluster_local_node_name(void);
223
const char *pcmk__node_name_from_uuid(const char *uuid);
224
225
pcmk__node_status_t *crm_update_peer_proc(const char *source,
226
                                          pcmk__node_status_t *peer,
227
                                          uint32_t flag, const char *status);
228
pcmk__node_status_t *pcmk__update_peer_state(const char *source,
229
                                             pcmk__node_status_t *node,
230
                                             const char *state,
231
                                             uint64_t membership);
232
233
void pcmk__update_peer_expected_as(const char *function,
234
                                   pcmk__node_status_t *node,
235
                                   const char *expected);
236
237
#define pcmk__update_peer_expected(node, expected)  \
238
        pcmk__update_peer_expected_as(__func__, (node), (expected));
239
240
void pcmk__reap_unseen_nodes(uint64_t ring_id);
241
242
void pcmk__corosync_quorum_connect(gboolean (*dispatch)(unsigned long long,
243
                                                        gboolean),
244
                                   void (*destroy) (gpointer));
245
246
bool pcmk__cluster_send_message(const pcmk__node_status_t *node,
247
                                enum pcmk_ipc_server service,
248
                                const xmlNode *data);
249
250
// Membership
251
252
extern GHashTable *pcmk__peer_cache;
253
extern GHashTable *pcmk__remote_peer_cache;
254
255
bool pcmk__cluster_has_quorum(void);
256
257
void pcmk__cluster_init_node_caches(void);
258
void pcmk__cluster_destroy_node_caches(void);
259
260
void pcmk__cluster_set_autoreap(bool enable);
261
void pcmk__cluster_set_status_callback(void (*dispatch)(enum pcmk__node_update,
262
                                                        pcmk__node_status_t *,
263
                                                        const void *));
264
265
bool pcmk__cluster_is_node_active(const pcmk__node_status_t *node);
266
unsigned int pcmk__cluster_num_active_nodes(void);
267
unsigned int pcmk__cluster_num_remote_nodes(void);
268
269
pcmk__node_status_t *pcmk__cluster_lookup_remote_node(const char *node_name);
270
void pcmk__cluster_forget_cluster_node(uint32_t id, const char *node_name);
271
void pcmk__cluster_forget_remote_node(const char *node_name);
272
pcmk__node_status_t *pcmk__search_node_caches(unsigned int id,
273
                                              const char *uname,
274
                                              const char *xml_id,
275
                                              uint32_t flags);
276
void pcmk__purge_node_from_cache(const char *node_name, uint32_t node_id);
277
278
void pcmk__refresh_node_caches_from_cib(xmlNode *cib);
279
280
pcmk__node_status_t *pcmk__get_node(unsigned int id, const char *uname,
281
                                    const char *xml_id, uint32_t flags);
282
283
#ifdef __cplusplus
284
}
285
#endif
286
287
#endif // PCMK__CRM_CLUSTER_INTERNAL__H