pacemaker  2.1.4-dc6eb4362
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>
25 #include <crm/cluster/internal.h>
26 #include "crmcluster_private.h"
27 
28 CRM_TRACE_INIT_DATA(cluster);
29 
37 const 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 
74 gboolean
76 {
78 
79  crm_notice("Connecting to %s cluster infrastructure",
81  switch (type) {
83 #if SUPPORT_COROSYNC
84  if (is_corosync_cluster()) {
85  crm_peer_init();
86  return pcmk__corosync_connect(cluster);
87  }
88 #endif
89  break;
90  default:
91  break;
92  }
93  return FALSE;
94 }
95 
101 void
103 {
105 
106  crm_info("Disconnecting from %s cluster infrastructure",
108  switch (type) {
110 #if SUPPORT_COROSYNC
111  if (is_corosync_cluster()) {
113  pcmk__corosync_disconnect(cluster);
114  }
115 #endif
116  break;
117  default:
118  break;
119  }
120 }
121 
132 gboolean
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 
154 const char *
156 {
157  static char *name = NULL;
158 
159  if (name == NULL) {
160  name = get_node_name(0);
161  }
162  return name;
163 }
164 
174 char *
175 get_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)) {
192  name = pcmk_hostname();
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 
220 const char *
221 crm_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 
276 void
277 set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
278 {
279  crm_xml_add(xml, attr, crm_peer_uuid(node));
280 }
281 
289 const 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 
310 enum cluster_type_e
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 
374 gboolean
376 {
378 }
void crm_peer_destroy(void)
Definition: membership.c:415
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
A dumping ground.
#define crm_notice(fmt, args...)
Definition: logging.h:360
char data[0]
Definition: cpg.c:55
crm_ais_msg_types
Definition: cluster.h:103
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
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition: results.c:775
void pcmk__corosync_disconnect(crm_cluster_t *cluster)
Definition: corosync.c:223
const char * name
Definition: cib.c:24
char * pcmk__corosync_name(uint64_t cmap_handle, uint32_t nodeid)
Definition: corosync.c:101
enum cluster_type_e get_cluster_type(void)
Get (and validate) the local cluster type.
Definition: cluster.c:311
char * uuid
Definition: cluster.h:54
const char * crm_peer_uuid(crm_node_t *peer)
Get (and set if needed) a node&#39;s UUID.
Definition: cluster.c:38
void crm_peer_init(void)
Definition: membership.c:399
GHashTable * crm_remote_peer_cache
Definition: membership.c:53
char * pcmk__corosync_uuid(crm_node_t *node)
Definition: corosync.c:55
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
void crm_cluster_disconnect(crm_cluster_t *cluster)
Disconnect from the cluster layer.
Definition: cluster.c:102
enum cluster_type_e pcmk__corosync_detect(void)
Definition: corosync.c:496
enum crm_ais_msg_types type
Definition: cpg.c:48
const char * get_local_node_name(void)
Get the local node&#39;s name.
Definition: cluster.c:155
const char * pcmk__env_option(const char *option)
Definition: options.c:286
gboolean is_corosync_cluster(void)
Check whether the local cluster is a Corosync cluster.
Definition: cluster.c:375
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:97
char * get_node_name(uint32_t nodeid)
Get the node name corresponding to a cluster node ID.
Definition: cluster.c:175
#define crm_debug(fmt, args...)
Definition: logging.h:363
gboolean pcmk__corosync_connect(crm_cluster_t *cluster)
Definition: corosync.c:451
cluster_type_e
Definition: cluster.h:176
const char * crm_peer_uname(const char *uuid)
Get the node name corresponding to a node UUID.
Definition: cluster.c:221
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
crm_node_t * pcmk__search_cluster_node_cache(unsigned int id, const char *uname)
Definition: membership.c:560
CRM_TRACE_INIT_DATA(cluster)
gboolean crm_cluster_connect(crm_cluster_t *cluster)
Connect to the cluster layer.
Definition: cluster.c:75
gboolean pcmk__cpg_send_xml(xmlNode *msg, crm_node_t *node, enum crm_ais_msg_types dest)
Definition: cpg.c:892
#define PCMK__ENV_CLUSTER_TYPE
uint32_t id
Definition: cpg.c:45
#define crm_err(fmt, args...)
Definition: logging.h:358
IPC interface to Pacemaker daemons.
void set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
Add a node&#39;s UUID as an XML attribute.
Definition: cluster.c:277
char * pcmk_hostname(void)
Get the local hostname.
Definition: utils.c:505
GHashTable * crm_peer_cache
Definition: membership.c:36
#define crm_info(fmt, args...)
Definition: logging.h:361
Do not respawn.
Definition: results.h:268