This source file includes following definitions.
- add_expected_result
- pcmk__probe_resource_list
- probe_then_start
- guest_resource_will_stop
- probe_action
- pcmk__probe_rsc_on_node
- probe_needed_before_action
- add_probe_orderings_for_stops
- add_start_orderings_for_probe
- add_restart_orderings_for_probe
- clear_actions_tracking_flag
- add_start_restart_orderings_for_rsc
- order_then_probes
- pcmk__order_probes
- pcmk__schedule_probes
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <glib.h>
13
14 #include <crm/crm.h>
15 #include <crm/pengine/status.h>
16 #include <pacemaker-internal.h>
17 #include "libpacemaker_private.h"
18
19
20
21
22
23
24
25
26
27 static void
28 add_expected_result(pcmk_action_t *probe, const pcmk_resource_t *rsc,
29 const pcmk_node_t *node)
30 {
31
32 pcmk_node_t *running = pe_find_node_id(rsc->running_on, node->details->id);
33
34
35 if (running == NULL) {
36 pe__add_action_expected_result(probe, CRM_EX_NOT_RUNNING);
37
38 } else if (rsc->role == pcmk_role_promoted) {
39 pe__add_action_expected_result(probe, CRM_EX_PROMOTED);
40 }
41 }
42
43
44
45
46
47
48
49
50
51
52 bool
53 pcmk__probe_resource_list(GList *rscs, pcmk_node_t *node)
54 {
55 bool any_created = false;
56
57 for (GList *iter = rscs; iter != NULL; iter = iter->next) {
58 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
59
60 if (rsc->cmds->create_probe(rsc, node)) {
61 any_created = true;
62 }
63 }
64 return any_created;
65 }
66
67
68
69
70
71
72
73
74 static void
75 probe_then_start(pcmk_resource_t *rsc1, pcmk_resource_t *rsc2)
76 {
77 if ((rsc1->allocated_to != NULL)
78 && (g_hash_table_lookup(rsc1->known_on,
79 rsc1->allocated_to->details->id) == NULL)) {
80
81 pcmk__new_ordering(rsc1,
82 pcmk__op_key(rsc1->id, PCMK_ACTION_MONITOR, 0),
83 NULL,
84 rsc2, pcmk__op_key(rsc2->id, PCMK_ACTION_START, 0),
85 NULL,
86 pcmk__ar_ordered, rsc1->cluster);
87 }
88 }
89
90
91
92
93
94
95
96
97
98 static bool
99 guest_resource_will_stop(const pcmk_node_t *node)
100 {
101 const pcmk_resource_t *guest_rsc = node->details->remote_rsc->container;
102
103
104
105
106 return node->details->remote_requires_reset
107 || node->details->unclean
108 || pcmk_is_set(guest_rsc->flags, pcmk_rsc_failed)
109 || (guest_rsc->next_role == pcmk_role_stopped)
110
111
112 || ((guest_rsc->role > pcmk_role_stopped)
113 && (guest_rsc->allocated_to != NULL)
114 && (pcmk__find_node_in_list(guest_rsc->running_on,
115 guest_rsc->allocated_to->details->uname) == NULL));
116 }
117
118
119
120
121
122
123
124
125
126
127 static pcmk_action_t *
128 probe_action(pcmk_resource_t *rsc, pcmk_node_t *node)
129 {
130 pcmk_action_t *probe = NULL;
131 char *key = pcmk__op_key(rsc->id, PCMK_ACTION_MONITOR, 0);
132
133 crm_debug("Scheduling probe of %s %s on %s",
134 pcmk_role_text(rsc->role), rsc->id, pcmk__node_name(node));
135
136 probe = custom_action(rsc, key, PCMK_ACTION_MONITOR, node, FALSE,
137 rsc->cluster);
138 pcmk__clear_action_flags(probe, pcmk_action_optional);
139
140 pcmk__order_vs_unfence(rsc, node, probe, pcmk__ar_ordered);
141 add_expected_result(probe, rsc, node);
142 return probe;
143 }
144
145
146
147
148
149
150
151
152
153
154
155
156 bool
157 pcmk__probe_rsc_on_node(pcmk_resource_t *rsc, pcmk_node_t *node)
158 {
159 uint32_t flags = pcmk__ar_ordered;
160 pcmk_action_t *probe = NULL;
161 pcmk_node_t *allowed = NULL;
162 pcmk_resource_t *top = uber_parent(rsc);
163 const char *reason = NULL;
164
165 pcmk__assert((rsc != NULL) && (node != NULL));
166
167 if (!pcmk_is_set(rsc->cluster->flags, pcmk_sched_probe_resources)) {
168 reason = "start-up probes are disabled";
169 goto no_probe;
170 }
171
172 if (pcmk__is_pacemaker_remote_node(node)) {
173 if (pcmk_is_set(rsc->flags, pcmk_rsc_fence_device)) {
174 reason = "Pacemaker Remote nodes cannot run stonith agents";
175 goto no_probe;
176
177 } else if (pcmk__is_guest_or_bundle_node(node)
178 && pe__resource_contains_guest_node(rsc->cluster, rsc)) {
179 reason = "guest nodes cannot run resources containing guest nodes";
180 goto no_probe;
181
182 } else if (rsc->is_remote_node) {
183 reason = "Pacemaker Remote nodes cannot host remote connections";
184 goto no_probe;
185 }
186 }
187
188
189 if (rsc->children != NULL) {
190 return pcmk__probe_resource_list(rsc->children, node);
191 }
192
193 if ((rsc->container != NULL) && !rsc->is_remote_node) {
194 reason = "resource is inside a container";
195 goto no_probe;
196
197 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_removed)) {
198 reason = "resource is orphaned";
199 goto no_probe;
200
201 } else if (g_hash_table_lookup(rsc->known_on, node->details->id) != NULL) {
202 reason = "resource state is already known";
203 goto no_probe;
204 }
205
206 allowed = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
207
208 if (rsc->exclusive_discover || top->exclusive_discover) {
209
210
211 if (allowed == NULL) {
212
213 reason = "resource has exclusive discovery but is not allowed "
214 "on node";
215 goto no_probe;
216
217 } else if (allowed->rsc_discover_mode != pcmk_probe_exclusive) {
218
219 reason = "resource has exclusive discovery but is not enabled "
220 "on node";
221 goto no_probe;
222 }
223 }
224
225 if (allowed == NULL) {
226 allowed = node;
227 }
228 if (allowed->rsc_discover_mode == pcmk_probe_never) {
229 reason = "node has discovery disabled";
230 goto no_probe;
231 }
232
233 if (pcmk__is_guest_or_bundle_node(node)) {
234 pcmk_resource_t *guest = node->details->remote_rsc->container;
235
236 if (guest->role == pcmk_role_stopped) {
237
238 reason = "node's guest is stopped";
239 probe_then_start(guest, top);
240 goto no_probe;
241
242 } else if (guest_resource_will_stop(node)) {
243 reason = "node's guest will stop";
244
245
246 pcmk__new_ordering(guest,
247 pcmk__op_key(guest->id, PCMK_ACTION_STOP, 0),
248 NULL, top,
249 pcmk__op_key(top->id, PCMK_ACTION_START, 0),
250 NULL, pcmk__ar_ordered, rsc->cluster);
251 goto no_probe;
252 }
253 }
254
255
256 probe = probe_action(rsc, node);
257
258
259
260
261
262
263 if (!pcmk__is_clone(top)) {
264 top = rsc;
265 }
266
267
268
269
270 if (!pcmk_is_set(probe->flags, pcmk_action_runnable)
271 && (top->running_on == NULL)) {
272 pcmk__set_relation_flags(flags, pcmk__ar_unrunnable_first_blocks);
273 }
274
275
276 pcmk__new_ordering(rsc, NULL, probe,
277 top, pcmk__op_key(top->id, PCMK_ACTION_START, 0), NULL,
278 flags, rsc->cluster);
279 pcmk__new_ordering(rsc, NULL, probe, top, reload_key(rsc), NULL,
280 pcmk__ar_ordered, rsc->cluster);
281
282 return true;
283
284 no_probe:
285 pcmk__rsc_trace(rsc,
286 "Skipping probe for %s on %s because %s",
287 rsc->id, node->details->id, reason);
288 return false;
289 }
290
291
292
293
294
295
296
297
298
299
300 static bool
301 probe_needed_before_action(const pcmk_action_t *probe,
302 const pcmk_action_t *then)
303 {
304
305 if (pcmk__str_eq(then->task, PCMK_ACTION_STONITH, pcmk__str_none)
306 && pcmk__same_node(probe->node, then->node)) {
307 const char *op = g_hash_table_lookup(then->meta,
308 PCMK__META_STONITH_ACTION);
309
310 if (pcmk__str_eq(op, PCMK_ACTION_ON, pcmk__str_casei)) {
311 return false;
312 }
313 }
314
315
316 if (pcmk__str_eq(then->task, PCMK_ACTION_DO_SHUTDOWN, pcmk__str_none)
317 && (probe->node != NULL) && (then->node != NULL)
318 && !pcmk__same_node(probe->node, then->node)) {
319 return false;
320 }
321
322
323 return true;
324 }
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339 static void
340 add_probe_orderings_for_stops(pcmk_scheduler_t *scheduler)
341 {
342 for (GList *iter = scheduler->ordering_constraints; iter != NULL;
343 iter = iter->next) {
344
345 pcmk__action_relation_t *order = iter->data;
346 uint32_t order_flags = pcmk__ar_ordered;
347 GList *probes = NULL;
348 GList *then_actions = NULL;
349 pcmk_action_t *first = NULL;
350 pcmk_action_t *then = NULL;
351
352
353 if (order->flags == pcmk__ar_none) {
354 continue;
355 }
356
357
358 if ((order->rsc1 == NULL) || (order->rsc1 == order->rsc2)) {
359 continue;
360 }
361
362
363 first = order->action1;
364 then = order->action2;
365 if (((first == NULL) && (order->task1 == NULL))
366 || ((then == NULL) && (order->task2 == NULL))) {
367 continue;
368 }
369
370
371 if ((first != NULL) && !pcmk__str_eq(first->task, PCMK_ACTION_STOP,
372 pcmk__str_none)) {
373 continue;
374 } else if ((first == NULL)
375 && !pcmk__ends_with(order->task1,
376 "_" PCMK_ACTION_STOP "_0")) {
377 continue;
378 }
379
380
381
382
383
384 if ((order->rsc2 != NULL) && (order->rsc1->container == order->rsc2)) {
385
386 if ((then != NULL) && pcmk__str_eq(then->task, PCMK_ACTION_STOP,
387 pcmk__str_none)) {
388 continue;
389 } else if ((then == NULL)
390 && pcmk__ends_with(order->task2,
391 "_" PCMK_ACTION_STOP "_0")) {
392 continue;
393 }
394 }
395
396
397 if (pcmk_is_set(order->flags, pcmk__ar_if_first_unmigratable)) {
398 pcmk__set_relation_flags(order_flags,
399 pcmk__ar_if_first_unmigratable);
400 }
401 if (pcmk_is_set(order->flags, pcmk__ar_if_on_same_node)) {
402 pcmk__set_relation_flags(order_flags, pcmk__ar_if_on_same_node);
403 }
404
405
406 if ((order->flags == pcmk__ar_if_required_on_same_node)
407 || (order->flags == pcmk__ar_if_on_same_node_or_target)) {
408 order_flags = order->flags;
409 }
410
411
412 probes = pe__resource_actions(order->rsc1, NULL, PCMK_ACTION_MONITOR,
413 FALSE);
414 if (probes == NULL) {
415 continue;
416 }
417
418
419 if (then != NULL) {
420 then_actions = g_list_prepend(NULL, then);
421
422 } else if (order->rsc2 != NULL) {
423 then_actions = find_actions(order->rsc2->actions, order->task2,
424 NULL);
425 if (then_actions == NULL) {
426 g_list_free(probes);
427 continue;
428 }
429 }
430
431 crm_trace("Implying 'probe then' orderings for '%s then %s' "
432 "(id=%d, type=%.6x)",
433 ((first == NULL)? order->task1 : first->uuid),
434 ((then == NULL)? order->task2 : then->uuid),
435 order->id, order->flags);
436
437 for (GList *probe_iter = probes; probe_iter != NULL;
438 probe_iter = probe_iter->next) {
439
440 pcmk_action_t *probe = (pcmk_action_t *) probe_iter->data;
441
442 for (GList *then_iter = then_actions; then_iter != NULL;
443 then_iter = then_iter->next) {
444
445 pcmk_action_t *then = (pcmk_action_t *) then_iter->data;
446
447 if (probe_needed_before_action(probe, then)) {
448 order_actions(probe, then, order_flags);
449 }
450 }
451 }
452
453 g_list_free(then_actions);
454 g_list_free(probes);
455 }
456 }
457
458
459
460
461
462
463
464
465
466
467
468 static void
469 add_start_orderings_for_probe(pcmk_action_t *probe,
470 pcmk__related_action_t *after)
471 {
472 uint32_t flags = pcmk__ar_ordered|pcmk__ar_unrunnable_first_blocks;
473
474
475
476
477
478
479
480
481
482
483
484 if ((after->action->rsc->variant <= pcmk_rsc_variant_group)
485 || pcmk_is_set(probe->flags, pcmk_action_runnable)
486
487 || pcmk_is_set(after->type, pcmk__ar_unrunnable_first_blocks)
488 || (pe__const_top_resource(probe->rsc, false) != after->action->rsc)
489 || !pcmk__str_eq(after->action->task, PCMK_ACTION_START,
490 pcmk__str_none)) {
491 return;
492 }
493
494 crm_trace("Adding probe start orderings for 'unrunnable %s@%s "
495 "then instances of %s@%s'",
496 probe->uuid, pcmk__node_name(probe->node),
497 after->action->uuid, pcmk__node_name(after->action->node));
498
499 for (GList *then_iter = after->action->actions_after; then_iter != NULL;
500 then_iter = then_iter->next) {
501
502 pcmk__related_action_t *then = then_iter->data;
503
504 if (then->action->rsc->running_on
505 || (pe__const_top_resource(then->action->rsc, false)
506 != after->action->rsc)
507 || !pcmk__str_eq(then->action->task, PCMK_ACTION_START,
508 pcmk__str_none)) {
509 continue;
510 }
511
512 crm_trace("Adding probe start ordering for 'unrunnable %s@%s "
513 "then %s@%s' (type=%#.6x)",
514 probe->uuid, pcmk__node_name(probe->node),
515 then->action->uuid, pcmk__node_name(then->action->node),
516 flags);
517
518
519
520
521 order_actions(probe, then->action, flags);
522 }
523
524 return;
525 }
526
527
528
529
530
531
532
533
534
535
536
537
538
539 static void
540 add_restart_orderings_for_probe(pcmk_action_t *probe, pcmk_action_t *after)
541 {
542 GList *iter = NULL;
543 bool interleave = false;
544 pcmk_resource_t *compatible_rsc = NULL;
545
546
547 if ((after == NULL) || (probe == NULL) || !pcmk__is_primitive(probe->rsc)
548 || !pcmk__str_eq(probe->task, PCMK_ACTION_MONITOR, pcmk__str_none)) {
549 return;
550 }
551
552
553 if (pcmk_is_set(after->flags, pcmk_action_detect_loop)) {
554 return;
555 }
556 pcmk__set_action_flags(after, pcmk_action_detect_loop);
557
558 crm_trace("Adding probe restart orderings for '%s@%s then %s@%s'",
559 probe->uuid, pcmk__node_name(probe->node),
560 after->uuid, pcmk__node_name(after->node));
561
562
563
564
565 if (pcmk__is_primitive(after->rsc) && (probe->rsc != after->rsc)) {
566
567 GList *then_actions = NULL;
568
569 if (pcmk__str_eq(after->task, PCMK_ACTION_START, pcmk__str_none)) {
570 then_actions = pe__resource_actions(after->rsc, NULL,
571 PCMK_ACTION_STOP, FALSE);
572
573 } else if (pcmk__str_eq(after->task, PCMK_ACTION_PROMOTE,
574 pcmk__str_none)) {
575 then_actions = pe__resource_actions(after->rsc, NULL,
576 PCMK_ACTION_DEMOTE, FALSE);
577 }
578
579 for (iter = then_actions; iter != NULL; iter = iter->next) {
580 pcmk_action_t *then = (pcmk_action_t *) iter->data;
581
582
583 if (!pcmk_is_set(then->flags, pcmk_action_pseudo)) {
584 order_actions(probe, then, pcmk__ar_ordered);
585 }
586 }
587 g_list_free(then_actions);
588 }
589
590
591
592
593 if ((after->rsc != NULL)
594 && (after->rsc->variant > pcmk_rsc_variant_group)) {
595 const char *interleave_s = g_hash_table_lookup(after->rsc->meta,
596 PCMK_META_INTERLEAVE);
597
598 interleave = crm_is_true(interleave_s);
599 if (interleave) {
600 compatible_rsc = pcmk__find_compatible_instance(probe->rsc,
601 after->rsc,
602 pcmk_role_unknown,
603 false);
604 }
605 }
606
607
608
609
610
611 for (iter = after->actions_after; iter != NULL; iter = iter->next) {
612 pcmk__related_action_t *after_wrapper = iter->data;
613
614
615
616
617
618
619
620
621
622 if (!pcmk_is_set(after_wrapper->type, pcmk__ar_first_implies_then)) {
623
624
625
626
627
628
629
630
631 if ((after->rsc == NULL)
632 || (after->rsc->variant < pcmk_rsc_variant_group)
633 || (probe->rsc->parent == after->rsc)
634 || (after_wrapper->action->rsc == NULL)
635 || (after_wrapper->action->rsc->variant > pcmk_rsc_variant_group)
636 || (after->rsc != after_wrapper->action->rsc->parent)) {
637 continue;
638 }
639
640
641
642
643 if ((after->rsc->variant > pcmk_rsc_variant_group) && interleave
644 && ((compatible_rsc == NULL)
645 || (compatible_rsc != after_wrapper->action->rsc))) {
646 continue;
647 }
648 }
649
650 crm_trace("Recursively adding probe restart orderings for "
651 "'%s@%s then %s@%s' (type=%#.6x)",
652 after->uuid, pcmk__node_name(after->node),
653 after_wrapper->action->uuid,
654 pcmk__node_name(after_wrapper->action->node),
655 after_wrapper->type);
656
657 add_restart_orderings_for_probe(probe, after_wrapper->action);
658 }
659 }
660
661
662
663
664
665
666
667 static void
668 clear_actions_tracking_flag(pcmk_scheduler_t *scheduler)
669 {
670 for (GList *iter = scheduler->actions; iter != NULL; iter = iter->next) {
671 pcmk_action_t *action = iter->data;
672
673 pcmk__clear_action_flags(action, pcmk_action_detect_loop);
674 }
675 }
676
677
678
679
680
681
682
683
684 static void
685 add_start_restart_orderings_for_rsc(gpointer data, gpointer user_data)
686 {
687 pcmk_resource_t *rsc = data;
688 GList *probes = NULL;
689
690
691 if (!pcmk__is_primitive(rsc)) {
692 g_list_foreach(rsc->children, add_start_restart_orderings_for_rsc,
693 NULL);
694 return;
695 }
696
697
698 probes = pe__resource_actions(rsc, NULL, PCMK_ACTION_MONITOR, FALSE);
699
700
701 for (GList *iter = probes; iter != NULL; iter = iter->next) {
702 pcmk_action_t *probe = (pcmk_action_t *) iter->data;
703
704 for (GList *then_iter = probe->actions_after; then_iter != NULL;
705 then_iter = then_iter->next) {
706
707 pcmk__related_action_t *then = then_iter->data;
708
709 add_start_orderings_for_probe(probe, then);
710 add_restart_orderings_for_probe(probe, then->action);
711 clear_actions_tracking_flag(rsc->cluster);
712 }
713 }
714
715 g_list_free(probes);
716 }
717
718
719
720
721
722
723
724
725
726 static void
727 order_then_probes(pcmk_scheduler_t *scheduler)
728 {
729 #if 0
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759 for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
760 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
761
762 pcmk_action_t *start = NULL;
763 GList *actions = NULL;
764 GList *probes = NULL;
765
766 actions = pe__resource_actions(rsc, NULL, PCMK_ACTION_START, FALSE);
767
768 if (actions) {
769 start = actions->data;
770 g_list_free(actions);
771 }
772
773 if (start == NULL) {
774 crm_debug("No start action for %s", rsc->id);
775 continue;
776 }
777
778 probes = pe__resource_actions(rsc, NULL, PCMK_ACTION_MONITOR, FALSE);
779
780 for (actions = start->actions_before; actions != NULL;
781 actions = actions->next) {
782
783 pcmk__related_action_t *before = actions->data;
784
785 pcmk_action_t *first = before->action;
786 pcmk_resource_t *first_rsc = first->rsc;
787
788 if (first->required_runnable_before) {
789 for (GList *clone_actions = first->actions_before;
790 clone_actions != NULL;
791 clone_actions = clone_actions->next) {
792
793 before = clone_actions->data;
794
795 crm_trace("Testing '%s then %s' for %s",
796 first->uuid, before->action->uuid, start->uuid);
797
798 pcmk__assert(before->action->rsc != NULL);
799 first_rsc = before->action->rsc;
800 break;
801 }
802
803 } else if (!pcmk__str_eq(first->task, PCMK_ACTION_START,
804 pcmk__str_none)) {
805 crm_trace("Not a start op %s for %s", first->uuid, start->uuid);
806 }
807
808 if (first_rsc == NULL) {
809 continue;
810
811 } else if (pe__const_top_resource(first_rsc, false)
812 == pe__const_top_resource(start->rsc, false)) {
813 crm_trace("Same parent %s for %s", first_rsc->id, start->uuid);
814 continue;
815
816 } else if (!pcmk__is_clone(pe__const_top_resource(first_rsc,
817 false))) {
818 crm_trace("Not a clone %s for %s", first_rsc->id, start->uuid);
819 continue;
820 }
821
822 crm_debug("Applying %s before %s %d", first->uuid, start->uuid,
823 pe__const_top_resource(first_rsc, false)->variant);
824
825 for (GList *probe_iter = probes; probe_iter != NULL;
826 probe_iter = probe_iter->next) {
827
828 pcmk_action_t *probe = (pcmk_action_t *) probe_iter->data;
829
830 crm_debug("Ordering %s before %s", first->uuid, probe->uuid);
831 order_actions(first, probe, pcmk__ar_ordered);
832 }
833 }
834 }
835 #endif
836 }
837
838 void
839 pcmk__order_probes(pcmk_scheduler_t *scheduler)
840 {
841
842 g_list_foreach(scheduler->resources, add_start_restart_orderings_for_rsc,
843 NULL);
844 add_probe_orderings_for_stops(scheduler);
845
846 order_then_probes(scheduler);
847 }
848
849
850
851
852
853
854
855
856
857 void
858 pcmk__schedule_probes(pcmk_scheduler_t *scheduler)
859 {
860
861 for (GList *iter = scheduler->nodes; iter != NULL; iter = iter->next) {
862 pcmk_node_t *node = (pcmk_node_t *) iter->data;
863 const char *probed = NULL;
864
865 if (!node->details->online) {
866 if (pcmk__is_failed_remote_node(node)) {
867 pe_fence_node(scheduler, node,
868 "the connection is unrecoverable", FALSE);
869 }
870 continue;
871
872 } else if (node->details->unclean) {
873 continue;
874
875 } else if (!node->details->rsc_discovery_enabled) {
876
877 continue;
878 }
879
880
881
882
883
884
885 probed = pcmk__node_attr(node, CRM_OP_PROBED, NULL,
886 pcmk__rsc_node_current);
887 if (probed != NULL && crm_is_true(probed) == FALSE) {
888 pcmk_action_t *probe_op = NULL;
889
890 probe_op = custom_action(NULL,
891 crm_strdup_printf("%s-%s", CRM_OP_REPROBE,
892 node->details->uname),
893 CRM_OP_REPROBE, node, FALSE, scheduler);
894 pcmk__insert_meta(probe_op, PCMK__META_OP_NO_WAIT, PCMK_VALUE_TRUE);
895 continue;
896 }
897
898
899 pcmk__probe_resource_list(scheduler->resources, node);
900 }
901 }