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
- is_message
- fsa_typed_data_adv
- do_msg_route
- route_message
- relay_message
- process_hello_message
- crmd_authorize_message
- handle_message
- handle_failcount_op
- handle_remote_state
- handle_request
- handle_response
- handle_shutdown_request
- send_msg_via_ipc
- new_ha_msg_input
- delete_ha_msg_input
- send_remote_state_message
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20
21 #include <sys/param.h>
22 #include <crm/crm.h>
23 #include <string.h>
24 #include <time.h>
25 #include <crmd_fsa.h>
26
27 #include <crm/msg_xml.h>
28 #include <crm/common/xml.h>
29
30 #include <crm/cluster/internal.h>
31 #include <crm/cib.h>
32 #include <crm/common/ipcs.h>
33
34 #include <crmd.h>
35 #include <crmd_messages.h>
36 #include <crmd_lrm.h>
37 #include <tengine.h>
38 #include <throttle.h>
39
40 GListPtr fsa_message_queue = NULL;
41 extern void crm_shutdown(int nsig);
42
43 extern crm_ipc_t *attrd_ipc;
44 void handle_response(xmlNode * stored_msg);
45 enum crmd_fsa_input handle_request(xmlNode * stored_msg, enum crmd_fsa_cause cause);
46 enum crmd_fsa_input handle_shutdown_request(xmlNode * stored_msg);
47
48 #define ROUTER_RESULT(x) crm_trace("Router result: %s", x)
49
50
51 int last_data_id = 0;
52
53 void
54 register_fsa_error_adv(enum crmd_fsa_cause cause, enum crmd_fsa_input input,
55 fsa_data_t * cur_data, void *new_data, const char *raised_from)
56 {
57
58 if (fsa_actions != A_NOTHING) {
59 register_fsa_input_adv(cur_data ? cur_data->fsa_cause : C_FSA_INTERNAL,
60 I_NULL, cur_data ? cur_data->data : NULL,
61 fsa_actions, TRUE, __FUNCTION__);
62 }
63
64
65 crm_info("Resetting the current action list");
66 fsa_dump_actions(fsa_actions, "Drop");
67 fsa_actions = A_NOTHING;
68
69
70 register_fsa_input_adv(cause, input, new_data, A_NOTHING, TRUE, raised_from);
71 }
72
73 int
74 register_fsa_input_adv(enum crmd_fsa_cause cause, enum crmd_fsa_input input,
75 void *data, long long with_actions,
76 gboolean prepend, const char *raised_from)
77 {
78 unsigned old_len = g_list_length(fsa_message_queue);
79 fsa_data_t *fsa_data = NULL;
80
81 CRM_CHECK(raised_from != NULL, raised_from = "<unknown>");
82
83 if (input == I_NULL && with_actions == A_NOTHING ) {
84
85 crm_err("Cannot add entry to queue: no input and no action");
86 return 0;
87 }
88
89 if (input == I_WAIT_FOR_EVENT) {
90 do_fsa_stall = TRUE;
91 crm_debug("Stalling the FSA pending further input: source=%s cause=%s data=%p queue=%d",
92 raised_from, fsa_cause2string(cause), data, old_len);
93
94 if (old_len > 0) {
95 fsa_dump_queue(LOG_TRACE);
96 prepend = FALSE;
97 }
98
99 if (data == NULL) {
100 fsa_actions |= with_actions;
101 fsa_dump_actions(with_actions, "Restored");
102 return 0;
103 }
104
105
106 with_actions |= fsa_actions;
107 fsa_actions = A_NOTHING;
108 }
109
110 last_data_id++;
111 crm_trace("%s %s FSA input %d (%s) (cause=%s) %s data",
112 raised_from, prepend ? "prepended" : "appended", last_data_id,
113 fsa_input2string(input), fsa_cause2string(cause), data ? "with" : "without");
114
115 fsa_data = calloc(1, sizeof(fsa_data_t));
116 fsa_data->id = last_data_id;
117 fsa_data->fsa_input = input;
118 fsa_data->fsa_cause = cause;
119 fsa_data->origin = raised_from;
120 fsa_data->data = NULL;
121 fsa_data->data_type = fsa_dt_none;
122 fsa_data->actions = with_actions;
123
124 if (with_actions != A_NOTHING) {
125 crm_trace("Adding actions %.16llx to input", with_actions);
126 }
127
128 if (data != NULL) {
129 switch (cause) {
130 case C_FSA_INTERNAL:
131 case C_CRMD_STATUS_CALLBACK:
132 case C_IPC_MESSAGE:
133 case C_HA_MESSAGE:
134 crm_trace("Copying %s data from %s as a HA msg",
135 fsa_cause2string(cause), raised_from);
136 CRM_CHECK(((ha_msg_input_t *) data)->msg != NULL,
137 crm_err("Bogus data from %s", raised_from));
138 fsa_data->data = copy_ha_msg_input(data);
139 fsa_data->data_type = fsa_dt_ha_msg;
140 break;
141
142 case C_LRM_OP_CALLBACK:
143 crm_trace("Copying %s data from %s as lrmd_event_data_t",
144 fsa_cause2string(cause), raised_from);
145 fsa_data->data = lrmd_copy_event((lrmd_event_data_t *) data);
146 fsa_data->data_type = fsa_dt_lrm;
147 break;
148
149 case C_CCM_CALLBACK:
150 case C_SUBSYSTEM_CONNECT:
151 case C_LRM_MONITOR_CALLBACK:
152 case C_TIMER_POPPED:
153 case C_SHUTDOWN:
154 case C_HEARTBEAT_FAILED:
155 case C_HA_DISCONNECT:
156 case C_ILLEGAL:
157 case C_UNKNOWN:
158 case C_STARTUP:
159 crm_err("Copying %s data (from %s)"
160 " not yet implemented", fsa_cause2string(cause), raised_from);
161 crmd_exit(pcmk_err_generic);
162 break;
163 }
164 crm_trace("%s data copied", fsa_cause2string(fsa_data->fsa_cause));
165 }
166
167
168 if (prepend) {
169 crm_trace("Prepending input");
170 fsa_message_queue = g_list_prepend(fsa_message_queue, fsa_data);
171 } else {
172 fsa_message_queue = g_list_append(fsa_message_queue, fsa_data);
173 }
174
175 crm_trace("Queue len: %d", g_list_length(fsa_message_queue));
176
177
178
179 if (old_len == g_list_length(fsa_message_queue)) {
180 crm_err("Couldn't add message to the queue");
181 }
182
183 if (fsa_source && input != I_WAIT_FOR_EVENT) {
184 crm_trace("Triggering FSA: %s", __FUNCTION__);
185 mainloop_set_trigger(fsa_source);
186 }
187 return last_data_id;
188 }
189
190 void
191 fsa_dump_queue(int log_level)
192 {
193 int offset = 0;
194 GListPtr lpc = NULL;
195
196 for (lpc = fsa_message_queue; lpc != NULL; lpc = lpc->next) {
197 fsa_data_t *data = (fsa_data_t *) lpc->data;
198
199 do_crm_log_unlikely(log_level,
200 "queue[%d.%d]: input %s raised by %s(%p.%d)\t(cause=%s)",
201 offset++, data->id, fsa_input2string(data->fsa_input),
202 data->origin, data->data, data->data_type,
203 fsa_cause2string(data->fsa_cause));
204 }
205 }
206
207 ha_msg_input_t *
208 copy_ha_msg_input(ha_msg_input_t * orig)
209 {
210 ha_msg_input_t *copy = NULL;
211 xmlNodePtr data = NULL;
212
213 if (orig != NULL) {
214 crm_trace("Copy msg");
215 data = copy_xml(orig->msg);
216
217 } else {
218 crm_trace("No message to copy");
219 }
220 copy = new_ha_msg_input(data);
221 if (orig && orig->msg != NULL) {
222 CRM_CHECK(copy->msg != NULL, crm_err("copy failed"));
223 }
224 return copy;
225 }
226
227 void
228 delete_fsa_input(fsa_data_t * fsa_data)
229 {
230 lrmd_event_data_t *op = NULL;
231 xmlNode *foo = NULL;
232
233 if (fsa_data == NULL) {
234 return;
235 }
236 crm_trace("About to free %s data", fsa_cause2string(fsa_data->fsa_cause));
237
238 if (fsa_data->data != NULL) {
239 switch (fsa_data->data_type) {
240 case fsa_dt_ha_msg:
241 delete_ha_msg_input(fsa_data->data);
242 break;
243
244 case fsa_dt_xml:
245 foo = fsa_data->data;
246 free_xml(foo);
247 break;
248
249 case fsa_dt_lrm:
250 op = (lrmd_event_data_t *) fsa_data->data;
251 lrmd_free_event(op);
252 break;
253
254 case fsa_dt_none:
255 if (fsa_data->data != NULL) {
256 crm_err("Don't know how to free %s data from %s",
257 fsa_cause2string(fsa_data->fsa_cause), fsa_data->origin);
258 crmd_exit(pcmk_err_generic);
259 }
260 break;
261 }
262 crm_trace("%s data freed", fsa_cause2string(fsa_data->fsa_cause));
263 }
264
265 free(fsa_data);
266 }
267
268
269 fsa_data_t *
270 get_message(void)
271 {
272 fsa_data_t *message = g_list_nth_data(fsa_message_queue, 0);
273
274 fsa_message_queue = g_list_remove(fsa_message_queue, message);
275 crm_trace("Processing input %d", message->id);
276 return message;
277 }
278
279
280 gboolean
281 is_message(void)
282 {
283 return (g_list_length(fsa_message_queue) > 0);
284 }
285
286 void *
287 fsa_typed_data_adv(fsa_data_t * fsa_data, enum fsa_data_type a_type, const char *caller)
288 {
289 void *ret_val = NULL;
290
291 if (fsa_data == NULL) {
292 crm_err("%s: No FSA data available", caller);
293
294 } else if (fsa_data->data == NULL) {
295 crm_err("%s: No message data available. Origin: %s", caller, fsa_data->origin);
296
297 } else if (fsa_data->data_type != a_type) {
298 crm_crit("%s: Message data was the wrong type! %d vs. requested=%d. Origin: %s",
299 caller, fsa_data->data_type, a_type, fsa_data->origin);
300 CRM_ASSERT(fsa_data->data_type == a_type);
301 } else {
302 ret_val = fsa_data->data;
303 }
304
305 return ret_val;
306 }
307
308
309 void
310 do_msg_route(long long action,
311 enum crmd_fsa_cause cause,
312 enum crmd_fsa_state cur_state,
313 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
314 {
315 ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg);
316
317 route_message(msg_data->fsa_cause, input->msg);
318 }
319
320 void
321 route_message(enum crmd_fsa_cause cause, xmlNode * input)
322 {
323 ha_msg_input_t fsa_input;
324 enum crmd_fsa_input result = I_NULL;
325
326 fsa_input.msg = input;
327 CRM_CHECK(cause == C_IPC_MESSAGE || cause == C_HA_MESSAGE, return);
328
329
330 if (relay_message(input, cause == C_IPC_MESSAGE)) {
331 return;
332 }
333
334
335 result = handle_message(input, cause);
336
337
338 switch (result) {
339 case I_NULL:
340 case I_CIB_OP:
341 case I_ROUTER:
342 case I_NODE_JOIN:
343 case I_JOIN_REQUEST:
344 case I_JOIN_RESULT:
345 break;
346 default:
347
348 register_fsa_input_later(cause, result, &fsa_input);
349 return;
350 }
351
352 if (result != I_NULL) {
353
354 register_fsa_input(cause, result, &fsa_input);
355 }
356 }
357
358 gboolean
359 relay_message(xmlNode * msg, gboolean originated_locally)
360 {
361 int dest = 1;
362 int is_for_dc = 0;
363 int is_for_dcib = 0;
364 int is_for_te = 0;
365 int is_for_crm = 0;
366 int is_for_cib = 0;
367 int is_local = 0;
368 gboolean processing_complete = FALSE;
369 const char *host_to = crm_element_value(msg, F_CRM_HOST_TO);
370 const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO);
371 const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM);
372 const char *type = crm_element_value(msg, F_TYPE);
373 const char *msg_error = NULL;
374
375 crm_trace("Routing message %s", crm_element_value(msg, XML_ATTR_REFERENCE));
376
377 if (msg == NULL) {
378 msg_error = "Cannot route empty message";
379
380 } else if (safe_str_eq(CRM_OP_HELLO, crm_element_value(msg, F_CRM_TASK))) {
381
382 processing_complete = TRUE;
383
384 } else if (safe_str_neq(type, T_CRM)) {
385 msg_error = "Bad message type";
386
387 } else if (sys_to == NULL) {
388 msg_error = "Bad message destination: no subsystem";
389 }
390
391 if (msg_error != NULL) {
392 processing_complete = TRUE;
393 crm_err("%s", msg_error);
394 crm_log_xml_warn(msg, "bad msg");
395 }
396
397 if (processing_complete) {
398 return TRUE;
399 }
400
401 processing_complete = TRUE;
402
403 is_for_dc = (strcasecmp(CRM_SYSTEM_DC, sys_to) == 0);
404 is_for_dcib = (strcasecmp(CRM_SYSTEM_DCIB, sys_to) == 0);
405 is_for_te = (strcasecmp(CRM_SYSTEM_TENGINE, sys_to) == 0);
406 is_for_cib = (strcasecmp(CRM_SYSTEM_CIB, sys_to) == 0);
407 is_for_crm = (strcasecmp(CRM_SYSTEM_CRMD, sys_to) == 0);
408
409 is_local = 0;
410 if (host_to == NULL || strlen(host_to) == 0) {
411 if (is_for_dc || is_for_te) {
412 is_local = 0;
413
414 } else if (is_for_crm && originated_locally) {
415 is_local = 0;
416
417 } else {
418 is_local = 1;
419 }
420
421 } else if (safe_str_eq(fsa_our_uname, host_to)) {
422 is_local = 1;
423 }
424
425 if (is_for_dc || is_for_dcib || is_for_te) {
426 if (AM_I_DC && is_for_te) {
427 ROUTER_RESULT("Message result: Local relay");
428 send_msg_via_ipc(msg, sys_to);
429
430 } else if (AM_I_DC) {
431 ROUTER_RESULT("Message result: DC/CRMd process");
432 processing_complete = FALSE;
433 } else if (originated_locally && safe_str_neq(sys_from, CRM_SYSTEM_PENGINE)
434 && safe_str_neq(sys_from, CRM_SYSTEM_TENGINE)) {
435
436
437
438
439
440
441
442
443 #if SUPPORT_COROSYNC
444 if (is_openais_cluster()) {
445 dest = text2msg_type(sys_to);
446 }
447 #endif
448 ROUTER_RESULT("Message result: External relay to DC");
449 send_cluster_message(host_to ? crm_get_peer(0, host_to) : NULL, dest, msg, TRUE);
450
451 } else {
452
453 ROUTER_RESULT("Message result: Discard, not DC");
454 }
455
456 } else if (is_local && (is_for_crm || is_for_cib)) {
457 ROUTER_RESULT("Message result: CRMd process");
458 processing_complete = FALSE;
459
460 } else if (is_local) {
461 ROUTER_RESULT("Message result: Local relay");
462 send_msg_via_ipc(msg, sys_to);
463
464 } else {
465 crm_node_t *node_to = NULL;
466
467 #if SUPPORT_COROSYNC
468 if (is_openais_cluster()) {
469 dest = text2msg_type(sys_to);
470
471 if (dest == crm_msg_none || dest > crm_msg_stonith_ng) {
472 dest = crm_msg_crmd;
473 }
474 }
475 #endif
476
477 if (host_to) {
478 node_to = crm_find_peer(0, host_to);
479 if (node_to == NULL) {
480 crm_err("Cannot route message to unknown node %s", host_to);
481 return TRUE;
482 }
483 }
484
485 ROUTER_RESULT("Message result: External relay");
486 send_cluster_message(host_to ? node_to : NULL, dest, msg, TRUE);
487 }
488
489 return processing_complete;
490 }
491
492 static gboolean
493 process_hello_message(xmlNode * hello,
494 char **client_name, char **major_version, char **minor_version)
495 {
496 const char *local_client_name;
497 const char *local_major_version;
498 const char *local_minor_version;
499
500 *client_name = NULL;
501 *major_version = NULL;
502 *minor_version = NULL;
503
504 if (hello == NULL) {
505 return FALSE;
506 }
507
508 local_client_name = crm_element_value(hello, "client_name");
509 local_major_version = crm_element_value(hello, "major_version");
510 local_minor_version = crm_element_value(hello, "minor_version");
511
512 if (local_client_name == NULL || strlen(local_client_name) == 0) {
513 crm_err("Hello message was not valid (field %s not found)", "client name");
514 return FALSE;
515
516 } else if (local_major_version == NULL || strlen(local_major_version) == 0) {
517 crm_err("Hello message was not valid (field %s not found)", "major version");
518 return FALSE;
519
520 } else if (local_minor_version == NULL || strlen(local_minor_version) == 0) {
521 crm_err("Hello message was not valid (field %s not found)", "minor version");
522 return FALSE;
523 }
524
525 *client_name = strdup(local_client_name);
526 *major_version = strdup(local_major_version);
527 *minor_version = strdup(local_minor_version);
528
529 crm_trace("Hello message ok");
530 return TRUE;
531 }
532
533 gboolean
534 crmd_authorize_message(xmlNode * client_msg, crm_client_t * curr_client, const char *proxy_session)
535 {
536 char *client_name = NULL;
537 char *major_version = NULL;
538 char *minor_version = NULL;
539 gboolean auth_result = FALSE;
540
541 xmlNode *xml = NULL;
542 const char *op = crm_element_value(client_msg, F_CRM_TASK);
543 const char *uuid = curr_client ? curr_client->id : proxy_session;
544
545 if (uuid == NULL) {
546 crm_warn("Message [%s] not authorized", crm_element_value(client_msg, XML_ATTR_REFERENCE));
547 return FALSE;
548
549 } else if (safe_str_neq(CRM_OP_HELLO, op)) {
550 return TRUE;
551 }
552
553 xml = get_message_xml(client_msg, F_CRM_DATA);
554 auth_result = process_hello_message(xml, &client_name, &major_version, &minor_version);
555
556 if (auth_result == TRUE) {
557 if (client_name == NULL) {
558 crm_err("Bad client details (client_name=%s, uuid=%s)",
559 crm_str(client_name), uuid);
560 auth_result = FALSE;
561 }
562 }
563
564 if (auth_result == TRUE) {
565
566 int mav = atoi(major_version);
567 int miv = atoi(minor_version);
568
569 crm_trace("Checking client version number");
570 if (mav < 0 || miv < 0) {
571 crm_err("Client version (%d:%d) is not acceptable", mav, miv);
572 auth_result = FALSE;
573 }
574 }
575
576 if (auth_result == TRUE) {
577 crm_trace("Accepted client %s", client_name);
578 if (curr_client) {
579 curr_client->userdata = strdup(client_name);
580 }
581
582 crm_trace("Triggering FSA: %s", __FUNCTION__);
583 mainloop_set_trigger(fsa_source);
584
585 } else {
586 crm_warn("Rejected client logon request");
587 if (curr_client) {
588 qb_ipcs_disconnect(curr_client->ipcs);
589 }
590 }
591
592 free(minor_version);
593 free(major_version);
594 free(client_name);
595
596
597 return FALSE;
598 }
599
600 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, F_CRM_MSG_TYPE);
608 if (crm_str_eq(type, XML_ATTR_REQUEST, TRUE)) {
609 return handle_request(msg, cause);
610
611 } else if (crm_str_eq(type, XML_ATTR_RESPONSE, TRUE)) {
612 handle_response(msg);
613 return I_NULL;
614 }
615
616 crm_err("Unknown message type: %s", type);
617 return I_NULL;
618 }
619
620 static enum crmd_fsa_input
621 handle_failcount_op(xmlNode * stored_msg)
622 {
623 const char *rsc = NULL;
624 const char *uname = NULL;
625 const char *op = NULL;
626 const char *interval = NULL;
627 int interval_ms = 0;
628 gboolean is_remote_node = FALSE;
629 xmlNode *xml_op = get_message_xml(stored_msg, F_CRM_DATA);
630
631 if (xml_op) {
632 xmlNode *xml_rsc = first_named_child(xml_op, XML_CIB_TAG_RESOURCE);
633 xmlNode *xml_attrs = first_named_child(xml_op, XML_TAG_ATTRS);
634
635 if (xml_rsc) {
636 rsc = ID(xml_rsc);
637 }
638 if (xml_attrs) {
639 op = crm_element_value(xml_attrs,
640 CRM_META "_" XML_RSC_ATTR_CLEAR_OP);
641 interval = crm_element_value(xml_attrs,
642 CRM_META "_" XML_RSC_ATTR_CLEAR_INTERVAL);
643 interval_ms = crm_parse_int(interval, "0");
644 }
645 }
646 uname = crm_element_value(xml_op, XML_LRM_ATTR_TARGET);
647
648 if ((rsc == NULL) || (uname == NULL)) {
649 crm_log_xml_warn(stored_msg, "invalid failcount op");
650 return I_NULL;
651 }
652
653 if (crm_element_value(xml_op, XML_LRM_ATTR_ROUTER_NODE)) {
654 is_remote_node = TRUE;
655 }
656 update_attrd_clear_failures(uname, rsc, op, interval, is_remote_node);
657 lrm_clear_last_failure(rsc, uname, op, interval_ms);
658
659 return I_NULL;
660 }
661
662
663
664
665
666
667
668
669 static enum crmd_fsa_input
670 handle_remote_state(xmlNode *msg)
671 {
672 const char *remote_uname = ID(msg);
673 const char *remote_is_up = crm_element_value(msg, XML_NODE_IN_CLUSTER);
674 crm_node_t *remote_peer;
675
676 CRM_CHECK(remote_uname && remote_is_up, return I_NULL);
677
678 remote_peer = crm_remote_peer_get(remote_uname);
679 CRM_CHECK(remote_peer, return I_NULL);
680
681 crm_update_peer_state(__FUNCTION__, remote_peer,
682 crm_is_true(remote_is_up)?
683 CRM_NODE_MEMBER : CRM_NODE_LOST, 0);
684 return I_NULL;
685 }
686
687 enum crmd_fsa_input
688 handle_request(xmlNode * stored_msg, enum crmd_fsa_cause cause)
689 {
690 xmlNode *msg = NULL;
691 const char *op = crm_element_value(stored_msg, F_CRM_TASK);
692
693
694
695 if (op == NULL) {
696 crm_log_xml_err(stored_msg, "Bad message");
697 return I_NULL;
698 }
699
700 if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
701 const char *from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
702 crm_node_t *node = crm_find_peer(0, from);
703
704 crm_update_peer_expected(__FUNCTION__, node, CRMD_JOINSTATE_DOWN);
705 if(AM_I_DC == FALSE) {
706 return I_NULL;
707 }
708 }
709
710
711 if (AM_I_DC) {
712 if (strcmp(op, CRM_OP_JOIN_ANNOUNCE) == 0) {
713 return I_NODE_JOIN;
714
715 } else if (strcmp(op, CRM_OP_JOIN_REQUEST) == 0) {
716 return I_JOIN_REQUEST;
717
718 } else if (strcmp(op, CRM_OP_JOIN_CONFIRM) == 0) {
719 return I_JOIN_RESULT;
720
721 } else if (strcmp(op, CRM_OP_SHUTDOWN) == 0) {
722 const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
723 gboolean dc_match = safe_str_eq(host_from, fsa_our_dc);
724
725 if (is_set(fsa_input_register, R_SHUTDOWN)) {
726 crm_info("Shutting ourselves down (DC)");
727 return I_STOP;
728
729 } else if (dc_match) {
730 crm_err("We didn't ask to be shut down, yet our"
731 " TE is telling us to. Better get out now!");
732 return I_TERMINATE;
733
734 } else if (fsa_state != S_STOPPING) {
735 crm_err("Another node is asking us to shutdown" " but we think we're ok.");
736 return I_ELECTION;
737 }
738
739 } else if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
740
741
742 return handle_shutdown_request(stored_msg);
743
744 } else if (strcmp(op, CRM_OP_REMOTE_STATE) == 0) {
745
746 return handle_remote_state(stored_msg);
747 }
748 }
749
750
751 if (strcmp(op, CRM_OP_NOVOTE) == 0) {
752 ha_msg_input_t fsa_input;
753
754 fsa_input.msg = stored_msg;
755 register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
756 A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__);
757
758 } else if (strcmp(op, CRM_OP_THROTTLE) == 0) {
759 throttle_update(stored_msg);
760 if (AM_I_DC && transition_graph != NULL) {
761 if (transition_graph->complete == FALSE) {
762 crm_debug("The throttle changed. Trigger a graph.");
763 trigger_graph();
764 }
765 }
766 return I_NULL;
767
768 } else if (strcmp(op, CRM_OP_CLEAR_FAILCOUNT) == 0) {
769 return handle_failcount_op(stored_msg);
770
771 } else if (strcmp(op, CRM_OP_VOTE) == 0) {
772
773 ha_msg_input_t fsa_input;
774
775 fsa_input.msg = stored_msg;
776 register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
777 A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__);
778
779
780 if (fsa_state == S_HALT) {
781 crm_debug("Forcing an election from S_HALT");
782 return I_ELECTION;
783 #if 0
784 } else if (AM_I_DC) {
785
786 return I_ELECTION;
787 #endif
788 }
789
790 } else if (strcmp(op, CRM_OP_JOIN_OFFER) == 0) {
791 crm_debug("Raising I_JOIN_OFFER: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
792 return I_JOIN_OFFER;
793
794 } else if (strcmp(op, CRM_OP_JOIN_ACKNAK) == 0) {
795 crm_debug("Raising I_JOIN_RESULT: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
796 return I_JOIN_RESULT;
797
798 } else if (strcmp(op, CRM_OP_LRM_DELETE) == 0
799 || strcmp(op, CRM_OP_LRM_FAIL) == 0
800 || strcmp(op, CRM_OP_LRM_REFRESH) == 0 || strcmp(op, CRM_OP_REPROBE) == 0) {
801
802 crm_xml_add(stored_msg, F_CRM_SYS_TO, CRM_SYSTEM_LRMD);
803 return I_ROUTER;
804
805 } else if (strcmp(op, CRM_OP_NOOP) == 0) {
806 return I_NULL;
807
808 } else if (strcmp(op, CRM_OP_LOCAL_SHUTDOWN) == 0) {
809
810 crm_shutdown(SIGTERM);
811
812 return I_NULL;
813
814
815 } else if (AM_I_DC == FALSE && strcmp(op, CRM_OP_SHUTDOWN) == 0) {
816
817 const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
818 gboolean dc_match = safe_str_eq(host_from, fsa_our_dc);
819
820 if (dc_match || fsa_our_dc == NULL) {
821 if (is_set(fsa_input_register, R_SHUTDOWN) == FALSE) {
822 crm_err("We didn't ask to be shut down, yet our DC is telling us to.");
823 set_bit(fsa_input_register, R_STAYDOWN);
824 return I_STOP;
825 }
826 crm_info("Shutting down");
827 return I_STOP;
828
829 } else {
830 crm_warn("Discarding %s op from %s", op, host_from);
831 }
832
833 } else if (strcmp(op, CRM_OP_PING) == 0) {
834
835
836
837 const char *sys_to = crm_element_value(stored_msg, F_CRM_SYS_TO);
838 xmlNode *ping = create_xml_node(NULL, XML_CRM_TAG_PING);
839
840 crm_xml_add(ping, XML_PING_ATTR_STATUS, "ok");
841 crm_xml_add(ping, XML_PING_ATTR_SYSFROM, sys_to);
842 crm_xml_add(ping, "crmd_state", fsa_state2string(fsa_state));
843
844
845 crm_notice("Current ping state: %s", fsa_state2string(fsa_state));
846
847 msg = create_reply(stored_msg, ping);
848 if (msg) {
849 (void)relay_message(msg, TRUE);
850 }
851
852 free_xml(ping);
853 free_xml(msg);
854
855 } else if (strcmp(op, CRM_OP_RM_NODE_CACHE) == 0) {
856 int id = 0;
857 const char *name = NULL;
858
859 crm_element_value_int(stored_msg, XML_ATTR_ID, &id);
860 name = crm_element_value(stored_msg, XML_ATTR_UNAME);
861
862 if(cause == C_IPC_MESSAGE) {
863 msg = create_request(CRM_OP_RM_NODE_CACHE, NULL, NULL, CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL);
864 if (send_cluster_message(NULL, crm_msg_crmd, msg, TRUE) == FALSE) {
865 crm_err("Could not instruct peers to remove references to node %s/%u", name, id);
866 } else {
867 crm_notice("Instructing peers to remove references to node %s/%u", name, id);
868 }
869 free_xml(msg);
870
871 } else {
872 reap_crm_member(id, name);
873
874
875
876
877
878 st_fail_count_reset(name);
879 }
880
881 } else if (strcmp(op, CRM_OP_MAINTENANCE_NODES) == 0) {
882 xmlNode *xml = get_message_xml(stored_msg, F_CRM_DATA);
883
884 remote_ra_process_maintenance_nodes(xml);
885
886 } else {
887 crm_err("Unexpected request (%s) sent to %s", op, AM_I_DC ? "the DC" : "non-DC node");
888 crm_log_xml_err(stored_msg, "Unexpected");
889 }
890
891 return I_NULL;
892 }
893
894 void
895 handle_response(xmlNode * stored_msg)
896 {
897 const char *op = crm_element_value(stored_msg, F_CRM_TASK);
898
899 if (op == NULL) {
900 crm_log_xml_err(stored_msg, "Bad message");
901
902 } else if (AM_I_DC && strcmp(op, CRM_OP_PECALC) == 0) {
903
904 const char *msg_ref = crm_element_value(stored_msg, XML_ATTR_REFERENCE);
905
906 if (msg_ref == NULL) {
907 crm_err("%s - Ignoring calculation with no reference", op);
908
909 } else if (safe_str_eq(msg_ref, fsa_pe_ref)) {
910 ha_msg_input_t fsa_input;
911
912 fsa_input.msg = stored_msg;
913 register_fsa_input_later(C_IPC_MESSAGE, I_PE_SUCCESS, &fsa_input);
914 crm_trace("Completed: %s...", fsa_pe_ref);
915
916 } else {
917 crm_info("%s calculation %s is obsolete", op, msg_ref);
918 }
919
920 } else if (strcmp(op, CRM_OP_VOTE) == 0
921 || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0 || strcmp(op, CRM_OP_SHUTDOWN) == 0) {
922
923 } else {
924 const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
925
926 crm_err("Unexpected response (op=%s, src=%s) sent to the %s",
927 op, host_from, AM_I_DC ? "DC" : "CRMd");
928 }
929 }
930
931 enum crmd_fsa_input
932 handle_shutdown_request(xmlNode * stored_msg)
933 {
934
935
936
937
938
939
940
941 char *now_s = NULL;
942 time_t now = time(NULL);
943 const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
944
945 if (host_from == NULL) {
946
947 host_from = fsa_our_uname;
948 }
949
950 crm_info("Creating shutdown request for %s (state=%s)", host_from, fsa_state2string(fsa_state));
951 crm_log_xml_trace(stored_msg, "message");
952
953 now_s = crm_itoa(now);
954 update_attrd(host_from, XML_CIB_ATTR_SHUTDOWN, now_s, NULL, FALSE);
955 free(now_s);
956
957
958 return I_NULL;
959 }
960
961
962 extern gboolean process_te_message(xmlNode * msg, xmlNode * xml_data);
963
964 gboolean
965 send_msg_via_ipc(xmlNode * msg, const char *sys)
966 {
967 gboolean send_ok = TRUE;
968 crm_client_t *client_channel = crm_client_get_by_id(sys);
969
970 if (crm_element_value(msg, F_CRM_HOST_FROM) == NULL) {
971 crm_xml_add(msg, F_CRM_HOST_FROM, fsa_our_uname);
972 }
973
974 if (client_channel != NULL) {
975
976 send_ok = crm_ipcs_send(client_channel, 0, msg, crm_ipc_server_event);
977
978 } else if (sys != NULL && strcmp(sys, CRM_SYSTEM_TENGINE) == 0) {
979 xmlNode *data = get_message_xml(msg, F_CRM_DATA);
980
981 process_te_message(msg, data);
982
983 } else if (sys != NULL && strcmp(sys, CRM_SYSTEM_LRMD) == 0) {
984 fsa_data_t fsa_data;
985 ha_msg_input_t fsa_input;
986
987 fsa_input.msg = msg;
988 fsa_input.xml = get_message_xml(msg, F_CRM_DATA);
989
990 fsa_data.id = 0;
991 fsa_data.actions = 0;
992 fsa_data.data = &fsa_input;
993 fsa_data.fsa_input = I_MESSAGE;
994 fsa_data.fsa_cause = C_IPC_MESSAGE;
995 fsa_data.origin = __FUNCTION__;
996 fsa_data.data_type = fsa_dt_ha_msg;
997
998 #ifdef FSA_TRACE
999 crm_trace("Invoking action A_LRM_INVOKE (%.16llx)", A_LRM_INVOKE);
1000 #endif
1001 do_lrm_invoke(A_LRM_INVOKE, C_IPC_MESSAGE, fsa_state, I_MESSAGE, &fsa_data);
1002
1003 } else if (sys != NULL && crmd_is_proxy_session(sys)) {
1004 crmd_proxy_send(sys, msg);
1005
1006 } else {
1007 crm_debug("Unknown Sub-system (%s)... discarding message.", crm_str(sys));
1008 send_ok = FALSE;
1009 }
1010
1011 return send_ok;
1012 }
1013
1014 ha_msg_input_t *
1015 new_ha_msg_input(xmlNode * orig)
1016 {
1017 ha_msg_input_t *input_copy = NULL;
1018
1019 input_copy = calloc(1, sizeof(ha_msg_input_t));
1020 input_copy->msg = orig;
1021 input_copy->xml = get_message_xml(input_copy->msg, F_CRM_DATA);
1022 return input_copy;
1023 }
1024
1025 void
1026 delete_ha_msg_input(ha_msg_input_t * orig)
1027 {
1028 if (orig == NULL) {
1029 return;
1030 }
1031 free_xml(orig->msg);
1032 free(orig);
1033 }
1034
1035
1036
1037
1038
1039
1040
1041
1042 void
1043 send_remote_state_message(const char *node_name, gboolean node_up)
1044 {
1045
1046
1047
1048
1049 if (fsa_our_dc) {
1050 xmlNode *msg = create_request(CRM_OP_REMOTE_STATE, NULL, fsa_our_dc,
1051 CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL);
1052
1053 crm_info("Notifying DC %s of pacemaker_remote node %s %s",
1054 fsa_our_dc, node_name, (node_up? "coming up" : "going down"));
1055 crm_xml_add(msg, XML_ATTR_ID, node_name);
1056 crm_xml_add_boolean(msg, XML_NODE_IN_CLUSTER, node_up);
1057 send_cluster_message(crm_get_peer(0, fsa_our_dc), crm_msg_crmd, msg,
1058 TRUE);
1059 free_xml(msg);
1060 } else {
1061 crm_debug("No DC to notify of pacemaker_remote node %s %s",
1062 node_name, (node_up? "coming up" : "going down"));
1063 }
1064 }
1065