This source file includes following definitions.
- pe_can_fence
- pe__copy_node
- pe__node_list2table
- pe__cmp_node_name
- pe__output_node_weights
- pe__log_node_weights
- pe__show_node_scores_as
- pe__cmp_rsc_priority
- resource_node_score
- resource_location
- get_effective_time
- get_target_role
- order_actions
- destroy_ticket
- ticket_new
- rsc_printable_id
- pe__clear_resource_flags_recursive
- pe__clear_resource_flags_on_all
- pe__set_resource_flags_recursive
- trigger_unfencing
- pe__shutdown_requested
- pe__update_recheck_time
- pe__unpack_dataset_nvpairs
- pe__resource_is_disabled
- pe__rsc_running_on_only
- pe__rsc_running_on_any
- pcmk__rsc_filtered_by_node
- pe__filter_rsc_list
- pe__build_node_name_list
- pe__build_rsc_list
- pe__failed_probe_for_rsc
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <glib.h>
13 #include <stdbool.h>
14
15 #include <crm/crm.h>
16 #include <crm/common/xml.h>
17 #include <crm/pengine/rules.h>
18 #include <crm/pengine/internal.h>
19
20 #include "pe_status_private.h"
21
22 extern bool pcmk__is_daemon;
23
24 gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
25
26
27
28
29
30
31
32
33
34
35 bool
36 pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
37 {
38 if (pcmk__is_guest_or_bundle_node(node)) {
39
40
41
42 pcmk_resource_t *rsc = node->priv->remote->priv->launcher;
43
44 for (GList *n = rsc->priv->active_nodes; n != NULL; n = n->next) {
45 pcmk_node_t *launcher_node = n->data;
46
47 if (!launcher_node->details->online
48 && !pe_can_fence(scheduler, launcher_node)) {
49 return false;
50 }
51 }
52 return true;
53
54 } else if (!pcmk_is_set(scheduler->flags, pcmk__sched_fencing_enabled)) {
55 return false;
56
57 } else if (!pcmk_is_set(scheduler->flags, pcmk__sched_have_fencing)) {
58 return false;
59
60 } else if (pcmk_is_set(scheduler->flags, pcmk__sched_quorate)) {
61 return true;
62
63 } else if (scheduler->no_quorum_policy == pcmk_no_quorum_ignore) {
64 return true;
65
66 } else if(node == NULL) {
67 return false;
68
69 } else if(node->details->online) {
70 crm_notice("We can fence %s without quorum because they're in our membership",
71 pcmk__node_name(node));
72 return true;
73 }
74
75 crm_trace("Cannot fence %s", pcmk__node_name(node));
76 return false;
77 }
78
79
80
81
82
83
84
85
86
87
88
89
90 pcmk_node_t *
91 pe__copy_node(const pcmk_node_t *this_node)
92 {
93 pcmk_node_t *new_node = NULL;
94
95 pcmk__assert(this_node != NULL);
96
97 new_node = pcmk__assert_alloc(1, sizeof(pcmk_node_t));
98 new_node->assign = pcmk__assert_alloc(1,
99 sizeof(struct pcmk__node_assignment));
100
101 new_node->assign->probe_mode = this_node->assign->probe_mode;
102 new_node->assign->score = this_node->assign->score;
103 new_node->assign->count = this_node->assign->count;
104 new_node->details = this_node->details;
105 new_node->priv = this_node->priv;
106
107 return new_node;
108 }
109
110
111
112
113
114
115
116
117
118 GHashTable *
119 pe__node_list2table(const GList *list)
120 {
121 GHashTable *result = NULL;
122
123 result = pcmk__strkey_table(NULL, pcmk__free_node_copy);
124 for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
125 pcmk_node_t *new_node = NULL;
126
127 new_node = pe__copy_node((const pcmk_node_t *) gIter->data);
128 g_hash_table_insert(result, (gpointer) new_node->priv->id, new_node);
129 }
130 return result;
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 gint
149 pe__cmp_node_name(gconstpointer a, gconstpointer b)
150 {
151 const pcmk_node_t *node1 = (const pcmk_node_t *) a;
152 const pcmk_node_t *node2 = (const pcmk_node_t *) b;
153
154 if ((node1 == NULL) && (node2 == NULL)) {
155 return 0;
156 }
157
158 if (node1 == NULL) {
159 return -1;
160 }
161
162 if (node2 == NULL) {
163 return 1;
164 }
165
166 return pcmk__numeric_strcasecmp(node1->priv->name, node2->priv->name);
167 }
168
169
170
171
172
173
174
175
176
177
178 static void
179 pe__output_node_weights(const pcmk_resource_t *rsc, const char *comment,
180 GHashTable *nodes, pcmk_scheduler_t *scheduler)
181 {
182 pcmk__output_t *out = scheduler->priv->out;
183
184
185 GList *list = g_list_sort(g_hash_table_get_values(nodes),
186 pe__cmp_node_name);
187
188 for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
189 const pcmk_node_t *node = (const pcmk_node_t *) gIter->data;
190
191 out->message(out, "node-weight", rsc, comment, node->priv->name,
192 pcmk_readable_score(node->assign->score));
193 }
194 g_list_free(list);
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208 static void
209 pe__log_node_weights(const char *file, const char *function, int line,
210 const pcmk_resource_t *rsc, const char *comment,
211 GHashTable *nodes)
212 {
213 GHashTableIter iter;
214 pcmk_node_t *node = NULL;
215
216
217 pcmk__if_tracing({}, return);
218
219 g_hash_table_iter_init(&iter, nodes);
220 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
221 if (rsc) {
222 qb_log_from_external_source(function, file,
223 "%s: %s allocation score on %s: %s",
224 LOG_TRACE, line, 0,
225 comment, rsc->id,
226 pcmk__node_name(node),
227 pcmk_readable_score(node->assign->score));
228 } else {
229 qb_log_from_external_source(function, file, "%s: %s = %s",
230 LOG_TRACE, line, 0,
231 comment, pcmk__node_name(node),
232 pcmk_readable_score(node->assign->score));
233 }
234 }
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251 void
252 pe__show_node_scores_as(const char *file, const char *function, int line,
253 bool to_log, const pcmk_resource_t *rsc,
254 const char *comment, GHashTable *nodes,
255 pcmk_scheduler_t *scheduler)
256 {
257 if ((rsc != NULL) && pcmk_is_set(rsc->flags, pcmk__rsc_removed)) {
258
259 return;
260 }
261 if (nodes == NULL) {
262
263 return;
264 }
265
266 if (to_log) {
267 pe__log_node_weights(file, function, line, rsc, comment, nodes);
268 } else {
269 pe__output_node_weights(rsc, comment, nodes, scheduler);
270 }
271
272 if (rsc == NULL) {
273 return;
274 }
275
276
277 for (GList *gIter = rsc->priv->children;
278 gIter != NULL; gIter = gIter->next) {
279
280 pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
281
282 pe__show_node_scores_as(file, function, line, to_log, child, comment,
283 child->priv->allowed_nodes, scheduler);
284 }
285 }
286
287
288
289
290
291
292
293
294
295
296
297
298 gint
299 pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
300 {
301 const pcmk_resource_t *resource1 = (const pcmk_resource_t *)a;
302 const pcmk_resource_t *resource2 = (const pcmk_resource_t *)b;
303
304 if (a == NULL && b == NULL) {
305 return 0;
306 }
307 if (a == NULL) {
308 return 1;
309 }
310 if (b == NULL) {
311 return -1;
312 }
313
314 if (resource1->priv->priority > resource2->priv->priority) {
315 return -1;
316 }
317
318 if (resource1->priv->priority < resource2->priv->priority) {
319 return 1;
320 }
321
322 return 0;
323 }
324
325 static void
326 resource_node_score(pcmk_resource_t *rsc, const pcmk_node_t *node, int score,
327 const char *tag)
328 {
329 pcmk_node_t *match = NULL;
330
331 if ((pcmk_is_set(rsc->flags, pcmk__rsc_exclusive_probes)
332 || (node->assign->probe_mode == pcmk__probe_never))
333 && pcmk__str_eq(tag, "symmetric_default", pcmk__str_casei)) {
334
335
336
337
338 return;
339
340 } else {
341 for (GList *gIter = rsc->priv->children;
342 gIter != NULL; gIter = gIter->next) {
343
344 pcmk_resource_t *child_rsc = (pcmk_resource_t *) gIter->data;
345
346 resource_node_score(child_rsc, node, score, tag);
347 }
348 }
349
350 match = g_hash_table_lookup(rsc->priv->allowed_nodes, node->priv->id);
351 if (match == NULL) {
352 match = pe__copy_node(node);
353 g_hash_table_insert(rsc->priv->allowed_nodes,
354 (gpointer) match->priv->id, match);
355 }
356 match->assign->score = pcmk__add_scores(match->assign->score, score);
357 pcmk__rsc_trace(rsc,
358 "Enabling %s preference (%s) for %s on %s (now %s)",
359 tag, pcmk_readable_score(score), rsc->id,
360 pcmk__node_name(node),
361 pcmk_readable_score(match->assign->score));
362 }
363
364 void
365 resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score,
366 const char *tag, pcmk_scheduler_t *scheduler)
367 {
368 if (node != NULL) {
369 resource_node_score(rsc, node, score, tag);
370
371 } else if (scheduler != NULL) {
372 GList *gIter = scheduler->nodes;
373
374 for (; gIter != NULL; gIter = gIter->next) {
375 pcmk_node_t *node_iter = (pcmk_node_t *) gIter->data;
376
377 resource_node_score(rsc, node_iter, score, tag);
378 }
379
380 } else {
381 GHashTableIter iter;
382 pcmk_node_t *node_iter = NULL;
383
384 g_hash_table_iter_init(&iter, rsc->priv->allowed_nodes);
385 while (g_hash_table_iter_next(&iter, NULL, (void **)&node_iter)) {
386 resource_node_score(rsc, node_iter, score, tag);
387 }
388 }
389
390 if ((node == NULL) && (score == -PCMK_SCORE_INFINITY)
391 && (rsc->priv->assigned_node != NULL)) {
392
393
394 crm_info("Unassigning %s from %s",
395 rsc->id, pcmk__node_name(rsc->priv->assigned_node));
396 pcmk__free_node_copy(rsc->priv->assigned_node);
397 rsc->priv->assigned_node = NULL;
398 }
399 }
400
401 time_t
402 get_effective_time(pcmk_scheduler_t *scheduler)
403 {
404 if(scheduler) {
405 if (scheduler->priv->now == NULL) {
406 crm_trace("Recording a new 'now'");
407 scheduler->priv->now = crm_time_new(NULL);
408 }
409 return crm_time_get_seconds_since_epoch(scheduler->priv->now);
410 }
411
412 crm_trace("Defaulting to 'now'");
413 return time(NULL);
414 }
415
416 gboolean
417 get_target_role(const pcmk_resource_t *rsc, enum rsc_role_e *role)
418 {
419 enum rsc_role_e local_role = pcmk_role_unknown;
420 const char *value = g_hash_table_lookup(rsc->priv->meta,
421 PCMK_META_TARGET_ROLE);
422
423 CRM_CHECK(role != NULL, return FALSE);
424
425 if (pcmk__str_eq(value, PCMK_ROLE_STARTED,
426 pcmk__str_null_matches|pcmk__str_casei)) {
427 return FALSE;
428 }
429 if (pcmk__str_eq(PCMK_VALUE_DEFAULT, value, pcmk__str_casei)) {
430
431 pcmk__config_warn("Support for setting " PCMK_META_TARGET_ROLE
432 " to the explicit value '" PCMK_VALUE_DEFAULT
433 "' is deprecated and will be removed in a "
434 "future release (just leave it unset)");
435 return FALSE;
436 }
437
438 local_role = pcmk_parse_role(value);
439 if (local_role == pcmk_role_unknown) {
440 pcmk__config_err("Ignoring '" PCMK_META_TARGET_ROLE "' for %s "
441 "because '%s' is not valid", rsc->id, value);
442 return FALSE;
443
444 } else if (local_role > pcmk_role_started) {
445 if (pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
446 pcmk__rsc_promotable)) {
447 if (local_role > pcmk_role_unpromoted) {
448
449 return FALSE;
450 }
451
452 } else {
453 pcmk__config_err("Ignoring '" PCMK_META_TARGET_ROLE "' for %s "
454 "because '%s' only makes sense for promotable "
455 "clones", rsc->id, value);
456 return FALSE;
457 }
458 }
459
460 *role = local_role;
461 return TRUE;
462 }
463
464 gboolean
465 order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
466 {
467 GList *gIter = NULL;
468 pcmk__related_action_t *wrapper = NULL;
469 GList *list = NULL;
470
471 if (flags == pcmk__ar_none) {
472 return FALSE;
473 }
474
475 if ((first == NULL) || (then == NULL)) {
476 return FALSE;
477 }
478
479 crm_trace("Creating action wrappers for ordering: %s then %s",
480 first->uuid, then->uuid);
481
482
483 pcmk__assert(first != then);
484
485
486 gIter = first->actions_after;
487 for (; gIter != NULL; gIter = gIter->next) {
488 pcmk__related_action_t *after = gIter->data;
489
490 if ((after->action == then)
491 && pcmk_any_flags_set(after->flags, flags)) {
492 return FALSE;
493 }
494 }
495
496 wrapper = pcmk__assert_alloc(1, sizeof(pcmk__related_action_t));
497 wrapper->action = then;
498 wrapper->flags = flags;
499 list = first->actions_after;
500 list = g_list_prepend(list, wrapper);
501 first->actions_after = list;
502
503 wrapper = pcmk__assert_alloc(1, sizeof(pcmk__related_action_t));
504 wrapper->action = first;
505 wrapper->flags = flags;
506 list = then->actions_before;
507 list = g_list_prepend(list, wrapper);
508 then->actions_before = list;
509 return TRUE;
510 }
511
512 void
513 destroy_ticket(gpointer data)
514 {
515 pcmk__ticket_t *ticket = data;
516
517 if (ticket->state) {
518 g_hash_table_destroy(ticket->state);
519 }
520 free(ticket->id);
521 free(ticket);
522 }
523
524 pcmk__ticket_t *
525 ticket_new(const char *ticket_id, pcmk_scheduler_t *scheduler)
526 {
527 pcmk__ticket_t *ticket = NULL;
528
529 if (pcmk__str_empty(ticket_id)) {
530 return NULL;
531 }
532
533 if (scheduler->priv->ticket_constraints == NULL) {
534 scheduler->priv->ticket_constraints =
535 pcmk__strkey_table(free, destroy_ticket);
536 }
537
538 ticket = g_hash_table_lookup(scheduler->priv->ticket_constraints,
539 ticket_id);
540 if (ticket == NULL) {
541
542 ticket = calloc(1, sizeof(pcmk__ticket_t));
543 if (ticket == NULL) {
544 pcmk__sched_err(scheduler, "Cannot allocate ticket '%s'",
545 ticket_id);
546 return NULL;
547 }
548
549 crm_trace("Creating ticket entry for %s", ticket_id);
550
551 ticket->id = strdup(ticket_id);
552 ticket->last_granted = -1;
553 ticket->state = pcmk__strkey_table(free, free);
554
555 g_hash_table_insert(scheduler->priv->ticket_constraints,
556 pcmk__str_copy(ticket->id), ticket);
557 }
558
559 return ticket;
560 }
561
562 const char *
563 rsc_printable_id(const pcmk_resource_t *rsc)
564 {
565 if (pcmk_is_set(rsc->flags, pcmk__rsc_unique)) {
566 return rsc->id;
567 }
568 return pcmk__xe_id(rsc->priv->xml);
569 }
570
571 void
572 pe__clear_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
573 {
574 pcmk__clear_rsc_flags(rsc, flags);
575
576 for (GList *gIter = rsc->priv->children;
577 gIter != NULL; gIter = gIter->next) {
578
579 pe__clear_resource_flags_recursive((pcmk_resource_t *) gIter->data,
580 flags);
581 }
582 }
583
584 void
585 pe__clear_resource_flags_on_all(pcmk_scheduler_t *scheduler, uint64_t flag)
586 {
587 for (GList *lpc = scheduler->priv->resources;
588 lpc != NULL; lpc = lpc->next) {
589
590 pcmk_resource_t *r = (pcmk_resource_t *) lpc->data;
591
592 pe__clear_resource_flags_recursive(r, flag);
593 }
594 }
595
596 void
597 pe__set_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
598 {
599 pcmk__set_rsc_flags(rsc, flags);
600
601 for (GList *gIter = rsc->priv->children;
602 gIter != NULL; gIter = gIter->next) {
603
604 pe__set_resource_flags_recursive((pcmk_resource_t *) gIter->data,
605 flags);
606 }
607 }
608
609 void
610 trigger_unfencing(pcmk_resource_t *rsc, pcmk_node_t *node, const char *reason,
611 pcmk_action_t *dependency, pcmk_scheduler_t *scheduler)
612 {
613 if (!pcmk_is_set(scheduler->flags, pcmk__sched_enable_unfencing)) {
614
615 return;
616
617 } else if ((rsc != NULL)
618 && !pcmk_is_set(rsc->flags, pcmk__rsc_fence_device)) {
619
620 return;
621
622 } else if(node
623 && node->details->online
624 && node->details->unclean == FALSE
625 && node->details->shutdown == FALSE) {
626 pcmk_action_t *unfence = pe_fence_op(node, PCMK_ACTION_ON, FALSE,
627 reason, FALSE, scheduler);
628
629 if(dependency) {
630 order_actions(unfence, dependency, pcmk__ar_ordered);
631 }
632
633 } else if(rsc) {
634 GHashTableIter iter;
635
636 g_hash_table_iter_init(&iter, rsc->priv->allowed_nodes);
637 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
638 if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
639 trigger_unfencing(rsc, node, reason, dependency, scheduler);
640 }
641 }
642 }
643 }
644
645
646
647
648
649
650
651
652
653
654
655
656
657 bool
658 pe__shutdown_requested(const pcmk_node_t *node)
659 {
660 const char *shutdown = pcmk__node_attr(node, PCMK__NODE_ATTR_SHUTDOWN, NULL,
661 pcmk__rsc_node_current);
662
663 return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches);
664 }
665
666
667
668
669
670
671
672
673
674 void
675 pe__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler,
676 const char *reason)
677 {
678 if ((recheck > get_effective_time(scheduler))
679 && ((scheduler->priv->recheck_by == 0)
680 || (scheduler->priv->recheck_by > recheck))) {
681 scheduler->priv->recheck_by = recheck;
682 crm_debug("Updated next scheduler recheck to %s for %s",
683 pcmk__trim(ctime(&recheck)), reason);
684 }
685 }
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700 void
701 pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name,
702 const pe_rule_eval_data_t *rule_data,
703 GHashTable *hash, const char *always_first,
704 pcmk_scheduler_t *scheduler)
705 {
706 crm_time_t *next_change = NULL;
707
708 CRM_CHECK((set_name != NULL) && (rule_data != NULL) && (hash != NULL)
709 && (scheduler != NULL), return);
710
711
712 CRM_CHECK((rule_data->node_hash == NULL)
713 || (strcmp(set_name, PCMK_XE_META_ATTRIBUTES) != 0), return);
714
715 if (xml_obj == NULL) {
716 return;
717 }
718
719 next_change = crm_time_new_undefined();
720 pe_eval_nvpairs(scheduler->input, xml_obj, set_name, rule_data, hash,
721 always_first, FALSE, next_change);
722 if (crm_time_is_defined(next_change)) {
723 time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
724
725 pe__update_recheck_time(recheck, scheduler, "rule evaluation");
726 }
727 crm_time_free(next_change);
728 }
729
730 bool
731 pe__resource_is_disabled(const pcmk_resource_t *rsc)
732 {
733 const char *target_role = NULL;
734
735 CRM_CHECK(rsc != NULL, return false);
736 target_role = g_hash_table_lookup(rsc->priv->meta,
737 PCMK_META_TARGET_ROLE);
738 if (target_role) {
739
740 enum rsc_role_e target_role_e = pcmk_parse_role(target_role);
741
742 if ((target_role_e == pcmk_role_stopped)
743 || ((target_role_e == pcmk_role_unpromoted)
744 && pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
745 pcmk__rsc_promotable))) {
746 return true;
747 }
748 }
749 return false;
750 }
751
752
753
754
755
756
757
758
759
760
761 bool
762 pe__rsc_running_on_only(const pcmk_resource_t *rsc, const pcmk_node_t *node)
763 {
764 return (rsc != NULL) && pcmk__list_of_1(rsc->priv->active_nodes)
765 && pcmk__same_node((const pcmk_node_t *)
766 rsc->priv->active_nodes->data, node);
767 }
768
769 bool
770 pe__rsc_running_on_any(pcmk_resource_t *rsc, GList *node_list)
771 {
772 if (rsc != NULL) {
773 for (GList *ele = rsc->priv->active_nodes; ele; ele = ele->next) {
774 pcmk_node_t *node = (pcmk_node_t *) ele->data;
775 if (pcmk__str_in_list(node->priv->name, node_list,
776 pcmk__str_star_matches|pcmk__str_casei)) {
777 return true;
778 }
779 }
780 }
781 return false;
782 }
783
784 bool
785 pcmk__rsc_filtered_by_node(pcmk_resource_t *rsc, GList *only_node)
786 {
787 return rsc->priv->fns->active(rsc, FALSE)
788 && !pe__rsc_running_on_any(rsc, only_node);
789 }
790
791 GList *
792 pe__filter_rsc_list(GList *rscs, GList *filter)
793 {
794 GList *retval = NULL;
795
796 for (GList *gIter = rscs; gIter; gIter = gIter->next) {
797 pcmk_resource_t *rsc = (pcmk_resource_t *) gIter->data;
798
799
800
801
802 if (pcmk__str_in_list(rsc_printable_id(rsc), filter, pcmk__str_star_matches) ||
803 ((rsc->priv->parent != NULL)
804 && pcmk__str_in_list(rsc_printable_id(rsc->priv->parent),
805 filter, pcmk__str_star_matches))) {
806 retval = g_list_prepend(retval, rsc);
807 }
808 }
809
810 return retval;
811 }
812
813 GList *
814 pe__build_node_name_list(pcmk_scheduler_t *scheduler, const char *s)
815 {
816 GList *nodes = NULL;
817
818 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
819
820
821
822
823 nodes = g_list_prepend(nodes, strdup("*"));
824 } else {
825 pcmk_node_t *node = pcmk_find_node(scheduler, s);
826
827 if (node) {
828
829
830
831 nodes = g_list_prepend(nodes, strdup(s));
832 } else {
833
834
835
836
837
838
839 nodes = pe__unames_with_tag(scheduler, s);
840 }
841 }
842
843 return nodes;
844 }
845
846 GList *
847 pe__build_rsc_list(pcmk_scheduler_t *scheduler, const char *s)
848 {
849 GList *resources = NULL;
850
851 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
852 resources = g_list_prepend(resources, strdup("*"));
853 } else {
854 const uint32_t flags = pcmk_rsc_match_history|pcmk_rsc_match_basename;
855 pcmk_resource_t *rsc =
856 pe_find_resource_with_flags(scheduler->priv->resources, s, flags);
857
858 if (rsc) {
859
860
861
862
863
864 if (strstr(s, ":") != NULL) {
865 resources = g_list_prepend(resources, strdup(rsc->id));
866 } else {
867 resources = g_list_prepend(resources, strdup(rsc_printable_id(rsc)));
868 }
869 } else {
870
871
872
873
874 resources = pe__rscs_with_tag(scheduler, s);
875 }
876 }
877
878 return resources;
879 }
880
881 xmlNode *
882 pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name)
883 {
884 const pcmk_resource_t *parent = pe__const_top_resource(rsc, false);
885 const char *rsc_id = rsc->id;
886 const pcmk_scheduler_t *scheduler = rsc->priv->scheduler;
887
888 if (pcmk__is_clone(parent)) {
889 rsc_id = pe__clone_child_id(parent);
890 }
891
892 for (xmlNode *xml_op = pcmk__xe_first_child(scheduler->priv->failed,
893 NULL, NULL, NULL);
894 xml_op != NULL; xml_op = pcmk__xe_next(xml_op, NULL)) {
895
896 const char *value = NULL;
897 char *op_id = NULL;
898
899
900 if (!pcmk_xe_mask_probe_failure(xml_op)) {
901 continue;
902 }
903
904
905
906
907 value = crm_element_value(xml_op, PCMK__META_ON_NODE);
908 if (value == NULL || !pcmk__str_eq(value, name, pcmk__str_casei|pcmk__str_null_matches)) {
909 continue;
910 }
911
912 if (!parse_op_key(pcmk__xe_history_key(xml_op), &op_id, NULL, NULL)) {
913 continue;
914 }
915
916
917 if (!pcmk__str_eq(op_id, rsc_id, pcmk__str_none)) {
918 free(op_id);
919 continue;
920 }
921
922 free(op_id);
923 return xml_op;
924 }
925
926 return NULL;
927 }