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