pacemaker 2.1.5-a3f44794f94
Scalable High-Availability cluster resource manager
cluster.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2021 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 <stdio.h>
14#include <unistd.h>
15#include <string.h>
16#include <stdlib.h>
17#include <time.h>
18#include <sys/param.h>
19#include <sys/types.h>
20
21#include <crm/crm.h>
22#include <crm/msg_xml.h>
23
24#include <crm/common/ipc.h>
26#include "crmcluster_private.h"
27
29
37const char *
39{
40 char *uuid = NULL;
41
42 // Check simple cases first, to avoid any calls that might block
43 if (peer == NULL) {
44 return NULL;
45 }
46 if (peer->uuid != NULL) {
47 return peer->uuid;
48 }
49
50 switch (get_cluster_type()) {
52#if SUPPORT_COROSYNC
53 uuid = pcmk__corosync_uuid(peer);
54#endif
55 break;
56
59 crm_err("Unsupported cluster type");
60 break;
61 }
62
63 peer->uuid = uuid;
64 return peer->uuid;
65}
66
74gboolean
76{
78
79 crm_notice("Connecting to %s cluster infrastructure",
81 switch (type) {
83#if SUPPORT_COROSYNC
84 if (is_corosync_cluster()) {
86 return pcmk__corosync_connect(cluster);
87 }
88#endif
89 break;
90 default:
91 break;
92 }
93 return FALSE;
94}
95
101void
103{
105
106 crm_info("Disconnecting from %s cluster infrastructure",
108 switch (type) {
110#if SUPPORT_COROSYNC
111 if (is_corosync_cluster()) {
114 }
115#endif
116 break;
117 default:
118 break;
119 }
120}
121
132gboolean
134 xmlNode *data, gboolean ordered)
135{
136 switch (get_cluster_type()) {
138#if SUPPORT_COROSYNC
139 return pcmk__cpg_send_xml(data, node, service);
140#endif
141 break;
142 default:
143 break;
144 }
145 return FALSE;
146}
147
154const char *
156{
157 static char *name = NULL;
158
159 if (name == NULL) {
160 name = get_node_name(0);
161 }
162 return name;
163}
164
174char *
175get_node_name(uint32_t nodeid)
176{
177 char *name = NULL;
178 enum cluster_type_e stack = get_cluster_type();
179
180 switch (stack) {
181# if SUPPORT_COROSYNC
183 name = pcmk__corosync_name(0, nodeid);
184 break;
185# endif
186
187 default:
188 crm_err("Unknown cluster type: %s (%d)", name_for_cluster_type(stack), stack);
189 }
190
191 if ((name == NULL) && (nodeid == 0)) {
193 if (name == NULL) {
194 // @TODO Maybe let the caller decide what to do
195 crm_err("Could not obtain the local %s node name",
196 name_for_cluster_type(stack));
198 }
199 crm_notice("Defaulting to uname -n for the local %s node name",
200 name_for_cluster_type(stack));
201 }
202
203 if (name == NULL) {
204 crm_notice("Could not obtain a node name for %s node with id %u",
205 name_for_cluster_type(stack), nodeid);
206 }
207 return name;
208}
209
220const char *
221crm_peer_uname(const char *uuid)
222{
223 GHashTableIter iter;
224 crm_node_t *node = NULL;
225
226 CRM_CHECK(uuid != NULL, return NULL);
227
228 /* remote nodes have the same uname and uuid */
229 if (g_hash_table_lookup(crm_remote_peer_cache, uuid)) {
230 return uuid;
231 }
232
233 /* avoid blocking calls where possible */
234 g_hash_table_iter_init(&iter, crm_peer_cache);
235 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
236 if (pcmk__str_eq(node->uuid, uuid, pcmk__str_casei)) {
237 if (node->uname != NULL) {
238 return node->uname;
239 }
240 break;
241 }
242 }
243 node = NULL;
244
245#if SUPPORT_COROSYNC
246 if (is_corosync_cluster()) {
247 long long id;
248
249 if ((pcmk__scan_ll(uuid, &id, 0LL) != pcmk_rc_ok)
250 || (id < 1LL) || (id > UINT32_MAX)) {
251 crm_err("Invalid Corosync node ID '%s'", uuid);
252 return NULL;
253 }
254
255 node = pcmk__search_cluster_node_cache((uint32_t) id, NULL);
256 if (node != NULL) {
257 crm_info("Setting uuid for node %s[%u] to %s",
258 node->uname, node->id, uuid);
259 node->uuid = strdup(uuid);
260 return node->uname;
261 }
262 return NULL;
263 }
264#endif
265
266 return NULL;
267}
268
276void
277set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
278{
279 crm_xml_add(xml, attr, crm_peer_uuid(node));
280}
281
289const char *
291{
292 switch (type) {
294 return "corosync";
296 return "unknown";
298 return "invalid";
299 }
300 crm_err("Invalid cluster type: %d", type);
301 return "invalid";
302}
303
312{
313 bool detected = false;
314 const char *cluster = NULL;
315 static enum cluster_type_e cluster_type = pcmk_cluster_unknown;
316
317 /* Return the previous calculation, if any */
318 if (cluster_type != pcmk_cluster_unknown) {
319 return cluster_type;
320 }
321
323
324#if SUPPORT_COROSYNC
325 /* If nothing is defined in the environment, try corosync (if supported) */
326 if (cluster == NULL) {
327 crm_debug("Testing with Corosync");
328 cluster_type = pcmk__corosync_detect();
329 if (cluster_type != pcmk_cluster_unknown) {
330 detected = true;
331 goto done;
332 }
333 }
334#endif
335
336 /* Something was defined in the environment, test it against what we support */
337 crm_info("Verifying cluster type: '%s'",
338 ((cluster == NULL)? "-unspecified-" : cluster));
339 if (cluster == NULL) {
340
341#if SUPPORT_COROSYNC
342 } else if (pcmk__str_eq(cluster, "corosync", pcmk__str_casei)) {
343 cluster_type = pcmk_cluster_corosync;
344#endif
345
346 } else {
347 cluster_type = pcmk_cluster_invalid;
348 goto done; /* Keep the compiler happy when no stacks are supported */
349 }
350
351 done:
352 if (cluster_type == pcmk_cluster_unknown) {
353 crm_notice("Could not determine the current cluster type");
354
355 } else if (cluster_type == pcmk_cluster_invalid) {
356 crm_notice("This installation does not support the '%s' cluster infrastructure: terminating.",
357 cluster);
359
360 } else {
361 crm_info("%s an active '%s' cluster",
362 (detected? "Detected" : "Assuming"),
363 name_for_cluster_type(cluster_type));
364 }
365
366 return cluster_type;
367}
368
374gboolean
376{
378}
const char * name
Definition: cib.c:24
crm_node_t * pcmk__search_cluster_node_cache(unsigned int id, const char *uname)
Definition: membership.c:560
gboolean is_corosync_cluster(void)
Check whether the local cluster is a Corosync cluster.
Definition: cluster.c:375
gboolean crm_cluster_connect(crm_cluster_t *cluster)
Connect to the cluster layer.
Definition: cluster.c:75
CRM_TRACE_INIT_DATA(cluster)
void set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
Add a node's UUID as an XML attribute.
Definition: cluster.c:277
const char * get_local_node_name(void)
Get the local node's name.
Definition: cluster.c:155
void crm_cluster_disconnect(crm_cluster_t *cluster)
Disconnect from the cluster layer.
Definition: cluster.c:102
gboolean send_cluster_message(crm_node_t *node, enum crm_ais_msg_types service, xmlNode *data, gboolean ordered)
Send an XML message via the cluster messaging layer.
Definition: cluster.c:133
enum cluster_type_e get_cluster_type(void)
Get (and validate) the local cluster type.
Definition: cluster.c:311
const char * crm_peer_uname(const char *uuid)
Get the node name corresponding to a node UUID.
Definition: cluster.c:221
char * get_node_name(uint32_t nodeid)
Get the node name corresponding to a cluster node ID.
Definition: cluster.c:175
const char * name_for_cluster_type(enum cluster_type_e type)
Get a log-friendly string equivalent of a cluster type.
Definition: cluster.c:290
const char * crm_peer_uuid(crm_node_t *peer)
Get (and set if needed) a node's UUID.
Definition: cluster.c:38
GHashTable * crm_peer_cache
Definition: membership.c:36
crm_ais_msg_types
Definition: cluster.h:103
GHashTable * crm_remote_peer_cache
Definition: membership.c:53
cluster_type_e
Definition: cluster.h:176
@ pcmk_cluster_unknown
Definition: cluster.h:177
@ pcmk_cluster_invalid
Definition: cluster.h:178
@ pcmk_cluster_corosync
Definition: cluster.h:181
void crm_peer_init(void)
Definition: membership.c:399
void crm_peer_destroy(void)
Definition: membership.c:415
char * pcmk_hostname(void)
Get the local hostname.
Definition: utils.c:535
char * pcmk__corosync_uuid(crm_node_t *node)
Definition: corosync.c:55
void pcmk__corosync_disconnect(crm_cluster_t *cluster)
Definition: corosync.c:223
char * pcmk__corosync_name(uint64_t cmap_handle, uint32_t nodeid)
Definition: corosync.c:101
gboolean pcmk__corosync_connect(crm_cluster_t *cluster)
Definition: corosync.c:451
enum cluster_type_e pcmk__corosync_detect(void)
Definition: corosync.c:496
gboolean pcmk__cpg_send_xml(xmlNode *msg, crm_node_t *node, enum crm_ais_msg_types dest)
Definition: cpg.c:892
enum crm_ais_msg_types type
Definition: cpg.c:3
char data[0]
Definition: cpg.c:10
uint32_t id
Definition: cpg.c:0
A dumping ground.
IPC interface to Pacemaker daemons.
#define crm_info(fmt, args...)
Definition: logging.h:362
#define crm_notice(fmt, args...)
Definition: logging.h:361
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
#define crm_debug(fmt, args...)
Definition: logging.h:364
#define crm_err(fmt, args...)
Definition: logging.h:359
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:323
#define PCMK__ENV_CLUSTER_TYPE
const char * pcmk__env_option(const char *option)
Definition: options.c:290
@ CRM_EX_FATAL
Do not respawn.
Definition: results.h:265
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition: results.c:856
@ pcmk_rc_ok
Definition: results.h:148
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:97
@ pcmk__str_casei
char * uname
Definition: cluster.h:53
uint32_t id
Definition: cluster.h:66
char * uuid
Definition: cluster.h:54