This source file includes following definitions.
- reap_dead_nodes
- post_cache_update
- crmd_node_update_complete
- create_node_state_update
- remove_conflicting_node_callback
- search_conflicting_node_callback
- node_list_update_callback
- populate_cib_nodes
- cib_quorum_update_complete
- crm_update_quorum
1
2
3
4
5
6
7
8
9
10
11 #include <crm_internal.h>
12
13 #include <string.h>
14
15 #include <crm/crm.h>
16 #include <crm/msg_xml.h>
17 #include <crm/common/xml.h>
18 #include <crm/common/xml_internal.h>
19 #include <crm/cluster/internal.h>
20
21 #include <pacemaker-controld.h>
22
23 void post_cache_update(int instance);
24
25 extern gboolean check_join_state(enum crmd_fsa_state cur_state, const char *source);
26
27 static void
28 reap_dead_nodes(gpointer key, gpointer value, gpointer user_data)
29 {
30 crm_node_t *node = value;
31
32 if (crm_is_peer_active(node) == FALSE) {
33 crm_update_peer_join(__func__, node, crm_join_none);
34
35 if(node && node->uname) {
36 if (pcmk__str_eq(controld_globals.our_nodename, node->uname,
37 pcmk__str_casei)) {
38 crm_err("We're not part of the cluster anymore");
39 register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL);
40
41 } else if (!AM_I_DC
42 && pcmk__str_eq(node->uname, controld_globals.dc_name,
43 pcmk__str_casei)) {
44 crm_warn("Our DC node (%s) left the cluster", node->uname);
45 register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
46 }
47 }
48
49 if ((controld_globals.fsa_state == S_INTEGRATION)
50 || (controld_globals.fsa_state == S_FINALIZE_JOIN)) {
51 check_join_state(controld_globals.fsa_state, __func__);
52 }
53 if ((node != NULL) && (node->uuid != NULL)) {
54 fail_incompletable_actions(controld_globals.transition_graph,
55 node->uuid);
56 }
57 }
58 }
59
60 void
61 post_cache_update(int instance)
62 {
63 xmlNode *no_op = NULL;
64
65 crm_peer_seq = instance;
66 crm_debug("Updated cache after membership event %d.", instance);
67
68 g_hash_table_foreach(crm_peer_cache, reap_dead_nodes, NULL);
69 controld_set_fsa_input_flags(R_MEMBERSHIP);
70
71 if (AM_I_DC) {
72 populate_cib_nodes(node_update_quick | node_update_cluster | node_update_peer |
73 node_update_expected, __func__);
74 }
75
76
77
78
79
80 controld_set_fsa_action_flags(A_ELECTION_CHECK);
81 controld_trigger_fsa();
82
83
84
85
86 no_op = create_request(CRM_OP_NOOP, NULL, NULL, CRM_SYSTEM_CRMD,
87 AM_I_DC ? CRM_SYSTEM_DC : CRM_SYSTEM_CRMD, NULL);
88 send_cluster_message(NULL, crm_msg_crmd, no_op, FALSE);
89 free_xml(no_op);
90 }
91
92 static void
93 crmd_node_update_complete(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
94 {
95 fsa_data_t *msg_data = NULL;
96
97 if (rc == pcmk_ok) {
98 crm_trace("Node update %d complete", call_id);
99
100 } else if(call_id < pcmk_ok) {
101 crm_err("Node update failed: %s (%d)", pcmk_strerror(call_id), call_id);
102 crm_log_xml_debug(msg, "failed");
103 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
104
105 } else {
106 crm_err("Node update %d failed: %s (%d)", call_id, pcmk_strerror(rc), rc);
107 crm_log_xml_debug(msg, "failed");
108 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
109 }
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123 xmlNode *
124 create_node_state_update(crm_node_t *node, int flags, xmlNode *parent,
125 const char *source)
126 {
127 const char *value = NULL;
128 xmlNode *node_state;
129
130 if (!node->state) {
131 crm_info("Node update for %s cancelled: no state, not seen yet", node->uname);
132 return NULL;
133 }
134
135 node_state = create_xml_node(parent, XML_CIB_TAG_STATE);
136
137 if (pcmk_is_set(node->flags, crm_remote_node)) {
138 pcmk__xe_set_bool_attr(node_state, XML_NODE_IS_REMOTE, true);
139 }
140
141 if (crm_xml_add(node_state, XML_ATTR_ID, crm_peer_uuid(node)) == NULL) {
142 crm_info("Node update for %s cancelled: no ID", node->uname);
143 free_xml(node_state);
144 return NULL;
145 }
146
147 crm_xml_add(node_state, XML_ATTR_UNAME, node->uname);
148
149 if ((flags & node_update_cluster) && node->state) {
150 if (compare_version(controld_globals.dc_version, "3.18.0") >= 0) {
151
152 crm_xml_add_ll(node_state, PCMK__XA_IN_CCM, node->when_member);
153
154 } else {
155 pcmk__xe_set_bool_attr(node_state, PCMK__XA_IN_CCM,
156 pcmk__str_eq(node->state, CRM_NODE_MEMBER,
157 pcmk__str_casei));
158 }
159 }
160
161 if (!pcmk_is_set(node->flags, crm_remote_node)) {
162 if (flags & node_update_peer) {
163 if (compare_version(controld_globals.dc_version, "3.18.0") >= 0) {
164
165 crm_xml_add_ll(node_state, PCMK__XA_CRMD, node->when_online);
166
167 } else {
168
169 value = OFFLINESTATUS;
170 if (pcmk_is_set(node->processes, crm_get_cluster_proc())) {
171 value = ONLINESTATUS;
172 }
173 crm_xml_add(node_state, PCMK__XA_CRMD, value);
174 }
175 }
176
177 if (flags & node_update_join) {
178 if (node->join <= crm_join_none) {
179 value = CRMD_JOINSTATE_DOWN;
180 } else {
181 value = CRMD_JOINSTATE_MEMBER;
182 }
183 crm_xml_add(node_state, PCMK__XA_JOIN, value);
184 }
185
186 if (flags & node_update_expected) {
187 crm_xml_add(node_state, PCMK__XA_EXPECTED, node->expected);
188 }
189 }
190
191 crm_xml_add(node_state, XML_ATTR_ORIGIN, source);
192
193 return node_state;
194 }
195
196 static void
197 remove_conflicting_node_callback(xmlNode * msg, int call_id, int rc,
198 xmlNode * output, void *user_data)
199 {
200 char *node_uuid = user_data;
201
202 do_crm_log_unlikely(rc == 0 ? LOG_DEBUG : LOG_NOTICE,
203 "Deletion of the unknown conflicting node \"%s\": %s (rc=%d)",
204 node_uuid, pcmk_strerror(rc), rc);
205 }
206
207 static void
208 search_conflicting_node_callback(xmlNode * msg, int call_id, int rc,
209 xmlNode * output, void *user_data)
210 {
211 char *new_node_uuid = user_data;
212 xmlNode *node_xml = NULL;
213
214 if (rc != pcmk_ok) {
215 if (rc != -ENXIO) {
216 crm_notice("Searching conflicting nodes for %s failed: %s (%d)",
217 new_node_uuid, pcmk_strerror(rc), rc);
218 }
219 return;
220
221 } else if (output == NULL) {
222 return;
223 }
224
225 if (pcmk__xe_is(output, XML_CIB_TAG_NODE)) {
226 node_xml = output;
227
228 } else {
229 node_xml = pcmk__xml_first_child(output);
230 }
231
232 for (; node_xml != NULL; node_xml = pcmk__xml_next(node_xml)) {
233 const char *node_uuid = NULL;
234 const char *node_uname = NULL;
235 GHashTableIter iter;
236 crm_node_t *node = NULL;
237 gboolean known = FALSE;
238
239 if (!pcmk__xe_is(node_xml, XML_CIB_TAG_NODE)) {
240 continue;
241 }
242
243 node_uuid = crm_element_value(node_xml, XML_ATTR_ID);
244 node_uname = crm_element_value(node_xml, XML_ATTR_UNAME);
245
246 if (node_uuid == NULL || node_uname == NULL) {
247 continue;
248 }
249
250 g_hash_table_iter_init(&iter, crm_peer_cache);
251 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
252 if (node->uuid
253 && pcmk__str_eq(node->uuid, node_uuid, pcmk__str_casei)
254 && node->uname
255 && pcmk__str_eq(node->uname, node_uname, pcmk__str_casei)) {
256
257 known = TRUE;
258 break;
259 }
260 }
261
262 if (known == FALSE) {
263 cib_t *cib_conn = controld_globals.cib_conn;
264 int delete_call_id = 0;
265 xmlNode *node_state_xml = NULL;
266
267 crm_notice("Deleting unknown node %s/%s which has conflicting uname with %s",
268 node_uuid, node_uname, new_node_uuid);
269
270 delete_call_id = cib_conn->cmds->remove(cib_conn, XML_CIB_TAG_NODES,
271 node_xml, cib_scope_local);
272 fsa_register_cib_callback(delete_call_id, strdup(node_uuid),
273 remove_conflicting_node_callback);
274
275 node_state_xml = create_xml_node(NULL, XML_CIB_TAG_STATE);
276 crm_xml_add(node_state_xml, XML_ATTR_ID, node_uuid);
277 crm_xml_add(node_state_xml, XML_ATTR_UNAME, node_uname);
278
279 delete_call_id = cib_conn->cmds->remove(cib_conn,
280 XML_CIB_TAG_STATUS,
281 node_state_xml,
282 cib_scope_local);
283 fsa_register_cib_callback(delete_call_id, strdup(node_uuid),
284 remove_conflicting_node_callback);
285 free_xml(node_state_xml);
286 }
287 }
288 }
289
290 static void
291 node_list_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
292 {
293 fsa_data_t *msg_data = NULL;
294
295 if(call_id < pcmk_ok) {
296 crm_err("Node list update failed: %s (%d)", pcmk_strerror(call_id), call_id);
297 crm_log_xml_debug(msg, "update:failed");
298 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
299
300 } else if(rc < pcmk_ok) {
301 crm_err("Node update %d failed: %s (%d)", call_id, pcmk_strerror(rc), rc);
302 crm_log_xml_debug(msg, "update:failed");
303 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
304 }
305 }
306
307 void
308 populate_cib_nodes(enum node_update_flags flags, const char *source)
309 {
310 cib_t *cib_conn = controld_globals.cib_conn;
311
312 int call_id = 0;
313 gboolean from_hashtable = TRUE;
314 xmlNode *node_list = create_xml_node(NULL, XML_CIB_TAG_NODES);
315
316 #if SUPPORT_COROSYNC
317 if (!pcmk_is_set(flags, node_update_quick) && is_corosync_cluster()) {
318 from_hashtable = pcmk__corosync_add_nodes(node_list);
319 }
320 #endif
321
322 if (from_hashtable) {
323 GHashTableIter iter;
324 crm_node_t *node = NULL;
325 GString *xpath = NULL;
326
327 g_hash_table_iter_init(&iter, crm_peer_cache);
328 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
329 xmlNode *new_node = NULL;
330
331 if ((node->uuid != NULL) && (node->uname != NULL)) {
332 crm_trace("Creating node entry for %s/%s", node->uname, node->uuid);
333 if (xpath == NULL) {
334 xpath = g_string_sized_new(512);
335 } else {
336 g_string_truncate(xpath, 0);
337 }
338
339
340 new_node = create_xml_node(node_list, XML_CIB_TAG_NODE);
341 crm_xml_add(new_node, XML_ATTR_ID, node->uuid);
342 crm_xml_add(new_node, XML_ATTR_UNAME, node->uname);
343
344
345 pcmk__g_strcat(xpath,
346 "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION
347 "/" XML_CIB_TAG_NODES "/" XML_CIB_TAG_NODE
348 "[@" XML_ATTR_UNAME "='", node->uname, "']"
349 "[@" XML_ATTR_ID "!='", node->uuid, "']", NULL);
350
351 call_id = cib_conn->cmds->query(cib_conn,
352 (const char *) xpath->str,
353 NULL,
354 cib_scope_local|cib_xpath);
355 fsa_register_cib_callback(call_id, strdup(node->uuid),
356 search_conflicting_node_callback);
357 }
358 }
359
360 if (xpath != NULL) {
361 g_string_free(xpath, TRUE);
362 }
363 }
364
365 crm_trace("Populating <nodes> section from %s", from_hashtable ? "hashtable" : "cluster");
366
367 if ((controld_update_cib(XML_CIB_TAG_NODES, node_list, cib_scope_local,
368 node_list_update_callback) == pcmk_rc_ok)
369 && (crm_peer_cache != NULL) && AM_I_DC) {
370
371
372
373
374 GHashTableIter iter;
375 crm_node_t *node = NULL;
376
377 free_xml(node_list);
378 node_list = create_xml_node(NULL, XML_CIB_TAG_STATUS);
379
380 g_hash_table_iter_init(&iter, crm_peer_cache);
381 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
382 create_node_state_update(node, flags, node_list, source);
383 }
384
385 if (crm_remote_peer_cache) {
386 g_hash_table_iter_init(&iter, crm_remote_peer_cache);
387 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
388 create_node_state_update(node, flags, node_list, source);
389 }
390 }
391
392 controld_update_cib(XML_CIB_TAG_STATUS, node_list, cib_scope_local,
393 crmd_node_update_complete);
394 }
395 free_xml(node_list);
396 }
397
398 static void
399 cib_quorum_update_complete(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
400 {
401 fsa_data_t *msg_data = NULL;
402
403 if (rc == pcmk_ok) {
404 crm_trace("Quorum update %d complete", call_id);
405
406 } else {
407 crm_err("Quorum update %d failed: %s (%d)", call_id, pcmk_strerror(rc), rc);
408 crm_log_xml_debug(msg, "failed");
409 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
410 }
411 }
412
413 void
414 crm_update_quorum(gboolean quorum, gboolean force_update)
415 {
416 bool has_quorum = pcmk_is_set(controld_globals.flags, controld_has_quorum);
417
418 if (quorum) {
419 controld_set_global_flags(controld_ever_had_quorum);
420
421 } else if (pcmk_all_flags_set(controld_globals.flags,
422 controld_ever_had_quorum
423 |controld_no_quorum_suicide)) {
424 pcmk__panic(__func__);
425 }
426
427 if (AM_I_DC
428 && ((has_quorum && !quorum) || (!has_quorum && quorum)
429 || force_update)) {
430 xmlNode *update = NULL;
431
432 update = create_xml_node(NULL, XML_TAG_CIB);
433 crm_xml_add_int(update, XML_ATTR_HAVE_QUORUM, quorum);
434 crm_xml_add(update, XML_ATTR_DC_UUID, controld_globals.our_uuid);
435
436 crm_debug("Updating quorum status to %s", pcmk__btoa(quorum));
437 controld_update_cib(XML_TAG_CIB, update, cib_scope_local,
438 cib_quorum_update_complete);
439 free_xml(update);
440
441
442
443
444
445
446
447
448
449
450
451 if (quorum) {
452
453
454
455
456 abort_after_delay(INFINITY, pcmk__graph_restart, "Quorum gained",
457 5000);
458 } else {
459 abort_transition(INFINITY, pcmk__graph_restart, "Quorum lost",
460 NULL);
461 }
462 }
463
464 if (quorum) {
465 controld_set_global_flags(controld_has_quorum);
466 } else {
467 controld_clear_global_flags(controld_has_quorum);
468 }
469 }