pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_sched_bundle.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2024 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU General Public License version 2
7 * or later (GPLv2+) WITHOUT ANY WARRANTY.
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
18
19struct assign_data {
20 const pcmk_node_t *prefer;
21 bool stop_if_fail;
22};
23
33static bool
34assign_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 /* REMOTE_CONTAINER_HACK: "Nested" connection resources must be on
55 * the same host because Pacemaker Remote only supports a single
56 * active connection.
57 */
58 pcmk__new_colocation("#replica-remote-with-host-remote", NULL,
60 container_host->details->remote_rsc, NULL,
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
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);
87 }
88 return true;
89}
90
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 CRM_ASSERT(pcmk__is_bundle(rsc));
119
120 pcmk__rsc_trace(rsc, "Assigning bundle %s", rsc->id);
122
125 rsc, __func__, rsc->allowed_nodes, rsc->cluster);
126
127 // Assign all containers first, so we know what nodes the bundle will be on
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 // Then assign remaining replica resources
134 pe__foreach_bundle_replica(rsc, assign_replica, (void *) &assign_data);
135
136 // Finally, assign the bundled resources to each bundle node
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 {
148 }
149 }
150 bundled_resource->cmds->assign(bundled_resource, prefer, stop_if_fail);
151 }
152
154 return NULL;
155}
156
166static bool
167create_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
187void
189{
190 pcmk_action_t *action = NULL;
191 GList *containers = NULL;
192 pcmk_resource_t *bundled_resource = NULL;
193
194 CRM_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)) {
209 true, true);
210 action->priority = PCMK_SCORE_INFINITY;
211
214 true, true);
215 action->priority = PCMK_SCORE_INFINITY;
216 }
217 }
218}
219
229static bool
230replica_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 // Start bundle -> start replica container
237 pcmk__order_starts(bundle, replica->container,
240
241 // Stop bundle -> stop replica child and container
242 if (replica->child != NULL) {
243 pcmk__order_stops(bundle, replica->child,
245 }
246 pcmk__order_stops(bundle, replica->container,
248
249 // Start replica container -> bundle is started
253
254 // Stop replica container -> bundle is stopped
258
259 if (replica->ip != NULL) {
260 replica->ip->cmds->internal_constraints(replica->ip);
261
262 // Replica IP address -> replica container (symmetric)
263 pcmk__order_starts(replica->ip, replica->container,
266 pcmk__order_stops(replica->container, replica->ip,
268
269 pcmk__new_colocation("#ip-with-container", NULL, PCMK_SCORE_INFINITY,
270 replica->ip, replica->container, NULL, NULL,
272 }
273
274 if (replica->remote != NULL) {
275 /* This handles ordering and colocating remote relative to container
276 * (via "#resource-with-container"). Since IP is also ordered and
277 * colocated relative to the container, we don't need to do anything
278 * explicit here with IP.
279 */
280 replica->remote->cmds->internal_constraints(replica->remote);
281 }
282
283 if (replica->child != NULL) {
284 CRM_ASSERT(replica->remote != NULL);
285 // "Start remote then child" is implicit in scheduler's remote logic
286 }
287 return true;
288}
289
296void
298{
299 pcmk_resource_t *bundled_resource = NULL;
300
301 CRM_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 // Start bundle -> start bundled clone
311 pcmk__order_resource_actions(rsc, PCMK_ACTION_START, bundled_resource,
314
315 // Bundled clone is started -> bundle is started
319
320 // Stop bundle -> stop bundled clone
321 pcmk__order_resource_actions(rsc, PCMK_ACTION_STOP, bundled_resource,
324
325 // Bundled clone is stopped -> bundle is stopped
329
330 bundled_resource->cmds->internal_constraints(bundled_resource);
331
332 if (!pcmk_is_set(bundled_resource->flags, pcmk_rsc_promotable)) {
333 return;
334 }
336
337 // Demote bundle -> demote bundled clone
341
342 // Bundled clone is demoted -> bundle is demoted
346
347 // Promote bundle -> promote bundled clone
349 bundled_resource, PCMK_ACTION_PROMOTE,
351
352 // Bundled clone is promoted -> bundle is promoted
356}
357
358struct match_data {
359 const pcmk_node_t *node; // Node to compare against replica
360 pcmk_resource_t *container; // Replica container corresponding to node
361};
362
373static bool
374match_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; // Match found, don't bother searching further replicas
382 }
383 return true; // No match, keep searching
384}
385
395static const pcmk_node_t *
396get_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
417static pcmk_resource_t *
418compatible_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 // If dependent is assigned, only check there
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 // Otherwise, check for any of the dependent's allowed nodes
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
453struct coloc_data {
454 const pcmk__colocation_t *colocation;
455 pcmk_resource_t *dependent;
456 GList *container_hosts;
457 int priority_delta;
458};
459
469static bool
470replica_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
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
524int
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 /* This should never be called for the bundle itself as a dependent.
533 * Instead, we add its colocation constraints to its containers and bundled
534 * primitive and call the apply_coloc_score() method for them as dependents.
535 */
536 CRM_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 /* If the constraint dependent is a clone or bundle, "dependent" here is one
551 * of its instances. Look for a compatible instance of this bundle.
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) { // Success, we found one
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 // Failure, and it's fatal
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 { // Failure, but we can ignore it
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// Bundle implementation of pcmk_assignment_methods_t:with_this_colocations()
593void
595 const pcmk_resource_t *orig_rsc, GList **list)
596{
597 const pcmk_resource_t *bundled_rsc = NULL;
598
599 CRM_ASSERT(pcmk__is_bundle(rsc) && (orig_rsc != NULL) && (list != NULL));
600
601 // The bundle itself and its containers always get its colocations
602 if ((orig_rsc == rsc)
604
605 pcmk__add_with_this_list(list, rsc->rsc_cons_lhs, orig_rsc);
606 return;
607 }
608
609 /* The bundled resource gets the colocations if it's promotable and we've
610 * begun choosing roles
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,
622 /* orig_rsc is the clone and we're setting roles (or have already
623 * done so)
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 /* orig_rsc is an instance and is already assigned. If something
630 * requests colocations for orig_rsc now, it's for setting roles.
631 */
632 pcmk__add_with_this_list(list, rsc->rsc_cons_lhs, orig_rsc);
633 }
634}
635
636// Bundle implementation of pcmk_assignment_methods_t:this_with_colocations()
637void
639 const pcmk_resource_t *orig_rsc, GList **list)
640{
641 const pcmk_resource_t *bundled_rsc = NULL;
642
643 CRM_ASSERT(pcmk__is_bundle(rsc) && (orig_rsc != NULL) && (list != NULL));
644
645 // The bundle itself and its containers always get its colocations
646 if ((orig_rsc == rsc)
648
649 pcmk__add_this_with_list(list, rsc->rsc_cons, orig_rsc);
650 return;
651 }
652
653 /* The bundled resource gets the colocations if it's promotable and we've
654 * begun choosing roles
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,
666 /* orig_rsc is the clone and we're setting roles (or have already
667 * done so)
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 /* orig_rsc is an instance and is already assigned. If something
674 * requests colocations for orig_rsc now, it's for setting roles.
675 */
676 pcmk__add_this_with_list(list, rsc->rsc_cons, orig_rsc);
677 }
678}
679
689uint32_t
691{
692 GList *containers = NULL;
693 uint32_t flags = 0;
694 pcmk_resource_t *bundled_resource = NULL;
695
696 CRM_ASSERT((action != NULL) && pcmk__is_bundle(action->rsc));
697
698 bundled_resource = pe__bundled_resource(action->rsc);
699 if (bundled_resource != NULL) {
700 // Clone actions are done on the bundled clone resource, not container
701 switch (get_complex_task(bundled_resource, action->task)) {
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
732static bool
733apply_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
753void
755{
756 pcmk_resource_t *bundled_resource = NULL;
757
758 CRM_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
784static bool
785add_replica_actions_to_graph(pcmk__bundle_replica_t *replica, void *user_data)
786{
787 if ((replica->remote != NULL) && (replica->container != NULL)
789
790 /* REMOTE_CONTAINER_HACK: Allow remote nodes to run containers that
791 * run pacemaker-remoted inside, without needing a separate IP for
792 * the container. This is done by configuring the inner remote's
793 * connection host as the magic string "#uname", then
794 * replacing it with the underlying host when needed.
795 */
796 xmlNode *nvpair = get_xpath_object(XPATH_REMOTE, replica->remote->xml,
797 LOG_ERR);
798 const char *calculated_addr = NULL;
799
800 // Replace the value in replica->remote->xml (if appropriate)
801 calculated_addr = pe__add_bundle_remote_name(replica->remote, nvpair,
803 if (calculated_addr != NULL) {
804 /* Since this is for the bundle as a resource, and not any
805 * particular action, replace the value in the default
806 * parameters (not evaluated for node). create_graph_action()
807 * will grab it from there to replace it in node-evaluated
808 * parameters.
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 /* The only way to get here is if the remote connection is
818 * neither currently running nor scheduled to run. That means we
819 * won't be doing any operations that require addr (only start
820 * requires it; we additionally use it to compare digests when
821 * unpacking status, promote, and migrate_from history, but
822 * that's already happened by this point).
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
847void
849{
850 pcmk_resource_t *bundled_resource = NULL;
851
852 CRM_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
861struct probe_data {
862 pcmk_resource_t *bundle; // Bundle being probed
863 pcmk_node_t *node; // Node to create probes on
864 bool any_created; // Whether any probes have been created
865};
866
876static bool
877order_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,
887 NULL, replica->container,
889 0),
891 replica->container->cluster);
892 return true;
893}
894
904static bool
905create_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 /* If we're limited to one replica per host (due to
925 * the lack of an IP range probably), then we don't
926 * want any of our peer containers starting until
927 * we've established that no other copies are already
928 * running.
929 *
930 * Partly this is to ensure that the maximum replicas per host is
931 * observed, but also to ensure that the containers
932 * don't fail to start because the necessary port
933 * mappings (which won't include an IP for uniqueness)
934 * are already taken
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 /* Do not probe the remote resource until we know where the container is
945 * running. This is required for REMOTE_CONTAINER_HACK to correctly
946 * probe remote resources.
947 */
948 char *probe_uuid = pcmk__op_key(replica->remote->id,
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));
961 pcmk__op_key(replica->container->id,
963 NULL, replica->remote, NULL, probe,
965 probe_data->bundle->cluster);
966 }
967 }
968 return true;
969}
970
981bool
983{
984 struct probe_data probe_data = { rsc, node, false };
985
986 CRM_ASSERT(pcmk__is_bundle(rsc));
987 pe__foreach_bundle_replica(rsc, create_replica_probes, &probe_data);
988 return probe_data.any_created;
989}
990
1000static bool
1001output_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
1024void
1026{
1027 CRM_ASSERT(pcmk__is_bundle(rsc));
1028 pe__foreach_bundle_replica(rsc, output_replica_actions, NULL);
1029}
1030
1031// Bundle implementation of pcmk_assignment_methods_t:add_utilization()
1032void
1034 const pcmk_resource_t *orig_rsc, GList *all_rscs,
1035 GHashTable *utilization)
1036{
1037 pcmk_resource_t *container = NULL;
1038
1039 CRM_ASSERT(pcmk__is_bundle(rsc));
1040
1042 return;
1043 }
1044
1045 /* All bundle replicas are identical, so using the utilization of the first
1046 * is sufficient for any. Only the implicit container resource can have
1047 * utilization values.
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// Bundle implementation of pcmk_assignment_methods_t:shutdown_lock()
1057void
1059{
1060 CRM_ASSERT(pcmk__is_bundle(rsc));
1061 // Bundles currently don't support shutdown locks
1062}
@ pcmk__ar_if_on_same_node
Relation applies only if actions are on same node.
@ pcmk__ar_then_implies_first
@ pcmk__ar_then_implies_first_graphed
If 'then' is required, 'first' must be added to the transition graph.
@ pcmk__ar_first_implies_then_graphed
If 'first' is required and runnable, 'then' must be in graph.
@ pcmk__ar_nested_remote_probe
@ pcmk__ar_unrunnable_first_blocks
'then' is runnable (and migratable) only if 'first' is runnable
@ pcmk__ar_ordered
Actions are ordered (optionally, if no other flags are set)
@ pcmk__ar_guest_allowed
Ordering applies even if 'first' runs on guest node created by 'then'.
#define PCMK_ACTION_PROMOTED
Definition actions.h:67
#define PCMK_ACTION_STOP
Definition actions.h:75
#define PCMK_ACTION_RUNNING
Definition actions.h:71
#define PCMK_ACTION_PROMOTE
Definition actions.h:66
#define PCMK_ACTION_START
Definition actions.h:72
@ pcmk_action_demote
Definition actions.h:101
@ pcmk_action_promote
Definition actions.h:98
@ pcmk_action_notified
Definition actions.h:96
@ pcmk_action_demoted
Definition actions.h:102
@ pcmk_action_unspecified
Definition actions.h:84
@ pcmk_action_promoted
Definition actions.h:99
@ pcmk_action_notify
Definition actions.h:95
#define PCMK_ACTION_STOPPED
Definition actions.h:76
#define PCMK_ACTION_MONITOR
Definition actions.h:60
#define PCMK_ACTION_DEMOTED
Definition actions.h:50
#define PCMK_ACTION_DEMOTE
Definition actions.h:49
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition actions.c:196
@ pcmk__clone_promotion_constrained
uint64_t flags
Definition remote.c:3
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:98
GHashTable * pe_rsc_params(pcmk_resource_t *rsc, const pcmk_node_t *node, pcmk_scheduler_t *scheduler)
Get a table of resource parameters.
Definition complex.c:484
G_GNUC_INTERNAL void pcmk__add_this_with_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
#define pcmk__order_starts(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__new_colocation(const char *id, const char *node_attr, int score, pcmk_resource_t *dependent, pcmk_resource_t *primary, const char *dependent_role, const char *primary_role, uint32_t flags)
G_GNUC_INTERNAL void pcmk__colocation_intersect_nodes(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, const GList *primary_nodes, bool merge_scores)
G_GNUC_INTERNAL void pcmk__new_ordering(pcmk_resource_t *first_rsc, char *first_task, pcmk_action_t *first_action, pcmk_resource_t *then_rsc, char *then_task, pcmk_action_t *then_action, uint32_t flags, pcmk_scheduler_t *sched)
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
G_GNUC_INTERNAL void pcmk__assign_instances(pcmk_resource_t *collective, GList *instances, int max_total, int max_per_node)
G_GNUC_INTERNAL uint32_t pcmk__collective_action_flags(pcmk_action_t *action, const GList *instances, const pcmk_node_t *node)
@ pcmk__coloc_influence
G_GNUC_INTERNAL bool pcmk__assign_resource(pcmk_resource_t *rsc, pcmk_node_t *node, bool force, bool stop_if_fail)
G_GNUC_INTERNAL gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
G_GNUC_INTERNAL GList * pcmk__sort_nodes(GList *nodes, pcmk_node_t *active_node)
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL bool pcmk__threshold_reached(pcmk_resource_t *rsc, const pcmk_node_t *node, pcmk_resource_t **failed)
G_GNUC_INTERNAL void pcmk__promotable_restart_ordering(pcmk_resource_t *rsc)
G_GNUC_INTERNAL bool pcmk__instance_matches(const pcmk_resource_t *instance, const pcmk_node_t *node, enum rsc_role_e role, bool current)
#define pcmk__order_stops(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__create_instance_actions(pcmk_resource_t *rsc, GList *instances)
G_GNUC_INTERNAL void pcmk__apply_location(pcmk_resource_t *rsc, pcmk__location_t *constraint)
#define crm_notice(fmt, args...)
Definition logging.h:395
#define PCMK_REMOTE_RA_ADDR
Definition options.h:122
const char * action
Definition pcmk_fence.c:30
void pcmk__bundle_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
#define XPATH_REMOTE
void pcmk__with_bundle_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void pcmk__bundle_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
int pcmk__bundle_apply_coloc_score(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void pcmk__bundle_shutdown_lock(pcmk_resource_t *rsc)
uint32_t pcmk__bundle_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
bool pcmk__bundle_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
void pcmk__output_bundle_actions(pcmk_resource_t *rsc)
pcmk_node_t * pcmk__bundle_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
void pcmk__bundle_add_actions_to_graph(pcmk_resource_t *rsc)
void pcmk__bundle_create_actions(pcmk_resource_t *rsc)
void pcmk__bundle_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void pcmk__bundle_internal_constraints(pcmk_resource_t *rsc)
const char * pe__add_bundle_remote_name(pcmk_resource_t *rsc, xmlNode *xml, const char *field)
Definition bundle.c:938
void pe__foreach_const_bundle_replica(const pcmk_resource_t *bundle, bool(*fn)(const pcmk__bundle_replica_t *, void *), void *user_data)
Definition bundle.c:232
bool is_set_recursive(const pcmk_resource_t *rsc, long long flag, bool any)
Definition clone.c:588
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
Definition complex.c:1032
#define pe__show_node_scores(level, rsc, text, nodes, scheduler)
Definition internal.h:176
pcmk_action_t * pe__new_rsc_pseudo_action(pcmk_resource_t *rsc, const char *task, bool optional, bool runnable)
bool pe__clone_flag_is_set(const pcmk_resource_t *clone, uint32_t flags)
Definition clone.c:1387
pcmk_resource_t * pe__first_container(const pcmk_resource_t *bundle)
Definition bundle.c:185
pcmk_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pcmk_node_t *on_node)
bool pe__bundle_needs_remote_name(pcmk_resource_t *rsc)
Definition bundle.c:920
GList * pe__bundle_containers(const pcmk_resource_t *bundle)
Definition bundle.c:2168
pcmk_resource_t * pe__bundled_resource(const pcmk_resource_t *rsc)
Definition bundle.c:111
bool pe__node_is_bundle_instance(const pcmk_resource_t *bundle, const pcmk_node_t *node)
Definition bundle.c:159
void pe__foreach_bundle_replica(pcmk_resource_t *bundle, bool(*fn)(pcmk__bundle_replica_t *, void *), void *user_data)
Definition bundle.c:208
enum action_tasks get_complex_task(const pcmk_resource_t *rsc, const char *name)
int pe__bundle_max(const pcmk_resource_t *rsc)
Definition bundle.c:94
@ pcmk_rsc_variant_group
Definition resources.h:38
@ pcmk_rsc_promotable
Definition resources.h:106
@ pcmk_rsc_unassigned
Definition resources.h:109
@ pcmk_rsc_assigning
Definition resources.h:112
@ pcmk_rsc_replica_container
Definition resources.h:163
@ pcmk_rsc_blocked
Definition resources.h:91
#define CRM_ASSERT(expr)
Definition results.h:42
@ pcmk_role_unknown
Resource role is unknown.
Definition roles.h:35
@ pcmk_role_unpromoted
Unpromoted.
Definition roles.h:38
@ pcmk_role_promoted
Promoted.
Definition roles.h:39
#define pcmk__set_rsc_flags(resource, flags_to_set)
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
@ pcmk_sched_output_scores
Definition scheduler.h:173
#define pcmk__rsc_info(rsc, fmt, args...)
#define pcmk__rsc_trace(rsc, fmt, args...)
#define pcmk__rsc_debug(rsc, fmt, args...)
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition scores.c:86
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition scores.h:24
int pcmk__add_scores(int score1, int score2)
Definition scores.c:116
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition strings.c:701
A single instance of a bundle.
pcmk_resource_t * child
Instance of bundled resource.
pcmk_resource_t * remote
Pacemaker Remote connection into container.
pcmk_node_t * node
Node created for this instance.
pcmk_resource_t * container
Container associated with this instance.
pcmk_resource_t * ip
IP address resource for ipaddr.
pcmk_resource_t * dependent
Location constraint object.
enum rsc_role_e role_filter
int weight
Definition nodes.h:162
struct pe_node_shared_s * details
Definition nodes.h:167
pcmk_resource_t * remote_rsc
Definition nodes.h:135
pcmk_assignment_methods_t * cmds
Definition resources.h:413
GList * actions
Definition resources.h:444
GList * rsc_location
Definition resources.h:443
enum pe_obj_types variant
Definition resources.h:410
GList * rsc_cons
Definition resources.h:442
GList * rsc_cons_lhs
Definition resources.h:441
GList * children
Definition resources.h:471
pcmk_scheduler_t * cluster
Definition resources.h:408
pcmk_resource_t * container
Definition resources.h:476
pcmk_rsc_methods_t * fns
Definition resources.h:412
pcmk_node_t * allocated_to
Definition resources.h:447
xmlNode * xml
Definition resources.h:400
GHashTable * allowed_nodes
Definition resources.h:462
unsigned long long flags
Definition resources.h:428
enum rsc_role_e next_role
Definition resources.h:465
pcmk_resource_t * parent
Definition resources.h:409
unsigned long long flags
Definition scheduler.h:211
void(* create_actions)(pcmk_resource_t *rsc)
void(* add_utilization)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void(* add_actions_to_graph)(pcmk_resource_t *rsc)
int(* apply_coloc_score)(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void(* output_actions)(pcmk_resource_t *rsc)
bool(* create_probe)(pcmk_resource_t *rsc, pcmk_node_t *node)
void(* internal_constraints)(pcmk_resource_t *rsc)
pcmk_node_t *(* assign)(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
void(* apply_location)(pcmk_resource_t *rsc, pcmk__location_t *location)
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, int current)
Definition resources.h:328
unsigned int(* max_per_node)(const pcmk_resource_t *rsc)
Definition resources.h:384
Wrappers for and extensions to libxml2.
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition xpath.c:189
#define PCMK_XA_VALUE
Definition xml_names.h:437