pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
cluster.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2022 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  crm_peer_init();
85  return pcmk__corosync_connect(cluster);
86 #else
87  break;
88 #endif // SUPPORT_COROSYNC
89  default:
90  break;
91  }
92  return FALSE;
93 }
94 
100 void
102 {
104 
105  crm_info("Disconnecting from %s cluster infrastructure",
107  switch (type) {
109 #if SUPPORT_COROSYNC
111  pcmk__corosync_disconnect(cluster);
112 #endif // SUPPORT_COROSYNC
113  break;
114  default:
115  break;
116  }
117 }
118 
128 {
129  crm_cluster_t *cluster = calloc(1, sizeof(crm_cluster_t));
130 
131  CRM_ASSERT(cluster != NULL);
132  return cluster;
133 }
134 
140 void
142 {
143  if (cluster == NULL) {
144  return;
145  }
146  free(cluster->uuid);
147  free(cluster->uname);
148  free(cluster);
149 }
150 
161 gboolean
163  xmlNode *data, gboolean ordered)
164 {
165  switch (get_cluster_type()) {
167 #if SUPPORT_COROSYNC
168  return pcmk__cpg_send_xml(data, node, service);
169 #endif
170  break;
171  default:
172  break;
173  }
174  return FALSE;
175 }
176 
183 const char *
185 {
186  static char *name = NULL;
187 
188  if (name == NULL) {
189  name = get_node_name(0);
190  }
191  return name;
192 }
193 
203 char *
204 get_node_name(uint32_t nodeid)
205 {
206  char *name = NULL;
207  enum cluster_type_e stack = get_cluster_type();
208 
209  switch (stack) {
211 #if SUPPORT_COROSYNC
212  name = pcmk__corosync_name(0, nodeid);
213  break;
214 #endif // SUPPORT_COROSYNC
215 
216  default:
217  crm_err("Unknown cluster type: %s (%d)", name_for_cluster_type(stack), stack);
218  }
219 
220  if ((name == NULL) && (nodeid == 0)) {
221  name = pcmk_hostname();
222  if (name == NULL) {
223  // @TODO Maybe let the caller decide what to do
224  crm_err("Could not obtain the local %s node name",
225  name_for_cluster_type(stack));
227  }
228  crm_notice("Defaulting to uname -n for the local %s node name",
229  name_for_cluster_type(stack));
230  }
231 
232  if (name == NULL) {
233  crm_notice("Could not obtain a node name for %s node with id %u",
234  name_for_cluster_type(stack), nodeid);
235  }
236  return name;
237 }
238 
249 const char *
250 crm_peer_uname(const char *uuid)
251 {
252  GHashTableIter iter;
253  crm_node_t *node = NULL;
254 
255  CRM_CHECK(uuid != NULL, return NULL);
256 
257  /* remote nodes have the same uname and uuid */
258  if (g_hash_table_lookup(crm_remote_peer_cache, uuid)) {
259  return uuid;
260  }
261 
262  /* avoid blocking calls where possible */
263  g_hash_table_iter_init(&iter, crm_peer_cache);
264  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
265  if (pcmk__str_eq(node->uuid, uuid, pcmk__str_casei)) {
266  if (node->uname != NULL) {
267  return node->uname;
268  }
269  break;
270  }
271  }
272  node = NULL;
273 
274  if (is_corosync_cluster()) {
275  long long id;
276 
277  if ((pcmk__scan_ll(uuid, &id, 0LL) != pcmk_rc_ok)
278  || (id < 1LL) || (id > UINT32_MAX)) {
279  crm_err("Invalid Corosync node ID '%s'", uuid);
280  return NULL;
281  }
282 
283  node = pcmk__search_cluster_node_cache((uint32_t) id, NULL);
284  if (node != NULL) {
285  crm_info("Setting uuid for node %s[%u] to %s",
286  node->uname, node->id, uuid);
287  node->uuid = strdup(uuid);
288  return node->uname;
289  }
290  return NULL;
291  }
292 
293  return NULL;
294 }
295 
303 void
304 set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
305 {
306  crm_xml_add(xml, attr, crm_peer_uuid(node));
307 }
308 
316 const char *
318 {
319  switch (type) {
321  return "corosync";
323  return "unknown";
325  return "invalid";
326  }
327  crm_err("Invalid cluster type: %d", type);
328  return "invalid";
329 }
330 
337 enum cluster_type_e
339 {
340  bool detected = false;
341  const char *cluster = NULL;
342  static enum cluster_type_e cluster_type = pcmk_cluster_unknown;
343 
344  /* Return the previous calculation, if any */
345  if (cluster_type != pcmk_cluster_unknown) {
346  return cluster_type;
347  }
348 
350 
351 #if SUPPORT_COROSYNC
352  /* If nothing is defined in the environment, try corosync (if supported) */
353  if (cluster == NULL) {
354  crm_debug("Testing with Corosync");
355  cluster_type = pcmk__corosync_detect();
356  if (cluster_type != pcmk_cluster_unknown) {
357  detected = true;
358  goto done;
359  }
360  }
361 #endif
362 
363  /* Something was defined in the environment, test it against what we support */
364  crm_info("Verifying cluster type: '%s'",
365  ((cluster == NULL)? "-unspecified-" : cluster));
366  if (cluster == NULL) {
367 
368 #if SUPPORT_COROSYNC
369  } else if (pcmk__str_eq(cluster, "corosync", pcmk__str_casei)) {
370  cluster_type = pcmk_cluster_corosync;
371 #endif
372 
373  } else {
374  cluster_type = pcmk_cluster_invalid;
375  goto done; /* Keep the compiler happy when no stacks are supported */
376  }
377 
378  done:
379  if (cluster_type == pcmk_cluster_unknown) {
380  crm_notice("Could not determine the current cluster type");
381 
382  } else if (cluster_type == pcmk_cluster_invalid) {
383  crm_notice("This installation does not support the '%s' cluster infrastructure: terminating.",
384  cluster);
386 
387  } else {
388  crm_info("%s an active '%s' cluster",
389  (detected? "Detected" : "Assuming"),
390  name_for_cluster_type(cluster_type));
391  }
392 
393  return cluster_type;
394 }
395 
401 gboolean
403 {
405 }
void crm_peer_destroy(void)
Definition: membership.c:416
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:235
A dumping ground.
#define crm_notice(fmt, args...)
Definition: logging.h:379
char data[0]
Definition: cpg.c:55
gboolean send_cluster_message(const 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:162
crm_ais_msg_types
Definition: cluster.h:115
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition: results.c:874
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:338
char * uuid
Definition: cluster.h:60
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:400
GHashTable * crm_remote_peer_cache
Definition: membership.c:53
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:302
void crm_cluster_disconnect(crm_cluster_t *cluster)
Disconnect from the cluster layer.
Definition: cluster.c:101
enum cluster_type_e pcmk__corosync_detect(void)
Definition: corosync.c:496
char * uuid
Definition: cluster.h:87
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:184
const char * pcmk__env_option(const char *option)
Definition: options.c:58
gboolean pcmk__cpg_send_xml(xmlNode *msg, const crm_node_t *node, enum crm_ais_msg_types dest)
Definition: cpg.c:892
gboolean is_corosync_cluster(void)
Check whether the local cluster is a Corosync cluster.
Definition: cluster.c:402
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:204
#define crm_debug(fmt, args...)
Definition: logging.h:382
gboolean pcmk__corosync_connect(crm_cluster_t *cluster)
Definition: corosync.c:451
cluster_type_e
Definition: cluster.h:189
const char * crm_peer_uname(const char *uuid)
Get the node name corresponding to a node UUID.
Definition: cluster.c:250
const char * name_for_cluster_type(enum cluster_type_e type)
Get a log-friendly string equivalent of a cluster type.
Definition: cluster.c:317
crm_node_t * pcmk__search_cluster_node_cache(unsigned int id, const char *uname)
Definition: membership.c:561
crm_cluster_t * pcmk_cluster_new(void)
Allocate a new crm_cluster_t object.
Definition: cluster.c:127
CRM_TRACE_INIT_DATA(cluster)
void pcmk_cluster_free(crm_cluster_t *cluster)
Free a crm_cluster_t object and its dynamically allocated members.
Definition: cluster.c:141
gboolean crm_cluster_connect(crm_cluster_t *cluster)
Connect to the cluster layer.
Definition: cluster.c:75
#define PCMK__ENV_CLUSTER_TYPE
uint32_t id
Definition: cpg.c:45
char * uname
Definition: cluster.h:88
#define crm_err(fmt, args...)
Definition: logging.h:377
#define CRM_ASSERT(expr)
Definition: results.h:42
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:304
char * pcmk__corosync_uuid(const crm_node_t *node)
Definition: corosync.c:55
char * pcmk_hostname(void)
Get the local hostname.
Definition: utils.c:535
GHashTable * crm_peer_cache
Definition: membership.c:36
#define crm_info(fmt, args...)
Definition: logging.h:380
Do not respawn.
Definition: results.h:268