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