pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
cluster.c
Go to the documentation of this file.
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#include <crm_internal.h>
11#include <dlfcn.h>
12
13#include <inttypes.h> // PRIu32
14#include <stdbool.h>
15#include <stdio.h>
16#include <unistd.h>
17#include <string.h>
18#include <stdlib.h>
19#include <time.h>
20#include <sys/param.h>
21#include <sys/types.h>
22#include <sys/utsname.h> // uname()
23
24#include <glib.h> // gboolean
25
26#include <crm/crm.h>
27
28#include <crm/common/ipc.h>
29#include <crm/common/xml.h>
31#include "crmcluster_private.h"
32
34
43const char *
45{
46 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
47
48 if (node == NULL) {
49 return NULL;
50 }
51 if (node->xml_id != NULL) {
52 return node->xml_id;
53 }
54
55 // xml_id is always set when a Pacemaker Remote node entry is created
57
58 switch (cluster_layer) {
59#if SUPPORT_COROSYNC
61 node->xml_id = pcmk__corosync_uuid(node);
62 return node->xml_id;
63#endif // SUPPORT_COROSYNC
64
65 default:
66 crm_err("Unsupported cluster layer %s",
67 pcmk_cluster_layer_text(cluster_layer));
68 return NULL;
69 }
70}
71
80int
82{
83 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
84 const char *cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
85
86 if (cluster == NULL) {
87 return EINVAL;
88 }
89
90 // cts-lab looks for this message
91 crm_notice("Connecting to %s cluster layer", cluster_layer_s);
92
93 switch (cluster_layer) {
94#if SUPPORT_COROSYNC
96 return pcmk__corosync_connect(cluster);
97#endif // SUPPORT_COROSYNC
98
99 default:
100 break;
101 }
102
103 crm_err("Failed to connect to unsupported cluster layer %s",
104 cluster_layer_s);
105 return EPROTONOSUPPORT;
106}
107
115int
117{
118 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
119 const char *cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
120
121 crm_info("Disconnecting from %s cluster layer", cluster_layer_s);
122
123 switch (cluster_layer) {
124#if SUPPORT_COROSYNC
128 return pcmk_rc_ok;
129#endif // SUPPORT_COROSYNC
130
131 default:
132 break;
133 }
134
135 crm_err("Failed to disconnect from unsupported cluster layer %s",
136 cluster_layer_s);
137 return EPROTONOSUPPORT;
138}
139
149{
150 pcmk_cluster_t *cluster = pcmk__assert_alloc(1, sizeof(pcmk_cluster_t));
151
152 cluster->priv = pcmk__assert_alloc(1, sizeof(pcmk__cluster_private_t));
154 return cluster;
155}
156
162void
164{
165 if (cluster == NULL) {
166 return;
167 }
168 election_fini(cluster);
169 free(cluster->priv->node_xml_id);
170 free(cluster->priv->node_name);
171 free(cluster->priv);
172 free(cluster);
173}
174
183int
184pcmk_cluster_set_destroy_fn(pcmk_cluster_t *cluster, void (*fn)(gpointer))
185{
186 if (cluster == NULL) {
187 return EINVAL;
188 }
189 cluster->destroy = fn;
190 return pcmk_rc_ok;
191}
192
203bool
205 enum pcmk_ipc_server service, const xmlNode *data)
206{
207 // @TODO Return standard Pacemaker return code
208 switch (pcmk_get_cluster_layer()) {
209#if SUPPORT_COROSYNC
211 return pcmk__cpg_send_xml(data, node, service);
212#endif // SUPPORT_COROSYNC
213
214 default:
215 break;
216 }
217 return false;
218}
219
236char *
238{
239 char *name = NULL;
240 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
241 const char *cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
242
243 switch (cluster_layer) {
244#if SUPPORT_COROSYNC
246 name = pcmk__corosync_name(0, nodeid);
247 if (name != NULL) {
248 return name;
249 }
250 break;
251#endif // SUPPORT_COROSYNC
252
253 default:
254 crm_err("Unsupported cluster layer: %s", cluster_layer_s);
255 break;
256 }
257
258 if (nodeid == 0) {
259 struct utsname hostinfo;
260
261 crm_notice("Could not get local node name from %s cluster layer, "
262 "defaulting to local hostname",
263 cluster_layer_s);
264
265 if (uname(&hostinfo) < 0) {
266 // @TODO Maybe let the caller decide what to do
267 crm_err("Failed to get the local hostname");
269 }
270 return pcmk__str_copy(hostinfo.nodename);
271 }
272
273 crm_notice("Could not obtain a node name for node with "
274 PCMK_XA_ID "=%" PRIu32,
275 nodeid);
276 return NULL;
277}
278
292const char *
294{
295 // @TODO Refactor to avoid trivially leaking name at exit
296 static char *name = NULL;
297
298 if (name == NULL) {
300 }
301 return name;
302}
303
314const char *
316{
317 /* @TODO There are too many functions in libcrmcluster that look up a node
318 * from the node caches (possibly creating a cache entry if none exists).
319 * There are at least the following:
320 * * pcmk__cluster_lookup_remote_node()
321 * * pcmk__get_node()
322 * * pcmk__node_name_from_uuid()
323 * * pcmk__search_node_caches()
324 *
325 * There's a lot of duplication among them, but they all do slightly
326 * different things. We should try to clean them up and consolidate them to
327 * the extent possible, likely with new helper functions.
328 */
329 GHashTableIter iter;
330 pcmk__node_status_t *node = NULL;
331
332 CRM_CHECK(uuid != NULL, return NULL);
333
334 // Remote nodes have the same uname and uuid
335 if (g_hash_table_lookup(pcmk__remote_peer_cache, uuid)) {
336 return uuid;
337 }
338
339 g_hash_table_iter_init(&iter, pcmk__peer_cache);
340 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
341 if (pcmk__str_eq(uuid, pcmk__cluster_get_xml_id(node),
343 return node->name;
344 }
345 }
346 return NULL;
347}
348
356const char *
358{
359 switch (layer) {
361 return "corosync";
363 return "unknown";
365 return "invalid";
366 default:
367 crm_err("Invalid cluster layer: %d", layer);
368 return "invalid";
369 }
370}
371
385{
386 static enum pcmk_cluster_layer cluster_layer = pcmk_cluster_layer_unknown;
387 const char *cluster = NULL;
388
389 // Cluster layer is stable once set
390 if (cluster_layer != pcmk_cluster_layer_unknown) {
391 return cluster_layer;
392 }
393
395
396 if (cluster != NULL) {
397 crm_info("Verifying configured cluster layer '%s'", cluster);
398 cluster_layer = pcmk_cluster_layer_invalid;
399
400#if SUPPORT_COROSYNC
401 if (pcmk__str_eq(cluster, PCMK_VALUE_COROSYNC, pcmk__str_casei)) {
402 cluster_layer = pcmk_cluster_layer_corosync;
403 }
404#endif // SUPPORT_COROSYNC
405
406 if (cluster_layer == pcmk_cluster_layer_invalid) {
407 crm_notice("This installation does not support the '%s' cluster "
408 "infrastructure: terminating",
409 cluster);
411 }
412 crm_info("Assuming an active '%s' cluster", cluster);
413
414 } else {
415 // Nothing configured, so test supported cluster layers
416#if SUPPORT_COROSYNC
417 crm_debug("Testing with Corosync");
419 cluster_layer = pcmk_cluster_layer_corosync;
420 }
421#endif // SUPPORT_COROSYNC
422
423 if (cluster_layer == pcmk_cluster_layer_unknown) {
424 crm_notice("Could not determine the current cluster layer");
425 } else {
426 crm_info("Detected an active '%s' cluster",
427 pcmk_cluster_layer_text(cluster_layer));
428 }
429 }
430
431 return cluster_layer;
432}
433
434// Deprecated functions kept only for backward API compatibility
435// LCOV_EXCL_START
436
437#include <crm/cluster/compat.h>
438
439gboolean
441{
442 if (cluster == NULL) {
443 return FALSE;
444 }
445 if (cluster->priv == NULL) {
446 /* sbd (as of at least 1.5.2) doesn't call pcmk_cluster_new() to
447 * allocate the pcmk_cluster_t
448 */
449 cluster->priv = pcmk__assert_alloc(1, sizeof(pcmk__cluster_private_t));
450 }
451 return pcmk_cluster_connect(cluster) == pcmk_rc_ok;
452}
453
454const char *
456{
457 switch (type) {
459 return "corosync";
461 return "unknown";
463 return "invalid";
464 }
465 crm_err("Invalid cluster type: %d", type);
466 return "invalid";
467}
468
471{
473}
474
475// LCOV_EXCL_STOP
476// End deprecated API
const char * name
Definition cib.c:26
GHashTable * pcmk__peer_cache
Definition membership.c:37
void pcmk__cluster_destroy_node_caches(void)
Definition membership.c:588
@ pcmk__node_status_remote
Definition internal.h:51
GHashTable * pcmk__remote_peer_cache
Definition membership.c:55
void pcmk_cluster_free(pcmk_cluster_t *cluster)
Free a pcmk_cluster_t object and its dynamically allocated members.
Definition cluster.c:163
pcmk_cluster_t * pcmk_cluster_new(void)
Allocate a new pcmk_cluster_t object.
Definition cluster.c:148
gboolean crm_cluster_connect(pcmk_cluster_t *cluster)
Definition cluster.c:440
const char * pcmk__cluster_get_xml_id(pcmk__node_status_t *node)
Definition cluster.c:44
int pcmk_cluster_connect(pcmk_cluster_t *cluster)
Definition cluster.c:81
enum cluster_type_e get_cluster_type(void)
Definition cluster.c:470
const char * pcmk__node_name_from_uuid(const char *uuid)
Definition cluster.c:315
const char * pcmk__cluster_local_node_name(void)
Definition cluster.c:293
bool pcmk__cluster_send_message(const pcmk__node_status_t *node, enum pcmk_ipc_server service, const xmlNode *data)
Definition cluster.c:204
const char * name_for_cluster_type(enum cluster_type_e type)
Definition cluster.c:455
int pcmk_cluster_set_destroy_fn(pcmk_cluster_t *cluster, void(*fn)(gpointer))
Set the destroy function for a cluster object.
Definition cluster.c:184
int pcmk_cluster_disconnect(pcmk_cluster_t *cluster)
Disconnect from the cluster layer.
Definition cluster.c:116
const char * pcmk_cluster_layer_text(enum pcmk_cluster_layer layer)
Get a log-friendly string equivalent of a cluster layer.
Definition cluster.c:357
enum pcmk_cluster_layer pcmk_get_cluster_layer(void)
Get and validate the local cluster layer.
Definition cluster.c:384
char * pcmk__cluster_node_name(uint32_t nodeid)
Definition cluster.c:237
pcmk_cluster_layer
Types of cluster layer.
Definition cluster.h:69
@ pcmk_cluster_layer_invalid
Invalid cluster layer.
Definition cluster.h:71
@ pcmk_cluster_layer_corosync
Corosync Cluster Engine.
Definition cluster.h:72
@ pcmk_cluster_layer_unknown
Unknown cluster layer.
Definition cluster.h:70
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:246
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:80
Deprecated Pacemaker cluster API.
cluster_type_e
Definition compat.h:39
@ pcmk_cluster_unknown
Definition compat.h:41
@ pcmk_cluster_invalid
Definition compat.h:43
@ pcmk_cluster_corosync
Definition compat.h:46
bool pcmk__corosync_is_active(void)
Definition corosync.c:511
char * pcmk__corosync_name(uint64_t cmap_handle, uint32_t nodeid)
Definition corosync.c:101
char * pcmk__corosync_uuid(const pcmk__node_status_t *node)
Definition corosync.c:53
int pcmk__corosync_connect(pcmk_cluster_t *cluster)
Definition corosync.c:459
void pcmk__corosync_disconnect(pcmk_cluster_t *cluster)
Definition corosync.c:223
bool pcmk__cpg_send_xml(const xmlNode *msg, const pcmk__node_status_t *node, enum pcmk_ipc_server dest)
Definition cpg.c:1039
char uname[MAX_NAME]
Definition cpg.c:5
char data[0]
Definition cpg.c:10
enum pcmk_ipc_server type
Definition cpg.c:3
A dumping ground.
char * crm_system_name
Definition utils.c:45
G_GNUC_INTERNAL void election_fini(pcmk_cluster_t *cluster)
Definition election.c:156
IPC interface to Pacemaker daemons.
pcmk_ipc_server
Available IPC interfaces.
Definition ipc.h:48
#define CRM_TRACE_INIT_DATA(name)
Definition logging.h:111
#define crm_info(fmt, args...)
Definition logging.h:365
#define crm_notice(fmt, args...)
Definition logging.h:363
#define CRM_CHECK(expr, failure_action)
Definition logging.h:213
#define crm_debug(fmt, args...)
Definition logging.h:368
#define crm_err(fmt, args...)
Definition logging.h:357
#define PCMK_VALUE_COROSYNC
Definition options.h:139
#define PCMK__ENV_CLUSTER_TYPE
const char * pcmk__env_option(const char *option)
Definition options.c:1085
@ CRM_EX_FATAL
Do not respawn.
Definition results.h:264
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition results.c:1058
@ pcmk_rc_ok
Definition results.h:159
enum pcmk_ipc_server pcmk__parse_server(const char *text)
Definition servers.c:178
@ pcmk__str_none
@ pcmk__str_casei
#define pcmk__str_copy(str)
Implementation of pcmk__cluster_private_t.
Definition internal.h:89
char * node_name
Local node name at cluster layer.
Definition internal.h:91
char * node_xml_id
Local node XML ID in CIB.
Definition internal.h:92
enum pcmk_ipc_server server
Server this connection is for (if any)
Definition internal.h:90
pcmk__cluster_private_t * priv
Definition cluster.h:36
void(* destroy)(gpointer)
Definition cluster.h:40
Node status data (may be a cluster node or a Pacemaker Remote node)
Definition internal.h:111
char * name
Node name as known to cluster layer, or Pacemaker Remote node name.
Definition internal.h:113
uint32_t flags
Group of enum pcmk__node_status_flags
Definition internal.h:136
Wrappers for and extensions to libxml2.
#define PCMK_XA_ID
Definition xml_names.h:301