This source file includes following definitions.
- register_fsa_error_adv
- register_fsa_input_adv
- fsa_dump_queue
- copy_ha_msg_input
- delete_fsa_input
- get_message
- fsa_typed_data_adv
- do_msg_route
- route_message
- relay_message
- authorize_version
- controld_authorize_ipc_message
- handle_message
- handle_failcount_op
- handle_lrm_delete
- handle_remote_state
- create_ping_reply
- handle_ping
- handle_node_list
- handle_node_info_request
- verify_feature_set
- handle_shutdown_self_ack
- handle_shutdown_ack
- handle_request
- handle_response
- handle_shutdown_request
- send_msg_via_ipc
- delete_ha_msg_input
- broadcast_remote_state_message
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <inttypes.h>
13 #include <stdint.h>
14 #include <string.h>
15 #include <sys/param.h>
16 #include <time.h>
17
18 #include <crm/crm.h>
19 #include <crm/common/xml.h>
20 #include <crm/cluster/internal.h>
21 #include <crm/cib.h>
22 #include <crm/common/ipc_internal.h>
23
24 #include <pacemaker-controld.h>
25
26 static enum crmd_fsa_input handle_message(xmlNode *msg,
27 enum crmd_fsa_cause cause);
28 static xmlNode* create_ping_reply(const xmlNode *msg);
29 static void handle_response(xmlNode *stored_msg);
30 static enum crmd_fsa_input handle_request(xmlNode *stored_msg,
31 enum crmd_fsa_cause cause);
32 static enum crmd_fsa_input handle_shutdown_request(xmlNode *stored_msg);
33 static void send_msg_via_ipc(xmlNode * msg, const char *sys, const char *src);
34
35
36 static int last_data_id = 0;
37
38 void
39 register_fsa_error_adv(enum crmd_fsa_cause cause, enum crmd_fsa_input input,
40 fsa_data_t * cur_data, void *new_data, const char *raised_from)
41 {
42
43 if (controld_globals.fsa_actions != A_NOTHING) {
44 register_fsa_input_adv(cur_data ? cur_data->fsa_cause : C_FSA_INTERNAL,
45 I_NULL, cur_data ? cur_data->data : NULL,
46 controld_globals.fsa_actions, TRUE, __func__);
47 }
48
49
50 crm_info("Resetting the current action list");
51 fsa_dump_actions(controld_globals.fsa_actions, "Drop");
52 controld_globals.fsa_actions = A_NOTHING;
53
54
55 register_fsa_input_adv(cause, input, new_data, A_NOTHING, TRUE, raised_from);
56 }
57
58 void
59 register_fsa_input_adv(enum crmd_fsa_cause cause, enum crmd_fsa_input input,
60 void *data, uint64_t with_actions,
61 gboolean prepend, const char *raised_from)
62 {
63 unsigned old_len = g_list_length(controld_globals.fsa_message_queue);
64 fsa_data_t *fsa_data = NULL;
65
66 if (raised_from == NULL) {
67 raised_from = "<unknown>";
68 }
69
70 if (input == I_NULL && with_actions == A_NOTHING ) {
71
72 crm_err("Cannot add entry to queue: no input and no action");
73 return;
74 }
75
76 if (input == I_WAIT_FOR_EVENT) {
77 controld_set_global_flags(controld_fsa_is_stalled);
78 crm_debug("Stalling the FSA pending further input: source=%s cause=%s data=%p queue=%d",
79 raised_from, fsa_cause2string(cause), data, old_len);
80
81 if (old_len > 0) {
82 fsa_dump_queue(LOG_TRACE);
83 prepend = FALSE;
84 }
85
86 if (data == NULL) {
87 controld_set_fsa_action_flags(with_actions);
88 fsa_dump_actions(with_actions, "Restored");
89 return;
90 }
91
92
93
94
95 with_actions |= controld_globals.fsa_actions;
96 controld_globals.fsa_actions = A_NOTHING;
97 }
98
99 last_data_id++;
100 crm_trace("%s %s FSA input %d (%s) due to %s, %s data",
101 raised_from, (prepend? "prepended" : "appended"), last_data_id,
102 fsa_input2string(input), fsa_cause2string(cause),
103 (data? "with" : "without"));
104
105 fsa_data = pcmk__assert_alloc(1, sizeof(fsa_data_t));
106 fsa_data->id = last_data_id;
107 fsa_data->fsa_input = input;
108 fsa_data->fsa_cause = cause;
109 fsa_data->origin = raised_from;
110 fsa_data->data = NULL;
111 fsa_data->data_type = fsa_dt_none;
112 fsa_data->actions = with_actions;
113
114 if (with_actions != A_NOTHING) {
115 crm_trace("Adding actions %.16" PRIx64 " to input", with_actions);
116 }
117
118 if (data != NULL) {
119 switch (cause) {
120 case C_FSA_INTERNAL:
121 case C_CRMD_STATUS_CALLBACK:
122 case C_IPC_MESSAGE:
123 case C_HA_MESSAGE:
124 CRM_CHECK(((ha_msg_input_t *) data)->msg != NULL,
125 crm_err("Bogus data from %s", raised_from));
126 crm_trace("Copying %s data from %s as cluster message data",
127 fsa_cause2string(cause), raised_from);
128 fsa_data->data = copy_ha_msg_input(data);
129 fsa_data->data_type = fsa_dt_ha_msg;
130 break;
131
132 case C_LRM_OP_CALLBACK:
133 crm_trace("Copying %s data from %s as lrmd_event_data_t",
134 fsa_cause2string(cause), raised_from);
135 fsa_data->data = lrmd_copy_event((lrmd_event_data_t *) data);
136 fsa_data->data_type = fsa_dt_lrm;
137 break;
138
139 case C_TIMER_POPPED:
140 case C_SHUTDOWN:
141 case C_UNKNOWN:
142 case C_STARTUP:
143 crm_crit("Copying %s data (from %s) is not yet implemented",
144 fsa_cause2string(cause), raised_from);
145 crmd_exit(CRM_EX_SOFTWARE);
146 break;
147 }
148 }
149
150
151 if (prepend) {
152 controld_globals.fsa_message_queue
153 = g_list_prepend(controld_globals.fsa_message_queue, fsa_data);
154 } else {
155 controld_globals.fsa_message_queue
156 = g_list_append(controld_globals.fsa_message_queue, fsa_data);
157 }
158
159 crm_trace("FSA message queue length is %d",
160 g_list_length(controld_globals.fsa_message_queue));
161
162
163
164 if (old_len == g_list_length(controld_globals.fsa_message_queue)) {
165 crm_err("Couldn't add message to the queue");
166 }
167
168 if (input != I_WAIT_FOR_EVENT) {
169 controld_trigger_fsa();
170 }
171 }
172
173 void
174 fsa_dump_queue(int log_level)
175 {
176 int offset = 0;
177
178 for (GList *iter = controld_globals.fsa_message_queue; iter != NULL;
179 iter = iter->next) {
180 fsa_data_t *data = (fsa_data_t *) iter->data;
181
182 do_crm_log_unlikely(log_level,
183 "queue[%d.%d]: input %s raised by %s(%p.%d)\t(cause=%s)",
184 offset++, data->id, fsa_input2string(data->fsa_input),
185 data->origin, data->data, data->data_type,
186 fsa_cause2string(data->fsa_cause));
187 }
188 }
189
190 ha_msg_input_t *
191 copy_ha_msg_input(ha_msg_input_t * orig)
192 {
193 xmlNode *wrapper = NULL;
194
195 ha_msg_input_t *copy = pcmk__assert_alloc(1, sizeof(ha_msg_input_t));
196
197 copy->msg = (orig != NULL)? pcmk__xml_copy(NULL, orig->msg) : NULL;
198
199 wrapper = pcmk__xe_first_child(copy->msg, PCMK__XE_CRM_XML, NULL, NULL);
200 copy->xml = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
201 return copy;
202 }
203
204 void
205 delete_fsa_input(fsa_data_t * fsa_data)
206 {
207 lrmd_event_data_t *op = NULL;
208 xmlNode *foo = NULL;
209
210 if (fsa_data == NULL) {
211 return;
212 }
213 crm_trace("About to free %s data", fsa_cause2string(fsa_data->fsa_cause));
214
215 if (fsa_data->data != NULL) {
216 switch (fsa_data->data_type) {
217 case fsa_dt_ha_msg:
218 delete_ha_msg_input(fsa_data->data);
219 break;
220
221 case fsa_dt_xml:
222 foo = fsa_data->data;
223 pcmk__xml_free(foo);
224 break;
225
226 case fsa_dt_lrm:
227 op = (lrmd_event_data_t *) fsa_data->data;
228 lrmd_free_event(op);
229 break;
230
231 case fsa_dt_none:
232 if (fsa_data->data != NULL) {
233 crm_err("Don't know how to free %s data from %s",
234 fsa_cause2string(fsa_data->fsa_cause), fsa_data->origin);
235 crmd_exit(CRM_EX_SOFTWARE);
236 }
237 break;
238 }
239 crm_trace("%s data freed", fsa_cause2string(fsa_data->fsa_cause));
240 }
241
242 free(fsa_data);
243 }
244
245
246 fsa_data_t *
247 get_message(void)
248 {
249 fsa_data_t *message
250 = (fsa_data_t *) controld_globals.fsa_message_queue->data;
251
252 controld_globals.fsa_message_queue
253 = g_list_remove(controld_globals.fsa_message_queue, message);
254 crm_trace("Processing input %d", message->id);
255 return message;
256 }
257
258 void *
259 fsa_typed_data_adv(fsa_data_t * fsa_data, enum fsa_data_type a_type, const char *caller)
260 {
261 void *ret_val = NULL;
262
263 if (fsa_data == NULL) {
264 crm_err("%s: No FSA data available", caller);
265
266 } else if (fsa_data->data == NULL) {
267 crm_err("%s: No message data available. Origin: %s", caller, fsa_data->origin);
268
269 } else if (fsa_data->data_type != a_type) {
270 crm_crit("%s: Message data was the wrong type! %d vs. requested=%d. Origin: %s",
271 caller, fsa_data->data_type, a_type, fsa_data->origin);
272 pcmk__assert(fsa_data->data_type == a_type);
273 } else {
274 ret_val = fsa_data->data;
275 }
276
277 return ret_val;
278 }
279
280
281 void
282 do_msg_route(long long action,
283 enum crmd_fsa_cause cause,
284 enum crmd_fsa_state cur_state,
285 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
286 {
287 ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg);
288
289 route_message(msg_data->fsa_cause, input->msg);
290 }
291
292 void
293 route_message(enum crmd_fsa_cause cause, xmlNode * input)
294 {
295 ha_msg_input_t fsa_input;
296 enum crmd_fsa_input result = I_NULL;
297
298 fsa_input.msg = input;
299 CRM_CHECK(cause == C_IPC_MESSAGE || cause == C_HA_MESSAGE, return);
300
301
302 if (relay_message(input, cause == C_IPC_MESSAGE)) {
303 return;
304 }
305
306
307 result = handle_message(input, cause);
308
309
310 switch (result) {
311 case I_NULL:
312 case I_ROUTER:
313 case I_NODE_JOIN:
314 case I_JOIN_REQUEST:
315 case I_JOIN_RESULT:
316 break;
317 default:
318
319 register_fsa_input_later(cause, result, &fsa_input);
320 return;
321 }
322
323 if (result != I_NULL) {
324
325 register_fsa_input(cause, result, &fsa_input);
326 }
327 }
328
329 gboolean
330 relay_message(xmlNode * msg, gboolean originated_locally)
331 {
332 enum pcmk_ipc_server dest = pcmk_ipc_unknown;
333 bool is_for_dc = false;
334 bool is_for_dcib = false;
335 bool is_for_te = false;
336 bool is_for_crm = false;
337 bool is_for_cib = false;
338 bool is_local = false;
339 bool broadcast = false;
340 const char *host_to = NULL;
341 const char *sys_to = NULL;
342 const char *sys_from = NULL;
343 const char *type = NULL;
344 const char *task = NULL;
345 const char *ref = NULL;
346 pcmk__node_status_t *node_to = NULL;
347
348 CRM_CHECK(msg != NULL, return TRUE);
349
350 host_to = crm_element_value(msg, PCMK__XA_CRM_HOST_TO);
351 sys_to = crm_element_value(msg, PCMK__XA_CRM_SYS_TO);
352 sys_from = crm_element_value(msg, PCMK__XA_CRM_SYS_FROM);
353 type = crm_element_value(msg, PCMK__XA_T);
354 task = crm_element_value(msg, PCMK__XA_CRM_TASK);
355 ref = crm_element_value(msg, PCMK_XA_REFERENCE);
356
357 broadcast = pcmk__str_empty(host_to);
358
359 if (ref == NULL) {
360 ref = "without reference ID";
361 }
362
363 if (pcmk__str_eq(task, CRM_OP_HELLO, pcmk__str_casei)) {
364 crm_trace("Received hello %s from %s (no processing needed)",
365 ref, pcmk__s(sys_from, "unidentified source"));
366 crm_log_xml_trace(msg, "hello");
367 return TRUE;
368 }
369
370
371 if (!pcmk__str_eq(type, PCMK__VALUE_CRMD, pcmk__str_none)) {
372 crm_warn("Ignoring invalid message %s with type '%s' "
373 "(not '" PCMK__VALUE_CRMD "')",
374 ref, pcmk__s(type, ""));
375 crm_log_xml_trace(msg, "ignored");
376 return TRUE;
377 }
378
379
380 if (sys_to == NULL) {
381 crm_warn("Ignoring invalid message %s with no " PCMK__XA_CRM_SYS_TO,
382 ref);
383 crm_log_xml_trace(msg, "ignored");
384 return TRUE;
385 }
386
387
388 if (pcmk_get_cluster_layer() == pcmk_cluster_layer_corosync) {
389 dest = pcmk__parse_server(sys_to);
390 if (dest == pcmk_ipc_unknown) {
391
392
393
394
395 dest = pcmk_ipc_controld;
396 }
397 }
398
399 is_for_dc = (strcasecmp(CRM_SYSTEM_DC, sys_to) == 0);
400 is_for_dcib = (strcasecmp(CRM_SYSTEM_DCIB, sys_to) == 0);
401 is_for_te = (strcasecmp(CRM_SYSTEM_TENGINE, sys_to) == 0);
402 is_for_cib = (strcasecmp(CRM_SYSTEM_CIB, sys_to) == 0);
403 is_for_crm = (strcasecmp(CRM_SYSTEM_CRMD, sys_to) == 0);
404
405
406 is_local = false;
407 if (broadcast) {
408 if (is_for_dc || is_for_te) {
409 is_local = false;
410
411 } else if (is_for_crm) {
412 if (pcmk__strcase_any_of(task, CRM_OP_NODE_INFO,
413 PCMK__CONTROLD_CMD_NODES, NULL)) {
414
415
416
417
418
419 is_local = true;
420 } else {
421 is_local = !originated_locally;
422 }
423
424 } else {
425 is_local = true;
426 }
427
428 } else if (controld_is_local_node(host_to)) {
429 is_local = true;
430
431 } else if (is_for_crm && pcmk__str_eq(task, CRM_OP_LRM_DELETE, pcmk__str_casei)) {
432 xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CRM_XML, NULL,
433 NULL);
434 xmlNode *msg_data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
435 const char *mode = crm_element_value(msg_data, PCMK__XA_MODE);
436
437 if (pcmk__str_eq(mode, PCMK__VALUE_CIB, pcmk__str_none)) {
438
439 is_local = true;
440 }
441 }
442
443
444 if (is_for_dc && pcmk__str_eq(task, CRM_OP_PING, pcmk__str_casei)
445 && (controld_globals.dc_name == NULL)) {
446
447 xmlNode *reply = create_ping_reply(msg);
448 sys_to = crm_element_value(reply, PCMK__XA_CRM_SYS_TO);
449
450 send_msg_via_ipc(reply, sys_to, NULL);
451 pcmk__xml_free(reply);
452 return TRUE;
453 }
454
455
456
457 if (is_for_dc || is_for_dcib || is_for_te) {
458 if (AM_I_DC) {
459 if (is_for_te) {
460 crm_trace("Route message %s locally as transition request",
461 ref);
462 crm_log_xml_trace(msg, sys_to);
463 send_msg_via_ipc(msg, sys_to, controld_globals.cluster->priv->node_name);
464
465 return TRUE;
466 }
467 crm_trace("Route message %s locally as DC request", ref);
468 return FALSE;
469 }
470
471 if (originated_locally
472 && !pcmk__strcase_any_of(sys_from, CRM_SYSTEM_PENGINE,
473 CRM_SYSTEM_TENGINE, NULL)) {
474 crm_trace("Relay message %s to DC (via %s)",
475 ref, pcmk__s(host_to, "broadcast"));
476 crm_log_xml_trace(msg, "relayed");
477 if (!broadcast) {
478 node_to = pcmk__get_node(0, host_to, NULL,
479 pcmk__node_search_cluster_member);
480 }
481 pcmk__cluster_send_message(node_to, dest, msg);
482 return TRUE;
483 }
484
485
486
487
488 crm_trace("Ignoring message %s because we are no longer DC", ref);
489 crm_log_xml_trace(msg, "ignored");
490 return TRUE;
491 }
492
493 if (is_local) {
494 if (is_for_crm || is_for_cib) {
495 crm_trace("Route message %s locally as controller request", ref);
496 return FALSE;
497 }
498 crm_trace("Relay message %s locally to %s", ref, sys_to);
499 crm_log_xml_trace(msg, "IPC-relay");
500 send_msg_via_ipc(msg, sys_to, controld_globals.cluster->priv->node_name);
501 return TRUE;
502 }
503
504 if (!broadcast) {
505 node_to = pcmk__search_node_caches(0, host_to, NULL,
506 pcmk__node_search_cluster_member);
507 if (node_to == NULL) {
508 crm_warn("Ignoring message %s because node %s is unknown",
509 ref, host_to);
510 crm_log_xml_trace(msg, "ignored");
511 return TRUE;
512 }
513 }
514
515 crm_trace("Relay message %s to %s",
516 ref, pcmk__s(host_to, "all peers"));
517 crm_log_xml_trace(msg, "relayed");
518 pcmk__cluster_send_message(node_to, dest, msg);
519 return TRUE;
520 }
521
522
523 static bool
524 authorize_version(xmlNode *message_data, const char *field,
525 const char *client_name, const char *ref, const char *uuid)
526 {
527 const char *version = crm_element_value(message_data, field);
528 long long version_num;
529
530 if ((pcmk__scan_ll(version, &version_num, -1LL) != pcmk_rc_ok)
531 || (version_num < 0LL)) {
532
533 crm_warn("Rejected IPC hello from %s: '%s' is not a valid protocol %s "
534 QB_XS " ref=%s uuid=%s",
535 client_name, ((version == NULL)? "" : version),
536 field, (ref? ref : "none"), uuid);
537 return false;
538 }
539 return true;
540 }
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557 bool
558 controld_authorize_ipc_message(const xmlNode *client_msg, pcmk__client_t *curr_client,
559 const char *proxy_session)
560 {
561 xmlNode *wrapper = NULL;
562 xmlNode *message_data = NULL;
563 const char *client_name = NULL;
564 const char *op = crm_element_value(client_msg, PCMK__XA_CRM_TASK);
565 const char *ref = crm_element_value(client_msg, PCMK_XA_REFERENCE);
566 const char *uuid = (curr_client? curr_client->id : proxy_session);
567
568 if (uuid == NULL) {
569 crm_warn("IPC message from client rejected: No client identifier "
570 QB_XS " ref=%s", (ref? ref : "none"));
571 goto rejected;
572 }
573
574 if (!pcmk__str_eq(CRM_OP_HELLO, op, pcmk__str_casei)) {
575
576 return true;
577 }
578
579 wrapper = pcmk__xe_first_child(client_msg, PCMK__XE_CRM_XML, NULL, NULL);
580 message_data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
581
582 client_name = crm_element_value(message_data, PCMK__XA_CLIENT_NAME);
583 if (pcmk__str_empty(client_name)) {
584 crm_warn("IPC hello from client rejected: No client name",
585 QB_XS " ref=%s uuid=%s", (ref? ref : "none"), uuid);
586 goto rejected;
587 }
588 if (!authorize_version(message_data, PCMK__XA_MAJOR_VERSION, client_name,
589 ref, uuid)) {
590 goto rejected;
591 }
592 if (!authorize_version(message_data, PCMK__XA_MINOR_VERSION, client_name,
593 ref, uuid)) {
594 goto rejected;
595 }
596
597 crm_trace("Validated IPC hello from client %s", client_name);
598 crm_log_xml_trace(client_msg, "hello");
599 if (curr_client) {
600 curr_client->userdata = pcmk__str_copy(client_name);
601 }
602 controld_trigger_fsa();
603 return false;
604
605 rejected:
606 crm_log_xml_trace(client_msg, "rejected");
607 if (curr_client) {
608 qb_ipcs_disconnect(curr_client->ipcs);
609 }
610 return false;
611 }
612
613 static enum crmd_fsa_input
614 handle_message(xmlNode *msg, enum crmd_fsa_cause cause)
615 {
616 const char *type = NULL;
617
618 CRM_CHECK(msg != NULL, return I_NULL);
619
620 type = crm_element_value(msg, PCMK__XA_SUBT);
621 if (pcmk__str_eq(type, PCMK__VALUE_REQUEST, pcmk__str_none)) {
622 return handle_request(msg, cause);
623 }
624
625 if (pcmk__str_eq(type, PCMK__VALUE_RESPONSE, pcmk__str_none)) {
626 handle_response(msg);
627 return I_NULL;
628 }
629
630 crm_warn("Ignoring message with unknown " PCMK__XA_SUBT" '%s'",
631 pcmk__s(type, ""));
632 crm_log_xml_trace(msg, "bad");
633 return I_NULL;
634 }
635
636 static enum crmd_fsa_input
637 handle_failcount_op(xmlNode * stored_msg)
638 {
639 const char *rsc = NULL;
640 const char *uname = NULL;
641 const char *op = NULL;
642 char *interval_spec = NULL;
643 guint interval_ms = 0;
644 gboolean is_remote_node = FALSE;
645
646 xmlNode *wrapper = pcmk__xe_first_child(stored_msg, PCMK__XE_CRM_XML, NULL,
647 NULL);
648 xmlNode *xml_op = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
649
650 if (xml_op) {
651 xmlNode *xml_rsc = pcmk__xe_first_child(xml_op, PCMK_XE_PRIMITIVE, NULL,
652 NULL);
653 xmlNode *xml_attrs = pcmk__xe_first_child(xml_op, PCMK__XE_ATTRIBUTES,
654 NULL, NULL);
655
656 if (xml_rsc) {
657 rsc = pcmk__xe_id(xml_rsc);
658 }
659 if (xml_attrs) {
660 op = crm_element_value(xml_attrs,
661 CRM_META "_" PCMK__META_CLEAR_FAILURE_OP);
662 crm_element_value_ms(xml_attrs,
663 CRM_META "_" PCMK__META_CLEAR_FAILURE_INTERVAL,
664 &interval_ms);
665 }
666 }
667 uname = crm_element_value(xml_op, PCMK__META_ON_NODE);
668
669 if ((rsc == NULL) || (uname == NULL)) {
670 crm_log_xml_warn(stored_msg, "invalid failcount op");
671 return I_NULL;
672 }
673
674 if (crm_element_value(xml_op, PCMK__XA_ROUTER_NODE)) {
675 is_remote_node = TRUE;
676 }
677
678 crm_debug("Clearing failures for %s-interval %s on %s "
679 "from attribute manager, CIB, and executor state",
680 pcmk__readable_interval(interval_ms), rsc, uname);
681
682 if (interval_ms) {
683 interval_spec = crm_strdup_printf("%ums", interval_ms);
684 }
685 update_attrd_clear_failures(uname, rsc, op, interval_spec, is_remote_node);
686 free(interval_spec);
687
688 controld_cib_delete_last_failure(rsc, uname, op, interval_ms);
689
690 lrm_clear_last_failure(rsc, uname, op, interval_ms);
691
692 return I_NULL;
693 }
694
695 static enum crmd_fsa_input
696 handle_lrm_delete(xmlNode *stored_msg)
697 {
698 const char *mode = NULL;
699 xmlNode *wrapper = pcmk__xe_first_child(stored_msg, PCMK__XE_CRM_XML, NULL,
700 NULL);
701 xmlNode *msg_data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
702
703 CRM_CHECK(msg_data != NULL, return I_NULL);
704
705
706
707
708
709
710
711
712
713
714
715 mode = crm_element_value(msg_data, PCMK__XA_MODE);
716 if (!pcmk__str_eq(mode, PCMK__VALUE_CIB, pcmk__str_none)) {
717
718 crm_xml_add(stored_msg, PCMK__XA_CRM_SYS_TO, CRM_SYSTEM_LRMD);
719 return I_ROUTER;
720
721 } else {
722
723 const char *from_sys = NULL;
724 const char *user_name = NULL;
725 const char *rsc_id = NULL;
726 const char *node = NULL;
727 xmlNode *rsc_xml = NULL;
728 int rc = pcmk_rc_ok;
729
730 rsc_xml = pcmk__xe_first_child(msg_data, PCMK_XE_PRIMITIVE, NULL, NULL);
731 CRM_CHECK(rsc_xml != NULL, return I_NULL);
732
733 rsc_id = pcmk__xe_id(rsc_xml);
734 from_sys = crm_element_value(stored_msg, PCMK__XA_CRM_SYS_FROM);
735 node = crm_element_value(msg_data, PCMK__META_ON_NODE);
736 user_name = pcmk__update_acl_user(stored_msg, PCMK__XA_CRM_USER, NULL);
737 crm_debug("Handling " CRM_OP_LRM_DELETE " for %s on %s locally%s%s "
738 "(clearing CIB resource history only)", rsc_id, node,
739 (user_name? " for user " : ""), (user_name? user_name : ""));
740 rc = controld_delete_resource_history(rsc_id, node, user_name,
741 cib_dryrun|cib_sync_call);
742 if (rc == pcmk_rc_ok) {
743 rc = controld_delete_resource_history(rsc_id, node, user_name,
744 crmd_cib_smart_opt());
745 }
746
747
748
749
750 if (from_sys) {
751 lrmd_event_data_t *op = NULL;
752 const char *from_host = crm_element_value(stored_msg, PCMK__XA_SRC);
753 const char *transition;
754
755 if (strcmp(from_sys, CRM_SYSTEM_TENGINE)) {
756 transition = crm_element_value(msg_data,
757 PCMK__XA_TRANSITION_KEY);
758 } else {
759 transition = crm_element_value(stored_msg,
760 PCMK__XA_TRANSITION_KEY);
761 }
762
763 crm_info("Notifying %s on %s that %s was%s deleted",
764 from_sys, (from_host? from_host : "local node"), rsc_id,
765 ((rc == pcmk_rc_ok)? "" : " not"));
766 op = lrmd_new_event(rsc_id, PCMK_ACTION_DELETE, 0);
767 op->type = lrmd_event_exec_complete;
768 op->user_data = pcmk__str_copy(pcmk__s(transition, FAKE_TE_ID));
769 op->params = pcmk__strkey_table(free, free);
770 pcmk__insert_dup(op->params, PCMK_XA_CRM_FEATURE_SET,
771 CRM_FEATURE_SET);
772 controld_rc2event(op, rc);
773 controld_ack_event_directly(from_host, from_sys, NULL, op, rsc_id);
774 lrmd_free_event(op);
775 controld_trigger_delete_refresh(from_sys, rsc_id);
776 }
777 return I_NULL;
778 }
779 }
780
781
782
783
784
785
786
787
788 static enum crmd_fsa_input
789 handle_remote_state(const xmlNode *msg)
790 {
791 const char *conn_host = NULL;
792 const char *remote_uname = pcmk__xe_id(msg);
793 pcmk__node_status_t *remote_peer;
794 bool remote_is_up = false;
795 int rc = pcmk_rc_ok;
796
797 rc = pcmk__xe_get_bool_attr(msg, PCMK__XA_IN_CCM, &remote_is_up);
798
799 CRM_CHECK(remote_uname && rc == pcmk_rc_ok, return I_NULL);
800
801 remote_peer = pcmk__cluster_lookup_remote_node(remote_uname);
802 CRM_CHECK(remote_peer, return I_NULL);
803
804 pcmk__update_peer_state(__func__, remote_peer,
805 remote_is_up ? PCMK_VALUE_MEMBER : PCMK__VALUE_LOST,
806 0);
807
808 conn_host = crm_element_value(msg, PCMK__XA_CONNECTION_HOST);
809 if (conn_host) {
810 pcmk__str_update(&remote_peer->conn_host, conn_host);
811 } else if (remote_peer->conn_host) {
812 free(remote_peer->conn_host);
813 remote_peer->conn_host = NULL;
814 }
815
816 return I_NULL;
817 }
818
819
820
821
822
823
824
825
826 static xmlNode*
827 create_ping_reply(const xmlNode *msg)
828 {
829 const char *value = NULL;
830 xmlNode *ping = NULL;
831 xmlNode *reply = NULL;
832
833
834
835 ping = pcmk__xe_create(NULL, PCMK__XE_PING_RESPONSE);
836 value = crm_element_value(msg, PCMK__XA_CRM_SYS_TO);
837 crm_xml_add(ping, PCMK__XA_CRM_SUBSYSTEM, value);
838
839
840 value = fsa_state2string(controld_globals.fsa_state);
841 crm_xml_add(ping, PCMK__XA_CRMD_STATE, value);
842 crm_notice("Current ping state: %s", value);
843
844
845
846 crm_xml_add(ping, PCMK_XA_RESULT, "ok");
847
848 reply = pcmk__new_reply(msg, ping);
849 pcmk__xml_free(ping);
850 return reply;
851 }
852
853 static enum crmd_fsa_input
854 handle_ping(const xmlNode *msg)
855 {
856 xmlNode *reply = create_ping_reply(msg);
857 if (reply != NULL) {
858 (void) relay_message(reply, TRUE);
859 pcmk__xml_free(reply);
860 }
861
862
863 return I_NULL;
864 }
865
866
867
868
869
870
871
872
873 static enum crmd_fsa_input
874 handle_node_list(const xmlNode *request)
875 {
876 GHashTableIter iter;
877 pcmk__node_status_t *node = NULL;
878 xmlNode *reply = NULL;
879 xmlNode *reply_data = NULL;
880
881
882 reply_data = pcmk__xe_create(NULL, PCMK_XE_NODES);
883 g_hash_table_iter_init(&iter, pcmk__peer_cache);
884 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
885 xmlNode *xml = pcmk__xe_create(reply_data, PCMK_XE_NODE);
886
887 crm_xml_add_ll(xml, PCMK_XA_ID,
888 (long long) node->cluster_layer_id);
889 crm_xml_add(xml, PCMK_XA_UNAME, node->name);
890 crm_xml_add(xml, PCMK__XA_IN_CCM, node->state);
891 }
892
893
894 reply = pcmk__new_reply(request, reply_data);
895 pcmk__xml_free(reply_data);
896 if (reply) {
897 (void) relay_message(reply, TRUE);
898 pcmk__xml_free(reply);
899 }
900
901
902 return I_NULL;
903 }
904
905
906
907
908
909
910
911
912 static enum crmd_fsa_input
913 handle_node_info_request(const xmlNode *msg)
914 {
915 const char *value = NULL;
916 pcmk__node_status_t *node = NULL;
917 int node_id = 0;
918 xmlNode *reply = NULL;
919 xmlNode *reply_data = NULL;
920
921
922
923 reply_data = pcmk__xe_create(NULL, PCMK_XE_NODE);
924 crm_xml_add(reply_data, PCMK__XA_CRM_SUBSYSTEM, CRM_SYSTEM_CRMD);
925
926
927 pcmk__xe_set_bool_attr(reply_data, PCMK_XA_HAVE_QUORUM,
928 pcmk_is_set(controld_globals.flags,
929 controld_has_quorum));
930
931
932
933
934
935
936 crm_element_value_int(msg, PCMK_XA_ID, &node_id);
937 if (node_id < 0) {
938 node_id = 0;
939 }
940 value = crm_element_value(msg, PCMK_XA_UNAME);
941
942
943 if ((node_id == 0) && (value == NULL)) {
944 value = controld_globals.cluster->priv->node_name;
945 }
946
947 node = pcmk__search_node_caches(node_id, value, NULL,
948 pcmk__node_search_any);
949 if (node) {
950 crm_xml_add(reply_data, PCMK_XA_ID, node->xml_id);
951 crm_xml_add(reply_data, PCMK_XA_UNAME, node->name);
952 crm_xml_add(reply_data, PCMK_XA_CRMD, node->state);
953 pcmk__xe_set_bool_attr(reply_data, PCMK_XA_REMOTE_NODE,
954 pcmk_is_set(node->flags,
955 pcmk__node_status_remote));
956 }
957
958
959 reply = pcmk__new_reply(msg, reply_data);
960 pcmk__xml_free(reply_data);
961 if (reply != NULL) {
962 (void) relay_message(reply, TRUE);
963 pcmk__xml_free(reply);
964 }
965
966
967 return I_NULL;
968 }
969
970 static void
971 verify_feature_set(xmlNode *msg)
972 {
973 const char *dc_version = crm_element_value(msg, PCMK_XA_CRM_FEATURE_SET);
974
975 if (dc_version == NULL) {
976
977
978
979 dc_version = "3.0.14";
980 }
981
982 if (feature_set_compatible(dc_version, CRM_FEATURE_SET)) {
983 crm_trace("Local feature set (%s) is compatible with DC's (%s)",
984 CRM_FEATURE_SET, dc_version);
985 } else {
986 crm_err("Local feature set (%s) is incompatible with DC's (%s)",
987 CRM_FEATURE_SET, dc_version);
988
989
990 controld_set_fsa_input_flags(R_STAYDOWN);
991 crmd_exit(CRM_EX_FATAL);
992 }
993 }
994
995
996 static enum crmd_fsa_input
997 handle_shutdown_self_ack(xmlNode *stored_msg)
998 {
999 const char *host_from = crm_element_value(stored_msg, PCMK__XA_SRC);
1000
1001 if (pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
1002
1003 crm_info("Shutting down controller");
1004 return I_STOP;
1005 }
1006
1007 if (pcmk__str_eq(host_from, controld_globals.dc_name, pcmk__str_casei)) {
1008
1009 crm_err("Shutting down controller immediately due to "
1010 "unexpected shutdown confirmation");
1011 return I_TERMINATE;
1012 }
1013
1014 if (controld_globals.fsa_state != S_STOPPING) {
1015
1016 crm_err("Starting new DC election because %s is "
1017 "confirming shutdown we did not request",
1018 (host_from? host_from : "another node"));
1019 return I_ELECTION;
1020 }
1021
1022
1023 crm_debug("Ignoring unexpected shutdown confirmation from %s",
1024 (host_from? host_from : "another node"));
1025 return I_NULL;
1026 }
1027
1028
1029 static enum crmd_fsa_input
1030 handle_shutdown_ack(xmlNode *stored_msg)
1031 {
1032 const char *host_from = crm_element_value(stored_msg, PCMK__XA_SRC);
1033
1034 if (host_from == NULL) {
1035 crm_warn("Ignoring shutdown request without origin specified");
1036 return I_NULL;
1037 }
1038
1039 if (pcmk__str_eq(host_from, controld_globals.dc_name,
1040 pcmk__str_null_matches|pcmk__str_casei)) {
1041
1042 if (pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
1043 crm_info("Shutting down controller after confirmation from %s",
1044 host_from);
1045 } else {
1046 crm_err("Shutting down controller after unexpected "
1047 "shutdown request from %s", host_from);
1048 controld_set_fsa_input_flags(R_STAYDOWN);
1049 }
1050 return I_STOP;
1051 }
1052
1053 crm_warn("Ignoring shutdown request from %s because DC is %s",
1054 host_from, controld_globals.dc_name);
1055 return I_NULL;
1056 }
1057
1058 static enum crmd_fsa_input
1059 handle_request(xmlNode *stored_msg, enum crmd_fsa_cause cause)
1060 {
1061 xmlNode *msg = NULL;
1062 const char *op = crm_element_value(stored_msg, PCMK__XA_CRM_TASK);
1063
1064
1065
1066 crm_log_xml_trace(stored_msg, "request");
1067 if (op == NULL) {
1068 crm_warn("Ignoring request without " PCMK__XA_CRM_TASK);
1069 return I_NULL;
1070 }
1071
1072 if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
1073 const char *from = crm_element_value(stored_msg, PCMK__XA_SRC);
1074 pcmk__node_status_t *node =
1075 pcmk__search_node_caches(0, from, NULL,
1076 pcmk__node_search_cluster_member);
1077
1078 pcmk__update_peer_expected(__func__, node, CRMD_JOINSTATE_DOWN);
1079 if(AM_I_DC == FALSE) {
1080 return I_NULL;
1081 }
1082 }
1083
1084
1085 if (AM_I_DC) {
1086 if (strcmp(op, CRM_OP_JOIN_ANNOUNCE) == 0) {
1087 return I_NODE_JOIN;
1088
1089 } else if (strcmp(op, CRM_OP_JOIN_REQUEST) == 0) {
1090 return I_JOIN_REQUEST;
1091
1092 } else if (strcmp(op, CRM_OP_JOIN_CONFIRM) == 0) {
1093 return I_JOIN_RESULT;
1094
1095 } else if (strcmp(op, CRM_OP_SHUTDOWN) == 0) {
1096 return handle_shutdown_self_ack(stored_msg);
1097
1098 } else if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
1099
1100 return handle_shutdown_request(stored_msg);
1101 }
1102 }
1103
1104
1105 if (strcmp(op, CRM_OP_NOVOTE) == 0) {
1106 ha_msg_input_t fsa_input;
1107
1108 fsa_input.msg = stored_msg;
1109 register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
1110 A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE,
1111 __func__);
1112
1113 } else if (strcmp(op, CRM_OP_REMOTE_STATE) == 0) {
1114
1115 return handle_remote_state(stored_msg);
1116
1117 } else if (strcmp(op, CRM_OP_THROTTLE) == 0) {
1118 throttle_update(stored_msg);
1119 if (AM_I_DC && (controld_globals.transition_graph != NULL)
1120 && !controld_globals.transition_graph->complete) {
1121
1122 crm_debug("The throttle changed. Trigger a graph.");
1123 trigger_graph();
1124 }
1125 return I_NULL;
1126
1127 } else if (strcmp(op, CRM_OP_CLEAR_FAILCOUNT) == 0) {
1128 return handle_failcount_op(stored_msg);
1129
1130 } else if (strcmp(op, CRM_OP_VOTE) == 0) {
1131
1132 ha_msg_input_t fsa_input;
1133
1134 fsa_input.msg = stored_msg;
1135 register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
1136 A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE,
1137 __func__);
1138
1139
1140 if (controld_globals.fsa_state == S_HALT) {
1141 crm_debug("Forcing an election from S_HALT");
1142 return I_ELECTION;
1143 }
1144
1145 } else if (strcmp(op, CRM_OP_JOIN_OFFER) == 0) {
1146 verify_feature_set(stored_msg);
1147 crm_debug("Raising I_JOIN_OFFER: join-%s",
1148 crm_element_value(stored_msg, PCMK__XA_JOIN_ID));
1149 return I_JOIN_OFFER;
1150
1151 } else if (strcmp(op, CRM_OP_JOIN_ACKNAK) == 0) {
1152 crm_debug("Raising I_JOIN_RESULT: join-%s",
1153 crm_element_value(stored_msg, PCMK__XA_JOIN_ID));
1154 return I_JOIN_RESULT;
1155
1156 } else if (strcmp(op, CRM_OP_LRM_DELETE) == 0) {
1157 return handle_lrm_delete(stored_msg);
1158
1159 } else if ((strcmp(op, CRM_OP_LRM_FAIL) == 0)
1160 || (strcmp(op, CRM_OP_REPROBE) == 0)) {
1161
1162 crm_xml_add(stored_msg, PCMK__XA_CRM_SYS_TO, CRM_SYSTEM_LRMD);
1163 return I_ROUTER;
1164
1165 } else if (strcmp(op, CRM_OP_NOOP) == 0) {
1166 return I_NULL;
1167
1168 } else if (strcmp(op, CRM_OP_PING) == 0) {
1169 return handle_ping(stored_msg);
1170
1171 } else if (strcmp(op, CRM_OP_NODE_INFO) == 0) {
1172 return handle_node_info_request(stored_msg);
1173
1174 } else if (strcmp(op, CRM_OP_RM_NODE_CACHE) == 0) {
1175 int id = 0;
1176 const char *name = NULL;
1177
1178 crm_element_value_int(stored_msg, PCMK_XA_ID, &id);
1179 name = crm_element_value(stored_msg, PCMK_XA_UNAME);
1180
1181 if(cause == C_IPC_MESSAGE) {
1182 msg = pcmk__new_request(pcmk_ipc_controld, CRM_SYSTEM_CRMD, NULL,
1183 CRM_SYSTEM_CRMD, CRM_OP_RM_NODE_CACHE,
1184 NULL);
1185 if (!pcmk__cluster_send_message(NULL, pcmk_ipc_controld, msg)) {
1186 crm_err("Could not instruct peers to remove references to node %s/%u", name, id);
1187 } else {
1188 crm_notice("Instructing peers to remove references to node %s/%u", name, id);
1189 }
1190 pcmk__xml_free(msg);
1191
1192 } else {
1193 pcmk__cluster_forget_cluster_node(id, name);
1194
1195
1196
1197
1198
1199 st_fail_count_reset(name);
1200 }
1201
1202 } else if (strcmp(op, CRM_OP_MAINTENANCE_NODES) == 0) {
1203 xmlNode *wrapper = pcmk__xe_first_child(stored_msg, PCMK__XE_CRM_XML,
1204 NULL, NULL);
1205 xmlNode *xml = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
1206
1207 remote_ra_process_maintenance_nodes(xml);
1208
1209 } else if (strcmp(op, PCMK__CONTROLD_CMD_NODES) == 0) {
1210 return handle_node_list(stored_msg);
1211
1212
1213 } else if (!AM_I_DC) {
1214
1215 if (strcmp(op, CRM_OP_SHUTDOWN) == 0) {
1216 return handle_shutdown_ack(stored_msg);
1217 }
1218
1219 } else {
1220 crm_err("Unexpected request (%s) sent to %s", op, AM_I_DC ? "the DC" : "non-DC node");
1221 crm_log_xml_err(stored_msg, "Unexpected");
1222 }
1223
1224 return I_NULL;
1225 }
1226
1227 static void
1228 handle_response(xmlNode *stored_msg)
1229 {
1230 const char *op = crm_element_value(stored_msg, PCMK__XA_CRM_TASK);
1231
1232 crm_log_xml_trace(stored_msg, "reply");
1233 if (op == NULL) {
1234 crm_warn("Ignoring reply without " PCMK__XA_CRM_TASK);
1235
1236 } else if (AM_I_DC && strcmp(op, CRM_OP_PECALC) == 0) {
1237
1238 const char *msg_ref = crm_element_value(stored_msg, PCMK_XA_REFERENCE);
1239
1240 if (msg_ref == NULL) {
1241 crm_err("%s - Ignoring calculation with no reference", op);
1242
1243 } else if (pcmk__str_eq(msg_ref, controld_globals.fsa_pe_ref,
1244 pcmk__str_none)) {
1245 ha_msg_input_t fsa_input;
1246
1247 controld_stop_sched_timer();
1248 fsa_input.msg = stored_msg;
1249 register_fsa_input_later(C_IPC_MESSAGE, I_PE_SUCCESS, &fsa_input);
1250
1251 } else {
1252 crm_info("%s calculation %s is obsolete", op, msg_ref);
1253 }
1254
1255 } else if (strcmp(op, CRM_OP_VOTE) == 0
1256 || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0 || strcmp(op, CRM_OP_SHUTDOWN) == 0) {
1257
1258 } else {
1259 const char *host_from = crm_element_value(stored_msg, PCMK__XA_SRC);
1260
1261 crm_err("Unexpected response (op=%s, src=%s) sent to the %s",
1262 op, host_from, AM_I_DC ? "DC" : "controller");
1263 }
1264 }
1265
1266 static enum crmd_fsa_input
1267 handle_shutdown_request(xmlNode * stored_msg)
1268 {
1269
1270
1271
1272
1273
1274
1275
1276 char *now_s = NULL;
1277 const char *host_from = crm_element_value(stored_msg, PCMK__XA_SRC);
1278
1279 if (host_from == NULL) {
1280
1281 host_from = controld_globals.cluster->priv->node_name;
1282 }
1283
1284 crm_info("Creating shutdown request for %s (state=%s)", host_from,
1285 fsa_state2string(controld_globals.fsa_state));
1286 crm_log_xml_trace(stored_msg, "message");
1287
1288 now_s = pcmk__ttoa(time(NULL));
1289 update_attrd(host_from, PCMK__NODE_ATTR_SHUTDOWN, now_s, NULL, FALSE);
1290 free(now_s);
1291
1292
1293 return I_NULL;
1294 }
1295
1296 static void
1297 send_msg_via_ipc(xmlNode * msg, const char *sys, const char *src)
1298 {
1299 pcmk__client_t *client_channel = NULL;
1300
1301 CRM_CHECK(sys != NULL, return);
1302
1303 client_channel = pcmk__find_client_by_id(sys);
1304
1305 if (crm_element_value(msg, PCMK__XA_SRC) == NULL) {
1306 crm_xml_add(msg, PCMK__XA_SRC, src);
1307 }
1308
1309 if (client_channel != NULL) {
1310
1311 pcmk__ipc_send_xml(client_channel, 0, msg, crm_ipc_server_event);
1312
1313 } else if (pcmk__str_eq(sys, CRM_SYSTEM_TENGINE, pcmk__str_none)) {
1314 xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CRM_XML, NULL,
1315 NULL);
1316 xmlNode *data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
1317
1318 process_te_message(msg, data);
1319
1320 } else if (pcmk__str_eq(sys, CRM_SYSTEM_LRMD, pcmk__str_none)) {
1321 fsa_data_t fsa_data;
1322 ha_msg_input_t fsa_input;
1323 xmlNode *wrapper = NULL;
1324
1325 fsa_input.msg = msg;
1326
1327 wrapper = pcmk__xe_first_child(msg, PCMK__XE_CRM_XML, NULL, NULL);
1328 fsa_input.xml = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
1329
1330 fsa_data.id = 0;
1331 fsa_data.actions = 0;
1332 fsa_data.data = &fsa_input;
1333 fsa_data.fsa_input = I_MESSAGE;
1334 fsa_data.fsa_cause = C_IPC_MESSAGE;
1335 fsa_data.origin = __func__;
1336 fsa_data.data_type = fsa_dt_ha_msg;
1337
1338 do_lrm_invoke(A_LRM_INVOKE, C_IPC_MESSAGE, controld_globals.fsa_state,
1339 I_MESSAGE, &fsa_data);
1340
1341 } else if (crmd_is_proxy_session(sys)) {
1342 crmd_proxy_send(sys, msg);
1343
1344 } else {
1345 crm_info("Received invalid request: unknown subsystem '%s'", sys);
1346 }
1347 }
1348
1349 void
1350 delete_ha_msg_input(ha_msg_input_t * orig)
1351 {
1352 if (orig == NULL) {
1353 return;
1354 }
1355 pcmk__xml_free(orig->msg);
1356 free(orig);
1357 }
1358
1359
1360
1361
1362
1363
1364
1365
1366 void
1367 broadcast_remote_state_message(const char *node_name, bool node_up)
1368 {
1369 xmlNode *msg = pcmk__new_request(pcmk_ipc_controld, CRM_SYSTEM_CRMD, NULL,
1370 CRM_SYSTEM_CRMD, CRM_OP_REMOTE_STATE,
1371 NULL);
1372
1373 crm_info("Notifying cluster of Pacemaker Remote node %s %s",
1374 node_name, node_up? "coming up" : "going down");
1375
1376 crm_xml_add(msg, PCMK_XA_ID, node_name);
1377 pcmk__xe_set_bool_attr(msg, PCMK__XA_IN_CCM, node_up);
1378
1379 if (node_up) {
1380 crm_xml_add(msg, PCMK__XA_CONNECTION_HOST,
1381 controld_globals.cluster->priv->node_name);
1382 }
1383
1384 pcmk__cluster_send_message(NULL, pcmk_ipc_controld, msg);
1385 pcmk__xml_free(msg);
1386 }