This source file includes following definitions.
- check_params
- failcount_clear_action_exists
- check_failure_threshold
- apply_exclusive_discovery
- apply_stickiness
- apply_shutdown_locks
- count_available_nodes
- apply_node_criteria
- assign_resources
- clear_failcounts_if_orphaned
- schedule_resource_actions
- is_managed
- any_managed_resources
- needs_fencing
- needs_shutdown
- add_nondc_fencing
- schedule_fencing
- schedule_fencing_and_shutdowns
- log_resource_details
- log_all_actions
- log_unrunnable_actions
- unpack_cib
- pcmk__schedule_actions
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/crm.h>
13 #include <crm/cib.h>
14 #include <crm/msg_xml.h>
15 #include <crm/common/xml.h>
16 #include <crm/common/xml_internal.h>
17 #include <crm/common/scheduler_internal.h>
18
19 #include <glib.h>
20
21 #include <crm/pengine/status.h>
22 #include <pacemaker-internal.h>
23 #include "libpacemaker_private.h"
24
25 CRM_TRACE_INIT_DATA(pacemaker);
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 static void
43 check_params(pcmk_resource_t *rsc, pcmk_node_t *node, const xmlNode *rsc_op,
44 enum pcmk__check_parameters check)
45 {
46 const char *reason = NULL;
47 op_digest_cache_t *digest_data = NULL;
48
49 switch (check) {
50 case pcmk__check_active:
51 if (pcmk__check_action_config(rsc, node, rsc_op)
52 && pe_get_failcount(node, rsc, NULL, pcmk__fc_effective,
53 NULL)) {
54 reason = "action definition changed";
55 }
56 break;
57
58 case pcmk__check_last_failure:
59 digest_data = rsc_action_digest_cmp(rsc, rsc_op, node,
60 rsc->cluster);
61 switch (digest_data->rc) {
62 case pcmk__digest_unknown:
63 crm_trace("Resource %s history entry %s on %s has "
64 "no digest to compare",
65 rsc->id, ID(rsc_op), node->details->id);
66 break;
67 case pcmk__digest_match:
68 break;
69 default:
70 reason = "resource parameters have changed";
71 break;
72 }
73 break;
74 }
75 if (reason != NULL) {
76 pe__clear_failcount(rsc, node, reason, rsc->cluster);
77 }
78 }
79
80
81
82
83
84
85
86
87
88
89
90 static bool
91 failcount_clear_action_exists(const pcmk_node_t *node,
92 const pcmk_resource_t *rsc)
93 {
94 GList *list = pe__resource_actions(rsc, node, PCMK_ACTION_CLEAR_FAILCOUNT,
95 TRUE);
96
97 if (list != NULL) {
98 g_list_free(list);
99 return true;
100 }
101 return false;
102 }
103
104
105
106
107
108
109
110
111 static void
112 check_failure_threshold(gpointer data, gpointer user_data)
113 {
114 pcmk_resource_t *rsc = data;
115 const pcmk_node_t *node = user_data;
116
117
118 if (rsc->children != NULL) {
119 g_list_foreach(rsc->children, check_failure_threshold, user_data);
120 return;
121 }
122
123 if (!failcount_clear_action_exists(node, rsc)) {
124
125
126
127
128
129
130
131
132
133
134 pcmk_resource_t *failed = NULL;
135
136 if (pcmk__threshold_reached(rsc, node, &failed)) {
137 resource_location(failed, node, -INFINITY, "__fail_limit__",
138 rsc->cluster);
139 }
140 }
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154
155 static void
156 apply_exclusive_discovery(gpointer data, gpointer user_data)
157 {
158 pcmk_resource_t *rsc = data;
159 const pcmk_node_t *node = user_data;
160
161 if (rsc->exclusive_discover
162 || pe__const_top_resource(rsc, false)->exclusive_discover) {
163 pcmk_node_t *match = NULL;
164
165
166 g_list_foreach(rsc->children, apply_exclusive_discovery, user_data);
167
168 match = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
169 if ((match != NULL)
170 && (match->rsc_discover_mode != pcmk_probe_exclusive)) {
171 match->weight = -INFINITY;
172 }
173 }
174 }
175
176
177
178
179
180
181
182
183 static void
184 apply_stickiness(gpointer data, gpointer user_data)
185 {
186 pcmk_resource_t *rsc = data;
187 pcmk_node_t *node = NULL;
188
189
190 if (rsc->children != NULL) {
191 g_list_foreach(rsc->children, apply_stickiness, NULL);
192 return;
193 }
194
195
196
197
198 if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)
199 || (rsc->stickiness < 1) || !pcmk__list_of_1(rsc->running_on)) {
200 return;
201 }
202
203 node = rsc->running_on->data;
204
205
206
207
208
209
210 if (!pcmk_is_set(rsc->cluster->flags, pcmk_sched_symmetric_cluster)
211 && (g_hash_table_lookup(rsc->allowed_nodes,
212 node->details->id) == NULL)) {
213 pe_rsc_debug(rsc,
214 "Ignoring %s stickiness because the cluster is "
215 "asymmetric and %s is not explicitly allowed",
216 rsc->id, pe__node_name(node));
217 return;
218 }
219
220 pe_rsc_debug(rsc, "Resource %s has %d stickiness on %s",
221 rsc->id, rsc->stickiness, pe__node_name(node));
222 resource_location(rsc, node, rsc->stickiness, "stickiness", rsc->cluster);
223 }
224
225
226
227
228
229
230
231 static void
232 apply_shutdown_locks(pcmk_scheduler_t *scheduler)
233 {
234 if (!pcmk_is_set(scheduler->flags, pcmk_sched_shutdown_lock)) {
235 return;
236 }
237 for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
238 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
239
240 rsc->cmds->shutdown_lock(rsc);
241 }
242 }
243
244
245
246
247
248
249
250 static void
251 count_available_nodes(pcmk_scheduler_t *scheduler)
252 {
253 if (pcmk_is_set(scheduler->flags, pcmk_sched_no_compat)) {
254 return;
255 }
256
257
258 for (GList *iter = scheduler->nodes; iter != NULL; iter = iter->next) {
259 pcmk_node_t *node = (pcmk_node_t *) iter->data;
260
261 if ((node != NULL) && (node->weight >= 0) && node->details->online
262 && (node->details->type != node_ping)) {
263 scheduler->max_valid_nodes++;
264 }
265 }
266 crm_trace("Online node count: %d", scheduler->max_valid_nodes);
267 }
268
269
270
271
272
273
274
275
276
277 static void
278 apply_node_criteria(pcmk_scheduler_t *scheduler)
279 {
280 crm_trace("Applying node-specific scheduling criteria");
281 apply_shutdown_locks(scheduler);
282 count_available_nodes(scheduler);
283 pcmk__apply_locations(scheduler);
284 g_list_foreach(scheduler->resources, apply_stickiness, NULL);
285
286 for (GList *node_iter = scheduler->nodes; node_iter != NULL;
287 node_iter = node_iter->next) {
288 for (GList *rsc_iter = scheduler->resources; rsc_iter != NULL;
289 rsc_iter = rsc_iter->next) {
290 check_failure_threshold(rsc_iter->data, node_iter->data);
291 apply_exclusive_discovery(rsc_iter->data, node_iter->data);
292 }
293 }
294 }
295
296
297
298
299
300
301
302 static void
303 assign_resources(pcmk_scheduler_t *scheduler)
304 {
305 GList *iter = NULL;
306
307 crm_trace("Assigning resources to nodes");
308
309 if (!pcmk__str_eq(scheduler->placement_strategy, "default",
310 pcmk__str_casei)) {
311 pcmk__sort_resources(scheduler);
312 }
313 pcmk__show_node_capacities("Original", scheduler);
314
315 if (pcmk_is_set(scheduler->flags, pcmk_sched_have_remote_nodes)) {
316
317
318
319
320 for (iter = scheduler->resources; iter != NULL; iter = iter->next) {
321 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
322
323 if (rsc->is_remote_node) {
324 pe_rsc_trace(rsc, "Assigning remote connection resource '%s'",
325 rsc->id);
326 rsc->cmds->assign(rsc, rsc->partial_migration_target, true);
327 }
328 }
329 }
330
331
332 for (iter = scheduler->resources; iter != NULL; iter = iter->next) {
333 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
334
335 if (!rsc->is_remote_node) {
336 pe_rsc_trace(rsc, "Assigning %s resource '%s'",
337 rsc->xml->name, rsc->id);
338 rsc->cmds->assign(rsc, NULL, true);
339 }
340 }
341
342 pcmk__show_node_capacities("Remaining", scheduler);
343 }
344
345
346
347
348
349
350
351
352 static void
353 clear_failcounts_if_orphaned(gpointer data, gpointer user_data)
354 {
355 pcmk_resource_t *rsc = data;
356
357 if (!pcmk_is_set(rsc->flags, pcmk_rsc_removed)) {
358 return;
359 }
360 crm_trace("Clear fail counts for orphaned resource %s", rsc->id);
361
362
363
364
365
366 for (GList *iter = rsc->cluster->nodes; iter != NULL; iter = iter->next) {
367 pcmk_node_t *node = (pcmk_node_t *) iter->data;
368 pcmk_action_t *clear_op = NULL;
369
370 if (!node->details->online) {
371 continue;
372 }
373 if (pe_get_failcount(node, rsc, NULL, pcmk__fc_effective, NULL) == 0) {
374 continue;
375 }
376
377 clear_op = pe__clear_failcount(rsc, node, "it is orphaned",
378 rsc->cluster);
379
380
381
382
383 pcmk__new_ordering(clear_op->rsc, NULL, clear_op, rsc, stop_key(rsc),
384 NULL, pcmk__ar_ordered, rsc->cluster);
385 }
386 }
387
388
389
390
391
392
393
394 static void
395 schedule_resource_actions(pcmk_scheduler_t *scheduler)
396 {
397
398 pe__foreach_param_check(scheduler, check_params);
399 pe__free_param_checks(scheduler);
400
401 if (pcmk_is_set(scheduler->flags, pcmk_sched_probe_resources)) {
402 crm_trace("Scheduling probes");
403 pcmk__schedule_probes(scheduler);
404 }
405
406 if (pcmk_is_set(scheduler->flags, pcmk_sched_stop_removed_resources)) {
407 g_list_foreach(scheduler->resources, clear_failcounts_if_orphaned,
408 NULL);
409 }
410
411 crm_trace("Scheduling resource actions");
412 for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
413 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
414
415 rsc->cmds->create_actions(rsc);
416 }
417 }
418
419
420
421
422
423
424
425
426
427 static bool
428 is_managed(const pcmk_resource_t *rsc)
429 {
430 if (pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
431 return true;
432 }
433 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
434 if (is_managed((pcmk_resource_t *) iter->data)) {
435 return true;
436 }
437 }
438 return false;
439 }
440
441
442
443
444
445
446
447
448
449 static bool
450 any_managed_resources(const pcmk_scheduler_t *scheduler)
451 {
452 for (const GList *iter = scheduler->resources;
453 iter != NULL; iter = iter->next) {
454 if (is_managed((const pcmk_resource_t *) iter->data)) {
455 return true;
456 }
457 }
458 return false;
459 }
460
461
462
463
464
465
466
467
468
469
470 static bool
471 needs_fencing(const pcmk_node_t *node, bool have_managed)
472 {
473 return have_managed && node->details->unclean
474 && pe_can_fence(node->details->data_set, node);
475 }
476
477
478
479
480
481
482
483
484
485 static bool
486 needs_shutdown(const pcmk_node_t *node)
487 {
488 if (pe__is_guest_or_remote_node(node)) {
489
490
491
492 return false;
493 }
494 return node->details->online && node->details->shutdown;
495 }
496
497
498
499
500
501
502
503
504
505
506
507 static GList *
508 add_nondc_fencing(GList *list, pcmk_action_t *action,
509 const pcmk_scheduler_t *scheduler)
510 {
511 if (!pcmk_is_set(scheduler->flags, pcmk_sched_concurrent_fencing)
512 && (list != NULL)) {
513
514
515
516
517
518 order_actions((pcmk_action_t *) list->data, action, pcmk__ar_ordered);
519 }
520 return g_list_prepend(list, action);
521 }
522
523
524
525
526
527
528
529 static pcmk_action_t *
530 schedule_fencing(pcmk_node_t *node)
531 {
532 pcmk_action_t *fencing = pe_fence_op(node, NULL, FALSE, "node is unclean",
533 FALSE, node->details->data_set);
534
535 pe_warn("Scheduling node %s for fencing", pe__node_name(node));
536 pcmk__order_vs_fence(fencing, node->details->data_set);
537 return fencing;
538 }
539
540
541
542
543
544
545
546 static void
547 schedule_fencing_and_shutdowns(pcmk_scheduler_t *scheduler)
548 {
549 pcmk_action_t *dc_down = NULL;
550 bool integrity_lost = false;
551 bool have_managed = any_managed_resources(scheduler);
552 GList *fencing_ops = NULL;
553 GList *shutdown_ops = NULL;
554
555 crm_trace("Scheduling fencing and shutdowns as needed");
556 if (!have_managed) {
557 crm_notice("No fencing will be done until there are resources "
558 "to manage");
559 }
560
561
562 for (GList *iter = scheduler->nodes; iter != NULL; iter = iter->next) {
563 pcmk_node_t *node = (pcmk_node_t *) iter->data;
564 pcmk_action_t *fencing = NULL;
565
566
567
568
569 if (pe__is_guest_node(node)) {
570 if (node->details->remote_requires_reset && have_managed
571 && pe_can_fence(scheduler, node)) {
572 pcmk__fence_guest(node);
573 }
574 continue;
575 }
576
577 if (needs_fencing(node, have_managed)) {
578 fencing = schedule_fencing(node);
579
580
581 if (node->details->is_dc) {
582 dc_down = fencing;
583 } else {
584 fencing_ops = add_nondc_fencing(fencing_ops, fencing,
585 scheduler);
586 }
587
588 } else if (needs_shutdown(node)) {
589 pcmk_action_t *down_op = pcmk__new_shutdown_action(node);
590
591
592 if (node->details->is_dc) {
593 dc_down = down_op;
594 } else {
595 shutdown_ops = g_list_prepend(shutdown_ops, down_op);
596 }
597 }
598
599 if ((fencing == NULL) && node->details->unclean) {
600 integrity_lost = true;
601 pe_warn("Node %s is unclean but cannot be fenced",
602 pe__node_name(node));
603 }
604 }
605
606 if (integrity_lost) {
607 if (!pcmk_is_set(scheduler->flags, pcmk_sched_fencing_enabled)) {
608 pe_warn("Resource functionality and data integrity cannot be "
609 "guaranteed (configure, enable, and test fencing to "
610 "correct this)");
611
612 } else if (!pcmk_is_set(scheduler->flags, pcmk_sched_quorate)) {
613 crm_notice("Unclean nodes will not be fenced until quorum is "
614 "attained or no-quorum-policy is set to ignore");
615 }
616 }
617
618 if (dc_down != NULL) {
619
620
621
622
623
624
625
626 if (pcmk__str_eq(dc_down->task, PCMK_ACTION_DO_SHUTDOWN,
627 pcmk__str_none)) {
628 pcmk__order_after_each(dc_down, shutdown_ops);
629 }
630
631
632
633 if (pcmk_is_set(scheduler->flags, pcmk_sched_concurrent_fencing)) {
634
635
636
637 pcmk__order_after_each(dc_down, fencing_ops);
638 } else if (fencing_ops != NULL) {
639
640
641
642
643
644 order_actions((pcmk_action_t *) fencing_ops->data, dc_down,
645 pcmk__ar_ordered);
646 }
647 }
648 g_list_free(fencing_ops);
649 g_list_free(shutdown_ops);
650 }
651
652 static void
653 log_resource_details(pcmk_scheduler_t *scheduler)
654 {
655 pcmk__output_t *out = scheduler->priv;
656 GList *all = NULL;
657
658
659
660
661
662 all = g_list_prepend(all, (gpointer) "*");
663
664 for (GList *item = scheduler->resources; item != NULL; item = item->next) {
665 pcmk_resource_t *rsc = (pcmk_resource_t *) item->data;
666
667
668 if (!pcmk_is_set(rsc->flags, pcmk_rsc_removed)
669 || (rsc->role != pcmk_role_stopped)) {
670 out->message(out, crm_map_element_name(rsc->xml), 0, rsc, all, all);
671 }
672 }
673
674 g_list_free(all);
675 }
676
677 static void
678 log_all_actions(pcmk_scheduler_t *scheduler)
679 {
680
681
682
683 pcmk__output_t *prev_out = scheduler->priv;
684 pcmk__output_t *out = NULL;
685
686 if (pcmk__log_output_new(&out) != pcmk_rc_ok) {
687 return;
688 }
689
690 pe__register_messages(out);
691 pcmk__register_lib_messages(out);
692 pcmk__output_set_log_level(out, LOG_NOTICE);
693 scheduler->priv = out;
694
695 out->begin_list(out, NULL, NULL, "Actions");
696 pcmk__output_actions(scheduler);
697 out->end_list(out);
698 out->finish(out, CRM_EX_OK, true, NULL);
699 pcmk__output_free(out);
700
701 scheduler->priv = prev_out;
702 }
703
704
705
706
707
708
709
710 static void
711 log_unrunnable_actions(const pcmk_scheduler_t *scheduler)
712 {
713 const uint64_t flags = pcmk_action_optional
714 |pcmk_action_runnable
715 |pcmk_action_pseudo;
716
717 crm_trace("Required but unrunnable actions:");
718 for (const GList *iter = scheduler->actions;
719 iter != NULL; iter = iter->next) {
720
721 const pcmk_action_t *action = (const pcmk_action_t *) iter->data;
722
723 if (!pcmk_any_flags_set(action->flags, flags)) {
724 pcmk__log_action("\t", action, true);
725 }
726 }
727 }
728
729
730
731
732
733
734
735
736
737 static void
738 unpack_cib(xmlNode *cib, unsigned long long flags, pcmk_scheduler_t *scheduler)
739 {
740 const char* localhost_save = NULL;
741
742 if (pcmk_is_set(scheduler->flags, pcmk_sched_have_status)) {
743 crm_trace("Reusing previously calculated cluster status");
744 pe__set_working_set_flags(scheduler, flags);
745 return;
746 }
747
748 if (scheduler->localhost) {
749 localhost_save = scheduler->localhost;
750 }
751
752 CRM_ASSERT(cib != NULL);
753 crm_trace("Calculating cluster status");
754
755
756
757
758
759
760 set_working_set_defaults(scheduler);
761
762 if (localhost_save) {
763 scheduler->localhost = localhost_save;
764 }
765
766 pe__set_working_set_flags(scheduler, flags);
767 scheduler->input = cib;
768 cluster_status(scheduler);
769 }
770
771
772
773
774
775
776
777
778
779 void
780 pcmk__schedule_actions(xmlNode *cib, unsigned long long flags,
781 pcmk_scheduler_t *scheduler)
782 {
783 unpack_cib(cib, flags, scheduler);
784 pcmk__set_assignment_methods(scheduler);
785 pcmk__apply_node_health(scheduler);
786 pcmk__unpack_constraints(scheduler);
787 if (pcmk_is_set(scheduler->flags, pcmk_sched_validate_only)) {
788 return;
789 }
790
791 if (!pcmk_is_set(scheduler->flags, pcmk_sched_location_only)
792 && pcmk__is_daemon) {
793 log_resource_details(scheduler);
794 }
795
796 apply_node_criteria(scheduler);
797
798 if (pcmk_is_set(scheduler->flags, pcmk_sched_location_only)) {
799 return;
800 }
801
802 pcmk__create_internal_constraints(scheduler);
803 pcmk__handle_rsc_config_changes(scheduler);
804 assign_resources(scheduler);
805 schedule_resource_actions(scheduler);
806
807
808
809
810 pcmk__order_remote_connection_actions(scheduler);
811
812 schedule_fencing_and_shutdowns(scheduler);
813 pcmk__apply_orderings(scheduler);
814 log_all_actions(scheduler);
815 pcmk__create_graph(scheduler);
816
817 if (get_crm_log_level() == LOG_TRACE) {
818 log_unrunnable_actions(scheduler);
819 }
820 }