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