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