pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
cluster.c
Go to the documentation of this file.
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#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
45{
46 CRM_CHECK(text != NULL, return crm_msg_none);
47
48 text = pcmk__message_name(text);
49
50 if (pcmk__str_eq(text, "ais", pcmk__str_none)) {
51 return crm_msg_ais;
52 }
53 if (pcmk__str_eq(text, CRM_SYSTEM_CIB, pcmk__str_none)) {
54 return crm_msg_cib;
55 }
57 return crm_msg_crmd;
58 }
59 if (pcmk__str_eq(text, CRM_SYSTEM_TENGINE, pcmk__str_none)) {
60 return crm_msg_te;
61 }
62 if (pcmk__str_eq(text, CRM_SYSTEM_PENGINE, pcmk__str_none)) {
63 return crm_msg_pe;
64 }
65 if (pcmk__str_eq(text, CRM_SYSTEM_LRMD, pcmk__str_none)) {
66 return crm_msg_lrmd;
67 }
68 if (pcmk__str_eq(text, CRM_SYSTEM_STONITHD, pcmk__str_none)) {
69 return crm_msg_stonithd;
70 }
71 if (pcmk__str_eq(text, "stonith-ng", pcmk__str_none)) {
72 return crm_msg_stonith_ng;
73 }
74 if (pcmk__str_eq(text, "attrd", pcmk__str_none)) {
75 return crm_msg_attrd;
76 }
77 return crm_msg_none;
78}
79
88const char *
90{
91 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
92
93 if (node == NULL) {
94 return NULL;
95 }
96 if (node->uuid != NULL) {
97 return node->uuid;
98 }
99
100 switch (cluster_layer) {
101#if SUPPORT_COROSYNC
103 node->uuid = pcmk__corosync_uuid(node);
104 return node->uuid;
105#endif // SUPPORT_COROSYNC
106
107 default:
108 crm_err("Unsupported cluster layer %s",
109 pcmk_cluster_layer_text(cluster_layer));
110 return NULL;
111 }
112}
113
122int
124{
125 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
126 const char *cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
127
128 // cts-lab looks for this message
129 crm_notice("Connecting to %s cluster layer", cluster_layer_s);
130
131 switch (cluster_layer) {
132#if SUPPORT_COROSYNC
134 return pcmk__corosync_connect(cluster);
135#endif // SUPPORT_COROSYNC
136
137 default:
138 break;
139 }
140
141 crm_err("Failed to connect to unsupported cluster layer %s",
142 cluster_layer_s);
143 return EPROTONOSUPPORT;
144}
145
153int
155{
156 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
157 const char *cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
158
159 crm_info("Disconnecting from %s cluster layer", cluster_layer_s);
160
161 switch (cluster_layer) {
162#if SUPPORT_COROSYNC
166 return pcmk_rc_ok;
167#endif // SUPPORT_COROSYNC
168
169 default:
170 break;
171 }
172
173 crm_err("Failed to disconnect from unsupported cluster layer %s",
174 cluster_layer_s);
175 return EPROTONOSUPPORT;
176}
177
187{
188 return (pcmk_cluster_t *) pcmk__assert_alloc(1, sizeof(pcmk_cluster_t));
189}
190
196void
198{
199 if (cluster == NULL) {
200 return;
201 }
202 free(cluster->uuid);
203 free(cluster->uname);
204 free(cluster);
205}
206
215int
216pcmk_cluster_set_destroy_fn(pcmk_cluster_t *cluster, void (*fn)(gpointer))
217{
218 if (cluster == NULL) {
219 return EINVAL;
220 }
221 cluster->destroy = fn;
222 return pcmk_rc_ok;
223}
224
235bool
237 enum crm_ais_msg_types service, const xmlNode *data)
238{
239 // @TODO Return standard Pacemaker return code
240 switch (pcmk_get_cluster_layer()) {
241#if SUPPORT_COROSYNC
243 return pcmk__cpg_send_xml(data, node, service);
244#endif // SUPPORT_COROSYNC
245
246 default:
247 break;
248 }
249 return false;
250}
251
268char *
270{
271 char *name = NULL;
272 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
273 const char *cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
274
275 switch (cluster_layer) {
276#if SUPPORT_COROSYNC
278 name = pcmk__corosync_name(0, nodeid);
279 if (name != NULL) {
280 return name;
281 }
282 break;
283#endif // SUPPORT_COROSYNC
284
285 default:
286 crm_err("Unsupported cluster layer: %s", cluster_layer_s);
287 break;
288 }
289
290 if (nodeid == 0) {
291 struct utsname hostinfo;
292
293 crm_notice("Could not get local node name from %s cluster layer, "
294 "defaulting to local hostname",
295 cluster_layer_s);
296
297 if (uname(&hostinfo) < 0) {
298 // @TODO Maybe let the caller decide what to do
299 crm_err("Failed to get the local hostname");
301 }
302 return pcmk__str_copy(hostinfo.nodename);
303 }
304
305 crm_notice("Could not obtain a node name for node with "
306 PCMK_XA_ID "=" PRIu32,
307 nodeid);
308 return NULL;
309}
310
324const char *
326{
327 // @TODO Refactor to avoid trivially leaking name at exit
328 static char *name = NULL;
329
330 if (name == NULL) {
332 }
333 return name;
334}
335
346const char *
348{
349 /* @TODO There are too many functions in libcrmcluster that look up a node
350 * from the node caches (possibly creating a cache entry if none exists).
351 * There are at least the following:
352 * * pcmk__cluster_lookup_remote_node()
353 * * pcmk__get_node()
354 * * pcmk__node_name_from_uuid()
355 * * pcmk__search_node_caches()
356 *
357 * There's a lot of duplication among them, but they all do slightly
358 * different things. We should try to clean them up and consolidate them to
359 * the extent possible, likely with new helper functions.
360 */
361 GHashTableIter iter;
362 crm_node_t *node = NULL;
363
364 CRM_CHECK(uuid != NULL, return NULL);
365
366 // Remote nodes have the same uname and uuid
367 if (g_hash_table_lookup(crm_remote_peer_cache, uuid)) {
368 return uuid;
369 }
370
371 g_hash_table_iter_init(&iter, crm_peer_cache);
372 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
373 if (pcmk__str_eq(node->uuid, uuid, pcmk__str_casei)) {
374 return node->uname;
375 }
376 }
377 return NULL;
378}
379
387const char *
389{
390 switch (layer) {
392 return "corosync";
394 return "unknown";
396 return "invalid";
397 default:
398 crm_err("Invalid cluster layer: %d", layer);
399 return "invalid";
400 }
401}
402
416{
417 static enum pcmk_cluster_layer cluster_layer = pcmk_cluster_layer_unknown;
418 const char *cluster = NULL;
419
420 // Cluster layer is stable once set
421 if (cluster_layer != pcmk_cluster_layer_unknown) {
422 return cluster_layer;
423 }
424
426
427 if (cluster != NULL) {
428 crm_info("Verifying configured cluster layer '%s'", cluster);
429 cluster_layer = pcmk_cluster_layer_invalid;
430
431#if SUPPORT_COROSYNC
432 if (pcmk__str_eq(cluster, PCMK_VALUE_COROSYNC, pcmk__str_casei)) {
433 cluster_layer = pcmk_cluster_layer_corosync;
434 }
435#endif // SUPPORT_COROSYNC
436
437 if (cluster_layer == pcmk_cluster_layer_invalid) {
438 crm_notice("This installation does not support the '%s' cluster "
439 "infrastructure: terminating",
440 cluster);
442 }
443 crm_info("Assuming an active '%s' cluster", cluster);
444
445 } else {
446 // Nothing configured, so test supported cluster layers
447#if SUPPORT_COROSYNC
448 crm_debug("Testing with Corosync");
450 cluster_layer = pcmk_cluster_layer_corosync;
451 }
452#endif // SUPPORT_COROSYNC
453
454 if (cluster_layer == pcmk_cluster_layer_unknown) {
455 crm_notice("Could not determine the current cluster layer");
456 } else {
457 crm_info("Detected an active '%s' cluster",
458 pcmk_cluster_layer_text(cluster_layer));
459 }
460 }
461
462 return cluster_layer;
463}
464
465// Deprecated functions kept only for backward API compatibility
466// LCOV_EXCL_START
467
468#include <crm/cluster/compat.h>
469
470void
471set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
472{
473 crm_xml_add(xml, attr, pcmk__cluster_node_uuid(node));
474}
475
476gboolean
478{
479 return pcmk_cluster_connect(cluster) == pcmk_rc_ok;
480}
481
482void
487
488const char *
490{
491 switch (type) {
493 return "corosync";
495 return "unknown";
497 return "invalid";
498 }
499 crm_err("Invalid cluster type: %d", type);
500 return "invalid";
501}
502
505{
507}
508
509gboolean
514
515gboolean
517 const xmlNode *data, gboolean ordered)
518{
519 return pcmk__cluster_send_message(node, service, data);
520}
521
522const char *
524{
525 return pcmk__cluster_node_uuid(peer);
526}
527
528char *
529get_node_name(uint32_t nodeid)
530{
531 return pcmk__cluster_node_name(nodeid);
532}
533
534const char *
539
540const char *
541crm_peer_uname(const char *uuid)
542{
543 return pcmk__node_name_from_uuid(uuid);
544}
545
546// LCOV_EXCL_STOP
547// End deprecated API
const char * name
Definition cib.c:26
void pcmk__cluster_destroy_node_caches(void)
Definition membership.c:557
void pcmk_cluster_free(pcmk_cluster_t *cluster)
Free a pcmk_cluster_t object and its dynamically allocated members.
Definition cluster.c:197
void crm_cluster_disconnect(pcmk_cluster_t *cluster)
Definition cluster.c:483
gboolean is_corosync_cluster(void)
Definition cluster.c:510
pcmk_cluster_t * pcmk_cluster_new(void)
Allocate a new pcmk_cluster_t object.
Definition cluster.c:186
gboolean crm_cluster_connect(pcmk_cluster_t *cluster)
Definition cluster.c:477
void set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
Definition cluster.c:471
const char * get_local_node_name(void)
Definition cluster.c:535
const char * pcmk__cluster_node_uuid(crm_node_t *node)
Definition cluster.c:89
int pcmk_cluster_connect(pcmk_cluster_t *cluster)
Definition cluster.c:123
enum cluster_type_e get_cluster_type(void)
Definition cluster.c:504
gboolean send_cluster_message(const crm_node_t *node, enum crm_ais_msg_types service, const xmlNode *data, gboolean ordered)
Definition cluster.c:516
const char * pcmk__node_name_from_uuid(const char *uuid)
Definition cluster.c:347
const char * crm_peer_uname(const char *uuid)
Definition cluster.c:541
const char * pcmk__cluster_local_node_name(void)
Definition cluster.c:325
char * get_node_name(uint32_t nodeid)
Definition cluster.c:529
const char * name_for_cluster_type(enum cluster_type_e type)
Definition cluster.c:489
const char * crm_peer_uuid(crm_node_t *peer)
Definition cluster.c:523
int pcmk_cluster_set_destroy_fn(pcmk_cluster_t *cluster, void(*fn)(gpointer))
Set the destroy function for a cluster object.
Definition cluster.c:216
int pcmk_cluster_disconnect(pcmk_cluster_t *cluster)
Disconnect from the cluster layer.
Definition cluster.c:154
enum crm_ais_msg_types pcmk__cluster_parse_msg_type(const char *text)
Definition cluster.c:44
const char * pcmk_cluster_layer_text(enum pcmk_cluster_layer layer)
Get a log-friendly string equivalent of a cluster layer.
Definition cluster.c:388
enum pcmk_cluster_layer pcmk_get_cluster_layer(void)
Get and validate the local cluster layer.
Definition cluster.c:415
char * pcmk__cluster_node_name(uint32_t nodeid)
Definition cluster.c:269
bool pcmk__cluster_send_message(const crm_node_t *node, enum crm_ais_msg_types service, const xmlNode *data)
Definition cluster.c:236
GHashTable * crm_peer_cache
Definition membership.c:40
crm_ais_msg_types
Definition cluster.h:197
@ crm_msg_stonithd
Definition cluster.h:204
@ crm_msg_none
Definition cluster.h:198
@ crm_msg_cib
Definition cluster.h:201
@ crm_msg_pe
Definition cluster.h:206
@ crm_msg_attrd
Definition cluster.h:203
@ crm_msg_ais
Definition cluster.h:199
@ crm_msg_te
Definition cluster.h:205
@ crm_msg_stonith_ng
Definition cluster.h:207
@ crm_msg_crmd
Definition cluster.h:202
@ crm_msg_lrmd
Definition cluster.h:200
GHashTable * crm_remote_peer_cache
Definition membership.c:57
pcmk_cluster_layer
Types of cluster layer.
Definition cluster.h:225
@ pcmk_cluster_layer_invalid
Invalid cluster layer.
Definition cluster.h:227
@ pcmk_cluster_layer_corosync
Corosync Cluster Engine.
Definition cluster.h:228
@ pcmk_cluster_layer_unknown
Unknown cluster layer.
Definition cluster.h:226
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:297
Deprecated Pacemaker cluster API.
cluster_type_e
Definition compat.h:135
@ pcmk_cluster_unknown
Definition compat.h:137
@ pcmk_cluster_invalid
Definition compat.h:139
@ pcmk_cluster_corosync
Definition compat.h:142
bool pcmk__corosync_is_active(void)
Definition corosync.c:504
char * pcmk__corosync_name(uint64_t cmap_handle, uint32_t nodeid)
Definition corosync.c:101
char * pcmk__corosync_uuid(const crm_node_t *node)
Definition corosync.c:53
int pcmk__corosync_connect(pcmk_cluster_t *cluster)
Definition corosync.c:455
void pcmk__corosync_disconnect(pcmk_cluster_t *cluster)
Definition corosync.c:223
bool pcmk__cpg_send_xml(const xmlNode *msg, const crm_node_t *node, enum crm_ais_msg_types dest)
Definition cpg.c:1091
enum crm_ais_msg_types type
Definition cpg.c:3
char uname[MAX_NAME]
Definition cpg.c:5
char data[0]
Definition cpg.c:10
A dumping ground.
#define CRM_SYSTEM_CIB
Definition crm.h:89
#define CRM_SYSTEM_CRMD
Definition crm.h:90
#define CRM_SYSTEM_DC
Definition crm.h:87
#define CRM_SYSTEM_STONITHD
Definition crm.h:94
#define CRM_SYSTEM_LRMD
Definition crm.h:91
#define CRM_SYSTEM_TENGINE
Definition crm.h:93
#define CRM_SYSTEM_PENGINE
Definition crm.h:92
IPC interface to Pacemaker daemons.
#define CRM_TRACE_INIT_DATA(name)
Definition logging.h:143
#define crm_info(fmt, args...)
Definition logging.h:397
#define crm_notice(fmt, args...)
Definition logging.h:395
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
#define crm_debug(fmt, args...)
Definition logging.h:400
#define crm_err(fmt, args...)
Definition logging.h:389
const char * pcmk__message_name(const char *name)
Get name to be used as identifier for cluster messages.
Definition messages.c:171
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition nvpair.c:301
#define PCMK_VALUE_COROSYNC
Definition options.h:138
#define PCMK__ENV_CLUSTER_TYPE
const char * pcmk__env_option(const char *option)
Definition options.c:1088
@ CRM_EX_FATAL
Do not respawn.
Definition results.h:286
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition results.c:936
@ pcmk_rc_ok
Definition results.h:162
@ pcmk__str_none
@ pcmk__str_casei
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:1050
#define pcmk__str_copy(str)
char * uuid
Definition cluster.h:140
char * uname
Definition cluster.h:141
void(* destroy)(gpointer)
Definition cluster.h:146
char * uname
Definition cluster.h:88
Wrappers for and extensions to libxml2.
#define PCMK_XA_ID
Definition xml_names.h:296