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