pacemaker  2.0.2-debe490
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cluster.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 #include <dlfcn.h>
10 
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <time.h>
16 #include <sys/param.h>
17 #include <sys/types.h>
18 
19 #include <crm/crm.h>
20 #include <crm/msg_xml.h>
21 
22 #include <crm/common/ipc.h>
23 #include <crm/cluster/internal.h>
24 
25 CRM_TRACE_INIT_DATA(cluster);
26 
27 const char *
29 {
30  char *uuid = NULL;
32 
33  // Check simple cases first, to avoid any calls that might block
34  if(peer == NULL) {
35  return NULL;
36 
37  } else if (peer->uuid) {
38  return peer->uuid;
39  }
40 
41  switch (type) {
43 #if SUPPORT_COROSYNC
44  uuid = get_corosync_uuid(peer);
45 #endif
46  break;
47 
50  crm_err("Unsupported cluster type");
51  break;
52  }
53 
54  peer->uuid = uuid;
55  return peer->uuid;
56 }
57 
58 gboolean
60 {
62 
63  crm_notice("Connecting to cluster infrastructure: %s",
64  name_for_cluster_type(type));
65  switch (type) {
67 #if SUPPORT_COROSYNC
68  if (is_corosync_cluster()) {
69  crm_peer_init();
70  return init_cs_connection(cluster);
71  }
72 #endif
73  break;
74  default:
75  break;
76  }
77  return FALSE;
78 }
79 
80 void
82 {
84 
85  crm_info("Disconnecting from cluster infrastructure: %s",
86  name_for_cluster_type(type));
87  switch (type) {
89 #if SUPPORT_COROSYNC
90  if (is_corosync_cluster()) {
92  terminate_cs_connection(cluster);
93  }
94 #endif
95  break;
96  default:
97  break;
98  }
99 }
100 
101 gboolean
102 send_cluster_message(crm_node_t * node, enum crm_ais_msg_types service, xmlNode * data,
103  gboolean ordered)
104 {
105  switch (get_cluster_type()) {
107 #if SUPPORT_COROSYNC
108  return send_cluster_message_cs(data, FALSE, node, service);
109 #endif
110  break;
111  default:
112  break;
113  }
114  return FALSE;
115 }
116 
117 const char *
119 {
120  static char *name = NULL;
121 
122  if(name) {
123  return name;
124  }
125  name = get_node_name(0);
126  return name;
127 }
128 
129 char *
130 get_node_name(uint32_t nodeid)
131 {
132  char *name = NULL;
133  enum cluster_type_e stack;
134 
135  stack = get_cluster_type();
136  switch (stack) {
137 # if SUPPORT_COROSYNC
139  name = corosync_node_name(0, nodeid);
140  break;
141 # endif
142 
143  default:
144  crm_err("Unknown cluster type: %s (%d)", name_for_cluster_type(stack), stack);
145  }
146 
147  if(name == NULL && nodeid == 0) {
148  name = pcmk_hostname();
149  if (name == NULL) {
150  crm_err("Could not obtain the local %s node name",
151  name_for_cluster_type(stack));
153  }
154  crm_notice("Defaulting to uname -n for the local %s node name",
155  name_for_cluster_type(stack));
156  }
157 
158  if (name == NULL) {
159  crm_notice("Could not obtain a node name for %s nodeid %u",
160  name_for_cluster_type(stack), nodeid);
161  }
162  return name;
163 }
164 
175 const char *
176 crm_peer_uname(const char *uuid)
177 {
178  GHashTableIter iter;
179  crm_node_t *node = NULL;
180 
181  CRM_CHECK(uuid != NULL, return NULL);
182 
183  /* remote nodes have the same uname and uuid */
184  if (g_hash_table_lookup(crm_remote_peer_cache, uuid)) {
185  return uuid;
186  }
187 
188  /* avoid blocking calls where possible */
189  g_hash_table_iter_init(&iter, crm_peer_cache);
190  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
191  if(node->uuid && strcasecmp(node->uuid, uuid) == 0) {
192  if(node->uname) {
193  return node->uname;
194  }
195  break;
196  }
197  }
198  node = NULL;
199 
200 #if SUPPORT_COROSYNC
201  if (is_corosync_cluster()) {
202  uint32_t id = crm_int_helper(uuid, NULL);
203 
204  if (id != 0) {
205  node = crm_find_peer(id, NULL);
206  } else {
207  crm_err("Invalid node id: %s", uuid);
208  }
209 
210  if (node) {
211  crm_info("Setting uuid for node %s[%u] to '%s'", node->uname, node->id, uuid);
212  node->uuid = strdup(uuid);
213  if(node->uname) {
214  return node->uname;
215  }
216  }
217  return NULL;
218  }
219 #endif
220 
221  return NULL;
222 }
223 
224 void
225 set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
226 {
227  const char *uuid_calc = crm_peer_uuid(node);
228 
229  crm_xml_add(xml, attr, uuid_calc);
230  return;
231 }
232 
233 const char *
235 {
236  switch (type) {
238  return "corosync";
240  return "unknown";
242  return "invalid";
243  }
244  crm_err("Invalid cluster type: %d", type);
245  return "invalid";
246 }
247 
248 /* Do not expose these two */
250 static enum cluster_type_e cluster_type = pcmk_cluster_unknown;
251 
252 int
254 {
255  if (cluster_type == pcmk_cluster_unknown) {
256  crm_info("Cluster type set to: %s", name_for_cluster_type(type));
257  cluster_type = type;
258  return 0;
259 
260  } else if (cluster_type == type) {
261  return 0;
262 
263  } else if (pcmk_cluster_unknown == type) {
264  cluster_type = type;
265  return 0;
266  }
267 
268  crm_err("Cluster type already set to %s, ignoring %s",
269  name_for_cluster_type(cluster_type), name_for_cluster_type(type));
270  return -1;
271 }
272 enum cluster_type_e
274 {
275  bool detected = FALSE;
276  const char *cluster = NULL;
277 
278  /* Return the previous calculation, if any */
279  if (cluster_type != pcmk_cluster_unknown) {
280  return cluster_type;
281  }
282 
283  cluster = daemon_option("cluster_type");
284 
285 #if SUPPORT_COROSYNC
286  /* If nothing is defined in the environment, try corosync (if supported) */
287  if(cluster == NULL) {
288  crm_debug("Testing with Corosync");
289  cluster_type = find_corosync_variant();
290  if (cluster_type != pcmk_cluster_unknown) {
291  detected = TRUE;
292  goto done;
293  }
294  }
295 #endif
296 
297  /* Something was defined in the environment, test it against what we support */
298  crm_info("Verifying cluster type: '%s'", cluster?cluster:"-unspecified-");
299  if (cluster == NULL) {
300 
301 #if SUPPORT_COROSYNC
302  } else if (safe_str_eq(cluster, "corosync")) {
303  cluster_type = pcmk_cluster_corosync;
304 #endif
305 
306  } else {
307  cluster_type = pcmk_cluster_invalid;
308  goto done; /* Keep the compiler happy when no stacks are supported */
309  }
310 
311  done:
312  if (cluster_type == pcmk_cluster_unknown) {
313  crm_notice("Could not determine the current cluster type");
314 
315  } else if (cluster_type == pcmk_cluster_invalid) {
316  crm_notice("This installation does not support the '%s' cluster infrastructure: terminating.",
317  cluster);
319 
320  } else {
321  crm_info("%s an active '%s' cluster", detected?"Detected":"Assuming", name_for_cluster_type(cluster_type));
322  }
323 
324  return cluster_type;
325 }
326 
327 gboolean
329 {
331 }
332 
333 gboolean
334 node_name_is_valid(const char *key, const char *name)
335 {
336  int octet;
337 
338  if (name == NULL) {
339  crm_trace("%s is empty", key);
340  return FALSE;
341 
342  } else if (sscanf(name, "%d.%d.%d.%d", &octet, &octet, &octet, &octet) == 4) {
343  crm_trace("%s contains an ipv4 address, ignoring: %s", key, name);
344  return FALSE;
345 
346  } else if (strstr(name, ":") != NULL) {
347  crm_trace("%s contains an ipv6 address, ignoring: %s", key, name);
348  return FALSE;
349  }
350  crm_trace("%s is valid", key);
351  return TRUE;
352 }
void crm_peer_destroy(void)
Definition: membership.c:406
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:156
A dumping ground.
#define crm_notice(fmt, args...)
Definition: logging.h:242
crm_ais_msg_types
Definition: cluster.h:96
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition: results.c:476
char * corosync_node_name(uint64_tcmap_handle, uint32_t nodeid)
Definition: corosync.c:61
uint32_t id
Definition: cluster.h:62
char * uuid
Definition: cluster.h:55
void terminate_cs_connection(crm_cluster_t *cluster)
Definition: corosync.c:174
const char * get_local_node_name(void)
Definition: cluster.c:118
void crm_peer_init(void)
Definition: membership.c:390
long long crm_int_helper(const char *text, char **end_text)
Definition: strings.c:34
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:275
char * get_node_name(uint32_t nodeid)
Definition: cluster.c:130
void crm_cluster_disconnect(crm_cluster_t *cluster)
Definition: cluster.c:81
gboolean init_cs_connection(crm_cluster_t *cluster)
Definition: corosync.c:356
#define CRM_TRACE_INIT_DATA(name)
Definition: logging.h:111
#define crm_debug(fmt, args...)
Definition: logging.h:245
cluster_type_e
Definition: cluster.h:174
#define crm_trace(fmt, args...)
Definition: logging.h:246
enum cluster_type_e find_corosync_variant(void)
Definition: corosync.c:484
const char * name_for_cluster_type(enum cluster_type_e type)
Definition: cluster.c:234
gboolean crm_cluster_connect(crm_cluster_t *cluster)
Definition: cluster.c:59
int set_cluster_type(enum cluster_type_e type)
Definition: cluster.c:253
gboolean is_corosync_cluster(void)
Definition: cluster.c:328
const char * daemon_option(const char *option)
Definition: logging.c:114
gboolean node_name_is_valid(const char *key, const char *name)
Definition: cluster.c:334
#define crm_err(fmt, args...)
Definition: logging.h:240
const char * crm_peer_uname(const char *uuid)
Get the node name corresponding to a node UUID.
Definition: cluster.c:176
gboolean send_cluster_message_cs(xmlNode *msg, gboolean local, crm_node_t *node, enum crm_ais_msg_types dest)
Definition: cpg.c:633
char data[0]
Definition: internal.h:92
char * get_corosync_uuid(crm_node_t *node)
Definition: corosync.c:44
Wrappers for and extensions to libqb IPC.
char * uname
Definition: cluster.h:54
char * pcmk_hostname(void)
Get the local hostname.
Definition: utils.c:1195
void set_uuid(xmlNode *xml, const char *attr, crm_node_t *node)
Definition: cluster.c:225
#define safe_str_eq(a, b)
Definition: util.h:59
crm_node_t * crm_find_peer(unsigned int id, const char *uname)
Definition: membership.c:522
gboolean send_cluster_message(crm_node_t *node, enum crm_ais_msg_types service, xmlNode *data, gboolean ordered)
Definition: cluster.c:102
GHashTable * crm_peer_cache
Definition: membership.c:34
#define crm_info(fmt, args...)
Definition: logging.h:243
const char * crm_peer_uuid(crm_node_t *node)
Definition: cluster.c:28
enum crm_ais_msg_types type
Definition: internal.h:85
enum cluster_type_e get_cluster_type(void)
Definition: cluster.c:273