This source file includes following definitions.
- pe_can_fence
- pe__copy_node
- node_list_exclude
- pe__node_list2table
- pe__cmp_node_name
- pe__output_node_weights
- pe__log_node_weights
- pe__show_node_weights_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
- add_tag_ref
- pe__shutdown_requested
- pe__update_recheck_time
- pe__unpack_dataset_nvpairs
- pe__resource_is_disabled
- 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/msg_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(pe_working_set_t *data_set, pe_node_t *node)
37 {
38 if (pe__is_guest_node(node)) {
39
40
41
42 pe_resource_t *rsc = node->details->remote_rsc->container;
43
44 for (GList *n = rsc->running_on; n != NULL; n = n->next) {
45 pe_node_t *container_node = n->data;
46
47 if (!container_node->details->online
48 && !pe_can_fence(data_set, container_node)) {
49 return false;
50 }
51 }
52 return true;
53
54 } else if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
55 return false;
56
57 } else if (!pcmk_is_set(data_set->flags, pe_flag_have_stonith_resource)) {
58 return false;
59
60 } else if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
61 return true;
62
63 } else if (data_set->no_quorum_policy == 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 pe__node_name(node));
72 return true;
73 }
74
75 crm_trace("Cannot fence %s", pe__node_name(node));
76 return false;
77 }
78
79
80
81
82
83
84
85
86
87
88 pe_node_t *
89 pe__copy_node(const pe_node_t *this_node)
90 {
91 pe_node_t *new_node = NULL;
92
93 CRM_ASSERT(this_node != NULL);
94
95 new_node = calloc(1, sizeof(pe_node_t));
96 CRM_ASSERT(new_node != NULL);
97
98 new_node->rsc_discover_mode = this_node->rsc_discover_mode;
99 new_node->weight = this_node->weight;
100 new_node->fixed = this_node->fixed;
101 new_node->details = this_node->details;
102
103 return new_node;
104 }
105
106
107 void
108 node_list_exclude(GHashTable * hash, GList *list, gboolean merge_scores)
109 {
110 GHashTable *result = hash;
111 pe_node_t *other_node = NULL;
112 GList *gIter = list;
113
114 GHashTableIter iter;
115 pe_node_t *node = NULL;
116
117 g_hash_table_iter_init(&iter, hash);
118 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
119
120 other_node = pe_find_node_id(list, node->details->id);
121 if (other_node == NULL) {
122 node->weight = -INFINITY;
123 } else if (merge_scores) {
124 node->weight = pcmk__add_scores(node->weight, other_node->weight);
125 }
126 }
127
128 for (; gIter != NULL; gIter = gIter->next) {
129 pe_node_t *node = (pe_node_t *) gIter->data;
130
131 other_node = pe_hash_table_lookup(result, node->details->id);
132
133 if (other_node == NULL) {
134 pe_node_t *new_node = pe__copy_node(node);
135
136 new_node->weight = -INFINITY;
137 g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
138 }
139 }
140 }
141
142
143
144
145
146
147
148
149
150 GHashTable *
151 pe__node_list2table(GList *list)
152 {
153 GHashTable *result = NULL;
154
155 result = pcmk__strkey_table(NULL, free);
156 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
157 pe_node_t *new_node = pe__copy_node((pe_node_t *) gIter->data);
158
159 g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
160 }
161 return result;
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179 gint
180 pe__cmp_node_name(gconstpointer a, gconstpointer b)
181 {
182 const pe_node_t *node1 = (const pe_node_t *) a;
183 const pe_node_t *node2 = (const pe_node_t *) b;
184
185 if ((node1 == NULL) && (node2 == NULL)) {
186 return 0;
187 }
188
189 if (node1 == NULL) {
190 return -1;
191 }
192
193 if (node2 == NULL) {
194 return 1;
195 }
196
197 return pcmk__numeric_strcasecmp(node1->details->uname,
198 node2->details->uname);
199 }
200
201
202
203
204
205
206
207
208
209 static void
210 pe__output_node_weights(pe_resource_t *rsc, const char *comment,
211 GHashTable *nodes, pe_working_set_t *data_set)
212 {
213 pcmk__output_t *out = data_set->priv;
214
215
216 GList *list = g_list_sort(g_hash_table_get_values(nodes),
217 pe__cmp_node_name);
218
219 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
220 pe_node_t *node = (pe_node_t *) gIter->data;
221
222 out->message(out, "node-weight", rsc, comment, node->details->uname,
223 pcmk_readable_score(node->weight));
224 }
225 g_list_free(list);
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239 static void
240 pe__log_node_weights(const char *file, const char *function, int line,
241 pe_resource_t *rsc, const char *comment, GHashTable *nodes)
242 {
243 GHashTableIter iter;
244 pe_node_t *node = NULL;
245
246
247 pcmk__log_else(LOG_TRACE, return);
248
249 g_hash_table_iter_init(&iter, nodes);
250 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
251 if (rsc) {
252 qb_log_from_external_source(function, file,
253 "%s: %s allocation score on %s: %s",
254 LOG_TRACE, line, 0,
255 comment, rsc->id,
256 pe__node_name(node),
257 pcmk_readable_score(node->weight));
258 } else {
259 qb_log_from_external_source(function, file, "%s: %s = %s",
260 LOG_TRACE, line, 0,
261 comment, pe__node_name(node),
262 pcmk_readable_score(node->weight));
263 }
264 }
265 }
266
267
268
269
270
271
272
273
274
275
276
277
278
279 void
280 pe__show_node_weights_as(const char *file, const char *function, int line,
281 bool to_log, pe_resource_t *rsc, const char *comment,
282 GHashTable *nodes, pe_working_set_t *data_set)
283 {
284 if (rsc != NULL && pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
285
286 return;
287 }
288 if (nodes == NULL) {
289
290 return;
291 }
292
293 if (to_log) {
294 pe__log_node_weights(file, function, line, rsc, comment, nodes);
295 } else {
296 pe__output_node_weights(rsc, comment, nodes, data_set);
297 }
298
299
300 if (rsc && rsc->children) {
301 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
302 pe_resource_t *child = (pe_resource_t *) gIter->data;
303
304 pe__show_node_weights_as(file, function, line, to_log, child,
305 comment, child->allowed_nodes, data_set);
306 }
307 }
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324 gint
325 pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
326 {
327 const pe_resource_t *resource1 = (const pe_resource_t *)a;
328 const pe_resource_t *resource2 = (const pe_resource_t *)b;
329
330 if (a == NULL && b == NULL) {
331 return 0;
332 }
333 if (a == NULL) {
334 return 1;
335 }
336 if (b == NULL) {
337 return -1;
338 }
339
340 if (resource1->priority > resource2->priority) {
341 return -1;
342 }
343
344 if (resource1->priority < resource2->priority) {
345 return 1;
346 }
347
348 return 0;
349 }
350
351 static void
352 resource_node_score(pe_resource_t * rsc, pe_node_t * node, int score, const char *tag)
353 {
354 pe_node_t *match = NULL;
355
356 if ((rsc->exclusive_discover || (node->rsc_discover_mode == pe_discover_never))
357 && pcmk__str_eq(tag, "symmetric_default", pcmk__str_casei)) {
358
359
360
361
362 return;
363
364 } else if (rsc->children) {
365 GList *gIter = rsc->children;
366
367 for (; gIter != NULL; gIter = gIter->next) {
368 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
369
370 resource_node_score(child_rsc, node, score, tag);
371 }
372 }
373
374 pe_rsc_trace(rsc, "Setting %s for %s on %s: %d",
375 tag, rsc->id, pe__node_name(node), score);
376 match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
377 if (match == NULL) {
378 match = pe__copy_node(node);
379 g_hash_table_insert(rsc->allowed_nodes, (gpointer) match->details->id, match);
380 }
381 match->weight = pcmk__add_scores(match->weight, score);
382 }
383
384 void
385 resource_location(pe_resource_t * rsc, pe_node_t * node, int score, const char *tag,
386 pe_working_set_t * data_set)
387 {
388 if (node != NULL) {
389 resource_node_score(rsc, node, score, tag);
390
391 } else if (data_set != NULL) {
392 GList *gIter = data_set->nodes;
393
394 for (; gIter != NULL; gIter = gIter->next) {
395 pe_node_t *node_iter = (pe_node_t *) gIter->data;
396
397 resource_node_score(rsc, node_iter, score, tag);
398 }
399
400 } else {
401 GHashTableIter iter;
402 pe_node_t *node_iter = NULL;
403
404 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
405 while (g_hash_table_iter_next(&iter, NULL, (void **)&node_iter)) {
406 resource_node_score(rsc, node_iter, score, tag);
407 }
408 }
409
410 if (node == NULL && score == -INFINITY) {
411 if (rsc->allocated_to) {
412 crm_info("Deallocating %s from %s",
413 rsc->id, pe__node_name(rsc->allocated_to));
414 free(rsc->allocated_to);
415 rsc->allocated_to = NULL;
416 }
417 }
418 }
419
420 time_t
421 get_effective_time(pe_working_set_t * data_set)
422 {
423 if(data_set) {
424 if (data_set->now == NULL) {
425 crm_trace("Recording a new 'now'");
426 data_set->now = crm_time_new(NULL);
427 }
428 return crm_time_get_seconds_since_epoch(data_set->now);
429 }
430
431 crm_trace("Defaulting to 'now'");
432 return time(NULL);
433 }
434
435 gboolean
436 get_target_role(pe_resource_t * rsc, enum rsc_role_e * role)
437 {
438 enum rsc_role_e local_role = RSC_ROLE_UNKNOWN;
439 const char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
440
441 CRM_CHECK(role != NULL, return FALSE);
442
443 if (pcmk__str_eq(value, "started", pcmk__str_null_matches | pcmk__str_casei)
444 || pcmk__str_eq("default", value, pcmk__str_casei)) {
445 return FALSE;
446 }
447
448 local_role = text2role(value);
449 if (local_role == RSC_ROLE_UNKNOWN) {
450 pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
451 "because '%s' is not valid", rsc->id, value);
452 return FALSE;
453
454 } else if (local_role > RSC_ROLE_STARTED) {
455 if (pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable)) {
456 if (local_role > RSC_ROLE_UNPROMOTED) {
457
458 return FALSE;
459 }
460
461 } else {
462 pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
463 "because '%s' only makes sense for promotable "
464 "clones", rsc->id, value);
465 return FALSE;
466 }
467 }
468
469 *role = local_role;
470 return TRUE;
471 }
472
473 gboolean
474 order_actions(pe_action_t * lh_action, pe_action_t * rh_action, enum pe_ordering order)
475 {
476 GList *gIter = NULL;
477 pe_action_wrapper_t *wrapper = NULL;
478 GList *list = NULL;
479
480 if (order == pe_order_none) {
481 return FALSE;
482 }
483
484 if (lh_action == NULL || rh_action == NULL) {
485 return FALSE;
486 }
487
488 crm_trace("Creating action wrappers for ordering: %s then %s",
489 lh_action->uuid, rh_action->uuid);
490
491
492 CRM_ASSERT(lh_action != rh_action);
493
494
495 gIter = lh_action->actions_after;
496 for (; gIter != NULL; gIter = gIter->next) {
497 pe_action_wrapper_t *after = (pe_action_wrapper_t *) gIter->data;
498
499 if (after->action == rh_action && (after->type & order)) {
500 return FALSE;
501 }
502 }
503
504 wrapper = calloc(1, sizeof(pe_action_wrapper_t));
505 wrapper->action = rh_action;
506 wrapper->type = order;
507 list = lh_action->actions_after;
508 list = g_list_prepend(list, wrapper);
509 lh_action->actions_after = list;
510
511 wrapper = calloc(1, sizeof(pe_action_wrapper_t));
512 wrapper->action = lh_action;
513 wrapper->type = order;
514 list = rh_action->actions_before;
515 list = g_list_prepend(list, wrapper);
516 rh_action->actions_before = list;
517 return TRUE;
518 }
519
520 void
521 destroy_ticket(gpointer data)
522 {
523 pe_ticket_t *ticket = data;
524
525 if (ticket->state) {
526 g_hash_table_destroy(ticket->state);
527 }
528 free(ticket->id);
529 free(ticket);
530 }
531
532 pe_ticket_t *
533 ticket_new(const char *ticket_id, pe_working_set_t * data_set)
534 {
535 pe_ticket_t *ticket = NULL;
536
537 if (pcmk__str_empty(ticket_id)) {
538 return NULL;
539 }
540
541 if (data_set->tickets == NULL) {
542 data_set->tickets = pcmk__strkey_table(free, destroy_ticket);
543 }
544
545 ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
546 if (ticket == NULL) {
547
548 ticket = calloc(1, sizeof(pe_ticket_t));
549 if (ticket == NULL) {
550 crm_err("Cannot allocate ticket '%s'", ticket_id);
551 return NULL;
552 }
553
554 crm_trace("Creaing ticket entry for %s", ticket_id);
555
556 ticket->id = strdup(ticket_id);
557 ticket->granted = FALSE;
558 ticket->last_granted = -1;
559 ticket->standby = FALSE;
560 ticket->state = pcmk__strkey_table(free, free);
561
562 g_hash_table_insert(data_set->tickets, strdup(ticket->id), ticket);
563 }
564
565 return ticket;
566 }
567
568 const char *rsc_printable_id(pe_resource_t *rsc)
569 {
570 if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
571 return ID(rsc->xml);
572 }
573 return rsc->id;
574 }
575
576 void
577 pe__clear_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
578 {
579 pe__clear_resource_flags(rsc, flags);
580 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
581 pe__clear_resource_flags_recursive((pe_resource_t *) gIter->data, flags);
582 }
583 }
584
585 void
586 pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
587 {
588 for (GList *lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
589 pe_resource_t *r = (pe_resource_t *) lpc->data;
590 pe__clear_resource_flags_recursive(r, flag);
591 }
592 }
593
594 void
595 pe__set_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
596 {
597 pe__set_resource_flags(rsc, flags);
598 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
599 pe__set_resource_flags_recursive((pe_resource_t *) gIter->data, flags);
600 }
601 }
602
603 void
604 trigger_unfencing(
605 pe_resource_t * rsc, pe_node_t *node, const char *reason, pe_action_t *dependency, pe_working_set_t * data_set)
606 {
607 if (!pcmk_is_set(data_set->flags, pe_flag_enable_unfencing)) {
608
609 return;
610
611 } else if ((rsc != NULL)
612 && !pcmk_is_set(rsc->flags, pe_rsc_fence_device)) {
613
614 return;
615
616 } else if(node
617 && node->details->online
618 && node->details->unclean == FALSE
619 && node->details->shutdown == FALSE) {
620 pe_action_t *unfence = pe_fence_op(node, "on", FALSE, reason, FALSE, data_set);
621
622 if(dependency) {
623 order_actions(unfence, dependency, pe_order_optional);
624 }
625
626 } else if(rsc) {
627 GHashTableIter iter;
628
629 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
630 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
631 if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
632 trigger_unfencing(rsc, node, reason, dependency, data_set);
633 }
634 }
635 }
636 }
637
638 gboolean
639 add_tag_ref(GHashTable * tags, const char * tag_name, const char * obj_ref)
640 {
641 pe_tag_t *tag = NULL;
642 GList *gIter = NULL;
643 gboolean is_existing = FALSE;
644
645 CRM_CHECK(tags && tag_name && obj_ref, return FALSE);
646
647 tag = g_hash_table_lookup(tags, tag_name);
648 if (tag == NULL) {
649 tag = calloc(1, sizeof(pe_tag_t));
650 if (tag == NULL) {
651 return FALSE;
652 }
653 tag->id = strdup(tag_name);
654 tag->refs = NULL;
655 g_hash_table_insert(tags, strdup(tag_name), tag);
656 }
657
658 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
659 const char *existing_ref = (const char *) gIter->data;
660
661 if (pcmk__str_eq(existing_ref, obj_ref, pcmk__str_none)){
662 is_existing = TRUE;
663 break;
664 }
665 }
666
667 if (is_existing == FALSE) {
668 tag->refs = g_list_append(tag->refs, strdup(obj_ref));
669 crm_trace("Added: tag=%s ref=%s", tag->id, obj_ref);
670 }
671
672 return TRUE;
673 }
674
675
676
677
678
679
680
681
682
683
684
685
686
687 bool
688 pe__shutdown_requested(pe_node_t *node)
689 {
690 const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
691
692 return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches);
693 }
694
695
696
697
698
699
700
701
702 void
703 pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
704 {
705 if ((recheck > get_effective_time(data_set))
706 && ((data_set->recheck_by == 0)
707 || (data_set->recheck_by > recheck))) {
708 data_set->recheck_by = recheck;
709 }
710 }
711
712
713
714
715
716 void
717 pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name,
718 pe_rule_eval_data_t *rule_data, GHashTable *hash,
719 const char *always_first, gboolean overwrite,
720 pe_working_set_t *data_set)
721 {
722 crm_time_t *next_change = crm_time_new_undefined();
723
724 pe_eval_nvpairs(data_set->input, xml_obj, set_name, rule_data, hash,
725 always_first, overwrite, next_change);
726 if (crm_time_is_defined(next_change)) {
727 time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
728
729 pe__update_recheck_time(recheck, data_set);
730 }
731 crm_time_free(next_change);
732 }
733
734 bool
735 pe__resource_is_disabled(pe_resource_t *rsc)
736 {
737 const char *target_role = NULL;
738
739 CRM_CHECK(rsc != NULL, return false);
740 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
741 if (target_role) {
742 enum rsc_role_e target_role_e = text2role(target_role);
743
744 if ((target_role_e == RSC_ROLE_STOPPED)
745 || ((target_role_e == RSC_ROLE_UNPROMOTED)
746 && pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable))) {
747 return true;
748 }
749 }
750 return false;
751 }
752
753 bool
754 pe__rsc_running_on_any(pe_resource_t *rsc, GList *node_list)
755 {
756 for (GList *ele = rsc->running_on; ele; ele = ele->next) {
757 pe_node_t *node = (pe_node_t *) ele->data;
758 if (pcmk__str_in_list(node->details->uname, node_list,
759 pcmk__str_star_matches|pcmk__str_casei)) {
760 return true;
761 }
762 }
763
764 return false;
765 }
766
767 bool
768 pcmk__rsc_filtered_by_node(pe_resource_t *rsc, GList *only_node)
769 {
770 return (rsc->fns->active(rsc, FALSE) && !pe__rsc_running_on_any(rsc, only_node));
771 }
772
773 GList *
774 pe__filter_rsc_list(GList *rscs, GList *filter)
775 {
776 GList *retval = NULL;
777
778 for (GList *gIter = rscs; gIter; gIter = gIter->next) {
779 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
780
781
782
783
784 if (pcmk__str_in_list(rsc_printable_id(rsc), filter, pcmk__str_star_matches) ||
785 (rsc->parent && pcmk__str_in_list(rsc_printable_id(rsc->parent), filter, pcmk__str_star_matches))) {
786 retval = g_list_prepend(retval, rsc);
787 }
788 }
789
790 return retval;
791 }
792
793 GList *
794 pe__build_node_name_list(pe_working_set_t *data_set, const char *s) {
795 GList *nodes = NULL;
796
797 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
798
799
800
801
802 nodes = g_list_prepend(nodes, strdup("*"));
803 } else {
804 pe_node_t *node = pe_find_node(data_set->nodes, s);
805
806 if (node) {
807
808
809
810 nodes = g_list_prepend(nodes, strdup(s));
811 } else {
812
813
814
815
816
817
818 nodes = pe__unames_with_tag(data_set, s);
819 }
820 }
821
822 return nodes;
823 }
824
825 GList *
826 pe__build_rsc_list(pe_working_set_t *data_set, const char *s) {
827 GList *resources = NULL;
828
829 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
830 resources = g_list_prepend(resources, strdup("*"));
831 } else {
832 pe_resource_t *rsc = pe_find_resource_with_flags(data_set->resources, s,
833 pe_find_renamed|pe_find_any);
834
835 if (rsc) {
836
837
838
839
840
841 if (strstr(s, ":") != NULL) {
842 resources = g_list_prepend(resources, strdup(rsc->id));
843 } else {
844 resources = g_list_prepend(resources, strdup(rsc_printable_id(rsc)));
845 }
846 } else {
847
848
849
850
851 resources = pe__rscs_with_tag(data_set, s);
852 }
853 }
854
855 return resources;
856 }
857
858 xmlNode *
859 pe__failed_probe_for_rsc(pe_resource_t *rsc, const char *name)
860 {
861 pe_resource_t *parent = uber_parent(rsc);
862 const char *rsc_id = rsc->id;
863
864 if (rsc->variant == pe_clone) {
865 rsc_id = pe__clone_child_id(rsc);
866 } else if (parent->variant == pe_clone) {
867 rsc_id = pe__clone_child_id(parent);
868 }
869
870 for (xmlNode *xml_op = pcmk__xml_first_child(rsc->cluster->failed); xml_op != NULL;
871 xml_op = pcmk__xml_next(xml_op)) {
872 const char *value = NULL;
873 char *op_id = NULL;
874
875
876 if (!pcmk_xe_mask_probe_failure(xml_op)) {
877 continue;
878 }
879
880
881
882
883 value = crm_element_value(xml_op, XML_LRM_ATTR_TARGET);
884 if (value == NULL || !pcmk__str_eq(value, name, pcmk__str_casei|pcmk__str_null_matches)) {
885 continue;
886 }
887
888
889 value = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
890 if (!parse_op_key(value ? value : ID(xml_op), &op_id, NULL, NULL)) {
891 continue;
892 }
893
894
895 if (!pcmk__str_eq(op_id, rsc_id, pcmk__str_none)) {
896 free(op_id);
897 continue;
898 }
899
900 free(op_id);
901 return xml_op;
902 }
903
904 return NULL;
905 }