pacemaker  2.0.5-ba59be712
Scalable High-Availability cluster resource manager
cluster.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 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 
27 CRM_TRACE_INIT_DATA(cluster);
28 
29 const char *
31 {
32  char *uuid = NULL;
34 
35  // Check simple cases first, to avoid any calls that might block
36  if(peer == NULL) {
37  return NULL;
38 
39  } else if (peer->uuid) {
40  return peer->uuid;
41  }
42 
43  switch (type) {
45 #if SUPPORT_COROSYNC
46  uuid = get_corosync_uuid(peer);
47 #endif
48  break;
49 
52  crm_err("Unsupported cluster type");
53  break;
54  }
55 
56  peer->uuid = uuid;
57  return peer->uuid;
58 }
59 
60 gboolean
62 {
64 
65  crm_notice("Connecting to cluster infrastructure: %s",
67  switch (type) {
69 #if SUPPORT_COROSYNC
70  if (is_corosync_cluster()) {
71  crm_peer_init();
72  return init_cs_connection(cluster);
73  }
74 #endif
75  break;
76  default:
77  break;
78  }
79  return FALSE;
80 }
81 
82 void
84 {
86 
87  crm_info("Disconnecting from cluster infrastructure: %s",
89  switch (type) {
91 #if SUPPORT_COROSYNC
92  if (is_corosync_cluster()) {
94  terminate_cs_connection(cluster);
95  }
96 #endif
97  break;
98  default:
99  break;
100  }
101 }
102 
103 gboolean
104 send_cluster_message(crm_node_t * node, enum crm_ais_msg_types service, xmlNode * data,
105  gboolean ordered)
106 {
107  switch (get_cluster_type()) {
109 #if SUPPORT_COROSYNC
110  return send_cluster_message_cs(data, FALSE, node, service);
111 #endif
112  break;
113  default:
114  break;
115  }
116  return FALSE;
117 }
118 
119 const char *
121 {
122  static char *name = NULL;
123 
124  if(name) {
125  return name;
126  }
127  name = get_node_name(0);
128  return name;
129 }
130 
131 char *
132 get_node_name(uint32_t nodeid)
133 {
134  char *name = NULL;
135  enum cluster_type_e stack;
136 
137  stack = get_cluster_type();
138  switch (stack) {
139 # if SUPPORT_COROSYNC
141  name = corosync_node_name(0, nodeid);
142  break;
143 # endif
144 
145  default:
146  crm_err("Unknown cluster type: %s (%d)", name_for_cluster_type(stack), stack);
147  }
148 
149  if(name == NULL && nodeid == 0) {
150  name = pcmk_hostname();
151  if (name == NULL) {
152  crm_err("Could not obtain the local %s node name",
153  name_for_cluster_type(stack));
155  }
156  crm_notice("Defaulting to uname -n for the local %s node name",
157  name_for_cluster_type(stack));
158  }
159 
160  if (name == NULL) {
161  crm_notice("Could not obtain a node name for %s nodeid %u",
162  name_for_cluster_type(stack), nodeid);
163  }
164  return name;
165 }
166 
177 const char *
178 crm_peer_uname(const char *uuid)
179 {
180  GHashTableIter iter;
181  crm_node_t *node = NULL;
182 
183  CRM_CHECK(uuid != NULL, return NULL);
184 
185  /* remote nodes have the same uname and uuid */
186  if (g_hash_table_lookup(crm_remote_peer_cache, uuid)) {
187  return uuid;
188  }
189 
190  /* avoid blocking calls where possible */
191  g_hash_table_iter_init(&iter, crm_peer_cache);
192  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
193  if(node->uuid && strcasecmp(node->uuid, uuid) == 0) {
194  if(node->uname) {
195  return node->uname;
196  }
197  break;
198  }
199  }
200  node = NULL;
201 
202 #if SUPPORT_COROSYNC
203  if (is_corosync_cluster()) {
204  uint32_t id = (uint32_t) crm_parse_ll(uuid, NULL);
205 
206  if (id != 0) {
207  node = crm_find_peer(id, NULL);
208  } else {
209  crm_err("Invalid node id: %s", uuid);
210  }
211 
212  if (node) {
213  crm_info("Setting uuid for node %s[%u] to '%s'", node->uname, node->id, uuid);
214  node->uuid = strdup(uuid);
215  if(node->uname) {
216  return node->uname;
217  }
218  }
219  return NULL;
220  }
221 #endif
222 
223  return NULL;
224 }
225 
226 void
227 set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
228 {
229  const char *uuid_calc = crm_peer_uuid(node);
230 
231  crm_xml_add(xml, attr, uuid_calc);
232  return;
233 }
234 
235 const char *
237 {
238  switch (type) {
240  return "corosync";
242  return "unknown";
244  return "invalid";
245  }
246  crm_err("Invalid cluster type: %d", type);
247  return "invalid";
248 }
249 
250 /* Do not expose these two */
252 static enum cluster_type_e cluster_type = pcmk_cluster_unknown;
253 
254 int
256 {
257  if (cluster_type == pcmk_cluster_unknown) {
258  crm_info("Cluster type set to: %s", name_for_cluster_type(type));
259  cluster_type = type;
260  return 0;
261 
262  } else if (cluster_type == type) {
263  return 0;
264 
265  } else if (pcmk_cluster_unknown == type) {
266  cluster_type = type;
267  return 0;
268  }
269 
270  crm_err("Cluster type already set to %s, ignoring %s",
272  return -1;
273 }
274 enum cluster_type_e
276 {
277  bool detected = FALSE;
278  const char *cluster = NULL;
279 
280  /* Return the previous calculation, if any */
281  if (cluster_type != pcmk_cluster_unknown) {
282  return cluster_type;
283  }
284 
285  cluster = pcmk__env_option("cluster_type");
286 
287 #if SUPPORT_COROSYNC
288  /* If nothing is defined in the environment, try corosync (if supported) */
289  if(cluster == NULL) {
290  crm_debug("Testing with Corosync");
291  cluster_type = find_corosync_variant();
292  if (cluster_type != pcmk_cluster_unknown) {
293  detected = TRUE;
294  goto done;
295  }
296  }
297 #endif
298 
299  /* Something was defined in the environment, test it against what we support */
300  crm_info("Verifying cluster type: '%s'", cluster?cluster:"-unspecified-");
301  if (cluster == NULL) {
302 
303 #if SUPPORT_COROSYNC
304  } else if (pcmk__str_eq(cluster, "corosync", pcmk__str_casei)) {
305  cluster_type = pcmk_cluster_corosync;
306 #endif
307 
308  } else {
309  cluster_type = pcmk_cluster_invalid;
310  goto done; /* Keep the compiler happy when no stacks are supported */
311  }
312 
313  done:
314  if (cluster_type == pcmk_cluster_unknown) {
315  crm_notice("Could not determine the current cluster type");
316 
317  } else if (cluster_type == pcmk_cluster_invalid) {
318  crm_notice("This installation does not support the '%s' cluster infrastructure: terminating.",
319  cluster);
321 
322  } else {
323  crm_info("%s an active '%s' cluster", detected?"Detected":"Assuming", name_for_cluster_type(cluster_type));
324  }
325 
326  return cluster_type;
327 }
328 
329 gboolean
331 {
333 }
334 
335 gboolean
336 node_name_is_valid(const char *key, const char *name)
337 {
338  int octet;
339 
340  if (name == NULL) {
341  crm_trace("%s is empty", key);
342  return FALSE;
343 
344  } else if (sscanf(name, "%d.%d.%d.%d", &octet, &octet, &octet, &octet) == 4) {
345  crm_trace("%s contains an ipv4 address, ignoring: %s", key, name);
346  return FALSE;
347 
348  } else if (strstr(name, ":") != NULL) {
349  crm_trace("%s contains an ipv6 address, ignoring: %s", key, name);
350  return FALSE;
351  }
352  crm_trace("%s is valid", key);
353  return TRUE;
354 }
void crm_peer_destroy(void)
Definition: membership.c:406
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:215
A dumping ground.
#define crm_notice(fmt, args...)
Definition: logging.h:349
crm_ais_msg_types
Definition: cluster.h:99
gboolean send_cluster_message(crm_node_t *node, enum crm_ais_msg_types service, xmlNode *data, gboolean ordered)
Definition: cluster.c:104
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition: results.c:759
enum cluster_type_e get_cluster_type(void)
Definition: cluster.c:275
char * uuid
Definition: cluster.h:58
void terminate_cs_connection(crm_cluster_t *cluster)
Definition: corosync.c:174
const char * crm_peer_uuid(crm_node_t *peer)
Definition: cluster.c:30
void crm_peer_init(void)
Definition: membership.c:390
GHashTable * crm_remote_peer_cache
Definition: membership.c:51
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:317
void crm_cluster_disconnect(crm_cluster_t *cluster)
Definition: cluster.c:83
const char * get_local_node_name(void)
Definition: cluster.c:120
const char * pcmk__env_option(const char *option)
Definition: options.c:285
gboolean init_cs_connection(crm_cluster_t *cluster)
Definition: corosync.c:357
gboolean is_corosync_cluster(void)
Definition: cluster.c:330
gboolean node_name_is_valid(const char *key, const char *name)
Definition: cluster.c:336
char * get_node_name(uint32_t nodeid)
Definition: cluster.c:132
#define crm_debug(fmt, args...)
Definition: logging.h:352
cluster_type_e
Definition: cluster.h:177
const char * crm_peer_uname(const char *uuid)
Get the node name corresponding to a node UUID.
Definition: cluster.c:178
const char * name_for_cluster_type(enum cluster_type_e type)
Definition: cluster.c:236
#define crm_trace(fmt, args...)
Definition: logging.h:353
CRM_TRACE_INIT_DATA(cluster)
char * corosync_node_name(uint64_t cmap_handle, uint32_t nodeid)
Definition: corosync.c:61
enum cluster_type_e find_corosync_variant(void)
Definition: corosync.c:484
gboolean crm_cluster_connect(crm_cluster_t *cluster)
Definition: cluster.c:61
int set_cluster_type(enum cluster_type_e type)
Definition: cluster.c:255
long long crm_parse_ll(const char *text, const char *default_text)
Parse a long long integer value from a string.
Definition: strings.c:107
#define crm_err(fmt, args...)
Definition: logging.h:347
gboolean send_cluster_message_cs(xmlNode *msg, gboolean local, crm_node_t *node, enum crm_ais_msg_types dest)
Definition: cpg.c:635
char data[0]
Definition: internal.h:90
char * get_corosync_uuid(crm_node_t *node)
Definition: corosync.c:44
IPC interface to Pacemaker daemons.
void set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
Definition: cluster.c:227
char * pcmk_hostname(void)
Get the local hostname.
Definition: utils.c:523
char * name
Definition: pcmk_fence.c:31
crm_node_t * crm_find_peer(unsigned int id, const char *uname)
Definition: membership.c:522
GHashTable * crm_peer_cache
Definition: membership.c:34
#define crm_info(fmt, args...)
Definition: logging.h:350
enum crm_ais_msg_types type
Definition: internal.h:83