/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 |