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