This source file includes following definitions.
- add_node_to_xml_by_id
- add_node_to_xml
- add_maintenance_nodes
- add_maintenance_update
- add_downed_nodes
- clone_op_key
- add_node_details
- add_resource_details
- add_action_attributes
- create_graph_action
- should_add_action_to_graph
- ordering_can_change_actions
- should_add_input_to_graph
- pcmk__graph_has_loop
- create_graph_synapse
- pcmk__add_action_to_graph
- pcmk__log_transition_summary
- pcmk__create_graph
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13 #include <crm/crm.h>
14 #include <crm/cib.h>
15 #include <crm/msg_xml.h>
16 #include <crm/common/xml.h>
17
18 #include <glib.h>
19
20 #include <pacemaker-internal.h>
21
22 #include "libpacemaker_private.h"
23
24
25
26 #define action_type_str(flags) \
27 (pcmk_is_set((flags), pe_action_pseudo)? "pseudo-action" : "action")
28
29 #define action_optional_str(flags) \
30 (pcmk_is_set((flags), pe_action_optional)? "optional" : "required")
31
32 #define action_runnable_str(flags) \
33 (pcmk_is_set((flags), pe_action_runnable)? "runnable" : "unrunnable")
34
35 #define action_node_str(a) \
36 (((a)->node == NULL)? "no node" : (a)->node->details->uname)
37
38
39
40
41
42
43
44
45 static xmlNode*
46 add_node_to_xml_by_id(const char *id, xmlNode *xml)
47 {
48 xmlNode *node_xml;
49
50 node_xml = create_xml_node(xml, XML_CIB_TAG_NODE);
51 crm_xml_add(node_xml, XML_ATTR_UUID, id);
52
53 return node_xml;
54 }
55
56
57
58
59
60
61
62
63 static void
64 add_node_to_xml(const pe_node_t *node, void *xml)
65 {
66 add_node_to_xml_by_id(node->details->id, (xmlNode *) xml);
67 }
68
69
70
71
72
73
74
75
76 static int
77 add_maintenance_nodes(xmlNode *xml, const pe_working_set_t *data_set)
78 {
79 GList *gIter = NULL;
80 xmlNode *maintenance =
81 xml?create_xml_node(xml, XML_GRAPH_TAG_MAINTENANCE):NULL;
82 int count = 0;
83
84 for (gIter = data_set->nodes; gIter != NULL;
85 gIter = gIter->next) {
86 pe_node_t *node = (pe_node_t *) gIter->data;
87 struct pe_node_shared_s *details = node->details;
88
89 if (!pe__is_guest_or_remote_node(node)) {
90 continue;
91 }
92
93 if (details->maintenance != details->remote_maintenance) {
94 if (maintenance) {
95 crm_xml_add(
96 add_node_to_xml_by_id(node->details->id, maintenance),
97 XML_NODE_IS_MAINTENANCE, details->maintenance?"1":"0");
98 }
99 count++;
100 }
101 }
102 crm_trace("%s %d nodes to adjust maintenance-mode "
103 "to transition", maintenance?"Added":"Counted", count);
104 return count;
105 }
106
107
108
109
110
111
112
113 void
114 add_maintenance_update(pe_working_set_t *data_set)
115 {
116 pe_action_t *action = NULL;
117
118 if (add_maintenance_nodes(NULL, data_set)) {
119 crm_trace("adding maintenance state update pseudo action");
120 action = get_pseudo_op(CRM_OP_MAINTENANCE_NODES, data_set);
121 pe__set_action_flags(action, pe_action_print_always);
122 }
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137 static void
138 add_downed_nodes(xmlNode *xml, const pe_action_t *action,
139 const pe_working_set_t *data_set)
140 {
141 CRM_CHECK(xml && action && action->node && data_set, return);
142
143 if (pcmk__str_eq(action->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
144
145
146 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
147 add_node_to_xml_by_id(action->node->details->id, downed);
148
149 } else if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei)) {
150
151
152 const char *fence = g_hash_table_lookup(action->meta, "stonith_action");
153
154 if (pcmk__is_fencing_action(fence)) {
155 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
156 add_node_to_xml_by_id(action->node->details->id, downed);
157 pe_foreach_guest_node(data_set, action->node, add_node_to_xml, downed);
158 }
159
160 } else if (action->rsc && action->rsc->is_remote_node
161 && pcmk__str_eq(action->task, CRMD_ACTION_STOP, pcmk__str_casei)) {
162
163
164
165
166 GList *iter;
167 pe_action_t *input;
168 gboolean migrating = FALSE;
169
170 for (iter = action->actions_before; iter != NULL; iter = iter->next) {
171 input = ((pe_action_wrapper_t *) iter->data)->action;
172 if (input->rsc && pcmk__str_eq(action->rsc->id, input->rsc->id, pcmk__str_casei)
173 && pcmk__str_eq(input->task, CRMD_ACTION_MIGRATED, pcmk__str_casei)) {
174 migrating = TRUE;
175 break;
176 }
177 }
178 if (!migrating) {
179 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
180 add_node_to_xml_by_id(action->rsc->id, downed);
181 }
182 }
183 }
184
185
186
187
188
189
190
191
192
193
194 static char *
195 clone_op_key(pe_action_t *action, guint interval_ms)
196 {
197 if (pcmk__str_eq(action->task, RSC_NOTIFY, pcmk__str_none)) {
198 const char *n_type = g_hash_table_lookup(action->meta, "notify_type");
199 const char *n_task = g_hash_table_lookup(action->meta,
200 "notify_operation");
201
202 CRM_LOG_ASSERT((n_type != NULL) && (n_task != NULL));
203 return pcmk__notify_key(action->rsc->clone_name, n_type, n_task);
204
205 } else if (action->cancel_task != NULL) {
206 return pcmk__op_key(action->rsc->clone_name, action->cancel_task,
207 interval_ms);
208 } else {
209 return pcmk__op_key(action->rsc->clone_name, action->task, interval_ms);
210 }
211 }
212
213
214
215
216
217
218
219
220 static void
221 add_node_details(pe_action_t *action, xmlNode *xml)
222 {
223 pe_node_t *router_node = pcmk__connection_host_for_action(action);
224
225 crm_xml_add(xml, XML_LRM_ATTR_TARGET, action->node->details->uname);
226 crm_xml_add(xml, XML_LRM_ATTR_TARGET_UUID, action->node->details->id);
227 if (router_node != NULL) {
228 crm_xml_add(xml, XML_LRM_ATTR_ROUTER_NODE, router_node->details->uname);
229 }
230 }
231
232
233
234
235
236
237
238
239 static void
240 add_resource_details(pe_action_t *action, xmlNode *action_xml)
241 {
242 xmlNode *rsc_xml = NULL;
243 const char *attr_list[] = {
244 XML_AGENT_ATTR_CLASS,
245 XML_AGENT_ATTR_PROVIDER,
246 XML_ATTR_TYPE
247 };
248
249
250
251
252 if (pcmk__action_locks_rsc_to_node(action)) {
253 crm_xml_add_ll(action_xml, XML_CONFIG_ATTR_SHUTDOWN_LOCK,
254 (long long) action->rsc->lock_time);
255 }
256
257
258
259 rsc_xml = create_xml_node(action_xml, crm_element_name(action->rsc->xml));
260 if (pcmk_is_set(action->rsc->flags, pe_rsc_orphan)
261 && (action->rsc->clone_name != NULL)) {
262
263
264
265
266
267
268
269
270 crm_debug("Using orphan clone name %s instead of %s",
271 action->rsc->id, action->rsc->clone_name);
272 crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->clone_name);
273 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
274
275 } else if (!pcmk_is_set(action->rsc->flags, pe_rsc_unique)) {
276 const char *xml_id = ID(action->rsc->xml);
277
278 crm_debug("Using anonymous clone name %s for %s (aka %s)",
279 xml_id, action->rsc->id, action->rsc->clone_name);
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 crm_xml_add(rsc_xml, XML_ATTR_ID, xml_id);
295 if ((action->rsc->clone_name != NULL)
296 && !pcmk__str_eq(xml_id, action->rsc->clone_name,
297 pcmk__str_none)) {
298 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->clone_name);
299 } else {
300 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
301 }
302
303 } else {
304 CRM_ASSERT(action->rsc->clone_name == NULL);
305 crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->id);
306 }
307
308 for (int lpc = 0; lpc < PCMK__NELEM(attr_list); lpc++) {
309 crm_xml_add(rsc_xml, attr_list[lpc],
310 g_hash_table_lookup(action->rsc->meta, attr_list[lpc]));
311 }
312 }
313
314
315
316
317
318
319
320
321 static void
322 add_action_attributes(pe_action_t *action, xmlNode *action_xml)
323 {
324 xmlNode *args_xml = NULL;
325
326
327
328
329
330 args_xml = create_xml_node(NULL, XML_TAG_ATTRS);
331
332 crm_xml_add(args_xml, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
333 g_hash_table_foreach(action->extra, hash2field, args_xml);
334
335 if ((action->rsc != NULL) && (action->node != NULL)) {
336
337 GHashTable *params = pe_rsc_params(action->rsc, action->node,
338 action->rsc->cluster);
339
340 pcmk__substitute_remote_addr(action->rsc, params, action->rsc->cluster);
341
342 g_hash_table_foreach(params, hash2smartfield, args_xml);
343
344 #if ENABLE_VERSIONED_ATTRS
345 {
346 xmlNode *versioned_parameters = create_xml_node(NULL, XML_TAG_RSC_VER_ATTRS);
347
348 pe_get_versioned_attributes(versioned_parameters, action->rsc,
349 action->node, action->rsc->cluster);
350 if (xml_has_children(versioned_parameters)) {
351 add_node_copy(action_xml, versioned_parameters);
352 }
353 free_xml(versioned_parameters);
354 }
355 #endif
356
357 } else if ((action->rsc != NULL) && (action->rsc->variant <= pe_native)) {
358 GHashTable *params = pe_rsc_params(action->rsc, NULL,
359 action->rsc->cluster);
360
361 g_hash_table_foreach(params, hash2smartfield, args_xml);
362
363 #if ENABLE_VERSIONED_ATTRS
364 if (xml_has_children(action->rsc->versioned_parameters)) {
365 add_node_copy(action_xml, action->rsc->versioned_parameters);
366 }
367 #endif
368 }
369
370 #if ENABLE_VERSIONED_ATTRS
371 if (rsc_details != NULL) {
372 if (xml_has_children(rsc_details->versioned_parameters)) {
373 add_node_copy(action_xml, rsc_details->versioned_parameters);
374 }
375 if (xml_has_children(rsc_details->versioned_meta)) {
376 add_node_copy(action_xml, rsc_details->versioned_meta);
377 }
378 }
379 #endif
380
381 g_hash_table_foreach(action->meta, hash2metafield, args_xml);
382 if (action->rsc != NULL) {
383 const char *value = g_hash_table_lookup(action->rsc->meta,
384 "external-ip");
385 pe_resource_t *parent = action->rsc;
386
387 while (parent != NULL) {
388 parent->cmds->append_meta(parent, args_xml);
389 parent = parent->parent;
390 }
391
392 if (value != NULL) {
393 hash2smartfield((gpointer) "pcmk_external_ip", (gpointer) value,
394 (gpointer) args_xml);
395 }
396
397 pcmk__add_bundle_meta_to_xml(args_xml, action);
398
399 } else if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_none)
400 && (action->node != NULL)) {
401
402
403
404
405
406
407 g_hash_table_foreach(action->node->details->attrs, hash2metafield, args_xml);
408 }
409
410 sorted_xml(args_xml, action_xml, FALSE);
411 free_xml(args_xml);
412 }
413
414
415
416
417
418
419
420
421
422
423 static void
424 create_graph_action(xmlNode *parent, pe_action_t *action, bool skip_details,
425 pe_working_set_t *data_set)
426 {
427 bool needs_node_info = true;
428 bool needs_maintenance_info = false;
429 xmlNode *action_xml = NULL;
430 #if ENABLE_VERSIONED_ATTRS
431 pe_rsc_action_details_t *rsc_details = NULL;
432 #endif
433
434 if ((action == NULL) || (data_set == NULL)) {
435 return;
436 }
437
438
439
440 if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei)) {
441
442 action_xml = create_xml_node(parent,
443 pcmk_is_set(action->flags, pe_action_pseudo)?
444 XML_GRAPH_TAG_PSEUDO_EVENT :
445 XML_GRAPH_TAG_CRM_EVENT);
446
447 } else if (pcmk__str_any_of(action->task,
448 CRM_OP_SHUTDOWN,
449 CRM_OP_CLEAR_FAILCOUNT,
450 CRM_OP_LRM_REFRESH, NULL)) {
451 action_xml = create_xml_node(parent, XML_GRAPH_TAG_CRM_EVENT);
452
453 } else if (pcmk__str_eq(action->task, CRM_OP_LRM_DELETE, pcmk__str_none)) {
454
455 action_xml = create_xml_node(parent, XML_GRAPH_TAG_CRM_EVENT);
456 crm_xml_add(action_xml, PCMK__XA_MODE, XML_TAG_CIB);
457
458 } else if (pcmk_is_set(action->flags, pe_action_pseudo)) {
459 if (pcmk__str_eq(action->task, CRM_OP_MAINTENANCE_NODES,
460 pcmk__str_none)) {
461 needs_maintenance_info = true;
462 }
463 action_xml = create_xml_node(parent, XML_GRAPH_TAG_PSEUDO_EVENT);
464 needs_node_info = false;
465
466 } else {
467 action_xml = create_xml_node(parent, XML_GRAPH_TAG_RSC_OP);
468 #if ENABLE_VERSIONED_ATTRS
469 rsc_details = pe_rsc_action_details(action);
470 #endif
471 }
472
473 crm_xml_add_int(action_xml, XML_ATTR_ID, action->id);
474 crm_xml_add(action_xml, XML_LRM_ATTR_TASK, action->task);
475
476 if ((action->rsc != NULL) && (action->rsc->clone_name != NULL)) {
477 char *clone_key = NULL;
478 guint interval_ms;
479
480 if (pcmk__guint_from_hash(action->meta, XML_LRM_ATTR_INTERVAL_MS, 0,
481 &interval_ms) != pcmk_rc_ok) {
482 interval_ms = 0;
483 }
484 clone_key = clone_op_key(action, interval_ms);
485 crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, clone_key);
486 crm_xml_add(action_xml, "internal_" XML_LRM_ATTR_TASK_KEY, action->uuid);
487 free(clone_key);
488 } else {
489 crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, action->uuid);
490 }
491
492 if (needs_node_info && (action->node != NULL)) {
493 add_node_details(action, action_xml);
494 g_hash_table_insert(action->meta, strdup(XML_LRM_ATTR_TARGET),
495 strdup(action->node->details->uname));
496 g_hash_table_insert(action->meta, strdup(XML_LRM_ATTR_TARGET_UUID),
497 strdup(action->node->details->id));
498 }
499
500 if (skip_details) {
501 return;
502 }
503
504 if ((action->rsc != NULL)
505 && !pcmk_is_set(action->flags, pe_action_pseudo)) {
506
507
508 add_resource_details(action, action_xml);
509 }
510
511
512 add_action_attributes(action, action_xml);
513
514
515 if (needs_node_info && (action->node != NULL)) {
516 add_downed_nodes(action_xml, action, data_set);
517 }
518
519 if (needs_maintenance_info) {
520 add_maintenance_nodes(action_xml, data_set);
521 }
522 }
523
524
525
526
527
528
529
530
531
532 static bool
533 should_add_action_to_graph(pe_action_t *action)
534 {
535 if (!pcmk_is_set(action->flags, pe_action_runnable)) {
536 crm_trace("Ignoring action %s (%d): unrunnable",
537 action->uuid, action->id);
538 return false;
539 }
540
541 if (pcmk_is_set(action->flags, pe_action_optional)
542 && !pcmk_is_set(action->flags, pe_action_print_always)) {
543 crm_trace("Ignoring action %s (%d): optional",
544 action->uuid, action->id);
545 return false;
546 }
547
548
549
550
551 if ((action->rsc != NULL)
552 && !pcmk_is_set(action->rsc->flags, pe_rsc_managed)
553 && !pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_none)) {
554 const char *interval_ms_s;
555
556
557
558
559
560
561 interval_ms_s = g_hash_table_lookup(action->meta,
562 XML_LRM_ATTR_INTERVAL_MS);
563 if (pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches)) {
564 crm_trace("Ignoring action %s (%d): for unmanaged resource (%s)",
565 action->uuid, action->id, action->rsc->id);
566 return false;
567 }
568 }
569
570
571
572
573 if (pcmk_is_set(action->flags, pe_action_pseudo)
574 || pcmk__strcase_any_of(action->task, CRM_OP_FENCE, CRM_OP_SHUTDOWN,
575 NULL)) {
576 return true;
577 }
578
579 if (action->node == NULL) {
580 pe_err("Skipping action %s (%d) "
581 "because it was not allocated to a node (bug?)",
582 action->uuid, action->id);
583 pcmk__log_action("Unallocated", action, false);
584 return false;
585 }
586
587 if (pcmk_is_set(action->flags, pe_action_dc)) {
588 crm_trace("Action %s (%d) should be dumped: "
589 "can run on DC instead of %s",
590 action->uuid, action->id, action->node->details->uname);
591
592 } else if (pe__is_guest_node(action->node)
593 && !action->node->details->remote_requires_reset) {
594 crm_trace("Action %s (%d) should be dumped: "
595 "assuming will be runnable on guest node %s",
596 action->uuid, action->id, action->node->details->uname);
597
598 } else if (!action->node->details->online) {
599 pe_err("Skipping action %s (%d) "
600 "because it was scheduled for offline node (bug?)",
601 action->uuid, action->id);
602 pcmk__log_action("Offline node", action, false);
603 return false;
604
605 } else if (action->node->details->unclean) {
606 pe_err("Skipping action %s (%d) "
607 "because it was scheduled for unclean node (bug?)",
608 action->uuid, action->id);
609 pcmk__log_action("Unclean node", action, false);
610 return false;
611 }
612 return true;
613 }
614
615
616
617
618
619
620
621
622
623 static bool
624 ordering_can_change_actions(pe_action_wrapper_t *ordering)
625 {
626 return pcmk_any_flags_set(ordering->type, ~(pe_order_implies_first_printed
627 |pe_order_implies_then_printed
628 |pe_order_optional));
629 }
630
631
632
633
634
635
636
637
638
639
640
641
642 static bool
643 should_add_input_to_graph(pe_action_t *action, pe_action_wrapper_t *input)
644 {
645 if (input->state == pe_link_dumped) {
646 return true;
647 }
648
649 if (input->type == pe_order_none) {
650 crm_trace("Ignoring %s (%d) input %s (%d): "
651 "ordering disabled",
652 action->uuid, action->id,
653 input->action->uuid, input->action->id);
654 return false;
655
656 } else if (!pcmk_is_set(input->action->flags, pe_action_runnable)
657 && !ordering_can_change_actions(input)) {
658 crm_trace("Ignoring %s (%d) input %s (%d): "
659 "optional and input unrunnable",
660 action->uuid, action->id,
661 input->action->uuid, input->action->id);
662 return false;
663
664 } else if (!pcmk_is_set(input->action->flags, pe_action_runnable)
665 && pcmk_is_set(input->type, pe_order_one_or_more)) {
666 crm_trace("Ignoring %s (%d) input %s (%d): "
667 "one-or-more and input unrunnable",
668 action->uuid, action->id,
669 input->action->uuid, input->action->id);
670 return false;
671
672 } else if (pcmk_is_set(input->type, pe_order_implies_first_migratable)
673 && !pcmk_is_set(input->action->flags, pe_action_runnable)) {
674 crm_trace("Ignoring %s (%d) input %s (%d): "
675 "implies input migratable but input unrunnable",
676 action->uuid, action->id,
677 input->action->uuid, input->action->id);
678 return false;
679
680 } else if (pcmk_is_set(input->type, pe_order_apply_first_non_migratable)
681 && pcmk_is_set(input->action->flags, pe_action_migrate_runnable)) {
682 crm_trace("Ignoring %s (%d) input %s (%d): "
683 "only if input unmigratable but input unrunnable",
684 action->uuid, action->id,
685 input->action->uuid, input->action->id);
686 return false;
687
688 } else if ((input->type == pe_order_optional)
689 && pcmk_is_set(input->action->flags, pe_action_migrate_runnable)
690 && pcmk__ends_with(input->action->uuid, "_stop_0")) {
691 crm_trace("Ignoring %s (%d) input %s (%d): "
692 "optional but stop in migration",
693 action->uuid, action->id,
694 input->action->uuid, input->action->id);
695 return false;
696
697 } else if (input->type == pe_order_load) {
698 pe_node_t *input_node = input->action->node;
699
700
701
702 if (action->rsc && pcmk__str_eq(action->task, RSC_MIGRATE, pcmk__str_casei)) {
703 pe_node_t *allocated = action->rsc->allocated_to;
704
705
706
707
708 if ((input_node == NULL) || (allocated == NULL)
709 || (input_node->details != allocated->details)) {
710 crm_trace("Ignoring %s (%d) input %s (%d): "
711 "load ordering node mismatch %s vs %s",
712 action->uuid, action->id,
713 input->action->uuid, input->action->id,
714 (allocated? allocated->details->uname : "<none>"),
715 (input_node? input_node->details->uname : "<none>"));
716 input->type = pe_order_none;
717 return false;
718 }
719
720 } else if ((input_node == NULL) || (action->node == NULL)
721 || (input_node->details != action->node->details)) {
722 crm_trace("Ignoring %s (%d) input %s (%d): "
723 "load ordering node mismatch %s vs %s",
724 action->uuid, action->id,
725 input->action->uuid, input->action->id,
726 (action->node? action->node->details->uname : "<none>"),
727 (input_node? input_node->details->uname : "<none>"));
728 input->type = pe_order_none;
729 return false;
730
731 } else if (pcmk_is_set(input->action->flags, pe_action_optional)) {
732 crm_trace("Ignoring %s (%d) input %s (%d): "
733 "load ordering input optional",
734 action->uuid, action->id,
735 input->action->uuid, input->action->id);
736 input->type = pe_order_none;
737 return false;
738 }
739
740 } else if (input->type == pe_order_anti_colocation) {
741 if (input->action->node && action->node
742 && (input->action->node->details != action->node->details)) {
743 crm_trace("Ignoring %s (%d) input %s (%d): "
744 "anti-colocation node mismatch %s vs %s",
745 action->uuid, action->id,
746 input->action->uuid, input->action->id,
747 action->node->details->uname,
748 input->action->node->details->uname);
749 input->type = pe_order_none;
750 return false;
751
752 } else if (pcmk_is_set(input->action->flags, pe_action_optional)) {
753 crm_trace("Ignoring %s (%d) input %s (%d): "
754 "anti-colocation input optional",
755 action->uuid, action->id,
756 input->action->uuid, input->action->id);
757 input->type = pe_order_none;
758 return false;
759 }
760
761 } else if (input->action->rsc
762 && input->action->rsc != action->rsc
763 && pcmk_is_set(input->action->rsc->flags, pe_rsc_failed)
764 && !pcmk_is_set(input->action->rsc->flags, pe_rsc_managed)
765 && pcmk__ends_with(input->action->uuid, "_stop_0")
766 && action->rsc && pe_rsc_is_clone(action->rsc)) {
767 crm_warn("Ignoring requirement that %s complete before %s:"
768 " unmanaged failed resources cannot prevent clone shutdown",
769 input->action->uuid, action->uuid);
770 return false;
771
772 } else if (pcmk_is_set(input->action->flags, pe_action_optional)
773 && !pcmk_any_flags_set(input->action->flags,
774 pe_action_print_always|pe_action_dumped)
775 && !should_add_action_to_graph(input->action)) {
776 crm_trace("Ignoring %s (%d) input %s (%d): "
777 "input optional",
778 action->uuid, action->id,
779 input->action->uuid, input->action->id);
780 return false;
781 }
782
783 crm_trace("%s (%d) input %s %s (%d) on %s should be dumped: %s %s %#.6x",
784 action->uuid, action->id, action_type_str(input->action->flags),
785 input->action->uuid, input->action->id,
786 action_node_str(input->action),
787 action_runnable_str(input->action->flags),
788 action_optional_str(input->action->flags), input->type);
789 return true;
790 }
791
792
793
794
795
796
797
798
799
800
801
802
803
804 bool
805 pcmk__graph_has_loop(pe_action_t *init_action, pe_action_t *action,
806 pe_action_wrapper_t *input)
807 {
808 bool has_loop = false;
809
810 if (pcmk_is_set(input->action->flags, pe_action_tracking)) {
811 crm_trace("Breaking tracking loop: %s@%s -> %s@%s (%#.6x)",
812 input->action->uuid,
813 input->action->node? input->action->node->details->uname : "",
814 action->uuid,
815 action->node? action->node->details->uname : "",
816 input->type);
817 return false;
818 }
819
820
821 if (!should_add_input_to_graph(action, input)) {
822 return false;
823 }
824
825 if (input->action == init_action) {
826 crm_debug("Input loop found in %s@%s ->...-> %s@%s",
827 action->uuid,
828 action->node? action->node->details->uname : "",
829 init_action->uuid,
830 init_action->node? init_action->node->details->uname : "");
831 return true;
832 }
833
834 pe__set_action_flags(input->action, pe_action_tracking);
835
836 crm_trace("Checking inputs of action %s@%s input %s@%s (%#.6x)"
837 "for graph loop with %s@%s ",
838 action->uuid,
839 action->node? action->node->details->uname : "",
840 input->action->uuid,
841 input->action->node? input->action->node->details->uname : "",
842 input->type,
843 init_action->uuid,
844 init_action->node? init_action->node->details->uname : "");
845
846
847 for (GList *iter = input->action->actions_before;
848 iter != NULL; iter = iter->next) {
849
850 if (pcmk__graph_has_loop(init_action, input->action,
851 (pe_action_wrapper_t *) iter->data)) {
852
853 has_loop = true;
854 break;
855 }
856 }
857
858 pe__clear_action_flags(input->action, pe_action_tracking);
859
860 if (!has_loop) {
861 crm_trace("No input loop found in %s@%s -> %s@%s (%#.6x)",
862 input->action->uuid,
863 input->action->node? input->action->node->details->uname : "",
864 action->uuid,
865 action->node? action->node->details->uname : "",
866 input->type);
867 }
868 return has_loop;
869 }
870
871
872
873
874
875
876
877
878
879
880 static xmlNode *
881 create_graph_synapse(pe_action_t *action, pe_working_set_t *data_set)
882 {
883 int synapse_priority = 0;
884 xmlNode *syn = create_xml_node(data_set->graph, "synapse");
885
886 crm_xml_add_int(syn, XML_ATTR_ID, data_set->num_synapse);
887 data_set->num_synapse++;
888
889 if (action->rsc != NULL) {
890 synapse_priority = action->rsc->priority;
891 }
892 if (action->priority > synapse_priority) {
893 synapse_priority = action->priority;
894 }
895 if (synapse_priority > 0) {
896 crm_xml_add_int(syn, XML_CIB_ATTR_PRIORITY, synapse_priority);
897 }
898 return syn;
899 }
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917 void
918 pcmk__add_action_to_graph(pe_action_t *action, pe_working_set_t *data_set)
919 {
920 xmlNode *syn = NULL;
921 xmlNode *set = NULL;
922 xmlNode *in = NULL;
923
924
925
926
927
928 if (!pcmk_is_set(action->flags, pe_action_dedup)) {
929 pcmk__deduplicate_action_inputs(action);
930 pe__set_action_flags(action, pe_action_dedup);
931 }
932
933 if (pcmk_is_set(action->flags, pe_action_dumped)
934 || !should_add_action_to_graph(action)) {
935 return;
936 }
937 pe__set_action_flags(action, pe_action_dumped);
938
939 syn = create_graph_synapse(action, data_set);
940 set = create_xml_node(syn, "action_set");
941 in = create_xml_node(syn, "inputs");
942
943 create_graph_action(set, action, false, data_set);
944
945 for (GList *lpc = action->actions_before; lpc != NULL; lpc = lpc->next) {
946 pe_action_wrapper_t *input = (pe_action_wrapper_t *) lpc->data;
947
948 if (should_add_input_to_graph(action, input)) {
949 xmlNode *input_xml = create_xml_node(in, "trigger");
950
951 input->state = pe_link_dumped;
952 create_graph_action(input_xml, input->action, true, data_set);
953 }
954 }
955 }
956
957 static int transition_id = -1;
958
959
960
961
962
963
964
965 void
966 pcmk__log_transition_summary(const char *filename)
967 {
968 if (was_processing_error) {
969 crm_err("Calculated transition %d (with errors)%s%s",
970 transition_id,
971 (filename == NULL)? "" : ", saving inputs in ",
972 (filename == NULL)? "" : filename);
973
974 } else if (was_processing_warning) {
975 crm_warn("Calculated transition %d (with warnings)%s%s",
976 transition_id,
977 (filename == NULL)? "" : ", saving inputs in ",
978 (filename == NULL)? "" : filename);
979
980 } else {
981 crm_notice("Calculated transition %d%s%s",
982 transition_id,
983 (filename == NULL)? "" : ", saving inputs in ",
984 (filename == NULL)? "" : filename);
985 }
986 if (crm_config_error) {
987 crm_notice("Configuration errors found during scheduler processing,"
988 " please run \"crm_verify -L\" to identify issues");
989 }
990 }
991
992
993
994
995
996
997
998 void
999 pcmk__create_graph(pe_working_set_t *data_set)
1000 {
1001 GList *iter = NULL;
1002 const char *value = NULL;
1003 long long limit = 0LL;
1004
1005 transition_id++;
1006 crm_trace("Creating transition graph %d", transition_id);
1007
1008 data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH);
1009
1010 value = pe_pref(data_set->config_hash, "cluster-delay");
1011 crm_xml_add(data_set->graph, "cluster-delay", value);
1012
1013 value = pe_pref(data_set->config_hash, "stonith-timeout");
1014 crm_xml_add(data_set->graph, "stonith-timeout", value);
1015
1016 crm_xml_add(data_set->graph, "failed-stop-offset", "INFINITY");
1017
1018 if (pcmk_is_set(data_set->flags, pe_flag_start_failure_fatal)) {
1019 crm_xml_add(data_set->graph, "failed-start-offset", "INFINITY");
1020 } else {
1021 crm_xml_add(data_set->graph, "failed-start-offset", "1");
1022 }
1023
1024 value = pe_pref(data_set->config_hash, "batch-limit");
1025 crm_xml_add(data_set->graph, "batch-limit", value);
1026
1027 crm_xml_add_int(data_set->graph, "transition_id", transition_id);
1028
1029 value = pe_pref(data_set->config_hash, "migration-limit");
1030 if ((pcmk__scan_ll(value, &limit, 0LL) == pcmk_rc_ok) && (limit > 0)) {
1031 crm_xml_add(data_set->graph, "migration-limit", value);
1032 }
1033
1034 if (data_set->recheck_by > 0) {
1035 char *recheck_epoch = NULL;
1036
1037 recheck_epoch = crm_strdup_printf("%llu",
1038 (long long) data_set->recheck_by);
1039 crm_xml_add(data_set->graph, "recheck-by", recheck_epoch);
1040 free(recheck_epoch);
1041 }
1042
1043
1044
1045
1046
1047
1048
1049 for (iter = data_set->resources; iter != NULL; iter = iter->next) {
1050 pe_resource_t *rsc = (pe_resource_t *) iter->data;
1051
1052 pe_rsc_trace(rsc, "Processing actions for %s", rsc->id);
1053 rsc->cmds->expand(rsc, data_set);
1054 }
1055
1056
1057 add_maintenance_update(data_set);
1058
1059
1060 for (iter = data_set->actions; iter != NULL; iter = iter->next) {
1061 pe_action_t *action = (pe_action_t *) iter->data;
1062
1063 if ((action->rsc != NULL)
1064 && (action->node != NULL)
1065 && action->node->details->shutdown
1066 && !pcmk_is_set(action->rsc->flags, pe_rsc_maintenance)
1067 && !pcmk_any_flags_set(action->flags,
1068 pe_action_optional|pe_action_runnable)
1069 && pcmk__str_eq(action->task, RSC_STOP, pcmk__str_none)) {
1070
1071
1072
1073
1074 if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)
1075 || (data_set->no_quorum_policy == no_quorum_ignore)) {
1076 crm_crit("Cannot %s node '%s' because of %s:%s%s (%s)",
1077 action->node->details->unclean? "fence" : "shut down",
1078 action->node->details->uname, action->rsc->id,
1079 pcmk_is_set(action->rsc->flags, pe_rsc_managed)? " blocked" : " unmanaged",
1080 pcmk_is_set(action->rsc->flags, pe_rsc_failed)? " failed" : "",
1081 action->uuid);
1082 }
1083 }
1084
1085 pcmk__add_action_to_graph(action, data_set);
1086 }
1087
1088 crm_log_xml_trace(data_set->graph, "graph");
1089 }