This source file includes following definitions.
- assign_replica
- pcmk__bundle_assign
- create_replica_actions
- pcmk__bundle_create_actions
- replica_internal_constraints
- pcmk__bundle_internal_constraints
- match_replica_container
- get_bundle_node_host
- compatible_container
- replica_apply_coloc_score
- pcmk__bundle_apply_coloc_score
- pcmk__with_bundle_colocations
- pcmk__bundle_with_colocations
- pcmk__bundle_action_flags
- apply_location_to_replica
- pcmk__bundle_apply_location
- add_replica_actions_to_graph
- pcmk__bundle_add_actions_to_graph
- order_replica_start_after
- create_replica_probes
- pcmk__bundle_create_probe
- output_replica_actions
- pcmk__output_bundle_actions
- pcmk__bundle_add_utilization
- pcmk__bundle_shutdown_lock
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdbool.h>
13
14 #include <libxml/tree.h>
15
16 #include <crm/common/xml.h>
17 #include <pacemaker-internal.h>
18
19 #include "libpacemaker_private.h"
20
21 struct assign_data {
22 const pcmk_node_t *prefer;
23 bool stop_if_fail;
24 };
25
26
27
28
29
30
31
32
33
34
35 static bool
36 assign_replica(pcmk__bundle_replica_t *replica, void *user_data)
37 {
38 pcmk_node_t *container_host = NULL;
39
40 struct assign_data *assign_data = user_data;
41 const pcmk_node_t *prefer = assign_data->prefer;
42 bool stop_if_fail = assign_data->stop_if_fail;
43
44 const pcmk_resource_t *bundle = pe__const_top_resource(replica->container,
45 true);
46
47 if (replica->ip != NULL) {
48 pcmk__rsc_trace(bundle, "Assigning bundle %s IP %s",
49 bundle->id, replica->ip->id);
50 replica->ip->priv->cmds->assign(replica->ip, prefer, stop_if_fail);
51 }
52
53 container_host = replica->container->priv->assigned_node;
54 if (replica->remote != NULL) {
55 if (pcmk__is_pacemaker_remote_node(container_host)) {
56
57
58
59
60 pcmk__new_colocation("#replica-remote-with-host-remote", NULL,
61 PCMK_SCORE_INFINITY, replica->remote,
62 container_host->priv->remote, NULL,
63 NULL, pcmk__coloc_influence);
64 }
65 pcmk__rsc_trace(bundle, "Assigning bundle %s connection %s",
66 bundle->id, replica->remote->id);
67 replica->remote->priv->cmds->assign(replica->remote, prefer,
68 stop_if_fail);
69 }
70
71 if (replica->child != NULL) {
72 pcmk_node_t *node = NULL;
73 GHashTableIter iter;
74
75 g_hash_table_iter_init(&iter, replica->child->priv->allowed_nodes);
76 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
77 if (!pcmk__same_node(node, replica->node)) {
78 node->assign->score = -PCMK_SCORE_INFINITY;
79 } else if (!pcmk__threshold_reached(replica->child, node, NULL)) {
80 node->assign->score = PCMK_SCORE_INFINITY;
81 }
82 }
83
84 pcmk__set_rsc_flags(replica->child->priv->parent,
85 pcmk__rsc_assigning);
86 pcmk__rsc_trace(bundle, "Assigning bundle %s replica child %s",
87 bundle->id, replica->child->id);
88 replica->child->priv->cmds->assign(replica->child, replica->node,
89 stop_if_fail);
90 pcmk__clear_rsc_flags(replica->child->priv->parent,
91 pcmk__rsc_assigning);
92 }
93 return true;
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 pcmk_node_t *
116 pcmk__bundle_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer,
117 bool stop_if_fail)
118 {
119 GList *containers = NULL;
120 pcmk_resource_t *bundled_resource = NULL;
121 struct assign_data assign_data = { prefer, stop_if_fail };
122
123 pcmk__assert(pcmk__is_bundle(rsc));
124
125 pcmk__rsc_trace(rsc, "Assigning bundle %s", rsc->id);
126 pcmk__set_rsc_flags(rsc, pcmk__rsc_assigning);
127
128 pe__show_node_scores(!pcmk_is_set(rsc->priv->scheduler->flags,
129 pcmk__sched_output_scores),
130 rsc, __func__, rsc->priv->allowed_nodes,
131 rsc->priv->scheduler);
132
133
134 containers = g_list_sort(pe__bundle_containers(rsc), pcmk__cmp_instance);
135 pcmk__assign_instances(rsc, containers, pe__bundle_max(rsc),
136 rsc->priv->fns->max_per_node(rsc));
137 g_list_free(containers);
138
139
140 pe__foreach_bundle_replica(rsc, assign_replica, (void *) &assign_data);
141
142
143 bundled_resource = pe__bundled_resource(rsc);
144 if (bundled_resource != NULL) {
145 pcmk_node_t *node = NULL;
146 GHashTableIter iter;
147
148 g_hash_table_iter_init(&iter, bundled_resource->priv->allowed_nodes);
149 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
150 if (pe__node_is_bundle_instance(rsc, node)) {
151 node->assign->score = 0;
152 } else {
153 node->assign->score = -PCMK_SCORE_INFINITY;
154 }
155 }
156 bundled_resource->priv->cmds->assign(bundled_resource, prefer,
157 stop_if_fail);
158 }
159
160 pcmk__clear_rsc_flags(rsc, pcmk__rsc_assigning|pcmk__rsc_unassigned);
161 return NULL;
162 }
163
164
165
166
167
168
169
170
171
172
173 static bool
174 create_replica_actions(pcmk__bundle_replica_t *replica, void *user_data)
175 {
176 if (replica->ip != NULL) {
177 replica->ip->priv->cmds->create_actions(replica->ip);
178 }
179 if (replica->container != NULL) {
180 replica->container->priv->cmds->create_actions(replica->container);
181 }
182 if (replica->remote != NULL) {
183 replica->remote->priv->cmds->create_actions(replica->remote);
184 }
185 return true;
186 }
187
188
189
190
191
192
193
194 void
195 pcmk__bundle_create_actions(pcmk_resource_t *rsc)
196 {
197 pcmk_action_t *action = NULL;
198 GList *containers = NULL;
199 pcmk_resource_t *bundled_resource = NULL;
200
201 pcmk__assert(pcmk__is_bundle(rsc));
202
203 pe__foreach_bundle_replica(rsc, create_replica_actions, NULL);
204
205 containers = pe__bundle_containers(rsc);
206 pcmk__create_instance_actions(rsc, containers);
207 g_list_free(containers);
208
209 bundled_resource = pe__bundled_resource(rsc);
210 if (bundled_resource != NULL) {
211 bundled_resource->priv->cmds->create_actions(bundled_resource);
212
213 if (pcmk_is_set(bundled_resource->flags, pcmk__rsc_promotable)) {
214 pe__new_rsc_pseudo_action(rsc, PCMK_ACTION_PROMOTE, true, true);
215 action = pe__new_rsc_pseudo_action(rsc, PCMK_ACTION_PROMOTED,
216 true, true);
217 action->priority = PCMK_SCORE_INFINITY;
218
219 pe__new_rsc_pseudo_action(rsc, PCMK_ACTION_DEMOTE, true, true);
220 action = pe__new_rsc_pseudo_action(rsc, PCMK_ACTION_DEMOTED,
221 true, true);
222 action->priority = PCMK_SCORE_INFINITY;
223 }
224 }
225 }
226
227
228
229
230
231
232
233
234
235
236 static bool
237 replica_internal_constraints(pcmk__bundle_replica_t *replica, void *user_data)
238 {
239 pcmk_resource_t *bundle = user_data;
240
241 replica->container->priv->cmds->internal_constraints(replica->container);
242
243
244 pcmk__order_starts(bundle, replica->container,
245 pcmk__ar_unrunnable_first_blocks
246 |pcmk__ar_then_implies_first_graphed);
247
248
249 if (replica->child != NULL) {
250 pcmk__order_stops(bundle, replica->child,
251 pcmk__ar_then_implies_first_graphed);
252 }
253 pcmk__order_stops(bundle, replica->container,
254 pcmk__ar_then_implies_first_graphed);
255
256
257 pcmk__order_resource_actions(replica->container, PCMK_ACTION_START, bundle,
258 PCMK_ACTION_RUNNING,
259 pcmk__ar_first_implies_then_graphed);
260
261
262 pcmk__order_resource_actions(replica->container, PCMK_ACTION_STOP, bundle,
263 PCMK_ACTION_STOPPED,
264 pcmk__ar_first_implies_then_graphed);
265
266 if (replica->ip != NULL) {
267 replica->ip->priv->cmds->internal_constraints(replica->ip);
268
269
270 pcmk__order_starts(replica->ip, replica->container,
271 pcmk__ar_unrunnable_first_blocks
272 |pcmk__ar_guest_allowed);
273 pcmk__order_stops(replica->container, replica->ip,
274 pcmk__ar_then_implies_first|pcmk__ar_guest_allowed);
275
276 pcmk__new_colocation("#ip-with-container", NULL, PCMK_SCORE_INFINITY,
277 replica->ip, replica->container, NULL, NULL,
278 pcmk__coloc_influence);
279 }
280
281 if (replica->remote != NULL) {
282
283
284
285
286
287 replica->remote->priv->cmds->internal_constraints(replica->remote);
288 }
289
290 if (replica->child != NULL) {
291 pcmk__assert(replica->remote != NULL);
292
293 }
294 return true;
295 }
296
297
298
299
300
301
302
303 void
304 pcmk__bundle_internal_constraints(pcmk_resource_t *rsc)
305 {
306 pcmk_resource_t *bundled_resource = NULL;
307
308 pcmk__assert(pcmk__is_bundle(rsc));
309
310 pe__foreach_bundle_replica(rsc, replica_internal_constraints, rsc);
311
312 bundled_resource = pe__bundled_resource(rsc);
313 if (bundled_resource == NULL) {
314 return;
315 }
316
317
318 pcmk__order_resource_actions(rsc, PCMK_ACTION_START, bundled_resource,
319 PCMK_ACTION_START,
320 pcmk__ar_then_implies_first_graphed);
321
322
323 pcmk__order_resource_actions(bundled_resource, PCMK_ACTION_RUNNING,
324 rsc, PCMK_ACTION_RUNNING,
325 pcmk__ar_first_implies_then_graphed);
326
327
328 pcmk__order_resource_actions(rsc, PCMK_ACTION_STOP, bundled_resource,
329 PCMK_ACTION_STOP,
330 pcmk__ar_then_implies_first_graphed);
331
332
333 pcmk__order_resource_actions(bundled_resource, PCMK_ACTION_STOPPED,
334 rsc, PCMK_ACTION_STOPPED,
335 pcmk__ar_first_implies_then_graphed);
336
337 bundled_resource->priv->cmds->internal_constraints(bundled_resource);
338
339 if (!pcmk_is_set(bundled_resource->flags, pcmk__rsc_promotable)) {
340 return;
341 }
342 pcmk__promotable_restart_ordering(rsc);
343
344
345 pcmk__order_resource_actions(rsc, PCMK_ACTION_DEMOTE, bundled_resource,
346 PCMK_ACTION_DEMOTE,
347 pcmk__ar_then_implies_first_graphed);
348
349
350 pcmk__order_resource_actions(bundled_resource, PCMK_ACTION_DEMOTED,
351 rsc, PCMK_ACTION_DEMOTED,
352 pcmk__ar_first_implies_then_graphed);
353
354
355 pcmk__order_resource_actions(rsc, PCMK_ACTION_PROMOTE,
356 bundled_resource, PCMK_ACTION_PROMOTE,
357 pcmk__ar_then_implies_first_graphed);
358
359
360 pcmk__order_resource_actions(bundled_resource, PCMK_ACTION_PROMOTED,
361 rsc, PCMK_ACTION_PROMOTED,
362 pcmk__ar_first_implies_then_graphed);
363 }
364
365 struct match_data {
366 const pcmk_node_t *node;
367 pcmk_resource_t *container;
368 };
369
370
371
372
373
374
375
376
377
378
379
380 static bool
381 match_replica_container(const pcmk__bundle_replica_t *replica, void *user_data)
382 {
383 struct match_data *match_data = user_data;
384
385 if (pcmk__instance_matches(replica->container, match_data->node,
386 pcmk_role_unknown, false)) {
387 match_data->container = replica->container;
388 return false;
389 }
390 return true;
391 }
392
393
394
395
396
397
398
399
400
401
402 static const pcmk_node_t *
403 get_bundle_node_host(const pcmk_node_t *node)
404 {
405 if (pcmk__is_bundle_node(node)) {
406 const pcmk_resource_t *container = NULL;
407
408 container = node->priv->remote->priv->launcher;
409 return container->priv->fns->location(container, NULL,
410 pcmk__rsc_node_assigned);
411 }
412 return node;
413 }
414
415
416
417
418
419
420
421
422
423
424
425
426 static pcmk_resource_t *
427 compatible_container(const pcmk_resource_t *dependent,
428 const pcmk_resource_t *bundle)
429 {
430 GList *scratch = NULL;
431 struct match_data match_data = { NULL, NULL };
432
433
434 match_data.node = dependent->priv->fns->location(dependent, NULL,
435 pcmk__rsc_node_assigned);
436 match_data.node = get_bundle_node_host(match_data.node);
437 if (match_data.node != NULL) {
438 pe__foreach_const_bundle_replica(bundle, match_replica_container,
439 &match_data);
440 return match_data.container;
441 }
442
443
444 scratch = g_hash_table_get_values(dependent->priv->allowed_nodes);
445 scratch = pcmk__sort_nodes(scratch, NULL);
446 for (const GList *iter = scratch; iter != NULL; iter = iter->next) {
447 match_data.node = iter->data;
448 match_data.node = get_bundle_node_host(match_data.node);
449 if (match_data.node == NULL) {
450 continue;
451 }
452
453 pe__foreach_const_bundle_replica(bundle, match_replica_container,
454 &match_data);
455 if (match_data.container != NULL) {
456 break;
457 }
458 }
459 g_list_free(scratch);
460 return match_data.container;
461 }
462
463 struct coloc_data {
464 const pcmk__colocation_t *colocation;
465 pcmk_resource_t *dependent;
466 GList *container_hosts;
467 int priority_delta;
468 };
469
470
471
472
473
474
475
476
477
478
479 static bool
480 replica_apply_coloc_score(const pcmk__bundle_replica_t *replica,
481 void *user_data)
482 {
483 struct coloc_data *coloc_data = user_data;
484 pcmk_node_t *chosen = NULL;
485 pcmk_resource_t *container = replica->container;
486
487 if (coloc_data->colocation->score < PCMK_SCORE_INFINITY) {
488 int priority_delta =
489 container->priv->cmds->apply_coloc_score(coloc_data->dependent,
490 container,
491 coloc_data->colocation,
492 false);
493
494 coloc_data->priority_delta =
495 pcmk__add_scores(coloc_data->priority_delta, priority_delta);
496 return true;
497 }
498
499 chosen = container->priv->fns->location(container, NULL,
500 pcmk__rsc_node_assigned);
501 if ((chosen == NULL)
502 || is_set_recursive(container, pcmk__rsc_blocked, true)) {
503 return true;
504 }
505
506 if ((coloc_data->colocation->primary_role >= pcmk_role_promoted)
507 && ((replica->child == NULL)
508 || (replica->child->priv->next_role < pcmk_role_promoted))) {
509 return true;
510 }
511
512 pcmk__rsc_trace(pe__const_top_resource(container, true),
513 "Allowing mandatory colocation %s using %s @%d",
514 coloc_data->colocation->id, pcmk__node_name(chosen),
515 chosen->assign->score);
516 coloc_data->container_hosts = g_list_prepend(coloc_data->container_hosts,
517 chosen);
518 return true;
519 }
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536 int
537 pcmk__bundle_apply_coloc_score(pcmk_resource_t *dependent,
538 const pcmk_resource_t *primary,
539 const pcmk__colocation_t *colocation,
540 bool for_dependent)
541 {
542 struct coloc_data coloc_data = { colocation, dependent, NULL, 0 };
543
544
545
546
547
548 pcmk__assert(pcmk__is_bundle(primary) && pcmk__is_primitive(dependent)
549 && (colocation != NULL) && !for_dependent);
550
551 if (pcmk_is_set(primary->flags, pcmk__rsc_unassigned)) {
552 pcmk__rsc_trace(primary,
553 "Skipping applying colocation %s "
554 "because %s is still provisional",
555 colocation->id, primary->id);
556 return 0;
557 }
558 pcmk__rsc_trace(primary, "Applying colocation %s (%s with %s at %s)",
559 colocation->id, dependent->id, primary->id,
560 pcmk_readable_score(colocation->score));
561
562
563
564
565 if (colocation->dependent->priv->variant > pcmk__rsc_variant_group) {
566 const pcmk_resource_t *primary_container = NULL;
567
568 primary_container = compatible_container(dependent, primary);
569 if (primary_container != NULL) {
570 pcmk__rsc_debug(primary, "Pairing %s with %s",
571 dependent->id, primary_container->id);
572
573 return dependent->priv->cmds->apply_coloc_score(dependent,
574 primary_container,
575 colocation, true);
576 }
577
578 if (colocation->score >= PCMK_SCORE_INFINITY) {
579
580 crm_notice("%s cannot run because there is no compatible "
581 "instance of %s to colocate with",
582 dependent->id, primary->id);
583 pcmk__assign_resource(dependent, NULL, true, true);
584
585 } else {
586 pcmk__rsc_debug(primary,
587 "%s cannot be colocated with any instance of %s",
588 dependent->id, primary->id);
589 }
590 return 0;
591 }
592
593 pe__foreach_const_bundle_replica(primary, replica_apply_coloc_score,
594 &coloc_data);
595
596 if (colocation->score >= PCMK_SCORE_INFINITY) {
597 pcmk__colocation_intersect_nodes(dependent, primary, colocation,
598 coloc_data.container_hosts, false);
599 }
600 g_list_free(coloc_data.container_hosts);
601 return coloc_data.priority_delta;
602 }
603
604
605 void
606 pcmk__with_bundle_colocations(const pcmk_resource_t *rsc,
607 const pcmk_resource_t *orig_rsc, GList **list)
608 {
609 const pcmk_resource_t *bundled_rsc = NULL;
610
611 pcmk__assert(pcmk__is_bundle(rsc) && (orig_rsc != NULL) && (list != NULL));
612
613
614 if ((orig_rsc == rsc)
615 || pcmk_is_set(orig_rsc->flags, pcmk__rsc_replica_container)) {
616
617 pcmk__add_with_this_list(list, rsc->priv->with_this_colocations,
618 orig_rsc);
619 return;
620 }
621
622
623
624
625 bundled_rsc = pe__bundled_resource(rsc);
626 if ((bundled_rsc == NULL)
627 || !pcmk_is_set(bundled_rsc->flags, pcmk__rsc_promotable)
628 || (pe__const_top_resource(orig_rsc, false) != bundled_rsc)) {
629 return;
630 }
631
632 if (orig_rsc == bundled_rsc) {
633 if (pe__clone_flag_is_set(orig_rsc,
634 pcmk__clone_promotion_constrained)) {
635
636
637
638 pcmk__add_with_this_list(list, rsc->priv->with_this_colocations,
639 orig_rsc);
640 }
641
642 } else if (!pcmk_is_set(orig_rsc->flags, pcmk__rsc_unassigned)) {
643
644
645
646 pcmk__add_with_this_list(list, rsc->priv->with_this_colocations,
647 orig_rsc);
648 }
649 }
650
651
652 void
653 pcmk__bundle_with_colocations(const pcmk_resource_t *rsc,
654 const pcmk_resource_t *orig_rsc, GList **list)
655 {
656 const pcmk_resource_t *bundled_rsc = NULL;
657
658 pcmk__assert(pcmk__is_bundle(rsc) && (orig_rsc != NULL) && (list != NULL));
659
660
661 if ((orig_rsc == rsc)
662 || pcmk_is_set(orig_rsc->flags, pcmk__rsc_replica_container)) {
663
664 pcmk__add_this_with_list(list, rsc->priv->this_with_colocations,
665 orig_rsc);
666 return;
667 }
668
669
670
671
672 bundled_rsc = pe__bundled_resource(rsc);
673 if ((bundled_rsc == NULL)
674 || !pcmk_is_set(bundled_rsc->flags, pcmk__rsc_promotable)
675 || (pe__const_top_resource(orig_rsc, false) != bundled_rsc)) {
676 return;
677 }
678
679 if (orig_rsc == bundled_rsc) {
680 if (pe__clone_flag_is_set(orig_rsc,
681 pcmk__clone_promotion_constrained)) {
682
683
684
685 pcmk__add_this_with_list(list, rsc->priv->this_with_colocations,
686 orig_rsc);
687 }
688
689 } else if (!pcmk_is_set(orig_rsc->flags, pcmk__rsc_unassigned)) {
690
691
692
693 pcmk__add_this_with_list(list, rsc->priv->this_with_colocations,
694 orig_rsc);
695 }
696 }
697
698
699
700
701
702
703
704
705
706
707 uint32_t
708 pcmk__bundle_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
709 {
710 GList *containers = NULL;
711 uint32_t flags = 0;
712 pcmk_resource_t *bundled_resource = NULL;
713
714 pcmk__assert((action != NULL) && pcmk__is_bundle(action->rsc));
715
716 bundled_resource = pe__bundled_resource(action->rsc);
717 if (bundled_resource != NULL) {
718 GList *children = bundled_resource->priv->children;
719
720
721 switch (get_complex_task(bundled_resource, action->task)) {
722 case pcmk__action_unspecified:
723 case pcmk__action_notify:
724 case pcmk__action_notified:
725 case pcmk__action_promote:
726 case pcmk__action_promoted:
727 case pcmk__action_demote:
728 case pcmk__action_demoted:
729 return pcmk__collective_action_flags(action, children, node);
730 default:
731 break;
732 }
733 }
734
735 containers = pe__bundle_containers(action->rsc);
736 flags = pcmk__collective_action_flags(action, containers, node);
737 g_list_free(containers);
738 return flags;
739 }
740
741
742
743
744
745
746
747
748
749
750 static bool
751 apply_location_to_replica(pcmk__bundle_replica_t *replica, void *user_data)
752 {
753 pcmk__location_t *location = user_data;
754
755 replica->container->priv->cmds->apply_location(replica->container,
756 location);
757 if (replica->ip != NULL) {
758 replica->ip->priv->cmds->apply_location(replica->ip, location);
759 }
760 return true;
761 }
762
763
764
765
766
767
768
769
770 void
771 pcmk__bundle_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
772 {
773 pcmk_resource_t *bundled_resource = NULL;
774
775 pcmk__assert((location != NULL) && pcmk__is_bundle(rsc));
776
777 pcmk__apply_location(rsc, location);
778 pe__foreach_bundle_replica(rsc, apply_location_to_replica, location);
779
780 bundled_resource = pe__bundled_resource(rsc);
781 if ((bundled_resource != NULL)
782 && ((location->role_filter == pcmk_role_unpromoted)
783 || (location->role_filter == pcmk_role_promoted))) {
784
785 bundled_resource->priv->cmds->apply_location(bundled_resource,
786 location);
787 bundled_resource->priv->location_constraints =
788 g_list_prepend(bundled_resource->priv->location_constraints,
789 location);
790 }
791 }
792
793 #define XPATH_REMOTE "//nvpair[@name='" PCMK_REMOTE_RA_ADDR "']"
794
795
796
797
798
799
800
801
802
803
804 static bool
805 add_replica_actions_to_graph(pcmk__bundle_replica_t *replica, void *user_data)
806 {
807 if ((replica->remote != NULL)
808 && pe__bundle_needs_remote_name(replica->remote)) {
809
810
811
812
813
814
815
816 xmlNode *nvpair = pcmk__xpath_find_one(replica->remote->priv->xml->doc,
817 XPATH_REMOTE, LOG_ERR);
818 const char *calculated_addr = NULL;
819
820
821 calculated_addr = pe__add_bundle_remote_name(replica->remote, nvpair,
822 PCMK_XA_VALUE);
823 if (calculated_addr != NULL) {
824
825
826
827
828
829
830 GHashTable *params = NULL;
831
832 params = pe_rsc_params(replica->remote, NULL,
833 replica->remote->priv->scheduler);
834 pcmk__insert_dup(params, PCMK_REMOTE_RA_ADDR, calculated_addr);
835 } else {
836 pcmk_resource_t *bundle = user_data;
837
838
839
840
841
842
843
844
845 pcmk__rsc_info(bundle,
846 "Unable to determine address for bundle %s "
847 "remote connection", bundle->id);
848 }
849 }
850 if (replica->ip != NULL) {
851 replica->ip->priv->cmds->add_actions_to_graph(replica->ip);
852 }
853 replica->container->priv->cmds->add_actions_to_graph(replica->container);
854 if (replica->remote != NULL) {
855 replica->remote->priv->cmds->add_actions_to_graph(replica->remote);
856 }
857 return true;
858 }
859
860
861
862
863
864
865
866 void
867 pcmk__bundle_add_actions_to_graph(pcmk_resource_t *rsc)
868 {
869 pcmk_resource_t *bundled_resource = NULL;
870
871 pcmk__assert(pcmk__is_bundle(rsc));
872
873 bundled_resource = pe__bundled_resource(rsc);
874 if (bundled_resource != NULL) {
875 bundled_resource->priv->cmds->add_actions_to_graph(bundled_resource);
876 }
877 pe__foreach_bundle_replica(rsc, add_replica_actions_to_graph, rsc);
878 }
879
880 struct probe_data {
881 pcmk_resource_t *bundle;
882 pcmk_node_t *node;
883 bool any_created;
884 };
885
886
887
888
889
890
891
892
893
894
895 static bool
896 order_replica_start_after(pcmk__bundle_replica_t *replica, void *user_data)
897 {
898 pcmk__bundle_replica_t *probed_replica = user_data;
899
900 if ((replica == probed_replica) || (replica->container == NULL)) {
901 return true;
902 }
903 pcmk__new_ordering(probed_replica->container,
904 pcmk__op_key(probed_replica->container->id,
905 PCMK_ACTION_MONITOR, 0),
906 NULL, replica->container,
907 pcmk__op_key(replica->container->id, PCMK_ACTION_START,
908 0),
909 NULL, pcmk__ar_ordered|pcmk__ar_if_on_same_node,
910 replica->container->priv->scheduler);
911 return true;
912 }
913
914
915
916
917
918
919
920
921
922
923 static bool
924 create_replica_probes(pcmk__bundle_replica_t *replica, void *user_data)
925 {
926 struct probe_data *probe_data = user_data;
927 pcmk_resource_t *bundle = probe_data->bundle;
928
929
930
931
932 pcmk__assert(bundle != NULL);
933
934 if ((replica->ip != NULL)
935 && replica->ip->priv->cmds->create_probe(replica->ip,
936 probe_data->node)) {
937 probe_data->any_created = true;
938 }
939 if ((replica->child != NULL)
940 && pcmk__same_node(probe_data->node, replica->node)
941 && replica->child->priv->cmds->create_probe(replica->child,
942 probe_data->node)) {
943 probe_data->any_created = true;
944 }
945 if (replica->container->priv->cmds->create_probe(replica->container,
946 probe_data->node)) {
947 probe_data->any_created = true;
948
949
950
951
952
953
954
955
956
957
958
959
960
961 if (bundle->priv->fns->max_per_node(bundle) == 1) {
962 pe__foreach_bundle_replica(bundle, order_replica_start_after,
963 replica);
964 }
965 }
966 if ((replica->remote != NULL)
967 && replica->remote->priv->cmds->create_probe(replica->remote,
968 probe_data->node)) {
969
970
971
972
973 char *probe_uuid = pcmk__op_key(replica->remote->id,
974 PCMK_ACTION_MONITOR, 0);
975 pcmk_action_t *probe = NULL;
976
977 probe = find_first_action(replica->remote->priv->actions, probe_uuid,
978 NULL, probe_data->node);
979 free(probe_uuid);
980 if (probe != NULL) {
981 probe_data->any_created = true;
982 pcmk__rsc_trace(bundle, "Ordering %s probe on %s",
983 replica->remote->id,
984 pcmk__node_name(probe_data->node));
985 pcmk__new_ordering(replica->container,
986 pcmk__op_key(replica->container->id,
987 PCMK_ACTION_START, 0),
988 NULL, replica->remote, NULL, probe,
989 pcmk__ar_nested_remote_probe,
990 bundle->priv->scheduler);
991 }
992 }
993 return true;
994 }
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006 bool
1007 pcmk__bundle_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
1008 {
1009 struct probe_data probe_data = { rsc, node, false };
1010
1011 pcmk__assert(pcmk__is_bundle(rsc));
1012 pe__foreach_bundle_replica(rsc, create_replica_probes, &probe_data);
1013 return probe_data.any_created;
1014 }
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025 static bool
1026 output_replica_actions(pcmk__bundle_replica_t *replica, void *user_data)
1027 {
1028 if (replica->ip != NULL) {
1029 replica->ip->priv->cmds->output_actions(replica->ip);
1030 }
1031 replica->container->priv->cmds->output_actions(replica->container);
1032 if (replica->remote != NULL) {
1033 replica->remote->priv->cmds->output_actions(replica->remote);
1034 }
1035 if (replica->child != NULL) {
1036 replica->child->priv->cmds->output_actions(replica->child);
1037 }
1038 return true;
1039 }
1040
1041
1042
1043
1044
1045
1046
1047 void
1048 pcmk__output_bundle_actions(pcmk_resource_t *rsc)
1049 {
1050 pcmk__assert(pcmk__is_bundle(rsc));
1051 pe__foreach_bundle_replica(rsc, output_replica_actions, NULL);
1052 }
1053
1054
1055 void
1056 pcmk__bundle_add_utilization(const pcmk_resource_t *rsc,
1057 const pcmk_resource_t *orig_rsc, GList *all_rscs,
1058 GHashTable *utilization)
1059 {
1060 pcmk_resource_t *container = NULL;
1061
1062 pcmk__assert(pcmk__is_bundle(rsc));
1063
1064 if (!pcmk_is_set(rsc->flags, pcmk__rsc_unassigned)) {
1065 return;
1066 }
1067
1068
1069
1070
1071
1072 container = pe__first_container(rsc);
1073 if (container != NULL) {
1074 container->priv->cmds->add_utilization(container, orig_rsc, all_rscs,
1075 utilization);
1076 }
1077 }
1078
1079
1080 void
1081 pcmk__bundle_shutdown_lock(pcmk_resource_t *rsc)
1082 {
1083 pcmk__assert(pcmk__is_bundle(rsc));
1084
1085 }