This source file includes following definitions.
- check_rsc_parameters
- CancelXmlOp
- check_action_definition
- check_params
- check_actions_for
- find_rsc_list
- check_actions
- failcount_clear_action_exists
- common_apply_stickiness
- complex_set_cmds
- set_alloc_actions
- calculate_system_health
- apply_system_health
- stage0
- probe_resources
- rsc_discover_filter
- shutdown_time
- apply_shutdown_lock
- stage2
- stage4
- convert_const_pointer
- sort_rsc_process_order
- allocate_resources
- cleanup_orphans
- stage5
- is_managed
- any_managed_resources
- stage6
- order_first_probe_unneeded
- order_first_probes_imply_stops
- order_first_probe_then_restart_repromote
- clear_actions_tracking_flag
- order_first_rsc_probes
- order_first_probes
- order_then_probes
- pcmk__order_probes
- pcmk__log_transition_summary
- stage8
- LogNodeActions
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13
14 #include <crm/crm.h>
15 #include <crm/cib.h>
16 #include <crm/msg_xml.h>
17 #include <crm/common/xml.h>
18 #include <crm/common/xml_internal.h>
19
20 #include <glib.h>
21
22 #include <crm/pengine/status.h>
23 #include <pacemaker-internal.h>
24 #include "libpacemaker_private.h"
25
26 CRM_TRACE_INIT_DATA(pacemaker);
27
28 extern bool pcmk__is_daemon;
29
30 void set_alloc_actions(pe_working_set_t * data_set);
31 extern void ReloadRsc(pe_resource_t * rsc, pe_node_t *node, pe_working_set_t * data_set);
32 extern gboolean DeleteRsc(pe_resource_t * rsc, pe_node_t * node, gboolean optional, pe_working_set_t * data_set);
33
34 resource_alloc_functions_t resource_class_alloc_functions[] = {
35 {
36 pcmk__native_merge_weights,
37 pcmk__native_allocate,
38 native_create_actions,
39 native_create_probe,
40 native_internal_constraints,
41 native_rsc_colocation_lh,
42 native_rsc_colocation_rh,
43 pcmk__colocated_resources,
44 native_rsc_location,
45 native_action_flags,
46 native_update_actions,
47 native_expand,
48 native_append_meta,
49 },
50 {
51 pcmk__group_merge_weights,
52 pcmk__group_allocate,
53 group_create_actions,
54 native_create_probe,
55 group_internal_constraints,
56 group_rsc_colocation_lh,
57 group_rsc_colocation_rh,
58 pcmk__group_colocated_resources,
59 group_rsc_location,
60 group_action_flags,
61 group_update_actions,
62 group_expand,
63 group_append_meta,
64 },
65 {
66 pcmk__native_merge_weights,
67 pcmk__clone_allocate,
68 clone_create_actions,
69 clone_create_probe,
70 clone_internal_constraints,
71 clone_rsc_colocation_lh,
72 clone_rsc_colocation_rh,
73 pcmk__colocated_resources,
74 clone_rsc_location,
75 clone_action_flags,
76 pcmk__multi_update_actions,
77 clone_expand,
78 clone_append_meta,
79 },
80 {
81 pcmk__native_merge_weights,
82 pcmk__bundle_allocate,
83 pcmk__bundle_create_actions,
84 pcmk__bundle_create_probe,
85 pcmk__bundle_internal_constraints,
86 pcmk__bundle_rsc_colocation_lh,
87 pcmk__bundle_rsc_colocation_rh,
88 pcmk__colocated_resources,
89 pcmk__bundle_rsc_location,
90 pcmk__bundle_action_flags,
91 pcmk__multi_update_actions,
92 pcmk__bundle_expand,
93 pcmk__bundle_append_meta,
94 }
95 };
96
97 static gboolean
98 check_rsc_parameters(pe_resource_t * rsc, pe_node_t * node, xmlNode * rsc_entry,
99 gboolean active_here, pe_working_set_t * data_set)
100 {
101 int attr_lpc = 0;
102 gboolean force_restart = FALSE;
103 gboolean delete_resource = FALSE;
104 gboolean changed = FALSE;
105
106 const char *value = NULL;
107 const char *old_value = NULL;
108
109 const char *attr_list[] = {
110 XML_ATTR_TYPE,
111 XML_AGENT_ATTR_CLASS,
112 XML_AGENT_ATTR_PROVIDER
113 };
114
115 for (; attr_lpc < PCMK__NELEM(attr_list); attr_lpc++) {
116 value = crm_element_value(rsc->xml, attr_list[attr_lpc]);
117 old_value = crm_element_value(rsc_entry, attr_list[attr_lpc]);
118 if (value == old_value
119 || pcmk__str_eq(value, old_value, pcmk__str_none)) {
120 continue;
121 }
122
123 changed = TRUE;
124 trigger_unfencing(rsc, node, "Device definition changed", NULL, data_set);
125 if (active_here) {
126 force_restart = TRUE;
127 crm_notice("Forcing restart of %s on %s, %s changed: %s -> %s",
128 rsc->id, node->details->uname, attr_list[attr_lpc],
129 crm_str(old_value), crm_str(value));
130 }
131 }
132 if (force_restart) {
133
134 stop_action(rsc, node, FALSE);
135 pe__set_resource_flags(rsc, pe_rsc_start_pending);
136 delete_resource = TRUE;
137
138 } else if (changed) {
139 delete_resource = TRUE;
140 }
141 return delete_resource;
142 }
143
144 static void
145 CancelXmlOp(pe_resource_t * rsc, xmlNode * xml_op, pe_node_t * active_node,
146 const char *reason, pe_working_set_t * data_set)
147 {
148 guint interval_ms = 0;
149 pe_action_t *cancel = NULL;
150
151 const char *task = NULL;
152 const char *call_id = NULL;
153
154 CRM_CHECK(xml_op != NULL, return);
155 CRM_CHECK(active_node != NULL, return);
156
157 task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
158 call_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
159 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
160
161 crm_info("Action " PCMK__OP_FMT " on %s will be stopped: %s",
162 rsc->id, task, interval_ms,
163 active_node->details->uname, (reason? reason : "unknown"));
164
165 cancel = pe_cancel_op(rsc, task, interval_ms, active_node, data_set);
166 add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id);
167 pcmk__new_ordering(rsc, stop_key(rsc), NULL, rsc, NULL, cancel,
168 pe_order_optional, data_set);
169 }
170
171 static gboolean
172 check_action_definition(pe_resource_t * rsc, pe_node_t * active_node, xmlNode * xml_op,
173 pe_working_set_t * data_set)
174 {
175 char *key = NULL;
176 guint interval_ms = 0;
177 const op_digest_cache_t *digest_data = NULL;
178 gboolean did_change = FALSE;
179
180 const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
181 const char *digest_secure = NULL;
182
183 CRM_CHECK(active_node != NULL, return FALSE);
184
185 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
186 if (interval_ms > 0) {
187 xmlNode *op_match = NULL;
188
189
190 key = pcmk__op_key(rsc->id, task, interval_ms);
191
192 pe_rsc_trace(rsc, "Checking parameters for %s", key);
193 op_match = find_rsc_op_entry(rsc, key);
194
195 if ((op_match == NULL)
196 && pcmk_is_set(data_set->flags, pe_flag_stop_action_orphans)) {
197 CancelXmlOp(rsc, xml_op, active_node, "orphan", data_set);
198 free(key);
199 return TRUE;
200
201 } else if (op_match == NULL) {
202 pe_rsc_debug(rsc, "Orphan action detected: %s on %s", key, active_node->details->uname);
203 free(key);
204 return TRUE;
205 }
206 free(key);
207 key = NULL;
208 }
209
210 crm_trace("Testing " PCMK__OP_FMT " on %s",
211 rsc->id, task, interval_ms, active_node->details->uname);
212 if ((interval_ms == 0) && pcmk__str_eq(task, RSC_STATUS, pcmk__str_casei)) {
213
214 task = RSC_START;
215
216 } else if ((interval_ms == 0) && pcmk__str_eq(task, RSC_MIGRATED, pcmk__str_casei)) {
217
218 task = RSC_START;
219 } else if ((interval_ms == 0) && pcmk__str_eq(task, RSC_PROMOTE, pcmk__str_casei)) {
220
221 task = RSC_START;
222 }
223
224 digest_data = rsc_action_digest_cmp(rsc, xml_op, active_node, data_set);
225
226 if (pcmk_is_set(data_set->flags, pe_flag_sanitized)) {
227 digest_secure = crm_element_value(xml_op, XML_LRM_ATTR_SECURE_DIGEST);
228 }
229
230 if(digest_data->rc != RSC_DIGEST_MATCH
231 && digest_secure
232 && digest_data->digest_secure_calc
233 && strcmp(digest_data->digest_secure_calc, digest_secure) == 0) {
234 if (!pcmk__is_daemon && data_set->priv != NULL) {
235 pcmk__output_t *out = data_set->priv;
236 out->info(out, "Only 'private' parameters to "
237 PCMK__OP_FMT " on %s changed: %s", rsc->id, task,
238 interval_ms, active_node->details->uname,
239 crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
240 }
241
242 } else if (digest_data->rc == RSC_DIGEST_RESTART) {
243
244 pe_action_t *required = NULL;
245
246 did_change = TRUE;
247 key = pcmk__op_key(rsc->id, task, interval_ms);
248 crm_log_xml_info(digest_data->params_restart, "params:restart");
249 required = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
250 pe_action_set_reason(required, "resource definition change", true);
251 trigger_unfencing(rsc, active_node, "Device parameters changed", NULL, data_set);
252
253 } else if ((digest_data->rc == RSC_DIGEST_ALL) || (digest_data->rc == RSC_DIGEST_UNKNOWN)) {
254
255 const char *digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
256
257 did_change = TRUE;
258 trigger_unfencing(rsc, active_node, "Device parameters changed (reload)", NULL, data_set);
259 crm_log_xml_info(digest_data->params_all, "params:reload");
260 key = pcmk__op_key(rsc->id, task, interval_ms);
261
262 if (interval_ms > 0) {
263 pe_action_t *op = NULL;
264
265 #if 0
266
267 ReloadRsc(rsc, active_node, data_set);
268 #else
269
270 op = custom_action(rsc, key, task, active_node, TRUE, TRUE, data_set);
271 pe__set_action_flags(op, pe_action_reschedule);
272 #endif
273
274 } else if (digest_restart) {
275 pe_rsc_trace(rsc, "Reloading '%s' action for resource %s", task, rsc->id);
276
277
278 ReloadRsc(rsc, active_node, data_set);
279 free(key);
280
281 } else {
282 pe_action_t *required = NULL;
283 pe_rsc_trace(rsc, "Resource %s doesn't support agent reloads",
284 rsc->id);
285
286
287
288
289 required = custom_action(rsc, key, task, NULL, FALSE, TRUE,
290 data_set);
291 pe_action_set_reason(required, "resource definition change", true);
292 }
293 }
294
295 return did_change;
296 }
297
298
299
300
301
302
303
304 static void
305 check_params(pe_resource_t *rsc, pe_node_t *node, xmlNode *rsc_op,
306 enum pe_check_parameters check, pe_working_set_t *data_set)
307 {
308 const char *reason = NULL;
309 op_digest_cache_t *digest_data = NULL;
310
311 switch (check) {
312 case pe_check_active:
313 if (check_action_definition(rsc, node, rsc_op, data_set)
314 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
315 data_set)) {
316
317 reason = "action definition changed";
318 }
319 break;
320
321 case pe_check_last_failure:
322 digest_data = rsc_action_digest_cmp(rsc, rsc_op, node, data_set);
323 switch (digest_data->rc) {
324 case RSC_DIGEST_UNKNOWN:
325 crm_trace("Resource %s history entry %s on %s has no digest to compare",
326 rsc->id, ID(rsc_op), node->details->id);
327 break;
328 case RSC_DIGEST_MATCH:
329 break;
330 default:
331 reason = "resource parameters have changed";
332 break;
333 }
334 break;
335 }
336
337 if (reason) {
338 pe__clear_failcount(rsc, node, reason, data_set);
339 }
340 }
341
342 static void
343 check_actions_for(xmlNode * rsc_entry, pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set)
344 {
345 GList *gIter = NULL;
346 int offset = -1;
347 int stop_index = 0;
348 int start_index = 0;
349
350 const char *task = NULL;
351
352 xmlNode *rsc_op = NULL;
353 GList *op_list = NULL;
354 GList *sorted_op_list = NULL;
355
356 CRM_CHECK(node != NULL, return);
357
358 if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
359 pe_resource_t *parent = uber_parent(rsc);
360 if(parent == NULL
361 || pe_rsc_is_clone(parent) == FALSE
362 || pcmk_is_set(parent->flags, pe_rsc_unique)) {
363 pe_rsc_trace(rsc, "Skipping param check for %s and deleting: orphan", rsc->id);
364 DeleteRsc(rsc, node, FALSE, data_set);
365 } else {
366 pe_rsc_trace(rsc, "Skipping param check for %s (orphan clone)", rsc->id);
367 }
368 return;
369
370 } else if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
371 if (check_rsc_parameters(rsc, node, rsc_entry, FALSE, data_set)) {
372 DeleteRsc(rsc, node, FALSE, data_set);
373 }
374 pe_rsc_trace(rsc, "Skipping param check for %s: no longer active on %s",
375 rsc->id, node->details->uname);
376 return;
377 }
378
379 pe_rsc_trace(rsc, "Processing %s on %s", rsc->id, node->details->uname);
380
381 if (check_rsc_parameters(rsc, node, rsc_entry, TRUE, data_set)) {
382 DeleteRsc(rsc, node, FALSE, data_set);
383 }
384
385 for (rsc_op = pcmk__xe_first_child(rsc_entry); rsc_op != NULL;
386 rsc_op = pcmk__xe_next(rsc_op)) {
387
388 if (pcmk__str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, pcmk__str_none)) {
389 op_list = g_list_prepend(op_list, rsc_op);
390 }
391 }
392
393 sorted_op_list = g_list_sort(op_list, sort_op_by_callid);
394 calculate_active_ops(sorted_op_list, &start_index, &stop_index);
395
396 for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
397 xmlNode *rsc_op = (xmlNode *) gIter->data;
398 guint interval_ms = 0;
399
400 offset++;
401
402 if (start_index < stop_index) {
403
404 continue;
405 } else if (offset < start_index) {
406
407 continue;
408 }
409
410 task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
411 crm_element_value_ms(rsc_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
412
413 if ((interval_ms > 0) &&
414 (pcmk_is_set(rsc->flags, pe_rsc_maintenance) || node->details->maintenance)) {
415
416 CancelXmlOp(rsc, rsc_op, node, "maintenance mode", data_set);
417
418 } else if ((interval_ms > 0) || pcmk__strcase_any_of(task, RSC_STATUS, RSC_START,
419 RSC_PROMOTE, RSC_MIGRATED, NULL)) {
420
421
422
423
424 if (pe__bundle_needs_remote_name(rsc, data_set)) {
425
426
427
428
429
430
431
432 pe__add_param_check(rsc_op, rsc, node, pe_check_active,
433 data_set);
434
435 } else if (check_action_definition(rsc, node, rsc_op, data_set)
436 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
437 data_set)) {
438 pe__clear_failcount(rsc, node, "action definition changed",
439 data_set);
440 }
441 }
442 }
443 g_list_free(sorted_op_list);
444 }
445
446 static GList *
447 find_rsc_list(GList *result, pe_resource_t * rsc, const char *id, gboolean renamed_clones,
448 gboolean partial, pe_working_set_t * data_set)
449 {
450 GList *gIter = NULL;
451 gboolean match = FALSE;
452
453 if (id == NULL) {
454 return NULL;
455 }
456
457 if (rsc == NULL) {
458 if (data_set == NULL) {
459 return NULL;
460 }
461 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
462 pe_resource_t *child = (pe_resource_t *) gIter->data;
463
464 result = find_rsc_list(result, child, id, renamed_clones, partial,
465 NULL);
466 }
467 return result;
468 }
469
470 if (partial) {
471 if (strstr(rsc->id, id)) {
472 match = TRUE;
473
474 } else if (renamed_clones && rsc->clone_name && strstr(rsc->clone_name, id)) {
475 match = TRUE;
476 }
477
478 } else {
479 if (strcmp(rsc->id, id) == 0) {
480 match = TRUE;
481
482 } else if (renamed_clones && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
483 match = TRUE;
484 }
485 }
486
487 if (match) {
488 result = g_list_prepend(result, rsc);
489 }
490
491 if (rsc->children) {
492 gIter = rsc->children;
493 for (; gIter != NULL; gIter = gIter->next) {
494 pe_resource_t *child = (pe_resource_t *) gIter->data;
495
496 result = find_rsc_list(result, child, id, renamed_clones, partial, NULL);
497 }
498 }
499
500 return result;
501 }
502
503 static void
504 check_actions(pe_working_set_t * data_set)
505 {
506 const char *id = NULL;
507 pe_node_t *node = NULL;
508 xmlNode *lrm_rscs = NULL;
509 xmlNode *status = get_object_root(XML_CIB_TAG_STATUS, data_set->input);
510
511 xmlNode *node_state = NULL;
512
513 for (node_state = pcmk__xe_first_child(status); node_state != NULL;
514 node_state = pcmk__xe_next(node_state)) {
515
516 if (pcmk__str_eq((const char *)node_state->name, XML_CIB_TAG_STATE,
517 pcmk__str_none)) {
518 id = crm_element_value(node_state, XML_ATTR_ID);
519 lrm_rscs = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
520 lrm_rscs = find_xml_node(lrm_rscs, XML_LRM_TAG_RESOURCES, FALSE);
521
522 node = pe_find_node_id(data_set->nodes, id);
523
524 if (node == NULL) {
525 continue;
526
527
528 } else if (can_run_resources(node) == FALSE && node->details->maintenance == FALSE) {
529 crm_trace("Skipping param check for %s: can't run resources",
530 node->details->uname);
531 continue;
532 }
533
534 crm_trace("Processing node %s", node->details->uname);
535 if (node->details->online
536 || pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
537 xmlNode *rsc_entry = NULL;
538
539 for (rsc_entry = pcmk__xe_first_child(lrm_rscs);
540 rsc_entry != NULL;
541 rsc_entry = pcmk__xe_next(rsc_entry)) {
542
543 if (pcmk__str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, pcmk__str_none)) {
544
545 if (xml_has_children(rsc_entry)) {
546 GList *gIter = NULL;
547 GList *result = NULL;
548 const char *rsc_id = ID(rsc_entry);
549
550 CRM_CHECK(rsc_id != NULL, return);
551
552 result = find_rsc_list(NULL, NULL, rsc_id, TRUE, FALSE, data_set);
553 for (gIter = result; gIter != NULL; gIter = gIter->next) {
554 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
555
556 if (rsc->variant != pe_native) {
557 continue;
558 }
559 check_actions_for(rsc_entry, rsc, node, data_set);
560 }
561 g_list_free(result);
562 }
563 }
564 }
565 }
566 }
567 }
568 }
569
570 static gboolean
571 failcount_clear_action_exists(pe_node_t * node, pe_resource_t * rsc)
572 {
573 gboolean rc = FALSE;
574 GList *list = pe__resource_actions(rsc, node, CRM_OP_CLEAR_FAILCOUNT, TRUE);
575
576 if (list) {
577 rc = TRUE;
578 }
579 g_list_free(list);
580 return rc;
581 }
582
583 static void
584 common_apply_stickiness(pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set)
585 {
586 if (rsc->children) {
587 GList *gIter = rsc->children;
588
589 for (; gIter != NULL; gIter = gIter->next) {
590 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
591
592 common_apply_stickiness(child_rsc, node, data_set);
593 }
594 return;
595 }
596
597 if (pcmk_is_set(rsc->flags, pe_rsc_managed)
598 && rsc->stickiness != 0 && pcmk__list_of_1(rsc->running_on)) {
599 pe_node_t *current = pe_find_node_id(rsc->running_on, node->details->id);
600 pe_node_t *match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
601
602 if (current == NULL) {
603
604 } else if ((match != NULL)
605 || pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster)) {
606 pe_resource_t *sticky_rsc = rsc;
607
608 resource_location(sticky_rsc, node, rsc->stickiness, "stickiness", data_set);
609 pe_rsc_debug(sticky_rsc, "Resource %s: preferring current location"
610 " (node=%s, weight=%d)", sticky_rsc->id,
611 node->details->uname, rsc->stickiness);
612 } else {
613 GHashTableIter iter;
614 pe_node_t *nIter = NULL;
615
616 pe_rsc_debug(rsc, "Ignoring stickiness for %s: the cluster is asymmetric"
617 " and node %s is not explicitly allowed", rsc->id, node->details->uname);
618 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
619 while (g_hash_table_iter_next(&iter, NULL, (void **)&nIter)) {
620 crm_err("%s[%s] = %d", rsc->id, nIter->details->uname, nIter->weight);
621 }
622 }
623 }
624
625
626
627
628
629
630
631
632
633
634
635
636 if (failcount_clear_action_exists(node, rsc) == FALSE) {
637 pe_resource_t *failed = NULL;
638
639 if (pcmk__threshold_reached(rsc, node, data_set, &failed)) {
640 resource_location(failed, node, -INFINITY, "__fail_limit__",
641 data_set);
642 }
643 }
644 }
645
646 void
647 complex_set_cmds(pe_resource_t * rsc)
648 {
649 GList *gIter = rsc->children;
650
651 rsc->cmds = &resource_class_alloc_functions[rsc->variant];
652
653 for (; gIter != NULL; gIter = gIter->next) {
654 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
655
656 complex_set_cmds(child_rsc);
657 }
658 }
659
660 void
661 set_alloc_actions(pe_working_set_t * data_set)
662 {
663
664 GList *gIter = data_set->resources;
665
666 for (; gIter != NULL; gIter = gIter->next) {
667 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
668
669 complex_set_cmds(rsc);
670 }
671 }
672
673 static void
674 calculate_system_health(gpointer gKey, gpointer gValue, gpointer user_data)
675 {
676 const char *key = (const char *)gKey;
677 const char *value = (const char *)gValue;
678 int *system_health = (int *)user_data;
679
680 if (!gKey || !gValue || !user_data) {
681 return;
682 }
683
684 if (pcmk__starts_with(key, "#health")) {
685 int score;
686
687
688 score = char2score(value);
689
690
691 *system_health = pe__add_scores(score, *system_health);
692 }
693 }
694
695 static gboolean
696 apply_system_health(pe_working_set_t * data_set)
697 {
698 GList *gIter = NULL;
699 const char *health_strategy = pe_pref(data_set->config_hash, "node-health-strategy");
700 int base_health = 0;
701
702 if (pcmk__str_eq(health_strategy, "none", pcmk__str_null_matches | pcmk__str_casei)) {
703
704 pcmk__score_red = 0;
705 pcmk__score_yellow = 0;
706 pcmk__score_green = 0;
707 return TRUE;
708
709 } else if (pcmk__str_eq(health_strategy, "migrate-on-red", pcmk__str_casei)) {
710
711
712
713
714 pcmk__score_red = -INFINITY;
715 pcmk__score_yellow = 0;
716 pcmk__score_green = 0;
717
718 } else if (pcmk__str_eq(health_strategy, "only-green", pcmk__str_casei)) {
719
720
721
722
723 pcmk__score_red = -INFINITY;
724 pcmk__score_yellow = -INFINITY;
725 pcmk__score_green = 0;
726
727 } else if (pcmk__str_eq(health_strategy, "progressive", pcmk__str_casei)) {
728
729
730
731
732 base_health = char2score(pe_pref(data_set->config_hash,
733 "node-health-base"));
734
735 } else if (pcmk__str_eq(health_strategy, "custom", pcmk__str_casei)) {
736
737
738
739
740
741 return TRUE;
742
743 } else {
744 crm_err("Unknown node health strategy: %s", health_strategy);
745 return FALSE;
746 }
747
748 crm_info("Applying automated node health strategy: %s", health_strategy);
749
750 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
751 int system_health = base_health;
752 pe_node_t *node = (pe_node_t *) gIter->data;
753
754
755 g_hash_table_foreach(node->details->attrs, calculate_system_health, &system_health);
756
757 crm_info(" Node %s has an combined system health of %d",
758 node->details->uname, system_health);
759
760
761
762
763 if (system_health != 0) {
764
765 GList *gIter2 = data_set->resources;
766
767 for (; gIter2 != NULL; gIter2 = gIter2->next) {
768 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
769
770 pcmk__new_location(health_strategy, rsc, system_health, NULL,
771 node, data_set);
772 }
773 }
774 }
775
776 return TRUE;
777 }
778
779 gboolean
780 stage0(pe_working_set_t * data_set)
781 {
782 if (data_set->input == NULL) {
783 return FALSE;
784 }
785
786 if (!pcmk_is_set(data_set->flags, pe_flag_have_status)) {
787 crm_trace("Calculating status");
788 cluster_status(data_set);
789 }
790
791 set_alloc_actions(data_set);
792 apply_system_health(data_set);
793 pcmk__unpack_constraints(data_set);
794
795 return TRUE;
796 }
797
798
799
800
801 gboolean
802 probe_resources(pe_working_set_t * data_set)
803 {
804 pe_action_t *probe_node_complete = NULL;
805
806 for (GList *gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
807 pe_node_t *node = (pe_node_t *) gIter->data;
808 const char *probed = pe_node_attribute_raw(node, CRM_OP_PROBED);
809
810 if (node->details->online == FALSE) {
811
812 if (pcmk__is_failed_remote_node(node)) {
813 pe_fence_node(data_set, node, "the connection is unrecoverable", FALSE);
814 }
815 continue;
816
817 } else if (node->details->unclean) {
818 continue;
819
820 } else if (node->details->rsc_discovery_enabled == FALSE) {
821
822 continue;
823 }
824
825 if (probed != NULL && crm_is_true(probed) == FALSE) {
826 pe_action_t *probe_op = custom_action(NULL, crm_strdup_printf("%s-%s", CRM_OP_REPROBE, node->details->uname),
827 CRM_OP_REPROBE, node, FALSE, TRUE, data_set);
828
829 add_hash_param(probe_op->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE);
830 continue;
831 }
832
833 for (GList *gIter2 = data_set->resources; gIter2 != NULL; gIter2 = gIter2->next) {
834 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
835
836 rsc->cmds->create_probe(rsc, node, probe_node_complete, FALSE, data_set);
837 }
838 }
839 return TRUE;
840 }
841
842 static void
843 rsc_discover_filter(pe_resource_t *rsc, pe_node_t *node)
844 {
845 pe_resource_t *top = uber_parent(rsc);
846 pe_node_t *match;
847
848 if (rsc->exclusive_discover == FALSE && top->exclusive_discover == FALSE) {
849 return;
850 }
851
852 g_list_foreach(rsc->children, (GFunc) rsc_discover_filter, node);
853
854 match = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
855 if (match && match->rsc_discover_mode != pe_discover_exclusive) {
856 match->weight = -INFINITY;
857 }
858 }
859
860 static time_t
861 shutdown_time(pe_node_t *node, pe_working_set_t *data_set)
862 {
863 const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
864 time_t result = 0;
865
866 if (shutdown) {
867 long long result_ll;
868
869 if (pcmk__scan_ll(shutdown, &result_ll, 0LL) == pcmk_rc_ok) {
870 result = (time_t) result_ll;
871 }
872 }
873 return result? result : get_effective_time(data_set);
874 }
875
876 static void
877 apply_shutdown_lock(pe_resource_t *rsc, pe_working_set_t *data_set)
878 {
879 const char *class;
880
881
882 if (rsc->variant == pe_group) {
883 g_list_foreach(rsc->children, (GFunc) apply_shutdown_lock, data_set);
884 } else if (rsc->variant != pe_native) {
885 return;
886 }
887
888
889 class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
890 if (pcmk__str_eq(class, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_null_matches)
891 || pe__resource_is_remote_conn(rsc, data_set)) {
892 return;
893 }
894
895 if (rsc->lock_node != NULL) {
896
897
898 if (rsc->running_on != NULL) {
899
900
901
902
903 pe_rsc_info(rsc,
904 "Cancelling shutdown lock because %s is already active",
905 rsc->id);
906 pe__clear_resource_history(rsc, rsc->lock_node, data_set);
907 rsc->lock_node = NULL;
908 rsc->lock_time = 0;
909 }
910
911
912 } else if (pcmk__list_of_1(rsc->running_on)) {
913 pe_node_t *node = rsc->running_on->data;
914
915 if (node->details->shutdown) {
916 if (node->details->unclean) {
917 pe_rsc_debug(rsc, "Not locking %s to unclean %s for shutdown",
918 rsc->id, node->details->uname);
919 } else {
920 rsc->lock_node = node;
921 rsc->lock_time = shutdown_time(node, data_set);
922 }
923 }
924 }
925
926 if (rsc->lock_node == NULL) {
927
928 return;
929 }
930
931 if (data_set->shutdown_lock > 0) {
932 time_t lock_expiration = rsc->lock_time + data_set->shutdown_lock;
933
934 pe_rsc_info(rsc, "Locking %s to %s due to shutdown (expires @%lld)",
935 rsc->id, rsc->lock_node->details->uname,
936 (long long) lock_expiration);
937 pe__update_recheck_time(++lock_expiration, data_set);
938 } else {
939 pe_rsc_info(rsc, "Locking %s to %s due to shutdown",
940 rsc->id, rsc->lock_node->details->uname);
941 }
942
943
944 for (GList *item = data_set->nodes; item != NULL; item = item->next) {
945 pe_node_t *node = item->data;
946
947 if (strcmp(node->details->uname, rsc->lock_node->details->uname)) {
948 resource_location(rsc, node, -CRM_SCORE_INFINITY,
949 XML_CONFIG_ATTR_SHUTDOWN_LOCK, data_set);
950 }
951 }
952 }
953
954
955
956
957
958
959
960
961 gboolean
962 stage2(pe_working_set_t * data_set)
963 {
964 GList *gIter = NULL;
965
966 if (pcmk_is_set(data_set->flags, pe_flag_shutdown_lock)) {
967 g_list_foreach(data_set->resources, (GFunc) apply_shutdown_lock, data_set);
968 }
969
970 if (!pcmk_is_set(data_set->flags, pe_flag_no_compat)) {
971
972 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
973 pe_node_t *node = (pe_node_t *) gIter->data;
974
975 if (node && (node->weight >= 0) && node->details->online
976 && (node->details->type != node_ping)) {
977 data_set->max_valid_nodes++;
978 }
979 }
980 }
981
982 pcmk__apply_locations(data_set);
983
984 gIter = data_set->nodes;
985 for (; gIter != NULL; gIter = gIter->next) {
986 GList *gIter2 = NULL;
987 pe_node_t *node = (pe_node_t *) gIter->data;
988
989 gIter2 = data_set->resources;
990 for (; gIter2 != NULL; gIter2 = gIter2->next) {
991 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
992
993 common_apply_stickiness(rsc, node, data_set);
994 rsc_discover_filter(rsc, node);
995 }
996 }
997
998 return TRUE;
999 }
1000
1001
1002
1003
1004 gboolean
1005 stage4(pe_working_set_t * data_set)
1006 {
1007 check_actions(data_set);
1008 return TRUE;
1009 }
1010
1011 static void *
1012 convert_const_pointer(const void *ptr)
1013 {
1014
1015 return (void *)ptr;
1016 }
1017
1018 static gint
1019 sort_rsc_process_order(gconstpointer a, gconstpointer b, gpointer data)
1020 {
1021 int rc = 0;
1022 int r1_weight = -INFINITY;
1023 int r2_weight = -INFINITY;
1024
1025 const char *reason = "existence";
1026
1027 GList *nodes = (GList *) data;
1028 const pe_resource_t *resource1 = a;
1029 const pe_resource_t *resource2 = b;
1030
1031 pe_node_t *r1_node = NULL;
1032 pe_node_t *r2_node = NULL;
1033 GList *gIter = NULL;
1034 GHashTable *r1_nodes = NULL;
1035 GHashTable *r2_nodes = NULL;
1036
1037 reason = "priority";
1038 r1_weight = resource1->priority;
1039 r2_weight = resource2->priority;
1040
1041 if (r1_weight > r2_weight) {
1042 rc = -1;
1043 goto done;
1044 }
1045
1046 if (r1_weight < r2_weight) {
1047 rc = 1;
1048 goto done;
1049 }
1050
1051 reason = "no node list";
1052 if (nodes == NULL) {
1053 goto done;
1054 }
1055
1056 r1_nodes = pcmk__native_merge_weights(convert_const_pointer(resource1),
1057 resource1->id, NULL, NULL, 1,
1058 pe_weights_forward | pe_weights_init);
1059 pe__show_node_weights(true, NULL, resource1->id, r1_nodes,
1060 resource1->cluster);
1061
1062 r2_nodes = pcmk__native_merge_weights(convert_const_pointer(resource2),
1063 resource2->id, NULL, NULL, 1,
1064 pe_weights_forward | pe_weights_init);
1065 pe__show_node_weights(true, NULL, resource2->id, r2_nodes,
1066 resource2->cluster);
1067
1068
1069 reason = "current location";
1070 r1_weight = -INFINITY;
1071 r2_weight = -INFINITY;
1072
1073 if (resource1->running_on) {
1074 r1_node = pe__current_node(resource1);
1075 r1_node = g_hash_table_lookup(r1_nodes, r1_node->details->id);
1076 if (r1_node != NULL) {
1077 r1_weight = r1_node->weight;
1078 }
1079 }
1080 if (resource2->running_on) {
1081 r2_node = pe__current_node(resource2);
1082 r2_node = g_hash_table_lookup(r2_nodes, r2_node->details->id);
1083 if (r2_node != NULL) {
1084 r2_weight = r2_node->weight;
1085 }
1086 }
1087
1088 if (r1_weight > r2_weight) {
1089 rc = -1;
1090 goto done;
1091 }
1092
1093 if (r1_weight < r2_weight) {
1094 rc = 1;
1095 goto done;
1096 }
1097
1098 reason = "score";
1099 for (gIter = nodes; gIter != NULL; gIter = gIter->next) {
1100 pe_node_t *node = (pe_node_t *) gIter->data;
1101
1102 r1_node = NULL;
1103 r2_node = NULL;
1104
1105 r1_weight = -INFINITY;
1106 if (r1_nodes) {
1107 r1_node = g_hash_table_lookup(r1_nodes, node->details->id);
1108 }
1109 if (r1_node) {
1110 r1_weight = r1_node->weight;
1111 }
1112
1113 r2_weight = -INFINITY;
1114 if (r2_nodes) {
1115 r2_node = g_hash_table_lookup(r2_nodes, node->details->id);
1116 }
1117 if (r2_node) {
1118 r2_weight = r2_node->weight;
1119 }
1120
1121 if (r1_weight > r2_weight) {
1122 rc = -1;
1123 goto done;
1124 }
1125
1126 if (r1_weight < r2_weight) {
1127 rc = 1;
1128 goto done;
1129 }
1130 }
1131
1132 done:
1133 crm_trace("%s (%d) on %s %c %s (%d) on %s: %s",
1134 resource1->id, r1_weight, r1_node ? r1_node->details->id : "n/a",
1135 rc < 0 ? '>' : rc > 0 ? '<' : '=',
1136 resource2->id, r2_weight, r2_node ? r2_node->details->id : "n/a", reason);
1137
1138 if (r1_nodes) {
1139 g_hash_table_destroy(r1_nodes);
1140 }
1141 if (r2_nodes) {
1142 g_hash_table_destroy(r2_nodes);
1143 }
1144
1145 return rc;
1146 }
1147
1148 static void
1149 allocate_resources(pe_working_set_t * data_set)
1150 {
1151 GList *gIter = NULL;
1152
1153 if (pcmk_is_set(data_set->flags, pe_flag_have_remote_nodes)) {
1154
1155
1156
1157
1158 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1159 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1160 if (rsc->is_remote_node == FALSE) {
1161 continue;
1162 }
1163 pe_rsc_trace(rsc, "Allocating remote connection resource '%s'",
1164 rsc->id);
1165 rsc->cmds->allocate(rsc, rsc->partial_migration_target, data_set);
1166 }
1167 }
1168
1169
1170 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1171 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1172 if (rsc->is_remote_node == TRUE) {
1173 continue;
1174 }
1175 pe_rsc_trace(rsc, "Allocating %s resource '%s'",
1176 crm_element_name(rsc->xml), rsc->id);
1177 rsc->cmds->allocate(rsc, NULL, data_set);
1178 }
1179 }
1180
1181
1182 static void
1183 cleanup_orphans(pe_resource_t * rsc, pe_working_set_t * data_set)
1184 {
1185 GList *gIter = NULL;
1186
1187 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1188 pe_node_t *node = (pe_node_t *) gIter->data;
1189
1190 if (node->details->online
1191 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
1192 data_set)) {
1193
1194 pe_action_t *clear_op = NULL;
1195
1196 clear_op = pe__clear_failcount(rsc, node, "it is orphaned",
1197 data_set);
1198
1199
1200
1201
1202 pcmk__new_ordering(clear_op->rsc, NULL, clear_op,
1203 rsc, stop_key(rsc), NULL,
1204 pe_order_optional, data_set);
1205 }
1206 }
1207 }
1208
1209 gboolean
1210 stage5(pe_working_set_t * data_set)
1211 {
1212 pcmk__output_t *out = data_set->priv;
1213 GList *gIter = NULL;
1214
1215 if (!pcmk__str_eq(data_set->placement_strategy, "default", pcmk__str_casei)) {
1216 GList *nodes = g_list_copy(data_set->nodes);
1217
1218 nodes = sort_nodes_by_weight(nodes, NULL, data_set);
1219 data_set->resources =
1220 g_list_sort_with_data(data_set->resources, sort_rsc_process_order, nodes);
1221
1222 g_list_free(nodes);
1223 }
1224
1225 gIter = data_set->nodes;
1226 for (; gIter != NULL; gIter = gIter->next) {
1227 pe_node_t *node = (pe_node_t *) gIter->data;
1228
1229 if (pcmk_is_set(data_set->flags, pe_flag_show_utilization)) {
1230 out->message(out, "node-capacity", node, "Original");
1231 }
1232 }
1233
1234 crm_trace("Allocating services");
1235
1236
1237 allocate_resources(data_set);
1238
1239 gIter = data_set->nodes;
1240 for (; gIter != NULL; gIter = gIter->next) {
1241 pe_node_t *node = (pe_node_t *) gIter->data;
1242
1243 if (pcmk_is_set(data_set->flags, pe_flag_show_utilization)) {
1244 out->message(out, "node-capacity", node, "Remaining");
1245 }
1246 }
1247
1248
1249 pe__foreach_param_check(data_set, check_params);
1250 pe__free_param_checks(data_set);
1251
1252 if (pcmk_is_set(data_set->flags, pe_flag_startup_probes)) {
1253 crm_trace("Calculating needed probes");
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288 probe_resources(data_set);
1289 }
1290
1291 crm_trace("Handle orphans");
1292 if (pcmk_is_set(data_set->flags, pe_flag_stop_rsc_orphans)) {
1293 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1294 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1295
1296
1297
1298
1299 if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
1300 cleanup_orphans(rsc, data_set);
1301 }
1302 }
1303 }
1304
1305 crm_trace("Creating actions");
1306
1307 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1308 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1309
1310 rsc->cmds->create_actions(rsc, data_set);
1311 }
1312
1313 crm_trace("Creating done");
1314 return TRUE;
1315 }
1316
1317 static gboolean
1318 is_managed(const pe_resource_t * rsc)
1319 {
1320 GList *gIter = rsc->children;
1321
1322 if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
1323 return TRUE;
1324 }
1325
1326 for (; gIter != NULL; gIter = gIter->next) {
1327 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
1328
1329 if (is_managed(child_rsc)) {
1330 return TRUE;
1331 }
1332 }
1333
1334 return FALSE;
1335 }
1336
1337 static gboolean
1338 any_managed_resources(pe_working_set_t * data_set)
1339 {
1340
1341 GList *gIter = data_set->resources;
1342
1343 for (; gIter != NULL; gIter = gIter->next) {
1344 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1345
1346 if (is_managed(rsc)) {
1347 return TRUE;
1348 }
1349 }
1350 return FALSE;
1351 }
1352
1353
1354
1355
1356 gboolean
1357 stage6(pe_working_set_t * data_set)
1358 {
1359 pe_action_t *dc_down = NULL;
1360 pe_action_t *stonith_op = NULL;
1361 gboolean integrity_lost = FALSE;
1362 gboolean need_stonith = TRUE;
1363 GList *gIter;
1364 GList *stonith_ops = NULL;
1365 GList *shutdown_ops = NULL;
1366
1367
1368
1369
1370 pcmk__order_remote_connection_actions(data_set);
1371
1372 crm_trace("Processing fencing and shutdown cases");
1373 if (any_managed_resources(data_set) == FALSE) {
1374 crm_notice("Delaying fencing operations until there are resources to manage");
1375 need_stonith = FALSE;
1376 }
1377
1378
1379 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1380 pe_node_t *node = (pe_node_t *) gIter->data;
1381
1382
1383
1384
1385 if (pe__is_guest_node(node)) {
1386 if (node->details->remote_requires_reset && need_stonith
1387 && pe_can_fence(data_set, node)) {
1388 pcmk__fence_guest(node, data_set);
1389 }
1390 continue;
1391 }
1392
1393 stonith_op = NULL;
1394
1395 if (node->details->unclean
1396 && need_stonith && pe_can_fence(data_set, node)) {
1397
1398 stonith_op = pe_fence_op(node, NULL, FALSE, "node is unclean", FALSE, data_set);
1399 pe_warn("Scheduling Node %s for STONITH", node->details->uname);
1400
1401 pcmk__order_vs_fence(stonith_op, data_set);
1402
1403 if (node->details->is_dc) {
1404
1405 dc_down = stonith_op;
1406
1407 } else {
1408
1409 if (!pcmk_is_set(data_set->flags, pe_flag_concurrent_fencing)
1410 && (stonith_ops != NULL)) {
1411
1412
1413
1414
1415
1416 order_actions((pe_action_t *) stonith_ops->data,
1417 stonith_op, pe_order_optional);
1418 }
1419
1420
1421 stonith_ops = g_list_prepend(stonith_ops, stonith_op);
1422 }
1423
1424 } else if (node->details->online && node->details->shutdown &&
1425
1426
1427
1428 pe__is_guest_or_remote_node(node) == FALSE) {
1429
1430 pe_action_t *down_op = sched_shutdown_op(node, data_set);
1431
1432 if (node->details->is_dc) {
1433
1434 dc_down = down_op;
1435 } else {
1436
1437 shutdown_ops = g_list_prepend(shutdown_ops, down_op);
1438 }
1439 }
1440
1441 if (node->details->unclean && stonith_op == NULL) {
1442 integrity_lost = TRUE;
1443 pe_warn("Node %s is unclean!", node->details->uname);
1444 }
1445 }
1446
1447 if (integrity_lost) {
1448 if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1449 pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
1450 pe_err("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
1451
1452 } else if (!pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
1453 crm_notice("Cannot fence unclean nodes until quorum is"
1454 " attained (or no-quorum-policy is set to ignore)");
1455 }
1456 }
1457
1458 if (dc_down != NULL) {
1459
1460
1461
1462
1463
1464
1465
1466 if (pcmk__str_eq(dc_down->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
1467 for (gIter = shutdown_ops; gIter != NULL; gIter = gIter->next) {
1468 pe_action_t *node_stop = (pe_action_t *) gIter->data;
1469
1470 crm_debug("Ordering shutdown on %s before %s on DC %s",
1471 node_stop->node->details->uname,
1472 dc_down->task, dc_down->node->details->uname);
1473
1474 order_actions(node_stop, dc_down, pe_order_optional);
1475 }
1476 }
1477
1478
1479
1480 if (pcmk_is_set(data_set->flags, pe_flag_concurrent_fencing)) {
1481
1482
1483
1484 for (gIter = stonith_ops; gIter != NULL; gIter = gIter->next) {
1485 order_actions((pe_action_t *) gIter->data, dc_down,
1486 pe_order_optional);
1487 }
1488 } else if (stonith_ops) {
1489
1490
1491
1492
1493
1494 order_actions((pe_action_t *) stonith_ops->data, dc_down,
1495 pe_order_optional);
1496 }
1497 }
1498 g_list_free(stonith_ops);
1499 g_list_free(shutdown_ops);
1500 return TRUE;
1501 }
1502
1503 static gboolean
1504 order_first_probe_unneeded(pe_action_t * probe, pe_action_t * rh_action)
1505 {
1506
1507
1508
1509
1510
1511 if (pcmk__str_eq(rh_action->task, CRM_OP_FENCE, pcmk__str_casei)
1512 && probe->node && rh_action->node
1513 && probe->node->details == rh_action->node->details) {
1514 const char *op = g_hash_table_lookup(rh_action->meta, "stonith_action");
1515
1516 if (pcmk__str_eq(op, "on", pcmk__str_casei)) {
1517 return TRUE;
1518 }
1519 }
1520
1521
1522 if ((pcmk__str_eq(rh_action->task, CRM_OP_SHUTDOWN, pcmk__str_casei))
1523 && probe->node && rh_action->node
1524 && probe->node->details != rh_action->node->details) {
1525 return TRUE;
1526 }
1527 return FALSE;
1528 }
1529
1530 static void
1531 order_first_probes_imply_stops(pe_working_set_t * data_set)
1532 {
1533 GList *gIter = NULL;
1534
1535 for (gIter = data_set->ordering_constraints; gIter != NULL; gIter = gIter->next) {
1536 pe__ordering_t *order = gIter->data;
1537 enum pe_ordering order_type = pe_order_optional;
1538
1539 pe_resource_t *lh_rsc = order->lh_rsc;
1540 pe_resource_t *rh_rsc = order->rh_rsc;
1541 pe_action_t *lh_action = order->lh_action;
1542 pe_action_t *rh_action = order->rh_action;
1543 const char *lh_action_task = order->lh_action_task;
1544 const char *rh_action_task = order->rh_action_task;
1545
1546 GList *probes = NULL;
1547 GList *rh_actions = NULL;
1548
1549 GList *pIter = NULL;
1550
1551 if (lh_rsc == NULL) {
1552 continue;
1553
1554 } else if (rh_rsc && lh_rsc == rh_rsc) {
1555 continue;
1556 }
1557
1558 if (lh_action == NULL && lh_action_task == NULL) {
1559 continue;
1560 }
1561
1562 if (rh_action == NULL && rh_action_task == NULL) {
1563 continue;
1564 }
1565
1566
1567
1568
1569
1570 if (lh_action && !pcmk__str_eq(lh_action->task, RSC_STOP, pcmk__str_casei)) {
1571 continue;
1572
1573 } else if (lh_action == NULL
1574 && lh_action_task
1575 && !pcmk__ends_with(lh_action_task, "_" RSC_STOP "_0")) {
1576 continue;
1577 }
1578
1579
1580
1581
1582
1583 if (rh_rsc && lh_rsc->container == rh_rsc) {
1584 if (rh_action && pcmk__str_eq(rh_action->task, RSC_STOP, pcmk__str_casei)) {
1585 continue;
1586
1587 } else if (rh_action == NULL && rh_action_task
1588 && pcmk__ends_with(rh_action_task,"_" RSC_STOP "_0")) {
1589 continue;
1590 }
1591 }
1592
1593 if (order->type == pe_order_none) {
1594 continue;
1595 }
1596
1597
1598 if (pcmk_is_set(order->type, pe_order_apply_first_non_migratable)) {
1599 pe__set_order_flags(order_type,
1600 pe_order_apply_first_non_migratable);
1601 }
1602
1603 if (pcmk_is_set(order->type, pe_order_same_node)) {
1604 pe__set_order_flags(order_type, pe_order_same_node);
1605 }
1606
1607
1608 if (order->type == pe_order_anti_colocation
1609 || order->type == pe_order_load) {
1610 order_type = order->type;
1611 }
1612
1613 probes = pe__resource_actions(lh_rsc, NULL, RSC_STATUS, FALSE);
1614 if (probes == NULL) {
1615 continue;
1616 }
1617
1618 if (rh_action) {
1619 rh_actions = g_list_prepend(rh_actions, rh_action);
1620
1621 } else if (rh_rsc && rh_action_task) {
1622 rh_actions = find_actions(rh_rsc->actions, rh_action_task, NULL);
1623 }
1624
1625 if (rh_actions == NULL) {
1626 g_list_free(probes);
1627 continue;
1628 }
1629
1630 crm_trace("Processing for LH probe based on ordering constraint %s -> %s"
1631 " (id=%d, type=%.6x)",
1632 lh_action ? lh_action->uuid : lh_action_task,
1633 rh_action ? rh_action->uuid : rh_action_task,
1634 order->id, order->type);
1635
1636 for (pIter = probes; pIter != NULL; pIter = pIter->next) {
1637 pe_action_t *probe = (pe_action_t *) pIter->data;
1638 GList *rIter = NULL;
1639
1640 for (rIter = rh_actions; rIter != NULL; rIter = rIter->next) {
1641 pe_action_t *rh_action_iter = (pe_action_t *) rIter->data;
1642
1643 if (order_first_probe_unneeded(probe, rh_action_iter)) {
1644 continue;
1645 }
1646 order_actions(probe, rh_action_iter, order_type);
1647 }
1648 }
1649
1650 g_list_free(rh_actions);
1651 g_list_free(probes);
1652 }
1653 }
1654
1655 static void
1656 order_first_probe_then_restart_repromote(pe_action_t * probe,
1657 pe_action_t * after,
1658 pe_working_set_t * data_set)
1659 {
1660 GList *gIter = NULL;
1661 bool interleave = FALSE;
1662 pe_resource_t *compatible_rsc = NULL;
1663
1664 if (probe == NULL
1665 || probe->rsc == NULL
1666 || probe->rsc->variant != pe_native) {
1667 return;
1668 }
1669
1670 if (after == NULL
1671
1672 || pcmk_is_set(after->flags, pe_action_tracking)) {
1673 return;
1674 }
1675
1676 if (!pcmk__str_eq(probe->task, RSC_STATUS, pcmk__str_casei)) {
1677 return;
1678 }
1679
1680 pe__set_action_flags(after, pe_action_tracking);
1681
1682 crm_trace("Processing based on %s %s -> %s %s",
1683 probe->uuid,
1684 probe->node ? probe->node->details->uname: "",
1685 after->uuid,
1686 after->node ? after->node->details->uname : "");
1687
1688 if (after->rsc
1689
1690
1691
1692
1693 && after->rsc->variant == pe_native
1694 && probe->rsc != after->rsc) {
1695
1696 GList *then_actions = NULL;
1697 enum pe_ordering probe_order_type = pe_order_optional;
1698
1699 if (pcmk__str_eq(after->task, RSC_START, pcmk__str_casei)) {
1700 then_actions = pe__resource_actions(after->rsc, NULL, RSC_STOP, FALSE);
1701
1702 } else if (pcmk__str_eq(after->task, RSC_PROMOTE, pcmk__str_casei)) {
1703 then_actions = pe__resource_actions(after->rsc, NULL, RSC_DEMOTE, FALSE);
1704 }
1705
1706 for (gIter = then_actions; gIter != NULL; gIter = gIter->next) {
1707 pe_action_t *then = (pe_action_t *) gIter->data;
1708
1709
1710 if (pcmk_is_set(then->flags, pe_action_pseudo)) {
1711 continue;
1712 }
1713
1714 order_actions(probe, then, probe_order_type);
1715 }
1716 g_list_free(then_actions);
1717 }
1718
1719 if (after->rsc
1720 && after->rsc->variant > pe_group) {
1721 const char *interleave_s = g_hash_table_lookup(after->rsc->meta,
1722 XML_RSC_ATTR_INTERLEAVE);
1723
1724 interleave = crm_is_true(interleave_s);
1725
1726 if (interleave) {
1727
1728
1729
1730 compatible_rsc = find_compatible_child(probe->rsc,
1731 after->rsc,
1732 RSC_ROLE_UNKNOWN,
1733 FALSE, data_set);
1734 }
1735 }
1736
1737 for (gIter = after->actions_after; gIter != NULL; gIter = gIter->next) {
1738 pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) gIter->data;
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748 if (!pcmk_is_set(after_wrapper->type, pe_order_implies_then)) {
1749
1750
1751
1752
1753
1754
1755
1756 if (after->rsc == NULL
1757 || after->rsc->variant < pe_group
1758 || probe->rsc->parent == after->rsc
1759 || after_wrapper->action->rsc == NULL
1760 || after_wrapper->action->rsc->variant > pe_group
1761 || after->rsc != after_wrapper->action->rsc->parent) {
1762 continue;
1763 }
1764
1765
1766
1767
1768 if (after->rsc->variant > pe_group
1769 && interleave == TRUE
1770 && (compatible_rsc == NULL
1771 || compatible_rsc != after_wrapper->action->rsc)) {
1772 continue;
1773 }
1774 }
1775
1776 crm_trace("Proceeding through %s %s -> %s %s (type=0x%.6x)",
1777 after->uuid,
1778 after->node ? after->node->details->uname: "",
1779 after_wrapper->action->uuid,
1780 after_wrapper->action->node ? after_wrapper->action->node->details->uname : "",
1781 after_wrapper->type);
1782
1783 order_first_probe_then_restart_repromote(probe, after_wrapper->action, data_set);
1784 }
1785 }
1786
1787 static void clear_actions_tracking_flag(pe_working_set_t * data_set)
1788 {
1789 GList *gIter = NULL;
1790
1791 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
1792 pe_action_t *action = (pe_action_t *) gIter->data;
1793
1794 if (pcmk_is_set(action->flags, pe_action_tracking)) {
1795 pe__clear_action_flags(action, pe_action_tracking);
1796 }
1797 }
1798 }
1799
1800 static void
1801 order_first_rsc_probes(pe_resource_t * rsc, pe_working_set_t * data_set)
1802 {
1803 GList *gIter = NULL;
1804 GList *probes = NULL;
1805
1806 g_list_foreach(rsc->children, (GFunc) order_first_rsc_probes, data_set);
1807
1808 if (rsc->variant != pe_native) {
1809 return;
1810 }
1811
1812 probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
1813
1814 for (gIter = probes; gIter != NULL; gIter= gIter->next) {
1815 pe_action_t *probe = (pe_action_t *) gIter->data;
1816 GList *aIter = NULL;
1817
1818 for (aIter = probe->actions_after; aIter != NULL; aIter = aIter->next) {
1819 pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) aIter->data;
1820
1821 order_first_probe_then_restart_repromote(probe, after_wrapper->action, data_set);
1822 clear_actions_tracking_flag(data_set);
1823 }
1824 }
1825
1826 g_list_free(probes);
1827 }
1828
1829 static void
1830 order_first_probes(pe_working_set_t * data_set)
1831 {
1832 GList *gIter = NULL;
1833
1834 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1835 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1836
1837 order_first_rsc_probes(rsc, data_set);
1838 }
1839
1840 order_first_probes_imply_stops(data_set);
1841 }
1842
1843 static void
1844 order_then_probes(pe_working_set_t * data_set)
1845 {
1846 #if 0
1847 GList *gIter = NULL;
1848
1849 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1850 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894 pe_action_t *start = NULL;
1895 GList *actions = NULL;
1896 GList *probes = NULL;
1897
1898 actions = pe__resource_actions(rsc, NULL, RSC_START, FALSE);
1899
1900 if (actions) {
1901 start = actions->data;
1902 g_list_free(actions);
1903 }
1904
1905 if(start == NULL) {
1906 crm_err("No start action for %s", rsc->id);
1907 continue;
1908 }
1909
1910 probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
1911
1912 for (actions = start->actions_before; actions != NULL; actions = actions->next) {
1913 pe_action_wrapper_t *before = (pe_action_wrapper_t *) actions->data;
1914
1915 GList *pIter = NULL;
1916 pe_action_t *first = before->action;
1917 pe_resource_t *first_rsc = first->rsc;
1918
1919 if(first->required_runnable_before) {
1920 GList *clone_actions = NULL;
1921 for (clone_actions = first->actions_before; clone_actions != NULL; clone_actions = clone_actions->next) {
1922 before = (pe_action_wrapper_t *) clone_actions->data;
1923
1924 crm_trace("Testing %s -> %s (%p) for %s", first->uuid, before->action->uuid, before->action->rsc, start->uuid);
1925
1926 CRM_ASSERT(before->action->rsc);
1927 first_rsc = before->action->rsc;
1928 break;
1929 }
1930
1931 } else if(!pcmk__str_eq(first->task, RSC_START, pcmk__str_casei)) {
1932 crm_trace("Not a start op %s for %s", first->uuid, start->uuid);
1933 }
1934
1935 if(first_rsc == NULL) {
1936 continue;
1937
1938 } else if(uber_parent(first_rsc) == uber_parent(start->rsc)) {
1939 crm_trace("Same parent %s for %s", first_rsc->id, start->uuid);
1940 continue;
1941
1942 } else if(FALSE && pe_rsc_is_clone(uber_parent(first_rsc)) == FALSE) {
1943 crm_trace("Not a clone %s for %s", first_rsc->id, start->uuid);
1944 continue;
1945 }
1946
1947 crm_err("Applying %s before %s %d", first->uuid, start->uuid, uber_parent(first_rsc)->variant);
1948
1949 for (pIter = probes; pIter != NULL; pIter = pIter->next) {
1950 pe_action_t *probe = (pe_action_t *) pIter->data;
1951
1952 crm_err("Ordering %s before %s", first->uuid, probe->uuid);
1953 order_actions(first, probe, pe_order_optional);
1954 }
1955 }
1956 }
1957 #endif
1958 }
1959
1960 void
1961 pcmk__order_probes(pe_working_set_t *data_set)
1962 {
1963 order_first_probes(data_set);
1964 order_then_probes(data_set);
1965 }
1966
1967 static int transition_id = -1;
1968
1969
1970
1971
1972
1973
1974
1975 void
1976 pcmk__log_transition_summary(const char *filename)
1977 {
1978 if (was_processing_error) {
1979 crm_err("Calculated transition %d (with errors)%s%s",
1980 transition_id,
1981 (filename == NULL)? "" : ", saving inputs in ",
1982 (filename == NULL)? "" : filename);
1983
1984 } else if (was_processing_warning) {
1985 crm_warn("Calculated transition %d (with warnings)%s%s",
1986 transition_id,
1987 (filename == NULL)? "" : ", saving inputs in ",
1988 (filename == NULL)? "" : filename);
1989
1990 } else {
1991 crm_notice("Calculated transition %d%s%s",
1992 transition_id,
1993 (filename == NULL)? "" : ", saving inputs in ",
1994 (filename == NULL)? "" : filename);
1995 }
1996 if (crm_config_error) {
1997 crm_notice("Configuration errors found during scheduler processing,"
1998 " please run \"crm_verify -L\" to identify issues");
1999 }
2000 }
2001
2002
2003
2004
2005 gboolean
2006 stage8(pe_working_set_t * data_set)
2007 {
2008 GList *gIter = NULL;
2009 const char *value = NULL;
2010 long long limit = 0LL;
2011
2012 transition_id++;
2013 crm_trace("Creating transition graph %d.", transition_id);
2014
2015 data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH);
2016
2017 value = pe_pref(data_set->config_hash, "cluster-delay");
2018 crm_xml_add(data_set->graph, "cluster-delay", value);
2019
2020 value = pe_pref(data_set->config_hash, "stonith-timeout");
2021 crm_xml_add(data_set->graph, "stonith-timeout", value);
2022
2023 crm_xml_add(data_set->graph, "failed-stop-offset", "INFINITY");
2024
2025 if (pcmk_is_set(data_set->flags, pe_flag_start_failure_fatal)) {
2026 crm_xml_add(data_set->graph, "failed-start-offset", "INFINITY");
2027 } else {
2028 crm_xml_add(data_set->graph, "failed-start-offset", "1");
2029 }
2030
2031 value = pe_pref(data_set->config_hash, "batch-limit");
2032 crm_xml_add(data_set->graph, "batch-limit", value);
2033
2034 crm_xml_add_int(data_set->graph, "transition_id", transition_id);
2035
2036 value = pe_pref(data_set->config_hash, "migration-limit");
2037 if ((pcmk__scan_ll(value, &limit, 0LL) == pcmk_rc_ok) && (limit > 0)) {
2038 crm_xml_add(data_set->graph, "migration-limit", value);
2039 }
2040
2041 if (data_set->recheck_by > 0) {
2042 char *recheck_epoch = NULL;
2043
2044 recheck_epoch = crm_strdup_printf("%llu",
2045 (long long) data_set->recheck_by);
2046 crm_xml_add(data_set->graph, "recheck-by", recheck_epoch);
2047 free(recheck_epoch);
2048 }
2049
2050
2051
2052
2053
2054
2055 gIter = data_set->resources;
2056 for (; gIter != NULL; gIter = gIter->next) {
2057 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2058
2059 pe_rsc_trace(rsc, "processing actions for rsc=%s", rsc->id);
2060 rsc->cmds->expand(rsc, data_set);
2061 }
2062
2063 crm_log_xml_trace(data_set->graph, "created resource-driven action list");
2064
2065
2066 add_maintenance_update(data_set);
2067
2068
2069 crm_trace("processing non-resource actions");
2070
2071 gIter = data_set->actions;
2072 for (; gIter != NULL; gIter = gIter->next) {
2073 pe_action_t *action = (pe_action_t *) gIter->data;
2074
2075 if (action->rsc
2076 && action->node
2077 && action->node->details->shutdown
2078 && !pcmk_is_set(action->rsc->flags, pe_rsc_maintenance)
2079 && !pcmk_any_flags_set(action->flags,
2080 pe_action_optional|pe_action_runnable)
2081 && pcmk__str_eq(action->task, RSC_STOP, pcmk__str_none)
2082 ) {
2083
2084
2085
2086
2087 if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)
2088 || data_set->no_quorum_policy == no_quorum_ignore) {
2089 crm_crit("Cannot %s node '%s' because of %s:%s%s (%s)",
2090 action->node->details->unclean ? "fence" : "shut down",
2091 action->node->details->uname, action->rsc->id,
2092 pcmk_is_set(action->rsc->flags, pe_rsc_managed)? " blocked" : " unmanaged",
2093 pcmk_is_set(action->rsc->flags, pe_rsc_failed)? " failed" : "",
2094 action->uuid);
2095 }
2096 }
2097
2098 graph_element_from_action(action, data_set);
2099 }
2100
2101 crm_log_xml_trace(data_set->graph, "created generic action list");
2102 crm_trace("Created transition graph %d.", transition_id);
2103
2104 return TRUE;
2105 }
2106
2107 void
2108 LogNodeActions(pe_working_set_t * data_set)
2109 {
2110 pcmk__output_t *out = data_set->priv;
2111 GList *gIter = NULL;
2112
2113 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2114 char *node_name = NULL;
2115 char *task = NULL;
2116 pe_action_t *action = (pe_action_t *) gIter->data;
2117
2118 if (action->rsc != NULL) {
2119 continue;
2120 } else if (pcmk_is_set(action->flags, pe_action_optional)) {
2121 continue;
2122 }
2123
2124 if (pe__is_guest_node(action->node)) {
2125 node_name = crm_strdup_printf("%s (resource: %s)", action->node->details->uname, action->node->details->remote_rsc->container->id);
2126 } else if(action->node) {
2127 node_name = crm_strdup_printf("%s", action->node->details->uname);
2128 }
2129
2130
2131 if (pcmk__str_eq(action->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
2132 task = strdup("Shutdown");
2133 } else if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei)) {
2134 const char *op = g_hash_table_lookup(action->meta, "stonith_action");
2135 task = crm_strdup_printf("Fence (%s)", op);
2136 }
2137
2138 out->message(out, "node-action", task, node_name, action->reason);
2139
2140 free(node_name);
2141 free(task);
2142 }
2143 }