This source file includes following definitions.
- state2text
- update_action_flags
- check_rsc_parameters
- CancelXmlOp
- check_action_definition
- check_params
- check_actions_for
- find_rsc_list
- check_actions
- apply_placement_constraints
- failcount_clear_action_exists
- check_migration_threshold
- 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
- stage3
- stage4
- convert_const_pointer
- sort_rsc_process_order
- allocate_resources
- order_start_then_action
- order_action_then_stop
- cleanup_orphans
- stage5
- is_managed
- any_managed_resources
- fence_guest
- stage6
- find_actions_by_task
- rsc_order_then
- rsc_order_first
- is_recurring_action
- apply_container_ordering
- get_remote_node_state
- apply_remote_ordering
- apply_remote_node_ordering
- 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
- order_probes
- stage7
- 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
25 CRM_TRACE_INIT_DATA(pacemaker);
26
27 extern bool pcmk__is_daemon;
28
29 void set_alloc_actions(pe_working_set_t * data_set);
30 extern void ReloadRsc(pe_resource_t * rsc, pe_node_t *node, pe_working_set_t * data_set);
31 extern gboolean DeleteRsc(pe_resource_t * rsc, pe_node_t * node, gboolean optional, pe_working_set_t * data_set);
32 static void apply_remote_node_ordering(pe_working_set_t *data_set);
33 static enum remote_connection_state get_remote_node_state(pe_node_t *node);
34
35 enum remote_connection_state {
36 remote_state_unknown = 0,
37 remote_state_alive = 1,
38 remote_state_resting = 2,
39 remote_state_failed = 3,
40 remote_state_stopped = 4
41 };
42
43 static const char *
44 state2text(enum remote_connection_state state)
45 {
46 switch (state) {
47 case remote_state_unknown:
48 return "unknown";
49 case remote_state_alive:
50 return "alive";
51 case remote_state_resting:
52 return "resting";
53 case remote_state_failed:
54 return "failed";
55 case remote_state_stopped:
56 return "stopped";
57 }
58
59 return "impossible";
60 }
61
62 resource_alloc_functions_t resource_class_alloc_functions[] = {
63 {
64 pcmk__native_merge_weights,
65 pcmk__native_allocate,
66 native_create_actions,
67 native_create_probe,
68 native_internal_constraints,
69 native_rsc_colocation_lh,
70 native_rsc_colocation_rh,
71 native_rsc_location,
72 native_action_flags,
73 native_update_actions,
74 native_expand,
75 native_append_meta,
76 },
77 {
78 pcmk__group_merge_weights,
79 pcmk__group_allocate,
80 group_create_actions,
81 native_create_probe,
82 group_internal_constraints,
83 group_rsc_colocation_lh,
84 group_rsc_colocation_rh,
85 group_rsc_location,
86 group_action_flags,
87 group_update_actions,
88 group_expand,
89 group_append_meta,
90 },
91 {
92 pcmk__native_merge_weights,
93 pcmk__clone_allocate,
94 clone_create_actions,
95 clone_create_probe,
96 clone_internal_constraints,
97 clone_rsc_colocation_lh,
98 clone_rsc_colocation_rh,
99 clone_rsc_location,
100 clone_action_flags,
101 pcmk__multi_update_actions,
102 clone_expand,
103 clone_append_meta,
104 },
105 {
106 pcmk__native_merge_weights,
107 pcmk__bundle_allocate,
108 pcmk__bundle_create_actions,
109 pcmk__bundle_create_probe,
110 pcmk__bundle_internal_constraints,
111 pcmk__bundle_rsc_colocation_lh,
112 pcmk__bundle_rsc_colocation_rh,
113 pcmk__bundle_rsc_location,
114 pcmk__bundle_action_flags,
115 pcmk__multi_update_actions,
116 pcmk__bundle_expand,
117 pcmk__bundle_append_meta,
118 }
119 };
120
121 gboolean
122 update_action_flags(pe_action_t * action, enum pe_action_flags flags, const char *source, int line)
123 {
124 static unsigned long calls = 0;
125 gboolean changed = FALSE;
126 gboolean clear = pcmk_is_set(flags, pe_action_clear);
127 enum pe_action_flags last = action->flags;
128
129 if (clear) {
130 pe__clear_action_flags_as(source, line, action, flags);
131 } else {
132 pe__set_action_flags_as(source, line, action, flags);
133 }
134
135 if (last != action->flags) {
136 calls++;
137 changed = TRUE;
138
139
140 pe__clear_raw_action_flags(flags, "action update", pe_action_clear);
141 crm_trace("%s on %s: %sset flags 0x%.6x (was 0x%.6x, now 0x%.6x, %lu, %s)",
142 action->uuid, action->node ? action->node->details->uname : "[none]",
143 clear ? "un-" : "", flags, last, action->flags, calls, source);
144 }
145
146 return changed;
147 }
148
149 static gboolean
150 check_rsc_parameters(pe_resource_t * rsc, pe_node_t * node, xmlNode * rsc_entry,
151 gboolean active_here, pe_working_set_t * data_set)
152 {
153 int attr_lpc = 0;
154 gboolean force_restart = FALSE;
155 gboolean delete_resource = FALSE;
156 gboolean changed = FALSE;
157
158 const char *value = NULL;
159 const char *old_value = NULL;
160
161 const char *attr_list[] = {
162 XML_ATTR_TYPE,
163 XML_AGENT_ATTR_CLASS,
164 XML_AGENT_ATTR_PROVIDER
165 };
166
167 for (; attr_lpc < PCMK__NELEM(attr_list); attr_lpc++) {
168 value = crm_element_value(rsc->xml, attr_list[attr_lpc]);
169 old_value = crm_element_value(rsc_entry, attr_list[attr_lpc]);
170 if (value == old_value
171 || pcmk__str_eq(value, old_value, pcmk__str_none)) {
172 continue;
173 }
174
175 changed = TRUE;
176 trigger_unfencing(rsc, node, "Device definition changed", NULL, data_set);
177 if (active_here) {
178 force_restart = TRUE;
179 crm_notice("Forcing restart of %s on %s, %s changed: %s -> %s",
180 rsc->id, node->details->uname, attr_list[attr_lpc],
181 crm_str(old_value), crm_str(value));
182 }
183 }
184 if (force_restart) {
185
186 stop_action(rsc, node, FALSE);
187 pe__set_resource_flags(rsc, pe_rsc_start_pending);
188 delete_resource = TRUE;
189
190 } else if (changed) {
191 delete_resource = TRUE;
192 }
193 return delete_resource;
194 }
195
196 static void
197 CancelXmlOp(pe_resource_t * rsc, xmlNode * xml_op, pe_node_t * active_node,
198 const char *reason, pe_working_set_t * data_set)
199 {
200 guint interval_ms = 0;
201 pe_action_t *cancel = NULL;
202
203 const char *task = NULL;
204 const char *call_id = NULL;
205
206 CRM_CHECK(xml_op != NULL, return);
207 CRM_CHECK(active_node != NULL, return);
208
209 task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
210 call_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
211 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
212
213 crm_info("Action " PCMK__OP_FMT " on %s will be stopped: %s",
214 rsc->id, task, interval_ms,
215 active_node->details->uname, (reason? reason : "unknown"));
216
217 cancel = pe_cancel_op(rsc, task, interval_ms, active_node, data_set);
218 add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id);
219 custom_action_order(rsc, stop_key(rsc), NULL, rsc, NULL, cancel, pe_order_optional, data_set);
220 }
221
222 static gboolean
223 check_action_definition(pe_resource_t * rsc, pe_node_t * active_node, xmlNode * xml_op,
224 pe_working_set_t * data_set)
225 {
226 char *key = NULL;
227 guint interval_ms = 0;
228 const op_digest_cache_t *digest_data = NULL;
229 gboolean did_change = FALSE;
230
231 const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
232 const char *digest_secure = NULL;
233
234 CRM_CHECK(active_node != NULL, return FALSE);
235
236 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
237 if (interval_ms > 0) {
238 xmlNode *op_match = NULL;
239
240
241 key = pcmk__op_key(rsc->id, task, interval_ms);
242
243 pe_rsc_trace(rsc, "Checking parameters for %s", key);
244 op_match = find_rsc_op_entry(rsc, key);
245
246 if ((op_match == NULL)
247 && pcmk_is_set(data_set->flags, pe_flag_stop_action_orphans)) {
248 CancelXmlOp(rsc, xml_op, active_node, "orphan", data_set);
249 free(key);
250 return TRUE;
251
252 } else if (op_match == NULL) {
253 pe_rsc_debug(rsc, "Orphan action detected: %s on %s", key, active_node->details->uname);
254 free(key);
255 return TRUE;
256 }
257 free(key);
258 key = NULL;
259 }
260
261 crm_trace("Testing " PCMK__OP_FMT " on %s",
262 rsc->id, task, interval_ms, active_node->details->uname);
263 if ((interval_ms == 0) && pcmk__str_eq(task, RSC_STATUS, pcmk__str_casei)) {
264
265 task = RSC_START;
266
267 } else if ((interval_ms == 0) && pcmk__str_eq(task, RSC_MIGRATED, pcmk__str_casei)) {
268
269 task = RSC_START;
270 } else if ((interval_ms == 0) && pcmk__str_eq(task, RSC_PROMOTE, pcmk__str_casei)) {
271
272 task = RSC_START;
273 }
274
275 digest_data = rsc_action_digest_cmp(rsc, xml_op, active_node, data_set);
276
277 if (pcmk_is_set(data_set->flags, pe_flag_sanitized)) {
278 digest_secure = crm_element_value(xml_op, XML_LRM_ATTR_SECURE_DIGEST);
279 }
280
281 if(digest_data->rc != RSC_DIGEST_MATCH
282 && digest_secure
283 && digest_data->digest_secure_calc
284 && strcmp(digest_data->digest_secure_calc, digest_secure) == 0) {
285 if (!pcmk__is_daemon && data_set->priv != NULL) {
286 pcmk__output_t *out = data_set->priv;
287 out->info(out, "Only 'private' parameters to "
288 PCMK__OP_FMT " on %s changed: %s", rsc->id, task,
289 interval_ms, active_node->details->uname,
290 crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
291 }
292
293 } else if (digest_data->rc == RSC_DIGEST_RESTART) {
294
295 pe_action_t *required = NULL;
296
297 did_change = TRUE;
298 key = pcmk__op_key(rsc->id, task, interval_ms);
299 crm_log_xml_info(digest_data->params_restart, "params:restart");
300 required = custom_action(rsc, key, task, NULL, TRUE, TRUE, data_set);
301 pe_action_set_flag_reason(__func__, __LINE__, required, NULL,
302 "resource definition change", pe_action_optional, TRUE);
303
304 trigger_unfencing(rsc, active_node, "Device parameters changed", NULL, data_set);
305
306 } else if ((digest_data->rc == RSC_DIGEST_ALL) || (digest_data->rc == RSC_DIGEST_UNKNOWN)) {
307
308 const char *digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
309
310 did_change = TRUE;
311 trigger_unfencing(rsc, active_node, "Device parameters changed (reload)", NULL, data_set);
312 crm_log_xml_info(digest_data->params_all, "params:reload");
313 key = pcmk__op_key(rsc->id, task, interval_ms);
314
315 if (interval_ms > 0) {
316 pe_action_t *op = NULL;
317
318 #if 0
319
320 ReloadRsc(rsc, active_node, data_set);
321 #else
322
323 op = custom_action(rsc, key, task, active_node, TRUE, TRUE, data_set);
324 pe__set_action_flags(op, pe_action_reschedule);
325 #endif
326
327 } else if (digest_restart) {
328 pe_rsc_trace(rsc, "Reloading '%s' action for resource %s", task, rsc->id);
329
330
331 ReloadRsc(rsc, active_node, data_set);
332 free(key);
333
334 } else {
335 pe_action_t *required = NULL;
336 pe_rsc_trace(rsc, "Resource %s doesn't support agent reloads",
337 rsc->id);
338
339
340
341
342 required = custom_action(rsc, key, task, NULL, TRUE, TRUE, data_set);
343 pe_action_set_flag_reason(__func__, __LINE__, required, NULL,
344 "resource definition change", pe_action_optional, TRUE);
345 }
346 }
347
348 return did_change;
349 }
350
351
352
353
354
355
356
357 static void
358 check_params(pe_resource_t *rsc, pe_node_t *node, xmlNode *rsc_op,
359 enum pe_check_parameters check, pe_working_set_t *data_set)
360 {
361 const char *reason = NULL;
362 op_digest_cache_t *digest_data = NULL;
363
364 switch (check) {
365 case pe_check_active:
366 if (check_action_definition(rsc, node, rsc_op, data_set)
367 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
368 data_set)) {
369
370 reason = "action definition changed";
371 }
372 break;
373
374 case pe_check_last_failure:
375 digest_data = rsc_action_digest_cmp(rsc, rsc_op, node, data_set);
376 switch (digest_data->rc) {
377 case RSC_DIGEST_UNKNOWN:
378 crm_trace("Resource %s history entry %s on %s has no digest to compare",
379 rsc->id, ID(rsc_op), node->details->id);
380 break;
381 case RSC_DIGEST_MATCH:
382 break;
383 default:
384 reason = "resource parameters have changed";
385 break;
386 }
387 break;
388 }
389
390 if (reason) {
391 pe__clear_failcount(rsc, node, reason, data_set);
392 }
393 }
394
395 static void
396 check_actions_for(xmlNode * rsc_entry, pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set)
397 {
398 GList *gIter = NULL;
399 int offset = -1;
400 int stop_index = 0;
401 int start_index = 0;
402
403 const char *task = NULL;
404
405 xmlNode *rsc_op = NULL;
406 GList *op_list = NULL;
407 GList *sorted_op_list = NULL;
408
409 CRM_CHECK(node != NULL, return);
410
411 if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
412 pe_resource_t *parent = uber_parent(rsc);
413 if(parent == NULL
414 || pe_rsc_is_clone(parent) == FALSE
415 || pcmk_is_set(parent->flags, pe_rsc_unique)) {
416 pe_rsc_trace(rsc, "Skipping param check for %s and deleting: orphan", rsc->id);
417 DeleteRsc(rsc, node, FALSE, data_set);
418 } else {
419 pe_rsc_trace(rsc, "Skipping param check for %s (orphan clone)", rsc->id);
420 }
421 return;
422
423 } else if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
424 if (check_rsc_parameters(rsc, node, rsc_entry, FALSE, data_set)) {
425 DeleteRsc(rsc, node, FALSE, data_set);
426 }
427 pe_rsc_trace(rsc, "Skipping param check for %s: no longer active on %s",
428 rsc->id, node->details->uname);
429 return;
430 }
431
432 pe_rsc_trace(rsc, "Processing %s on %s", rsc->id, node->details->uname);
433
434 if (check_rsc_parameters(rsc, node, rsc_entry, TRUE, data_set)) {
435 DeleteRsc(rsc, node, FALSE, data_set);
436 }
437
438 for (rsc_op = pcmk__xe_first_child(rsc_entry); rsc_op != NULL;
439 rsc_op = pcmk__xe_next(rsc_op)) {
440
441 if (pcmk__str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, pcmk__str_none)) {
442 op_list = g_list_prepend(op_list, rsc_op);
443 }
444 }
445
446 sorted_op_list = g_list_sort(op_list, sort_op_by_callid);
447 calculate_active_ops(sorted_op_list, &start_index, &stop_index);
448
449 for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
450 xmlNode *rsc_op = (xmlNode *) gIter->data;
451 guint interval_ms = 0;
452
453 offset++;
454
455 if (start_index < stop_index) {
456
457 continue;
458 } else if (offset < start_index) {
459
460 continue;
461 }
462
463 task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
464 crm_element_value_ms(rsc_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
465
466 if ((interval_ms > 0) &&
467 (pcmk_is_set(rsc->flags, pe_rsc_maintenance) || node->details->maintenance)) {
468
469 CancelXmlOp(rsc, rsc_op, node, "maintenance mode", data_set);
470
471 } else if ((interval_ms > 0) || pcmk__strcase_any_of(task, RSC_STATUS, RSC_START,
472 RSC_PROMOTE, RSC_MIGRATED, NULL)) {
473
474
475
476
477 if (pe__bundle_needs_remote_name(rsc, data_set)) {
478
479
480
481
482
483
484
485 pe__add_param_check(rsc_op, rsc, node, pe_check_active,
486 data_set);
487
488 } else if (check_action_definition(rsc, node, rsc_op, data_set)
489 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
490 data_set)) {
491 pe__clear_failcount(rsc, node, "action definition changed",
492 data_set);
493 }
494 }
495 }
496 g_list_free(sorted_op_list);
497 }
498
499 static GList *
500 find_rsc_list(GList *result, pe_resource_t * rsc, const char *id, gboolean renamed_clones,
501 gboolean partial, pe_working_set_t * data_set)
502 {
503 GList *gIter = NULL;
504 gboolean match = FALSE;
505
506 if (id == NULL) {
507 return NULL;
508 }
509
510 if (rsc == NULL) {
511 if (data_set == NULL) {
512 return NULL;
513 }
514 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
515 pe_resource_t *child = (pe_resource_t *) gIter->data;
516
517 result = find_rsc_list(result, child, id, renamed_clones, partial,
518 NULL);
519 }
520 return result;
521 }
522
523 if (partial) {
524 if (strstr(rsc->id, id)) {
525 match = TRUE;
526
527 } else if (renamed_clones && rsc->clone_name && strstr(rsc->clone_name, id)) {
528 match = TRUE;
529 }
530
531 } else {
532 if (strcmp(rsc->id, id) == 0) {
533 match = TRUE;
534
535 } else if (renamed_clones && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
536 match = TRUE;
537 }
538 }
539
540 if (match) {
541 result = g_list_prepend(result, rsc);
542 }
543
544 if (rsc->children) {
545 gIter = rsc->children;
546 for (; gIter != NULL; gIter = gIter->next) {
547 pe_resource_t *child = (pe_resource_t *) gIter->data;
548
549 result = find_rsc_list(result, child, id, renamed_clones, partial, NULL);
550 }
551 }
552
553 return result;
554 }
555
556 static void
557 check_actions(pe_working_set_t * data_set)
558 {
559 const char *id = NULL;
560 pe_node_t *node = NULL;
561 xmlNode *lrm_rscs = NULL;
562 xmlNode *status = get_object_root(XML_CIB_TAG_STATUS, data_set->input);
563
564 xmlNode *node_state = NULL;
565
566 for (node_state = pcmk__xe_first_child(status); node_state != NULL;
567 node_state = pcmk__xe_next(node_state)) {
568
569 if (pcmk__str_eq((const char *)node_state->name, XML_CIB_TAG_STATE,
570 pcmk__str_none)) {
571 id = crm_element_value(node_state, XML_ATTR_ID);
572 lrm_rscs = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
573 lrm_rscs = find_xml_node(lrm_rscs, XML_LRM_TAG_RESOURCES, FALSE);
574
575 node = pe_find_node_id(data_set->nodes, id);
576
577 if (node == NULL) {
578 continue;
579
580
581 } else if (can_run_resources(node) == FALSE && node->details->maintenance == FALSE) {
582 crm_trace("Skipping param check for %s: can't run resources",
583 node->details->uname);
584 continue;
585 }
586
587 crm_trace("Processing node %s", node->details->uname);
588 if (node->details->online
589 || pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
590 xmlNode *rsc_entry = NULL;
591
592 for (rsc_entry = pcmk__xe_first_child(lrm_rscs);
593 rsc_entry != NULL;
594 rsc_entry = pcmk__xe_next(rsc_entry)) {
595
596 if (pcmk__str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, pcmk__str_none)) {
597
598 if (xml_has_children(rsc_entry)) {
599 GList *gIter = NULL;
600 GList *result = NULL;
601 const char *rsc_id = ID(rsc_entry);
602
603 CRM_CHECK(rsc_id != NULL, return);
604
605 result = find_rsc_list(NULL, NULL, rsc_id, TRUE, FALSE, data_set);
606 for (gIter = result; gIter != NULL; gIter = gIter->next) {
607 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
608
609 if (rsc->variant != pe_native) {
610 continue;
611 }
612 check_actions_for(rsc_entry, rsc, node, data_set);
613 }
614 g_list_free(result);
615 }
616 }
617 }
618 }
619 }
620 }
621 }
622
623 static void
624 apply_placement_constraints(pe_working_set_t * data_set)
625 {
626 for (GList *gIter = data_set->placement_constraints;
627 gIter != NULL; gIter = gIter->next) {
628 pe__location_t *cons = gIter->data;
629
630 cons->rsc_lh->cmds->rsc_location(cons->rsc_lh, cons);
631 }
632 }
633
634 static gboolean
635 failcount_clear_action_exists(pe_node_t * node, pe_resource_t * rsc)
636 {
637 gboolean rc = FALSE;
638 GList *list = pe__resource_actions(rsc, node, CRM_OP_CLEAR_FAILCOUNT, TRUE);
639
640 if (list) {
641 rc = TRUE;
642 }
643 g_list_free(list);
644 return rc;
645 }
646
647
648
649
650
651
652
653
654
655 static void
656 check_migration_threshold(pe_resource_t *rsc, pe_node_t *node,
657 pe_working_set_t *data_set)
658 {
659 int fail_count, countdown;
660 pe_resource_t *failed;
661
662
663 if (rsc->migration_threshold == 0) {
664 return;
665 }
666
667
668 if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
669 return;
670 }
671
672
673 fail_count = pe_get_failcount(node, rsc, NULL,
674 pe_fc_effective|pe_fc_fillers, NULL,
675 data_set);
676 if (fail_count <= 0) {
677 return;
678 }
679
680
681 countdown = QB_MAX(rsc->migration_threshold - fail_count, 0);
682
683
684 failed = rsc;
685 if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
686 failed = uber_parent(rsc);
687 }
688
689 if (countdown == 0) {
690 resource_location(failed, node, -INFINITY, "__fail_limit__", data_set);
691 crm_warn("Forcing %s away from %s after %d failures (max=%d)",
692 failed->id, node->details->uname, fail_count,
693 rsc->migration_threshold);
694 } else {
695 crm_info("%s can fail %d more times on %s before being forced off",
696 failed->id, countdown, node->details->uname);
697 }
698 }
699
700 static void
701 common_apply_stickiness(pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set)
702 {
703 if (rsc->children) {
704 GList *gIter = rsc->children;
705
706 for (; gIter != NULL; gIter = gIter->next) {
707 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
708
709 common_apply_stickiness(child_rsc, node, data_set);
710 }
711 return;
712 }
713
714 if (pcmk_is_set(rsc->flags, pe_rsc_managed)
715 && rsc->stickiness != 0 && pcmk__list_of_1(rsc->running_on)) {
716 pe_node_t *current = pe_find_node_id(rsc->running_on, node->details->id);
717 pe_node_t *match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
718
719 if (current == NULL) {
720
721 } else if ((match != NULL)
722 || pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster)) {
723 pe_resource_t *sticky_rsc = rsc;
724
725 resource_location(sticky_rsc, node, rsc->stickiness, "stickiness", data_set);
726 pe_rsc_debug(sticky_rsc, "Resource %s: preferring current location"
727 " (node=%s, weight=%d)", sticky_rsc->id,
728 node->details->uname, rsc->stickiness);
729 } else {
730 GHashTableIter iter;
731 pe_node_t *nIter = NULL;
732
733 pe_rsc_debug(rsc, "Ignoring stickiness for %s: the cluster is asymmetric"
734 " and node %s is not explicitly allowed", rsc->id, node->details->uname);
735 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
736 while (g_hash_table_iter_next(&iter, NULL, (void **)&nIter)) {
737 crm_err("%s[%s] = %d", rsc->id, nIter->details->uname, nIter->weight);
738 }
739 }
740 }
741
742
743
744
745
746
747
748
749
750
751
752
753 if (failcount_clear_action_exists(node, rsc) == FALSE) {
754 check_migration_threshold(rsc, node, data_set);
755 }
756 }
757
758 void
759 complex_set_cmds(pe_resource_t * rsc)
760 {
761 GList *gIter = rsc->children;
762
763 rsc->cmds = &resource_class_alloc_functions[rsc->variant];
764
765 for (; gIter != NULL; gIter = gIter->next) {
766 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
767
768 complex_set_cmds(child_rsc);
769 }
770 }
771
772 void
773 set_alloc_actions(pe_working_set_t * data_set)
774 {
775
776 GList *gIter = data_set->resources;
777
778 for (; gIter != NULL; gIter = gIter->next) {
779 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
780
781 complex_set_cmds(rsc);
782 }
783 }
784
785 static void
786 calculate_system_health(gpointer gKey, gpointer gValue, gpointer user_data)
787 {
788 const char *key = (const char *)gKey;
789 const char *value = (const char *)gValue;
790 int *system_health = (int *)user_data;
791
792 if (!gKey || !gValue || !user_data) {
793 return;
794 }
795
796 if (pcmk__starts_with(key, "#health")) {
797 int score;
798
799
800 score = char2score(value);
801
802
803 *system_health = pe__add_scores(score, *system_health);
804 }
805 }
806
807 static gboolean
808 apply_system_health(pe_working_set_t * data_set)
809 {
810 GList *gIter = NULL;
811 const char *health_strategy = pe_pref(data_set->config_hash, "node-health-strategy");
812 int base_health = 0;
813
814 if (pcmk__str_eq(health_strategy, "none", pcmk__str_null_matches | pcmk__str_casei)) {
815
816 pcmk__score_red = 0;
817 pcmk__score_yellow = 0;
818 pcmk__score_green = 0;
819 return TRUE;
820
821 } else if (pcmk__str_eq(health_strategy, "migrate-on-red", pcmk__str_casei)) {
822
823
824
825
826 pcmk__score_red = -INFINITY;
827 pcmk__score_yellow = 0;
828 pcmk__score_green = 0;
829
830 } else if (pcmk__str_eq(health_strategy, "only-green", pcmk__str_casei)) {
831
832
833
834
835 pcmk__score_red = -INFINITY;
836 pcmk__score_yellow = -INFINITY;
837 pcmk__score_green = 0;
838
839 } else if (pcmk__str_eq(health_strategy, "progressive", pcmk__str_casei)) {
840
841
842
843
844 base_health = char2score(pe_pref(data_set->config_hash,
845 "node-health-base"));
846
847 } else if (pcmk__str_eq(health_strategy, "custom", pcmk__str_casei)) {
848
849
850
851
852
853 return TRUE;
854
855 } else {
856 crm_err("Unknown node health strategy: %s", health_strategy);
857 return FALSE;
858 }
859
860 crm_info("Applying automated node health strategy: %s", health_strategy);
861
862 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
863 int system_health = base_health;
864 pe_node_t *node = (pe_node_t *) gIter->data;
865
866
867 g_hash_table_foreach(node->details->attrs, calculate_system_health, &system_health);
868
869 crm_info(" Node %s has an combined system health of %d",
870 node->details->uname, system_health);
871
872
873
874
875 if (system_health != 0) {
876
877 GList *gIter2 = data_set->resources;
878
879 for (; gIter2 != NULL; gIter2 = gIter2->next) {
880 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
881
882 rsc2node_new(health_strategy, rsc, system_health, NULL, node, data_set);
883 }
884 }
885 }
886
887 return TRUE;
888 }
889
890 gboolean
891 stage0(pe_working_set_t * data_set)
892 {
893 xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input);
894
895 if (data_set->input == NULL) {
896 return FALSE;
897 }
898
899 if (!pcmk_is_set(data_set->flags, pe_flag_have_status)) {
900 crm_trace("Calculating status");
901 cluster_status(data_set);
902 }
903
904 set_alloc_actions(data_set);
905 apply_system_health(data_set);
906 unpack_constraints(cib_constraints, data_set);
907
908 return TRUE;
909 }
910
911
912
913
914 gboolean
915 probe_resources(pe_working_set_t * data_set)
916 {
917 pe_action_t *probe_node_complete = NULL;
918
919 for (GList *gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
920 pe_node_t *node = (pe_node_t *) gIter->data;
921 const char *probed = pe_node_attribute_raw(node, CRM_OP_PROBED);
922
923 if (node->details->online == FALSE) {
924
925 if (pe__is_remote_node(node) && node->details->remote_rsc
926 && (get_remote_node_state(node) == remote_state_failed)) {
927
928 pe_fence_node(data_set, node, "the connection is unrecoverable", FALSE);
929 }
930 continue;
931
932 } else if (node->details->unclean) {
933 continue;
934
935 } else if (node->details->rsc_discovery_enabled == FALSE) {
936
937 continue;
938 }
939
940 if (probed != NULL && crm_is_true(probed) == FALSE) {
941 pe_action_t *probe_op = custom_action(NULL, crm_strdup_printf("%s-%s", CRM_OP_REPROBE, node->details->uname),
942 CRM_OP_REPROBE, node, FALSE, TRUE, data_set);
943
944 add_hash_param(probe_op->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE);
945 continue;
946 }
947
948 for (GList *gIter2 = data_set->resources; gIter2 != NULL; gIter2 = gIter2->next) {
949 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
950
951 rsc->cmds->create_probe(rsc, node, probe_node_complete, FALSE, data_set);
952 }
953 }
954 return TRUE;
955 }
956
957 static void
958 rsc_discover_filter(pe_resource_t *rsc, pe_node_t *node)
959 {
960 GList *gIter = rsc->children;
961 pe_resource_t *top = uber_parent(rsc);
962 pe_node_t *match;
963
964 if (rsc->exclusive_discover == FALSE && top->exclusive_discover == FALSE) {
965 return;
966 }
967
968 for (; gIter != NULL; gIter = gIter->next) {
969 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
970 rsc_discover_filter(child_rsc, node);
971 }
972
973 match = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
974 if (match && match->rsc_discover_mode != pe_discover_exclusive) {
975 match->weight = -INFINITY;
976 }
977 }
978
979 static time_t
980 shutdown_time(pe_node_t *node, pe_working_set_t *data_set)
981 {
982 const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
983 time_t result = 0;
984
985 if (shutdown) {
986 long long result_ll;
987
988 if (pcmk__scan_ll(shutdown, &result_ll, 0LL) == pcmk_rc_ok) {
989 result = (time_t) result_ll;
990 }
991 }
992 return result? result : get_effective_time(data_set);
993 }
994
995 static void
996 apply_shutdown_lock(pe_resource_t *rsc, pe_working_set_t *data_set)
997 {
998 const char *class;
999
1000
1001 if (rsc->variant == pe_group) {
1002 for (GList *item = rsc->children; item != NULL;
1003 item = item->next) {
1004 apply_shutdown_lock((pe_resource_t *) item->data, data_set);
1005 }
1006 } else if (rsc->variant != pe_native) {
1007 return;
1008 }
1009
1010
1011 class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1012 if (pcmk__str_eq(class, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_null_matches)
1013 || pe__resource_is_remote_conn(rsc, data_set)) {
1014 return;
1015 }
1016
1017 if (rsc->lock_node != NULL) {
1018
1019
1020 if (rsc->running_on != NULL) {
1021
1022
1023
1024
1025 pe_rsc_info(rsc,
1026 "Cancelling shutdown lock because %s is already active",
1027 rsc->id);
1028 pe__clear_resource_history(rsc, rsc->lock_node, data_set);
1029 rsc->lock_node = NULL;
1030 rsc->lock_time = 0;
1031 }
1032
1033
1034 } else if (pcmk__list_of_1(rsc->running_on)) {
1035 pe_node_t *node = rsc->running_on->data;
1036
1037 if (node->details->shutdown) {
1038 if (node->details->unclean) {
1039 pe_rsc_debug(rsc, "Not locking %s to unclean %s for shutdown",
1040 rsc->id, node->details->uname);
1041 } else {
1042 rsc->lock_node = node;
1043 rsc->lock_time = shutdown_time(node, data_set);
1044 }
1045 }
1046 }
1047
1048 if (rsc->lock_node == NULL) {
1049
1050 return;
1051 }
1052
1053 if (data_set->shutdown_lock > 0) {
1054 time_t lock_expiration = rsc->lock_time + data_set->shutdown_lock;
1055
1056 pe_rsc_info(rsc, "Locking %s to %s due to shutdown (expires @%lld)",
1057 rsc->id, rsc->lock_node->details->uname,
1058 (long long) lock_expiration);
1059 pe__update_recheck_time(++lock_expiration, data_set);
1060 } else {
1061 pe_rsc_info(rsc, "Locking %s to %s due to shutdown",
1062 rsc->id, rsc->lock_node->details->uname);
1063 }
1064
1065
1066 for (GList *item = data_set->nodes; item != NULL; item = item->next) {
1067 pe_node_t *node = item->data;
1068
1069 if (strcmp(node->details->uname, rsc->lock_node->details->uname)) {
1070 resource_location(rsc, node, -CRM_SCORE_INFINITY,
1071 XML_CONFIG_ATTR_SHUTDOWN_LOCK, data_set);
1072 }
1073 }
1074 }
1075
1076
1077
1078
1079
1080
1081
1082
1083 gboolean
1084 stage2(pe_working_set_t * data_set)
1085 {
1086 GList *gIter = NULL;
1087
1088 if (pcmk_is_set(data_set->flags, pe_flag_shutdown_lock)) {
1089 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1090 apply_shutdown_lock((pe_resource_t *) gIter->data, data_set);
1091 }
1092 }
1093
1094 if (!pcmk_is_set(data_set->flags, pe_flag_no_compat)) {
1095
1096 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1097 pe_node_t *node = (pe_node_t *) gIter->data;
1098
1099 if (node && (node->weight >= 0) && node->details->online
1100 && (node->details->type != node_ping)) {
1101 data_set->max_valid_nodes++;
1102 }
1103 }
1104 }
1105
1106 apply_placement_constraints(data_set);
1107
1108 gIter = data_set->nodes;
1109 for (; gIter != NULL; gIter = gIter->next) {
1110 GList *gIter2 = NULL;
1111 pe_node_t *node = (pe_node_t *) gIter->data;
1112
1113 gIter2 = data_set->resources;
1114 for (; gIter2 != NULL; gIter2 = gIter2->next) {
1115 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
1116
1117 common_apply_stickiness(rsc, node, data_set);
1118 rsc_discover_filter(rsc, node);
1119 }
1120 }
1121
1122 return TRUE;
1123 }
1124
1125
1126
1127
1128 gboolean
1129 stage3(pe_working_set_t * data_set)
1130 {
1131
1132 GList *gIter = data_set->resources;
1133
1134 for (; gIter != NULL; gIter = gIter->next) {
1135 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1136
1137 rsc->cmds->internal_constraints(rsc, data_set);
1138 }
1139
1140 return TRUE;
1141 }
1142
1143
1144
1145
1146 gboolean
1147 stage4(pe_working_set_t * data_set)
1148 {
1149 check_actions(data_set);
1150 return TRUE;
1151 }
1152
1153 static void *
1154 convert_const_pointer(const void *ptr)
1155 {
1156
1157 return (void *)ptr;
1158 }
1159
1160 static gint
1161 sort_rsc_process_order(gconstpointer a, gconstpointer b, gpointer data)
1162 {
1163 int rc = 0;
1164 int r1_weight = -INFINITY;
1165 int r2_weight = -INFINITY;
1166
1167 const char *reason = "existence";
1168
1169 GList *nodes = (GList *) data;
1170 const pe_resource_t *resource1 = a;
1171 const pe_resource_t *resource2 = b;
1172
1173 pe_node_t *r1_node = NULL;
1174 pe_node_t *r2_node = NULL;
1175 GList *gIter = NULL;
1176 GHashTable *r1_nodes = NULL;
1177 GHashTable *r2_nodes = NULL;
1178
1179 reason = "priority";
1180 r1_weight = resource1->priority;
1181 r2_weight = resource2->priority;
1182
1183 if (r1_weight > r2_weight) {
1184 rc = -1;
1185 goto done;
1186 }
1187
1188 if (r1_weight < r2_weight) {
1189 rc = 1;
1190 goto done;
1191 }
1192
1193 reason = "no node list";
1194 if (nodes == NULL) {
1195 goto done;
1196 }
1197
1198 r1_nodes = pcmk__native_merge_weights(convert_const_pointer(resource1),
1199 resource1->id, NULL, NULL, 1,
1200 pe_weights_forward | pe_weights_init);
1201 pe__show_node_weights(true, NULL, resource1->id, r1_nodes,
1202 resource1->cluster);
1203
1204 r2_nodes = pcmk__native_merge_weights(convert_const_pointer(resource2),
1205 resource2->id, NULL, NULL, 1,
1206 pe_weights_forward | pe_weights_init);
1207 pe__show_node_weights(true, NULL, resource2->id, r2_nodes,
1208 resource2->cluster);
1209
1210
1211 reason = "current location";
1212 r1_weight = -INFINITY;
1213 r2_weight = -INFINITY;
1214
1215 if (resource1->running_on) {
1216 r1_node = pe__current_node(resource1);
1217 r1_node = g_hash_table_lookup(r1_nodes, r1_node->details->id);
1218 if (r1_node != NULL) {
1219 r1_weight = r1_node->weight;
1220 }
1221 }
1222 if (resource2->running_on) {
1223 r2_node = pe__current_node(resource2);
1224 r2_node = g_hash_table_lookup(r2_nodes, r2_node->details->id);
1225 if (r2_node != NULL) {
1226 r2_weight = r2_node->weight;
1227 }
1228 }
1229
1230 if (r1_weight > r2_weight) {
1231 rc = -1;
1232 goto done;
1233 }
1234
1235 if (r1_weight < r2_weight) {
1236 rc = 1;
1237 goto done;
1238 }
1239
1240 reason = "score";
1241 for (gIter = nodes; gIter != NULL; gIter = gIter->next) {
1242 pe_node_t *node = (pe_node_t *) gIter->data;
1243
1244 r1_node = NULL;
1245 r2_node = NULL;
1246
1247 r1_weight = -INFINITY;
1248 if (r1_nodes) {
1249 r1_node = g_hash_table_lookup(r1_nodes, node->details->id);
1250 }
1251 if (r1_node) {
1252 r1_weight = r1_node->weight;
1253 }
1254
1255 r2_weight = -INFINITY;
1256 if (r2_nodes) {
1257 r2_node = g_hash_table_lookup(r2_nodes, node->details->id);
1258 }
1259 if (r2_node) {
1260 r2_weight = r2_node->weight;
1261 }
1262
1263 if (r1_weight > r2_weight) {
1264 rc = -1;
1265 goto done;
1266 }
1267
1268 if (r1_weight < r2_weight) {
1269 rc = 1;
1270 goto done;
1271 }
1272 }
1273
1274 done:
1275 crm_trace("%s (%d) on %s %c %s (%d) on %s: %s",
1276 resource1->id, r1_weight, r1_node ? r1_node->details->id : "n/a",
1277 rc < 0 ? '>' : rc > 0 ? '<' : '=',
1278 resource2->id, r2_weight, r2_node ? r2_node->details->id : "n/a", reason);
1279
1280 if (r1_nodes) {
1281 g_hash_table_destroy(r1_nodes);
1282 }
1283 if (r2_nodes) {
1284 g_hash_table_destroy(r2_nodes);
1285 }
1286
1287 return rc;
1288 }
1289
1290 static void
1291 allocate_resources(pe_working_set_t * data_set)
1292 {
1293 GList *gIter = NULL;
1294
1295 if (pcmk_is_set(data_set->flags, pe_flag_have_remote_nodes)) {
1296
1297
1298
1299
1300 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1301 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1302 if (rsc->is_remote_node == FALSE) {
1303 continue;
1304 }
1305 pe_rsc_trace(rsc, "Allocating remote connection resource '%s'",
1306 rsc->id);
1307 rsc->cmds->allocate(rsc, rsc->partial_migration_target, data_set);
1308 }
1309 }
1310
1311
1312 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1313 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1314 if (rsc->is_remote_node == TRUE) {
1315 continue;
1316 }
1317 pe_rsc_trace(rsc, "Allocating %s resource '%s'",
1318 crm_element_name(rsc->xml), rsc->id);
1319 rsc->cmds->allocate(rsc, NULL, data_set);
1320 }
1321 }
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331 static inline void
1332 order_start_then_action(pe_resource_t *lh_rsc, pe_action_t *rh_action,
1333 enum pe_ordering extra, pe_working_set_t *data_set)
1334 {
1335 if (lh_rsc && rh_action && data_set) {
1336 custom_action_order(lh_rsc, start_key(lh_rsc), NULL,
1337 rh_action->rsc, NULL, rh_action,
1338 pe_order_preserve | pe_order_runnable_left | extra,
1339 data_set);
1340 }
1341 }
1342
1343 static inline void
1344 order_action_then_stop(pe_action_t *lh_action, pe_resource_t *rh_rsc,
1345 enum pe_ordering extra, pe_working_set_t *data_set)
1346 {
1347 if (lh_action && rh_rsc && data_set) {
1348 custom_action_order(lh_action->rsc, NULL, lh_action,
1349 rh_rsc, stop_key(rh_rsc), NULL,
1350 pe_order_preserve | extra, data_set);
1351 }
1352 }
1353
1354
1355 static void
1356 cleanup_orphans(pe_resource_t * rsc, pe_working_set_t * data_set)
1357 {
1358 GList *gIter = NULL;
1359
1360 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1361 pe_node_t *node = (pe_node_t *) gIter->data;
1362
1363 if (node->details->online
1364 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
1365 data_set)) {
1366
1367 pe_action_t *clear_op = NULL;
1368
1369 clear_op = pe__clear_failcount(rsc, node, "it is orphaned",
1370 data_set);
1371
1372
1373
1374
1375 custom_action_order(clear_op->rsc, NULL, clear_op,
1376 rsc, stop_key(rsc), NULL,
1377 pe_order_optional, data_set);
1378 }
1379 }
1380 }
1381
1382 gboolean
1383 stage5(pe_working_set_t * data_set)
1384 {
1385 pcmk__output_t *out = data_set->priv;
1386 GList *gIter = NULL;
1387
1388 if (!pcmk__str_eq(data_set->placement_strategy, "default", pcmk__str_casei)) {
1389 GList *nodes = g_list_copy(data_set->nodes);
1390
1391 nodes = sort_nodes_by_weight(nodes, NULL, data_set);
1392 data_set->resources =
1393 g_list_sort_with_data(data_set->resources, sort_rsc_process_order, nodes);
1394
1395 g_list_free(nodes);
1396 }
1397
1398 gIter = data_set->nodes;
1399 for (; gIter != NULL; gIter = gIter->next) {
1400 pe_node_t *node = (pe_node_t *) gIter->data;
1401
1402 if (pcmk_is_set(data_set->flags, pe_flag_show_utilization)) {
1403 out->message(out, "node-capacity", node, "Original");
1404 }
1405 }
1406
1407 crm_trace("Allocating services");
1408
1409
1410 allocate_resources(data_set);
1411
1412 gIter = data_set->nodes;
1413 for (; gIter != NULL; gIter = gIter->next) {
1414 pe_node_t *node = (pe_node_t *) gIter->data;
1415
1416 if (pcmk_is_set(data_set->flags, pe_flag_show_utilization)) {
1417 out->message(out, "node-capacity", node, "Remaining");
1418 }
1419 }
1420
1421
1422 pe__foreach_param_check(data_set, check_params);
1423 pe__free_param_checks(data_set);
1424
1425 if (pcmk_is_set(data_set->flags, pe_flag_startup_probes)) {
1426 crm_trace("Calculating needed probes");
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461 probe_resources(data_set);
1462 }
1463
1464 crm_trace("Handle orphans");
1465 if (pcmk_is_set(data_set->flags, pe_flag_stop_rsc_orphans)) {
1466 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1467 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1468
1469
1470
1471
1472 if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
1473 cleanup_orphans(rsc, data_set);
1474 }
1475 }
1476 }
1477
1478 crm_trace("Creating actions");
1479
1480 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1481 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1482
1483 rsc->cmds->create_actions(rsc, data_set);
1484 }
1485
1486 crm_trace("Creating done");
1487 return TRUE;
1488 }
1489
1490 static gboolean
1491 is_managed(const pe_resource_t * rsc)
1492 {
1493 GList *gIter = rsc->children;
1494
1495 if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
1496 return TRUE;
1497 }
1498
1499 for (; gIter != NULL; gIter = gIter->next) {
1500 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
1501
1502 if (is_managed(child_rsc)) {
1503 return TRUE;
1504 }
1505 }
1506
1507 return FALSE;
1508 }
1509
1510 static gboolean
1511 any_managed_resources(pe_working_set_t * data_set)
1512 {
1513
1514 GList *gIter = data_set->resources;
1515
1516 for (; gIter != NULL; gIter = gIter->next) {
1517 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1518
1519 if (is_managed(rsc)) {
1520 return TRUE;
1521 }
1522 }
1523 return FALSE;
1524 }
1525
1526
1527
1528
1529
1530
1531
1532
1533 static void
1534 fence_guest(pe_node_t *node, pe_working_set_t *data_set)
1535 {
1536 pe_resource_t *container = node->details->remote_rsc->container;
1537 pe_action_t *stop = NULL;
1538 pe_action_t *stonith_op = NULL;
1539
1540
1541
1542
1543
1544
1545
1546 const char *fence_action = "off";
1547
1548
1549
1550
1551 if (container) {
1552 stop = find_first_action(container->actions, NULL, CRMD_ACTION_STOP, NULL);
1553
1554 if (find_first_action(container->actions, NULL, CRMD_ACTION_START, NULL)) {
1555 fence_action = "reboot";
1556 }
1557 }
1558
1559
1560
1561
1562 stonith_op = pe_fence_op(node, fence_action, FALSE, "guest is unclean", FALSE, data_set);
1563 update_action_flags(stonith_op, pe_action_pseudo | pe_action_runnable,
1564 __func__, __LINE__);
1565
1566
1567
1568
1569
1570 if ((stop != NULL) && pcmk_is_set(stop->flags, pe_action_pseudo)) {
1571 pe_action_t *parent_stonith_op = pe_fence_op(stop->node, NULL, FALSE, NULL, FALSE, data_set);
1572 crm_info("Implying guest node %s is down (action %d) after %s fencing",
1573 node->details->uname, stonith_op->id, stop->node->details->uname);
1574 order_actions(parent_stonith_op, stonith_op,
1575 pe_order_runnable_left|pe_order_implies_then);
1576
1577 } else if (stop) {
1578 order_actions(stop, stonith_op,
1579 pe_order_runnable_left|pe_order_implies_then);
1580 crm_info("Implying guest node %s is down (action %d) "
1581 "after container %s is stopped (action %d)",
1582 node->details->uname, stonith_op->id,
1583 container->id, stop->id);
1584 } else {
1585
1586
1587
1588
1589
1590
1591
1592 stop = find_first_action(node->details->remote_rsc->actions, NULL,
1593 RSC_STOP, NULL);
1594
1595 if (stop) {
1596 order_actions(stop, stonith_op, pe_order_optional);
1597 crm_info("Implying guest node %s is down (action %d) "
1598 "after connection is stopped (action %d)",
1599 node->details->uname, stonith_op->id, stop->id);
1600 } else {
1601
1602
1603
1604 crm_info("Implying guest node %s is down (action %d) ",
1605 node->details->uname, stonith_op->id);
1606 }
1607 }
1608
1609
1610 pcmk__order_vs_fence(stonith_op, data_set);
1611 }
1612
1613
1614
1615
1616 gboolean
1617 stage6(pe_working_set_t * data_set)
1618 {
1619 pe_action_t *dc_down = NULL;
1620 pe_action_t *stonith_op = NULL;
1621 gboolean integrity_lost = FALSE;
1622 gboolean need_stonith = TRUE;
1623 GList *gIter;
1624 GList *stonith_ops = NULL;
1625 GList *shutdown_ops = NULL;
1626
1627
1628
1629
1630
1631
1632
1633 crm_trace("Creating remote ordering constraints");
1634 apply_remote_node_ordering(data_set);
1635
1636 crm_trace("Processing fencing and shutdown cases");
1637 if (any_managed_resources(data_set) == FALSE) {
1638 crm_notice("Delaying fencing operations until there are resources to manage");
1639 need_stonith = FALSE;
1640 }
1641
1642
1643 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1644 pe_node_t *node = (pe_node_t *) gIter->data;
1645
1646
1647
1648
1649 if (pe__is_guest_node(node)) {
1650 if (node->details->remote_requires_reset && need_stonith
1651 && pe_can_fence(data_set, node)) {
1652 fence_guest(node, data_set);
1653 }
1654 continue;
1655 }
1656
1657 stonith_op = NULL;
1658
1659 if (node->details->unclean
1660 && need_stonith && pe_can_fence(data_set, node)) {
1661
1662 stonith_op = pe_fence_op(node, NULL, FALSE, "node is unclean", FALSE, data_set);
1663 pe_warn("Scheduling Node %s for STONITH", node->details->uname);
1664
1665 pcmk__order_vs_fence(stonith_op, data_set);
1666
1667 if (node->details->is_dc) {
1668
1669 dc_down = stonith_op;
1670
1671 } else {
1672
1673 if (!pcmk_is_set(data_set->flags, pe_flag_concurrent_fencing)
1674 && (stonith_ops != NULL)) {
1675
1676
1677
1678
1679
1680 order_actions((pe_action_t *) stonith_ops->data,
1681 stonith_op, pe_order_optional);
1682 }
1683
1684
1685 stonith_ops = g_list_prepend(stonith_ops, stonith_op);
1686 }
1687
1688 } else if (node->details->online && node->details->shutdown &&
1689
1690
1691
1692 pe__is_guest_or_remote_node(node) == FALSE) {
1693
1694 pe_action_t *down_op = sched_shutdown_op(node, data_set);
1695
1696 if (node->details->is_dc) {
1697
1698 dc_down = down_op;
1699 } else {
1700
1701 shutdown_ops = g_list_prepend(shutdown_ops, down_op);
1702 }
1703 }
1704
1705 if (node->details->unclean && stonith_op == NULL) {
1706 integrity_lost = TRUE;
1707 pe_warn("Node %s is unclean!", node->details->uname);
1708 }
1709 }
1710
1711 if (integrity_lost) {
1712 if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1713 pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
1714 pe_err("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
1715
1716 } else if (!pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
1717 crm_notice("Cannot fence unclean nodes until quorum is"
1718 " attained (or no-quorum-policy is set to ignore)");
1719 }
1720 }
1721
1722 if (dc_down != NULL) {
1723
1724
1725
1726
1727
1728
1729
1730 if (pcmk__str_eq(dc_down->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
1731 for (gIter = shutdown_ops; gIter != NULL; gIter = gIter->next) {
1732 pe_action_t *node_stop = (pe_action_t *) gIter->data;
1733
1734 crm_debug("Ordering shutdown on %s before %s on DC %s",
1735 node_stop->node->details->uname,
1736 dc_down->task, dc_down->node->details->uname);
1737
1738 order_actions(node_stop, dc_down, pe_order_optional);
1739 }
1740 }
1741
1742
1743
1744 if (pcmk_is_set(data_set->flags, pe_flag_concurrent_fencing)) {
1745
1746
1747
1748 for (gIter = stonith_ops; gIter != NULL; gIter = gIter->next) {
1749 order_actions((pe_action_t *) gIter->data, dc_down,
1750 pe_order_optional);
1751 }
1752 } else if (stonith_ops) {
1753
1754
1755
1756
1757
1758 order_actions((pe_action_t *) stonith_ops->data, dc_down,
1759 pe_order_optional);
1760 }
1761 }
1762 g_list_free(stonith_ops);
1763 g_list_free(shutdown_ops);
1764 return TRUE;
1765 }
1766
1767
1768
1769
1770
1771
1772
1773
1774 static GList *
1775 find_actions_by_task(GList *actions, pe_resource_t * rsc, const char *original_key)
1776 {
1777 GList *list = NULL;
1778
1779 list = find_actions(actions, original_key, NULL);
1780 if (list == NULL) {
1781
1782 char *key = NULL;
1783 char *task = NULL;
1784 guint interval_ms = 0;
1785
1786 if (parse_op_key(original_key, NULL, &task, &interval_ms)) {
1787 key = pcmk__op_key(rsc->id, task, interval_ms);
1788 list = find_actions(actions, key, NULL);
1789
1790 } else {
1791 crm_err("search key: %s", original_key);
1792 }
1793
1794 free(key);
1795 free(task);
1796 }
1797
1798 return list;
1799 }
1800
1801 static void
1802 rsc_order_then(pe_action_t *lh_action, pe_resource_t *rsc,
1803 pe__ordering_t *order)
1804 {
1805 GList *gIter = NULL;
1806 GList *rh_actions = NULL;
1807 pe_action_t *rh_action = NULL;
1808 enum pe_ordering type;
1809
1810 CRM_CHECK(rsc != NULL, return);
1811 CRM_CHECK(order != NULL, return);
1812
1813 type = order->type;
1814 rh_action = order->rh_action;
1815 crm_trace("Processing RH of ordering constraint %d", order->id);
1816
1817 if (rh_action != NULL) {
1818 rh_actions = g_list_prepend(NULL, rh_action);
1819
1820 } else if (rsc != NULL) {
1821 rh_actions = find_actions_by_task(rsc->actions, rsc, order->rh_action_task);
1822 }
1823
1824 if (rh_actions == NULL) {
1825 pe_rsc_trace(rsc, "No RH-Side (%s/%s) found for constraint..."
1826 " ignoring", rsc->id, order->rh_action_task);
1827 if (lh_action) {
1828 pe_rsc_trace(rsc, "LH-Side was: %s", lh_action->uuid);
1829 }
1830 return;
1831 }
1832
1833 if ((lh_action != NULL) && (lh_action->rsc == rsc)
1834 && pcmk_is_set(lh_action->flags, pe_action_dangle)) {
1835
1836 pe_rsc_trace(rsc, "Detected dangling operation %s -> %s", lh_action->uuid,
1837 order->rh_action_task);
1838 pe__clear_order_flags(type, pe_order_implies_then);
1839 }
1840
1841 gIter = rh_actions;
1842 for (; gIter != NULL; gIter = gIter->next) {
1843 pe_action_t *rh_action_iter = (pe_action_t *) gIter->data;
1844
1845 if (lh_action) {
1846 order_actions(lh_action, rh_action_iter, type);
1847
1848 } else if (type & pe_order_implies_then) {
1849 update_action_flags(rh_action_iter, pe_action_runnable | pe_action_clear,
1850 __func__, __LINE__);
1851 crm_warn("Unrunnable %s 0x%.6x", rh_action_iter->uuid, type);
1852 } else {
1853 crm_warn("neither %s 0x%.6x", rh_action_iter->uuid, type);
1854 }
1855 }
1856
1857 g_list_free(rh_actions);
1858 }
1859
1860 static void
1861 rsc_order_first(pe_resource_t *lh_rsc, pe__ordering_t *order,
1862 pe_working_set_t *data_set)
1863 {
1864 GList *gIter = NULL;
1865 GList *lh_actions = NULL;
1866 pe_action_t *lh_action = order->lh_action;
1867 pe_resource_t *rh_rsc = order->rh_rsc;
1868
1869 crm_trace("Processing LH of ordering constraint %d", order->id);
1870 CRM_ASSERT(lh_rsc != NULL);
1871
1872 if (lh_action != NULL) {
1873 lh_actions = g_list_prepend(NULL, lh_action);
1874
1875 } else {
1876 lh_actions = find_actions_by_task(lh_rsc->actions, lh_rsc, order->lh_action_task);
1877 }
1878
1879 if (lh_actions == NULL && lh_rsc != rh_rsc) {
1880 char *key = NULL;
1881 char *op_type = NULL;
1882 guint interval_ms = 0;
1883
1884 parse_op_key(order->lh_action_task, NULL, &op_type, &interval_ms);
1885 key = pcmk__op_key(lh_rsc->id, op_type, interval_ms);
1886
1887 if (lh_rsc->fns->state(lh_rsc, TRUE) == RSC_ROLE_STOPPED && pcmk__str_eq(op_type, RSC_STOP, pcmk__str_casei)) {
1888 free(key);
1889 pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - ignoring",
1890 lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1891
1892 } else if ((lh_rsc->fns->state(lh_rsc, TRUE) == RSC_ROLE_UNPROMOTED)
1893 && pcmk__str_eq(op_type, RSC_DEMOTE, pcmk__str_casei)) {
1894 free(key);
1895 pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - ignoring",
1896 lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1897
1898 } else {
1899 pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - creating",
1900 lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1901 lh_action = custom_action(lh_rsc, key, op_type, NULL, TRUE, TRUE, data_set);
1902 lh_actions = g_list_prepend(NULL, lh_action);
1903 }
1904
1905 free(op_type);
1906 }
1907
1908 gIter = lh_actions;
1909 for (; gIter != NULL; gIter = gIter->next) {
1910 pe_action_t *lh_action_iter = (pe_action_t *) gIter->data;
1911
1912 if (rh_rsc == NULL && order->rh_action) {
1913 rh_rsc = order->rh_action->rsc;
1914 }
1915 if (rh_rsc) {
1916 rsc_order_then(lh_action_iter, rh_rsc, order);
1917
1918 } else if (order->rh_action) {
1919 order_actions(lh_action_iter, order->rh_action, order->type);
1920 }
1921 }
1922
1923 g_list_free(lh_actions);
1924 }
1925
1926 extern void update_colo_start_chain(pe_action_t *action,
1927 pe_working_set_t *data_set);
1928
1929 static int
1930 is_recurring_action(pe_action_t *action)
1931 {
1932 guint interval_ms;
1933
1934 if (pcmk__guint_from_hash(action->meta,
1935 XML_LRM_ATTR_INTERVAL_MS, 0,
1936 &interval_ms) != pcmk_rc_ok) {
1937 return 0;
1938 }
1939 return (interval_ms > 0);
1940 }
1941
1942 static void
1943 apply_container_ordering(pe_action_t *action, pe_working_set_t *data_set)
1944 {
1945
1946
1947
1948
1949
1950
1951
1952 pe_resource_t *remote_rsc = NULL;
1953 pe_resource_t *container = NULL;
1954 enum action_tasks task = text2task(action->task);
1955
1956 CRM_ASSERT(action->rsc);
1957 CRM_ASSERT(action->node);
1958 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
1959
1960 remote_rsc = action->node->details->remote_rsc;
1961 CRM_ASSERT(remote_rsc);
1962
1963 container = remote_rsc->container;
1964 CRM_ASSERT(container);
1965
1966 if (pcmk_is_set(container->flags, pe_rsc_failed)) {
1967 pe_fence_node(data_set, action->node, "container failed", FALSE);
1968 }
1969
1970 crm_trace("Order %s action %s relative to %s%s for %s%s",
1971 action->task, action->uuid,
1972 pcmk_is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
1973 remote_rsc->id,
1974 pcmk_is_set(container->flags, pe_rsc_failed)? "failed " : "",
1975 container->id);
1976
1977 if (pcmk__strcase_any_of(action->task, CRMD_ACTION_MIGRATE, CRMD_ACTION_MIGRATED, NULL)) {
1978
1979
1980
1981 task = stop_rsc;
1982 }
1983
1984 switch (task) {
1985 case start_rsc:
1986 case action_promote:
1987
1988 order_start_then_action(container, action, pe_order_implies_then,
1989 data_set);
1990
1991
1992 order_start_then_action(remote_rsc, action, pe_order_none,
1993 data_set);
1994 break;
1995
1996 case stop_rsc:
1997 case action_demote:
1998 if (pcmk_is_set(container->flags, pe_rsc_failed)) {
1999
2000
2001
2002
2003
2004
2005 } else {
2006
2007
2008
2009
2010
2011
2012
2013
2014 order_action_then_stop(action, remote_rsc, pe_order_none,
2015 data_set);
2016 }
2017 break;
2018
2019 default:
2020
2021 if (is_recurring_action(action)) {
2022
2023
2024
2025
2026 if(task != no_action) {
2027 order_start_then_action(remote_rsc, action,
2028 pe_order_implies_then, data_set);
2029 }
2030 } else {
2031 order_start_then_action(remote_rsc, action, pe_order_none,
2032 data_set);
2033 }
2034 break;
2035 }
2036 }
2037
2038 static enum remote_connection_state
2039 get_remote_node_state(pe_node_t *node)
2040 {
2041 pe_resource_t *remote_rsc = NULL;
2042 pe_node_t *cluster_node = NULL;
2043
2044 CRM_ASSERT(node);
2045
2046 remote_rsc = node->details->remote_rsc;
2047 CRM_ASSERT(remote_rsc);
2048
2049 cluster_node = pe__current_node(remote_rsc);
2050
2051
2052
2053
2054
2055 if(remote_rsc->next_role == RSC_ROLE_STOPPED || remote_rsc->allocated_to == NULL) {
2056
2057
2058 if (cluster_node && cluster_node->details->unclean) {
2059
2060
2061
2062 return remote_state_failed;
2063 }
2064
2065 if (!pcmk_is_set(remote_rsc->flags, pe_rsc_failed)) {
2066
2067 return remote_state_stopped;
2068 }
2069
2070
2071
2072 if ((remote_rsc->next_role == RSC_ROLE_STOPPED)
2073 && remote_rsc->remote_reconnect_ms
2074 && node->details->remote_was_fenced
2075 && !pe__shutdown_requested(node)) {
2076
2077
2078
2079
2080 return remote_state_unknown;
2081 }
2082
2083
2084
2085
2086
2087 return remote_state_failed;
2088
2089 } else if (cluster_node == NULL) {
2090
2091 return remote_state_unknown;
2092
2093 } else if(cluster_node->details->unclean == TRUE
2094 || cluster_node->details->online == FALSE) {
2095
2096 return remote_state_resting;
2097
2098 } else if (pcmk__list_of_multiple(remote_rsc->running_on)
2099 && remote_rsc->partial_migration_source
2100 && remote_rsc->partial_migration_target) {
2101
2102
2103
2104
2105 return remote_state_resting;
2106
2107 }
2108 return remote_state_alive;
2109 }
2110
2111
2112
2113
2114
2115 static void
2116 apply_remote_ordering(pe_action_t *action, pe_working_set_t *data_set)
2117 {
2118 pe_resource_t *remote_rsc = NULL;
2119 enum action_tasks task = text2task(action->task);
2120 enum remote_connection_state state = get_remote_node_state(action->node);
2121
2122 enum pe_ordering order_opts = pe_order_none;
2123
2124 if (action->rsc == NULL) {
2125 return;
2126 }
2127
2128 CRM_ASSERT(action->node);
2129 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
2130
2131 remote_rsc = action->node->details->remote_rsc;
2132 CRM_ASSERT(remote_rsc);
2133
2134 crm_trace("Order %s action %s relative to %s%s (state: %s)",
2135 action->task, action->uuid,
2136 pcmk_is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
2137 remote_rsc->id, state2text(state));
2138
2139 if (pcmk__strcase_any_of(action->task, CRMD_ACTION_MIGRATE, CRMD_ACTION_MIGRATED, NULL)) {
2140
2141
2142
2143 task = stop_rsc;
2144 }
2145
2146 switch (task) {
2147 case start_rsc:
2148 case action_promote:
2149 order_opts = pe_order_none;
2150
2151 if (state == remote_state_failed) {
2152
2153 pe__set_order_flags(order_opts, pe_order_implies_then);
2154 }
2155
2156
2157 order_start_then_action(remote_rsc, action, order_opts, data_set);
2158 break;
2159
2160 case stop_rsc:
2161 if(state == remote_state_alive) {
2162 order_action_then_stop(action, remote_rsc,
2163 pe_order_implies_first, data_set);
2164
2165 } else if(state == remote_state_failed) {
2166
2167
2168
2169
2170
2171
2172 pe_fence_node(data_set, action->node, "resources are active and the connection is unrecoverable", FALSE);
2173
2174 } else if(remote_rsc->next_role == RSC_ROLE_STOPPED) {
2175
2176
2177
2178
2179 order_action_then_stop(action, remote_rsc,
2180 pe_order_implies_first, data_set);
2181
2182 } else {
2183
2184
2185
2186 order_start_then_action(remote_rsc, action, pe_order_none, data_set);
2187 }
2188 break;
2189
2190 case action_demote:
2191
2192
2193
2194
2195 if(state == remote_state_resting || state == remote_state_unknown) {
2196 order_start_then_action(remote_rsc, action, pe_order_none,
2197 data_set);
2198 }
2199 break;
2200
2201 default:
2202
2203 if (is_recurring_action(action)) {
2204
2205
2206
2207
2208 order_start_then_action(remote_rsc, action,
2209 pe_order_implies_then, data_set);
2210
2211 } else {
2212 pe_node_t *cluster_node = pe__current_node(remote_rsc);
2213
2214 if(task == monitor_rsc && state == remote_state_failed) {
2215
2216
2217
2218
2219
2220 pe_fence_node(data_set, action->node, "resources are in an unknown state and the connection is unrecoverable", FALSE);
2221 }
2222
2223 if(cluster_node && state == remote_state_stopped) {
2224
2225
2226
2227
2228
2229
2230
2231 order_action_then_stop(action, remote_rsc,
2232 pe_order_runnable_left, data_set);
2233
2234 } else {
2235 order_start_then_action(remote_rsc, action, pe_order_none,
2236 data_set);
2237 }
2238 }
2239 break;
2240 }
2241 }
2242
2243 static void
2244 apply_remote_node_ordering(pe_working_set_t *data_set)
2245 {
2246 if (!pcmk_is_set(data_set->flags, pe_flag_have_remote_nodes)) {
2247 return;
2248 }
2249
2250 for (GList *gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2251 pe_action_t *action = (pe_action_t *) gIter->data;
2252 pe_resource_t *remote = NULL;
2253
2254
2255 if (action->rsc == NULL) {
2256 continue;
2257 }
2258
2259
2260
2261
2262
2263 if (action->rsc->is_remote_node &&
2264 pcmk__str_eq(action->task, CRM_OP_CLEAR_FAILCOUNT, pcmk__str_casei)) {
2265
2266 custom_action_order(action->rsc,
2267 NULL,
2268 action,
2269 action->rsc,
2270 pcmk__op_key(action->rsc->id, RSC_START, 0),
2271 NULL,
2272 pe_order_optional,
2273 data_set);
2274
2275 continue;
2276 }
2277
2278
2279 if (action->node == NULL) {
2280 continue;
2281 }
2282
2283 if (!pe__is_guest_or_remote_node(action->node)) {
2284 continue;
2285 }
2286
2287
2288
2289
2290
2291
2292
2293 if (pcmk_is_set(action->flags, pe_action_pseudo)) {
2294 continue;
2295 }
2296
2297 remote = action->node->details->remote_rsc;
2298 if (remote == NULL) {
2299
2300 continue;
2301 }
2302
2303
2304
2305
2306
2307
2308 if (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)) {
2309 for (GList *item = action->rsc->actions; item != NULL;
2310 item = item->next) {
2311 pe_action_t *rsc_action = item->data;
2312
2313 if ((rsc_action->node->details != action->node->details)
2314 && pcmk__str_eq(rsc_action->task, RSC_STOP, pcmk__str_casei)) {
2315 custom_action_order(remote, start_key(remote), NULL,
2316 action->rsc, NULL, rsc_action,
2317 pe_order_optional, data_set);
2318 }
2319 }
2320 }
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331 if (remote->container) {
2332 crm_trace("Container ordering for %s", action->uuid);
2333 apply_container_ordering(action, data_set);
2334
2335 } else {
2336 crm_trace("Remote ordering for %s", action->uuid);
2337 apply_remote_ordering(action, data_set);
2338 }
2339 }
2340 }
2341
2342 static gboolean
2343 order_first_probe_unneeded(pe_action_t * probe, pe_action_t * rh_action)
2344 {
2345
2346
2347
2348
2349
2350 if (pcmk__str_eq(rh_action->task, CRM_OP_FENCE, pcmk__str_casei)
2351 && probe->node && rh_action->node
2352 && probe->node->details == rh_action->node->details) {
2353 const char *op = g_hash_table_lookup(rh_action->meta, "stonith_action");
2354
2355 if (pcmk__str_eq(op, "on", pcmk__str_casei)) {
2356 return TRUE;
2357 }
2358 }
2359
2360
2361 if ((pcmk__str_eq(rh_action->task, CRM_OP_SHUTDOWN, pcmk__str_casei))
2362 && probe->node && rh_action->node
2363 && probe->node->details != rh_action->node->details) {
2364 return TRUE;
2365 }
2366 return FALSE;
2367 }
2368
2369 static void
2370 order_first_probes_imply_stops(pe_working_set_t * data_set)
2371 {
2372 GList *gIter = NULL;
2373
2374 for (gIter = data_set->ordering_constraints; gIter != NULL; gIter = gIter->next) {
2375 pe__ordering_t *order = gIter->data;
2376 enum pe_ordering order_type = pe_order_optional;
2377
2378 pe_resource_t *lh_rsc = order->lh_rsc;
2379 pe_resource_t *rh_rsc = order->rh_rsc;
2380 pe_action_t *lh_action = order->lh_action;
2381 pe_action_t *rh_action = order->rh_action;
2382 const char *lh_action_task = order->lh_action_task;
2383 const char *rh_action_task = order->rh_action_task;
2384
2385 GList *probes = NULL;
2386 GList *rh_actions = NULL;
2387
2388 GList *pIter = NULL;
2389
2390 if (lh_rsc == NULL) {
2391 continue;
2392
2393 } else if (rh_rsc && lh_rsc == rh_rsc) {
2394 continue;
2395 }
2396
2397 if (lh_action == NULL && lh_action_task == NULL) {
2398 continue;
2399 }
2400
2401 if (rh_action == NULL && rh_action_task == NULL) {
2402 continue;
2403 }
2404
2405
2406
2407
2408
2409 if (lh_action && !pcmk__str_eq(lh_action->task, RSC_STOP, pcmk__str_casei)) {
2410 continue;
2411
2412 } else if (lh_action == NULL
2413 && lh_action_task
2414 && !pcmk__ends_with(lh_action_task, "_" RSC_STOP "_0")) {
2415 continue;
2416 }
2417
2418
2419
2420
2421
2422 if (rh_rsc && lh_rsc->container == rh_rsc) {
2423 if (rh_action && pcmk__str_eq(rh_action->task, RSC_STOP, pcmk__str_casei)) {
2424 continue;
2425
2426 } else if (rh_action == NULL && rh_action_task
2427 && pcmk__ends_with(rh_action_task,"_" RSC_STOP "_0")) {
2428 continue;
2429 }
2430 }
2431
2432 if (order->type == pe_order_none) {
2433 continue;
2434 }
2435
2436
2437 if (pcmk_is_set(order->type, pe_order_apply_first_non_migratable)) {
2438 pe__set_order_flags(order_type,
2439 pe_order_apply_first_non_migratable);
2440 }
2441
2442 if (pcmk_is_set(order->type, pe_order_same_node)) {
2443 pe__set_order_flags(order_type, pe_order_same_node);
2444 }
2445
2446
2447 if (order->type == pe_order_anti_colocation
2448 || order->type == pe_order_load) {
2449 order_type = order->type;
2450 }
2451
2452 probes = pe__resource_actions(lh_rsc, NULL, RSC_STATUS, FALSE);
2453 if (probes == NULL) {
2454 continue;
2455 }
2456
2457 if (rh_action) {
2458 rh_actions = g_list_prepend(rh_actions, rh_action);
2459
2460 } else if (rh_rsc && rh_action_task) {
2461 rh_actions = find_actions(rh_rsc->actions, rh_action_task, NULL);
2462 }
2463
2464 if (rh_actions == NULL) {
2465 g_list_free(probes);
2466 continue;
2467 }
2468
2469 crm_trace("Processing for LH probe based on ordering constraint %s -> %s"
2470 " (id=%d, type=%.6x)",
2471 lh_action ? lh_action->uuid : lh_action_task,
2472 rh_action ? rh_action->uuid : rh_action_task,
2473 order->id, order->type);
2474
2475 for (pIter = probes; pIter != NULL; pIter = pIter->next) {
2476 pe_action_t *probe = (pe_action_t *) pIter->data;
2477 GList *rIter = NULL;
2478
2479 for (rIter = rh_actions; rIter != NULL; rIter = rIter->next) {
2480 pe_action_t *rh_action_iter = (pe_action_t *) rIter->data;
2481
2482 if (order_first_probe_unneeded(probe, rh_action_iter)) {
2483 continue;
2484 }
2485 order_actions(probe, rh_action_iter, order_type);
2486 }
2487 }
2488
2489 g_list_free(rh_actions);
2490 g_list_free(probes);
2491 }
2492 }
2493
2494 static void
2495 order_first_probe_then_restart_repromote(pe_action_t * probe,
2496 pe_action_t * after,
2497 pe_working_set_t * data_set)
2498 {
2499 GList *gIter = NULL;
2500 bool interleave = FALSE;
2501 pe_resource_t *compatible_rsc = NULL;
2502
2503 if (probe == NULL
2504 || probe->rsc == NULL
2505 || probe->rsc->variant != pe_native) {
2506 return;
2507 }
2508
2509 if (after == NULL
2510
2511 || pcmk_is_set(after->flags, pe_action_tracking)) {
2512 return;
2513 }
2514
2515 if (!pcmk__str_eq(probe->task, RSC_STATUS, pcmk__str_casei)) {
2516 return;
2517 }
2518
2519 pe__set_action_flags(after, pe_action_tracking);
2520
2521 crm_trace("Processing based on %s %s -> %s %s",
2522 probe->uuid,
2523 probe->node ? probe->node->details->uname: "",
2524 after->uuid,
2525 after->node ? after->node->details->uname : "");
2526
2527 if (after->rsc
2528
2529
2530
2531
2532 && after->rsc->variant == pe_native
2533 && probe->rsc != after->rsc) {
2534
2535 GList *then_actions = NULL;
2536 enum pe_ordering probe_order_type = pe_order_optional;
2537
2538 if (pcmk__str_eq(after->task, RSC_START, pcmk__str_casei)) {
2539 then_actions = pe__resource_actions(after->rsc, NULL, RSC_STOP, FALSE);
2540
2541 } else if (pcmk__str_eq(after->task, RSC_PROMOTE, pcmk__str_casei)) {
2542 then_actions = pe__resource_actions(after->rsc, NULL, RSC_DEMOTE, FALSE);
2543 }
2544
2545 for (gIter = then_actions; gIter != NULL; gIter = gIter->next) {
2546 pe_action_t *then = (pe_action_t *) gIter->data;
2547
2548
2549 if (pcmk_is_set(then->flags, pe_action_pseudo)) {
2550 continue;
2551 }
2552
2553 order_actions(probe, then, probe_order_type);
2554 }
2555 g_list_free(then_actions);
2556 }
2557
2558 if (after->rsc
2559 && after->rsc->variant > pe_group) {
2560 const char *interleave_s = g_hash_table_lookup(after->rsc->meta,
2561 XML_RSC_ATTR_INTERLEAVE);
2562
2563 interleave = crm_is_true(interleave_s);
2564
2565 if (interleave) {
2566
2567
2568
2569 compatible_rsc = find_compatible_child(probe->rsc,
2570 after->rsc,
2571 RSC_ROLE_UNKNOWN,
2572 FALSE, data_set);
2573 }
2574 }
2575
2576 for (gIter = after->actions_after; gIter != NULL; gIter = gIter->next) {
2577 pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) gIter->data;
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587 if (!pcmk_is_set(after_wrapper->type, pe_order_implies_then)) {
2588
2589
2590
2591
2592
2593
2594
2595 if (after->rsc == NULL
2596 || after->rsc->variant < pe_group
2597 || probe->rsc->parent == after->rsc
2598 || after_wrapper->action->rsc == NULL
2599 || after_wrapper->action->rsc->variant > pe_group
2600 || after->rsc != after_wrapper->action->rsc->parent) {
2601 continue;
2602 }
2603
2604
2605
2606
2607 if (after->rsc->variant > pe_group
2608 && interleave == TRUE
2609 && (compatible_rsc == NULL
2610 || compatible_rsc != after_wrapper->action->rsc)) {
2611 continue;
2612 }
2613 }
2614
2615 crm_trace("Proceeding through %s %s -> %s %s (type=0x%.6x)",
2616 after->uuid,
2617 after->node ? after->node->details->uname: "",
2618 after_wrapper->action->uuid,
2619 after_wrapper->action->node ? after_wrapper->action->node->details->uname : "",
2620 after_wrapper->type);
2621
2622 order_first_probe_then_restart_repromote(probe, after_wrapper->action, data_set);
2623 }
2624 }
2625
2626 static void clear_actions_tracking_flag(pe_working_set_t * data_set)
2627 {
2628 GList *gIter = NULL;
2629
2630 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2631 pe_action_t *action = (pe_action_t *) gIter->data;
2632
2633 if (pcmk_is_set(action->flags, pe_action_tracking)) {
2634 pe__clear_action_flags(action, pe_action_tracking);
2635 }
2636 }
2637 }
2638
2639 static void
2640 order_first_rsc_probes(pe_resource_t * rsc, pe_working_set_t * data_set)
2641 {
2642 GList *gIter = NULL;
2643 GList *probes = NULL;
2644
2645 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
2646 pe_resource_t * child = (pe_resource_t *) gIter->data;
2647
2648 order_first_rsc_probes(child, data_set);
2649 }
2650
2651 if (rsc->variant != pe_native) {
2652 return;
2653 }
2654
2655 probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
2656
2657 for (gIter = probes; gIter != NULL; gIter= gIter->next) {
2658 pe_action_t *probe = (pe_action_t *) gIter->data;
2659 GList *aIter = NULL;
2660
2661 for (aIter = probe->actions_after; aIter != NULL; aIter = aIter->next) {
2662 pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) aIter->data;
2663
2664 order_first_probe_then_restart_repromote(probe, after_wrapper->action, data_set);
2665 clear_actions_tracking_flag(data_set);
2666 }
2667 }
2668
2669 g_list_free(probes);
2670 }
2671
2672 static void
2673 order_first_probes(pe_working_set_t * data_set)
2674 {
2675 GList *gIter = NULL;
2676
2677 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2678 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2679
2680 order_first_rsc_probes(rsc, data_set);
2681 }
2682
2683 order_first_probes_imply_stops(data_set);
2684 }
2685
2686 static void
2687 order_then_probes(pe_working_set_t * data_set)
2688 {
2689 #if 0
2690 GList *gIter = NULL;
2691
2692 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2693 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737 pe_action_t *start = NULL;
2738 GList *actions = NULL;
2739 GList *probes = NULL;
2740
2741 actions = pe__resource_actions(rsc, NULL, RSC_START, FALSE);
2742
2743 if (actions) {
2744 start = actions->data;
2745 g_list_free(actions);
2746 }
2747
2748 if(start == NULL) {
2749 crm_err("No start action for %s", rsc->id);
2750 continue;
2751 }
2752
2753 probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
2754
2755 for (actions = start->actions_before; actions != NULL; actions = actions->next) {
2756 pe_action_wrapper_t *before = (pe_action_wrapper_t *) actions->data;
2757
2758 GList *pIter = NULL;
2759 pe_action_t *first = before->action;
2760 pe_resource_t *first_rsc = first->rsc;
2761
2762 if(first->required_runnable_before) {
2763 GList *clone_actions = NULL;
2764 for (clone_actions = first->actions_before; clone_actions != NULL; clone_actions = clone_actions->next) {
2765 before = (pe_action_wrapper_t *) clone_actions->data;
2766
2767 crm_trace("Testing %s -> %s (%p) for %s", first->uuid, before->action->uuid, before->action->rsc, start->uuid);
2768
2769 CRM_ASSERT(before->action->rsc);
2770 first_rsc = before->action->rsc;
2771 break;
2772 }
2773
2774 } else if(!pcmk__str_eq(first->task, RSC_START, pcmk__str_casei)) {
2775 crm_trace("Not a start op %s for %s", first->uuid, start->uuid);
2776 }
2777
2778 if(first_rsc == NULL) {
2779 continue;
2780
2781 } else if(uber_parent(first_rsc) == uber_parent(start->rsc)) {
2782 crm_trace("Same parent %s for %s", first_rsc->id, start->uuid);
2783 continue;
2784
2785 } else if(FALSE && pe_rsc_is_clone(uber_parent(first_rsc)) == FALSE) {
2786 crm_trace("Not a clone %s for %s", first_rsc->id, start->uuid);
2787 continue;
2788 }
2789
2790 crm_err("Applying %s before %s %d", first->uuid, start->uuid, uber_parent(first_rsc)->variant);
2791
2792 for (pIter = probes; pIter != NULL; pIter = pIter->next) {
2793 pe_action_t *probe = (pe_action_t *) pIter->data;
2794
2795 crm_err("Ordering %s before %s", first->uuid, probe->uuid);
2796 order_actions(first, probe, pe_order_optional);
2797 }
2798 }
2799 }
2800 #endif
2801 }
2802
2803 static void
2804 order_probes(pe_working_set_t * data_set)
2805 {
2806 order_first_probes(data_set);
2807 order_then_probes(data_set);
2808 }
2809
2810 gboolean
2811 stage7(pe_working_set_t * data_set)
2812 {
2813 pcmk__output_t *prev_out = data_set->priv;
2814 pcmk__output_t *out = NULL;
2815 GList *gIter = NULL;
2816
2817 crm_trace("Applying ordering constraints");
2818
2819
2820
2821
2822
2823
2824
2825 data_set->ordering_constraints = g_list_reverse(data_set->ordering_constraints);
2826
2827 for (gIter = data_set->ordering_constraints; gIter != NULL; gIter = gIter->next) {
2828 pe__ordering_t *order = gIter->data;
2829 pe_resource_t *rsc = order->lh_rsc;
2830
2831 crm_trace("Applying ordering constraint: %d", order->id);
2832
2833 if (rsc != NULL) {
2834 crm_trace("rsc_action-to-*");
2835 rsc_order_first(rsc, order, data_set);
2836 continue;
2837 }
2838
2839 rsc = order->rh_rsc;
2840 if (rsc != NULL) {
2841 crm_trace("action-to-rsc_action");
2842 rsc_order_then(order->lh_action, rsc, order);
2843
2844 } else {
2845 crm_trace("action-to-action");
2846 order_actions(order->lh_action, order->rh_action, order->type);
2847 }
2848 }
2849
2850 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2851 pe_action_t *action = (pe_action_t *) gIter->data;
2852
2853 update_colo_start_chain(action, data_set);
2854 }
2855
2856 crm_trace("Ordering probes");
2857 order_probes(data_set);
2858
2859 crm_trace("Updating %d actions", g_list_length(data_set->actions));
2860 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2861 pe_action_t *action = (pe_action_t *) gIter->data;
2862
2863 update_action(action, data_set);
2864 }
2865
2866
2867 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2868 pe_action_t *action = (pe_action_t *) gIter->data;
2869 pe_action_wrapper_t *input = NULL;
2870
2871 for (GList *input_iter = action->actions_before;
2872 input_iter != NULL; input_iter = input_iter->next) {
2873
2874 input = (pe_action_wrapper_t *) input_iter->data;
2875 if (pcmk__ordering_is_invalid(action, input)) {
2876 input->type = pe_order_none;
2877 }
2878 }
2879 }
2880
2881
2882
2883
2884 out = pcmk__new_logger();
2885 if (out == NULL) {
2886 return FALSE;
2887 }
2888
2889 pcmk__output_set_log_level(out, LOG_NOTICE);
2890 data_set->priv = out;
2891
2892 out->begin_list(out, NULL, NULL, "Actions");
2893 LogNodeActions(data_set);
2894
2895 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2896 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2897
2898 LogActions(rsc, data_set);
2899 }
2900
2901 out->end_list(out);
2902 out->finish(out, CRM_EX_OK, true, NULL);
2903 pcmk__output_free(out);
2904
2905 data_set->priv = prev_out;
2906 return TRUE;
2907 }
2908
2909 static int transition_id = -1;
2910
2911
2912
2913
2914
2915
2916
2917 void
2918 pcmk__log_transition_summary(const char *filename)
2919 {
2920 if (was_processing_error) {
2921 crm_err("Calculated transition %d (with errors)%s%s",
2922 transition_id,
2923 (filename == NULL)? "" : ", saving inputs in ",
2924 (filename == NULL)? "" : filename);
2925
2926 } else if (was_processing_warning) {
2927 crm_warn("Calculated transition %d (with warnings)%s%s",
2928 transition_id,
2929 (filename == NULL)? "" : ", saving inputs in ",
2930 (filename == NULL)? "" : filename);
2931
2932 } else {
2933 crm_notice("Calculated transition %d%s%s",
2934 transition_id,
2935 (filename == NULL)? "" : ", saving inputs in ",
2936 (filename == NULL)? "" : filename);
2937 }
2938 if (crm_config_error) {
2939 crm_notice("Configuration errors found during scheduler processing,"
2940 " please run \"crm_verify -L\" to identify issues");
2941 }
2942 }
2943
2944
2945
2946
2947 gboolean
2948 stage8(pe_working_set_t * data_set)
2949 {
2950 GList *gIter = NULL;
2951 const char *value = NULL;
2952 long long limit = 0LL;
2953
2954 transition_id++;
2955 crm_trace("Creating transition graph %d.", transition_id);
2956
2957 data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH);
2958
2959 value = pe_pref(data_set->config_hash, "cluster-delay");
2960 crm_xml_add(data_set->graph, "cluster-delay", value);
2961
2962 value = pe_pref(data_set->config_hash, "stonith-timeout");
2963 crm_xml_add(data_set->graph, "stonith-timeout", value);
2964
2965 crm_xml_add(data_set->graph, "failed-stop-offset", "INFINITY");
2966
2967 if (pcmk_is_set(data_set->flags, pe_flag_start_failure_fatal)) {
2968 crm_xml_add(data_set->graph, "failed-start-offset", "INFINITY");
2969 } else {
2970 crm_xml_add(data_set->graph, "failed-start-offset", "1");
2971 }
2972
2973 value = pe_pref(data_set->config_hash, "batch-limit");
2974 crm_xml_add(data_set->graph, "batch-limit", value);
2975
2976 crm_xml_add_int(data_set->graph, "transition_id", transition_id);
2977
2978 value = pe_pref(data_set->config_hash, "migration-limit");
2979 if ((pcmk__scan_ll(value, &limit, 0LL) == pcmk_rc_ok) && (limit > 0)) {
2980 crm_xml_add(data_set->graph, "migration-limit", value);
2981 }
2982
2983 if (data_set->recheck_by > 0) {
2984 char *recheck_epoch = NULL;
2985
2986 recheck_epoch = crm_strdup_printf("%llu",
2987 (long long) data_set->recheck_by);
2988 crm_xml_add(data_set->graph, "recheck-by", recheck_epoch);
2989 free(recheck_epoch);
2990 }
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005 gIter = data_set->resources;
3006 for (; gIter != NULL; gIter = gIter->next) {
3007 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
3008
3009 pe_rsc_trace(rsc, "processing actions for rsc=%s", rsc->id);
3010 rsc->cmds->expand(rsc, data_set);
3011 }
3012
3013 crm_log_xml_trace(data_set->graph, "created resource-driven action list");
3014
3015
3016 add_maintenance_update(data_set);
3017
3018
3019 crm_trace("processing non-resource actions");
3020
3021 gIter = data_set->actions;
3022 for (; gIter != NULL; gIter = gIter->next) {
3023 pe_action_t *action = (pe_action_t *) gIter->data;
3024
3025 if (action->rsc
3026 && action->node
3027 && action->node->details->shutdown
3028 && !pcmk_is_set(action->rsc->flags, pe_rsc_maintenance)
3029 && !pcmk_any_flags_set(action->flags,
3030 pe_action_optional|pe_action_runnable)
3031 && pcmk__str_eq(action->task, RSC_STOP, pcmk__str_none)
3032 ) {
3033
3034
3035
3036
3037 if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)
3038 || data_set->no_quorum_policy == no_quorum_ignore) {
3039 crm_crit("Cannot %s node '%s' because of %s:%s%s (%s)",
3040 action->node->details->unclean ? "fence" : "shut down",
3041 action->node->details->uname, action->rsc->id,
3042 pcmk_is_set(action->rsc->flags, pe_rsc_managed)? " blocked" : " unmanaged",
3043 pcmk_is_set(action->rsc->flags, pe_rsc_failed)? " failed" : "",
3044 action->uuid);
3045 }
3046 }
3047
3048 graph_element_from_action(action, data_set);
3049 }
3050
3051 crm_log_xml_trace(data_set->graph, "created generic action list");
3052 crm_trace("Created transition graph %d.", transition_id);
3053
3054 return TRUE;
3055 }
3056
3057 void
3058 LogNodeActions(pe_working_set_t * data_set)
3059 {
3060 pcmk__output_t *out = data_set->priv;
3061 GList *gIter = NULL;
3062
3063 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
3064 char *node_name = NULL;
3065 char *task = NULL;
3066 pe_action_t *action = (pe_action_t *) gIter->data;
3067
3068 if (action->rsc != NULL) {
3069 continue;
3070 } else if (pcmk_is_set(action->flags, pe_action_optional)) {
3071 continue;
3072 }
3073
3074 if (pe__is_guest_node(action->node)) {
3075 node_name = crm_strdup_printf("%s (resource: %s)", action->node->details->uname, action->node->details->remote_rsc->container->id);
3076 } else if(action->node) {
3077 node_name = crm_strdup_printf("%s", action->node->details->uname);
3078 }
3079
3080
3081 if (pcmk__str_eq(action->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
3082 task = strdup("Shutdown");
3083 } else if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei)) {
3084 const char *op = g_hash_table_lookup(action->meta, "stonith_action");
3085 task = crm_strdup_printf("Fence (%s)", op);
3086 }
3087
3088 out->message(out, "node-action", task, node_name, action->reason);
3089
3090 free(node_name);
3091 free(task);
3092 }
3093 }