pacemaker 2.1.6-6fdc9deea29
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-2023 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/msg_xml.h>
15#include <pacemaker-internal.h>
16
18
19#define PE__VARIANT_BUNDLE 1
20#include <lib/pengine/variant.h>
21
22static bool
23is_bundle_node(pe__bundle_variant_data_t *data, pe_node_t *node)
24{
25 for (GList *gIter = data->replicas; gIter != NULL; gIter = gIter->next) {
26 pe__bundle_replica_t *replica = gIter->data;
27
28 if (node->details == replica->node->details) {
29 return TRUE;
30 }
31 }
32 return FALSE;
33}
34
46{
47 GList *containers = NULL;
48 pe__bundle_variant_data_t *bundle_data = NULL;
49
50 CRM_CHECK(rsc != NULL, return NULL);
51
52 get_bundle_variant_data(bundle_data, rsc);
53
55 containers = pe__bundle_containers(rsc);
56
58 rsc, __func__, rsc->allowed_nodes, rsc->cluster);
59
60 containers = g_list_sort(containers, pcmk__cmp_instance);
61 pcmk__assign_instances(rsc, containers, bundle_data->nreplicas,
62 bundle_data->nreplicas_per_host);
63 g_list_free(containers);
64
65 for (GList *gIter = bundle_data->replicas; gIter != NULL;
66 gIter = gIter->next) {
67 pe__bundle_replica_t *replica = gIter->data;
68 pe_node_t *container_host = NULL;
69
70 CRM_ASSERT(replica);
71 if (replica->ip) {
72 pe_rsc_trace(rsc, "Allocating bundle %s IP %s",
73 rsc->id, replica->ip->id);
74 replica->ip->cmds->assign(replica->ip, prefer);
75 }
76
77 container_host = replica->container->allocated_to;
78 if (replica->remote && pe__is_guest_or_remote_node(container_host)) {
79 /* We need 'nested' connection resources to be on the same
80 * host because pacemaker-remoted only supports a single
81 * active connection
82 */
83 pcmk__new_colocation("child-remote-with-docker-remote", NULL,
84 INFINITY, replica->remote,
85 container_host->details->remote_rsc, NULL,
86 NULL, true, rsc->cluster);
87 }
88
89 if (replica->remote) {
90 pe_rsc_trace(rsc, "Allocating bundle %s connection %s",
91 rsc->id, replica->remote->id);
92 replica->remote->cmds->assign(replica->remote, prefer);
93 }
94
95 // Explicitly allocate replicas' children before bundle child
96 if (replica->child) {
97 pe_node_t *node = NULL;
98 GHashTableIter iter;
99
100 g_hash_table_iter_init(&iter, replica->child->allowed_nodes);
101 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
102 if (node->details != replica->node->details) {
103 node->weight = -INFINITY;
104 } else if (!pcmk__threshold_reached(replica->child, node,
105 NULL)) {
106 node->weight = INFINITY;
107 }
108 }
109
110 pe__set_resource_flags(replica->child->parent, pe_rsc_allocating);
111 pe_rsc_trace(rsc, "Allocating bundle %s replica child %s",
112 rsc->id, replica->child->id);
113 replica->child->cmds->assign(replica->child, replica->node);
114 pe__clear_resource_flags(replica->child->parent,
116 }
117 }
118
119 if (bundle_data->child) {
120 pe_node_t *node = NULL;
121 GHashTableIter iter;
122 g_hash_table_iter_init(&iter, bundle_data->child->allowed_nodes);
123 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
124 if (is_bundle_node(bundle_data, node)) {
125 node->weight = 0;
126 } else {
127 node->weight = -INFINITY;
128 }
129 }
130 pe_rsc_trace(rsc, "Allocating bundle %s child %s",
131 rsc->id, bundle_data->child->id);
132 bundle_data->child->cmds->assign(bundle_data->child, prefer);
133 }
134
136 return NULL;
137}
138
139
140void
142{
143 pe_action_t *action = NULL;
144 GList *containers = NULL;
145 pe__bundle_variant_data_t *bundle_data = NULL;
146
147 CRM_CHECK(rsc != NULL, return);
148
149 containers = pe__bundle_containers(rsc);
150 get_bundle_variant_data(bundle_data, rsc);
151 for (GList *gIter = bundle_data->replicas; gIter != NULL;
152 gIter = gIter->next) {
153 pe__bundle_replica_t *replica = gIter->data;
154
155 CRM_ASSERT(replica);
156 if (replica->ip) {
157 replica->ip->cmds->create_actions(replica->ip);
158 }
159 if (replica->container) {
160 replica->container->cmds->create_actions(replica->container);
161 }
162 if (replica->remote) {
163 replica->remote->cmds->create_actions(replica->remote);
164 }
165 }
166
167 pcmk__create_instance_actions(rsc, containers);
168
169 if (bundle_data->child) {
170 bundle_data->child->cmds->create_actions(bundle_data->child);
171
172 if (pcmk_is_set(bundle_data->child->flags, pe_rsc_promotable)) {
173 /* promote */
174 pe__new_rsc_pseudo_action(rsc, RSC_PROMOTE, true, true);
176 action->priority = INFINITY;
177
178 /* demote */
179 pe__new_rsc_pseudo_action(rsc, RSC_DEMOTE, true, true);
180 action = pe__new_rsc_pseudo_action(rsc, RSC_DEMOTED, true, true);
181 action->priority = INFINITY;
182 }
183 }
184
185 g_list_free(containers);
186}
187
188void
190{
191 pe__bundle_variant_data_t *bundle_data = NULL;
192
193 CRM_CHECK(rsc != NULL, return);
194
195 get_bundle_variant_data(bundle_data, rsc);
196
197 if (bundle_data->child) {
198 pcmk__order_resource_actions(rsc, RSC_START, bundle_data->child,
200 pcmk__order_resource_actions(rsc, RSC_STOP, bundle_data->child,
202
203 if (bundle_data->child->children) {
204 pcmk__order_resource_actions(bundle_data->child, RSC_STARTED, rsc,
207 pcmk__order_resource_actions(bundle_data->child, RSC_STOPPED, rsc,
210 } else {
211 pcmk__order_resource_actions(bundle_data->child, RSC_START, rsc,
214 pcmk__order_resource_actions(bundle_data->child, RSC_STOP, rsc,
217 }
218 }
219
220 for (GList *gIter = bundle_data->replicas; gIter != NULL;
221 gIter = gIter->next) {
222 pe__bundle_replica_t *replica = gIter->data;
223
224 CRM_ASSERT(replica);
225 CRM_ASSERT(replica->container);
226
227 replica->container->cmds->internal_constraints(replica->container);
228
229 pcmk__order_starts(rsc, replica->container,
231
232 if (replica->child) {
233 pcmk__order_stops(rsc, replica->child,
235 }
236 pcmk__order_stops(rsc, replica->container,
238 pcmk__order_resource_actions(replica->container, RSC_START, rsc,
241 pcmk__order_resource_actions(replica->container, RSC_STOP, rsc,
244
245 if (replica->ip) {
246 replica->ip->cmds->internal_constraints(replica->ip);
247
248 // Start IP then container
249 pcmk__order_starts(replica->ip, replica->container,
251 pcmk__order_stops(replica->container, replica->ip,
253
254 pcmk__new_colocation("ip-with-docker", NULL, INFINITY, replica->ip,
255 replica->container, NULL, NULL, true,
256 rsc->cluster);
257 }
258
259 if (replica->remote) {
260 /* This handles ordering and colocating remote relative to container
261 * (via "resource-with-container"). Since IP is also ordered and
262 * colocated relative to the container, we don't need to do anything
263 * explicit here with IP.
264 */
265 replica->remote->cmds->internal_constraints(replica->remote);
266 }
267
268 if (replica->child) {
269 CRM_ASSERT(replica->remote);
270
271 // "Start remote then child" is implicit in scheduler's remote logic
272 }
273
274 }
275
276 if (bundle_data->child) {
277 bundle_data->child->cmds->internal_constraints(bundle_data->child);
278 if (pcmk_is_set(bundle_data->child->flags, pe_rsc_promotable)) {
280
281 /* child demoted before global demoted */
282 pcmk__order_resource_actions(bundle_data->child, RSC_DEMOTED, rsc,
285
286 /* global demote before child demote */
287 pcmk__order_resource_actions(rsc, RSC_DEMOTE, bundle_data->child,
290
291 /* child promoted before global promoted */
292 pcmk__order_resource_actions(bundle_data->child, RSC_PROMOTED, rsc,
295
296 /* global promote before child promote */
297 pcmk__order_resource_actions(rsc, RSC_PROMOTE, bundle_data->child,
300 }
301 }
302}
303
304static pe_resource_t *
305compatible_replica_for_node(const pe_resource_t *rsc_lh,
306 const pe_node_t *candidate,
307 const pe_resource_t *rsc, enum rsc_role_e filter,
308 gboolean current)
309{
310 pe__bundle_variant_data_t *bundle_data = NULL;
311
312 CRM_CHECK(candidate != NULL, return NULL);
313 get_bundle_variant_data(bundle_data, rsc);
314
315 crm_trace("Looking for compatible child from %s for %s on %s",
316 rsc_lh->id, rsc->id, pe__node_name(candidate));
317
318 for (GList *gIter = bundle_data->replicas; gIter != NULL;
319 gIter = gIter->next) {
320 pe__bundle_replica_t *replica = gIter->data;
321
322 if (pcmk__instance_matches(replica->container, candidate, filter,
323 current)) {
324 crm_trace("Pairing %s with %s on %s",
325 rsc_lh->id, replica->container->id,
326 pe__node_name(candidate));
327 return replica->container;
328 }
329 }
330
331 crm_trace("Can't pair %s with %s", rsc_lh->id, rsc->id);
332 return NULL;
333}
334
335static pe_resource_t *
336compatible_replica(const pe_resource_t *rsc_lh, const pe_resource_t *rsc,
337 enum rsc_role_e filter, gboolean current,
339{
340 GList *scratch = NULL;
341 pe_resource_t *pair = NULL;
342 pe_node_t *active_node_lh = NULL;
343
344 active_node_lh = rsc_lh->fns->location(rsc_lh, NULL, current);
345 if (active_node_lh) {
346 return compatible_replica_for_node(rsc_lh, active_node_lh, rsc, filter,
347 current);
348 }
349
350 scratch = g_hash_table_get_values(rsc_lh->allowed_nodes);
351 scratch = pcmk__sort_nodes(scratch, NULL);
352
353 for (GList *gIter = scratch; gIter != NULL; gIter = gIter->next) {
354 pe_node_t *node = (pe_node_t *) gIter->data;
355
356 pair = compatible_replica_for_node(rsc_lh, node, rsc, filter, current);
357 if (pair) {
358 goto done;
359 }
360 }
361
362 pe_rsc_debug(rsc, "Can't pair %s with %s", rsc_lh->id, (rsc? rsc->id : "none"));
363 done:
364 g_list_free(scratch);
365 return pair;
366}
367
369{
370 /* Strictly speaking, there should be a 'copies_per_node' addition
371 * to the resource function table and each case would be a
372 * function. However that would be serious overkill to return an
373 * int. In fact, it seems to me that both function tables
374 * could/should be replaced by resources.{c,h} full of
375 * rsc_{some_operation} functions containing a switch as below
376 * which calls out to functions named {variant}_{some_operation}
377 * as needed.
378 */
379 switch(rsc->variant) {
380 case pe_unknown:
381 return 0;
382 case pe_native:
383 case pe_group:
384 return 1;
385 case pe_clone:
386 {
387 const char *max_clones_node = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_NODEMAX);
388
389 if (max_clones_node == NULL) {
390 return 1;
391
392 } else {
393 int max_i;
394
395 pcmk__scan_min_int(max_clones_node, &max_i, 0);
396 return max_i;
397 }
398 }
399 case pe_container:
400 {
401 pe__bundle_variant_data_t *data = NULL;
402 get_bundle_variant_data(data, rsc);
403 return data->nreplicas_per_host;
404 }
405 }
406 return 0;
407}
408
422void
424 const pe_resource_t *primary,
425 const pcmk__colocation_t *colocation,
426 bool for_dependent)
427{
428 GList *allocated_primaries = NULL;
429 pe__bundle_variant_data_t *bundle_data = NULL;
430
431 /* This should never be called for the bundle itself as a dependent.
432 * Instead, we add its colocation constraints to its replicas and call the
433 * apply_coloc_score() for the replicas as dependents.
434 */
435 CRM_ASSERT(!for_dependent);
436
437 CRM_CHECK((colocation != NULL) && (dependent != NULL) && (primary != NULL),
438 return);
439 CRM_ASSERT(dependent->variant == pe_native);
440
441 if (pcmk_is_set(primary->flags, pe_rsc_provisional)) {
442 pe_rsc_trace(primary, "%s is still provisional", primary->id);
443 return;
444
445 } else if (colocation->dependent->variant > pe_group) {
446 pe_resource_t *primary_replica = compatible_replica(dependent, primary,
448 FALSE,
449 dependent->cluster);
450
451 if (primary_replica) {
452 pe_rsc_debug(primary, "Pairing %s with %s",
453 dependent->id, primary_replica->id);
454 dependent->cmds->apply_coloc_score(dependent, primary_replica,
455 colocation, true);
456
457 } else if (colocation->score >= INFINITY) {
458 crm_notice("Cannot pair %s with instance of %s",
459 dependent->id, primary->id);
460 pcmk__assign_resource(dependent, NULL, true);
461
462 } else {
463 pe_rsc_debug(primary, "Cannot pair %s with instance of %s",
464 dependent->id, primary->id);
465 }
466
467 return;
468 }
469
470 get_bundle_variant_data(bundle_data, primary);
471 pe_rsc_trace(primary, "Processing constraint %s: %s -> %s %d",
472 colocation->id, dependent->id, primary->id, colocation->score);
473
474 for (GList *gIter = bundle_data->replicas; gIter != NULL;
475 gIter = gIter->next) {
476 pe__bundle_replica_t *replica = gIter->data;
477
478 if (colocation->score < INFINITY) {
479 replica->container->cmds->apply_coloc_score(dependent,
480 replica->container,
481 colocation, false);
482
483 } else {
484 pe_node_t *chosen = replica->container->fns->location(replica->container,
485 NULL, FALSE);
486
487 if ((chosen == NULL)
488 || is_set_recursive(replica->container, pe_rsc_block, TRUE)) {
489 continue;
490 }
491 if ((colocation->primary_role >= RSC_ROLE_PROMOTED)
492 && (replica->child == NULL)) {
493 continue;
494 }
495 if ((colocation->primary_role >= RSC_ROLE_PROMOTED)
496 && (replica->child->next_role < RSC_ROLE_PROMOTED)) {
497 continue;
498 }
499
500 pe_rsc_trace(primary, "Allowing %s: %s %d",
501 colocation->id, pe__node_name(chosen), chosen->weight);
502 allocated_primaries = g_list_prepend(allocated_primaries, chosen);
503 }
504 }
505
506 if (colocation->score >= INFINITY) {
507 node_list_exclude(dependent->allowed_nodes, allocated_primaries, FALSE);
508 }
509 g_list_free(allocated_primaries);
510}
511
512// Bundle implementation of resource_alloc_functions_t:with_this_colocations()
513void
515 const pe_resource_t *orig_rsc, GList **list)
516{
517 CRM_CHECK((rsc != NULL) && (rsc->variant == pe_container)
518 && (orig_rsc != NULL) && (list != NULL),
519 return);
520
521 if (rsc == orig_rsc) { // Colocations are wanted for bundle itself
523
524 // Only the bundle replicas' containers get the bundle's constraints
525 } else if (pcmk_is_set(orig_rsc->flags, pe_rsc_replica_container)) {
526 pcmk__add_collective_constraints(list, orig_rsc, rsc, true);
527 }
528}
529
530// Bundle implementation of resource_alloc_functions_t:this_with_colocations()
531void
533 const pe_resource_t *orig_rsc, GList **list)
534{
535 CRM_CHECK((rsc != NULL) && (rsc->variant == pe_container)
536 && (orig_rsc != NULL) && (list != NULL),
537 return);
538
539 if (rsc == orig_rsc) { // Colocations are wanted for bundle itself
541
542 // Only the bundle replicas' containers get the bundle's constraints
543 } else if (pcmk_is_set(orig_rsc->flags, pe_rsc_replica_container)) {
544 pcmk__add_collective_constraints(list, orig_rsc, rsc, false);
545 }
546}
547
550{
551 GList *containers = NULL;
552 enum pe_action_flags flags = 0;
553 pe__bundle_variant_data_t *data = NULL;
554
555 get_bundle_variant_data(data, action->rsc);
556 if(data->child) {
557 enum action_tasks task = get_complex_task(data->child, action->task);
558 switch(task) {
559 case no_action:
560 case action_notify:
561 case action_notified:
562 case action_promote:
563 case action_promoted:
564 case action_demote:
565 case action_demoted:
567 data->child->children,
568 node);
569 default:
570 break;
571 }
572 }
573
574 containers = pe__bundle_containers(action->rsc);
575 flags = pcmk__collective_action_flags(action, containers, node);
576 g_list_free(containers);
577 return flags;
578}
579
589const pe_resource_t *
591{
592 const pe__bundle_variant_data_t *data = NULL;
593 const pe_resource_t *top = pe__const_top_resource(instance, true);
594
595 if ((top == NULL) || (top->variant != pe_container)) {
596 return NULL;
597 }
598 get_bundle_variant_data(data, top);
599
600 for (const GList *iter = data->replicas; iter != NULL; iter = iter->next) {
601 const pe__bundle_replica_t *replica = iter->data;
602
603 if (instance == replica->container) {
604 return replica->child;
605 }
606 }
607 return NULL;
608}
609
610void
612{
613 pe__bundle_variant_data_t *bundle_data = NULL;
614 get_bundle_variant_data(bundle_data, rsc);
615
616 pcmk__apply_location(rsc, constraint);
617
618 for (GList *gIter = bundle_data->replicas; gIter != NULL;
619 gIter = gIter->next) {
620 pe__bundle_replica_t *replica = gIter->data;
621
622 if (replica->container) {
623 replica->container->cmds->apply_location(replica->container,
624 constraint);
625 }
626 if (replica->ip) {
627 replica->ip->cmds->apply_location(replica->ip, constraint);
628 }
629 }
630
631 if (bundle_data->child
632 && ((constraint->role_filter == RSC_ROLE_UNPROMOTED)
633 || (constraint->role_filter == RSC_ROLE_PROMOTED))) {
634 bundle_data->child->cmds->apply_location(bundle_data->child,
635 constraint);
636 bundle_data->child->rsc_location = g_list_prepend(bundle_data->child->rsc_location,
637 constraint);
638 }
639}
640
647void
649{
650 pe__bundle_variant_data_t *bundle_data = NULL;
651
652 CRM_CHECK(rsc != NULL, return);
653
654 get_bundle_variant_data(bundle_data, rsc);
655
656 if (bundle_data->child) {
657 bundle_data->child->cmds->add_actions_to_graph(bundle_data->child);
658 }
659
660 for (GList *gIter = bundle_data->replicas; gIter != NULL;
661 gIter = gIter->next) {
662 pe__bundle_replica_t *replica = gIter->data;
663
664 CRM_ASSERT(replica);
665 if (replica->remote && replica->container
666 && pe__bundle_needs_remote_name(replica->remote)) {
667
668 /* REMOTE_CONTAINER_HACK: Allow remote nodes to run containers that
669 * run pacemaker-remoted inside, without needing a separate IP for
670 * the container. This is done by configuring the inner remote's
671 * connection host as the magic string "#uname", then
672 * replacing it with the underlying host when needed.
673 */
674 xmlNode *nvpair = get_xpath_object("//nvpair[@name='" XML_RSC_ATTR_REMOTE_RA_ADDR "']",
675 replica->remote->xml, LOG_ERR);
676 const char *calculated_addr = NULL;
677
678 // Replace the value in replica->remote->xml (if appropriate)
679 calculated_addr = pe__add_bundle_remote_name(replica->remote,
680 rsc->cluster,
681 nvpair, "value");
682 if (calculated_addr) {
683 /* Since this is for the bundle as a resource, and not any
684 * particular action, replace the value in the default
685 * parameters (not evaluated for node). create_graph_action()
686 * will grab it from there to replace it in node-evaluated
687 * parameters.
688 */
689 GHashTable *params = pe_rsc_params(replica->remote,
690 NULL, rsc->cluster);
691
692 g_hash_table_replace(params,
694 strdup(calculated_addr));
695 } else {
696 /* The only way to get here is if the remote connection is
697 * neither currently running nor scheduled to run. That means we
698 * won't be doing any operations that require addr (only start
699 * requires it; we additionally use it to compare digests when
700 * unpacking status, promote, and migrate_from history, but
701 * that's already happened by this point).
702 */
703 crm_info("Unable to determine address for bundle %s remote connection",
704 rsc->id);
705 }
706 }
707 if (replica->ip) {
708 replica->ip->cmds->add_actions_to_graph(replica->ip);
709 }
710 if (replica->container) {
711 replica->container->cmds->add_actions_to_graph(replica->container);
712 }
713 if (replica->remote) {
714 replica->remote->cmds->add_actions_to_graph(replica->remote);
715 }
716 }
717}
718
729bool
731{
732 bool any_created = false;
733 pe__bundle_variant_data_t *bundle_data = NULL;
734
735 CRM_CHECK(rsc != NULL, return false);
736
737 get_bundle_variant_data(bundle_data, rsc);
738 for (GList *gIter = bundle_data->replicas; gIter != NULL;
739 gIter = gIter->next) {
740 pe__bundle_replica_t *replica = gIter->data;
741
742 CRM_ASSERT(replica);
743 if ((replica->ip != NULL)
744 && replica->ip->cmds->create_probe(replica->ip, node)) {
745 any_created = true;
746 }
747 if ((replica->child != NULL) && (node->details == replica->node->details)
748 && replica->child->cmds->create_probe(replica->child, node)) {
749 any_created = true;
750 }
751 if ((replica->container != NULL)
752 && replica->container->cmds->create_probe(replica->container,
753 node)) {
754 any_created = true;
755
756 /* If we're limited to one replica per host (due to
757 * the lack of an IP range probably), then we don't
758 * want any of our peer containers starting until
759 * we've established that no other copies are already
760 * running.
761 *
762 * Partly this is to ensure that nreplicas_per_host is
763 * observed, but also to ensure that the containers
764 * don't fail to start because the necessary port
765 * mappings (which won't include an IP for uniqueness)
766 * are already taken
767 */
768
769 for (GList *tIter = bundle_data->replicas;
770 tIter && (bundle_data->nreplicas_per_host == 1);
771 tIter = tIter->next) {
772 pe__bundle_replica_t *other = tIter->data;
773
774 if ((other != replica) && (other != NULL)
775 && (other->container != NULL)) {
776
777 pcmk__new_ordering(replica->container,
778 pcmk__op_key(replica->container->id, RSC_STATUS, 0),
779 NULL, other->container,
780 pcmk__op_key(other->container->id, RSC_START, 0),
781 NULL,
783 rsc->cluster);
784 }
785 }
786 }
787 if ((replica->container != NULL) && (replica->remote != NULL)
788 && replica->remote->cmds->create_probe(replica->remote, node)) {
789
790 /* Do not probe the remote resource until we know where the
791 * container is running. This is required for REMOTE_CONTAINER_HACK
792 * to correctly probe remote resources.
793 */
794 char *probe_uuid = pcmk__op_key(replica->remote->id, RSC_STATUS,
795 0);
796 pe_action_t *probe = find_first_action(replica->remote->actions,
797 probe_uuid, NULL, node);
798
799 free(probe_uuid);
800 if (probe != NULL) {
801 any_created = true;
802 crm_trace("Ordering %s probe on %s",
803 replica->remote->id, pe__node_name(node));
804 pcmk__new_ordering(replica->container,
805 pcmk__op_key(replica->container->id, RSC_START, 0),
806 NULL, replica->remote, NULL, probe,
807 pe_order_probe, rsc->cluster);
808 }
809 }
810 }
811 return any_created;
812}
813
814void
816{
817 pe__bundle_variant_data_t *bundle_data = NULL;
818
819 CRM_CHECK(rsc != NULL, return);
820
821 get_bundle_variant_data(bundle_data, rsc);
822 for (GList *gIter = bundle_data->replicas; gIter != NULL;
823 gIter = gIter->next) {
824 pe__bundle_replica_t *replica = gIter->data;
825
826 CRM_ASSERT(replica);
827 if (replica->ip != NULL) {
828 replica->ip->cmds->output_actions(replica->ip);
829 }
830 if (replica->container != NULL) {
831 replica->container->cmds->output_actions(replica->container);
832 }
833 if (replica->remote != NULL) {
834 replica->remote->cmds->output_actions(replica->remote);
835 }
836 if (replica->child != NULL) {
837 replica->child->cmds->output_actions(replica->child);
838 }
839 }
840}
841
842// Bundle implementation of resource_alloc_functions_t:add_utilization()
843void
845 const pe_resource_t *orig_rsc, GList *all_rscs,
846 GHashTable *utilization)
847{
848 pe__bundle_variant_data_t *bundle_data = NULL;
849 pe__bundle_replica_t *replica = NULL;
850
852 return;
853 }
854
855 get_bundle_variant_data(bundle_data, rsc);
856 if (bundle_data->replicas == NULL) {
857 return;
858 }
859
860 /* All bundle replicas are identical, so using the utilization of the first
861 * is sufficient for any. Only the implicit container resource can have
862 * utilization values.
863 */
864 replica = (pe__bundle_replica_t *) bundle_data->replicas->data;
865 if (replica->container != NULL) {
866 replica->container->cmds->add_utilization(replica->container, orig_rsc,
867 all_rscs, utilization);
868 }
869}
870
871// Bundle implementation of resource_alloc_functions_t:shutdown_lock()
872void
874{
875 return; // Bundles currently don't support shutdown locks
876}
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition operations.c:42
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:121
action_tasks
Definition common.h:61
@ no_action
Definition common.h:62
@ action_demote
Definition common.h:72
@ action_demoted
Definition common.h:73
@ action_notified
Definition common.h:69
@ action_promote
Definition common.h:70
@ action_promoted
Definition common.h:71
@ action_notify
Definition common.h:68
rsc_role_e
Possible roles that a resource can be in.
Definition common.h:92
@ RSC_ROLE_PROMOTED
Definition common.h:97
@ RSC_ROLE_UNKNOWN
Definition common.h:93
@ RSC_ROLE_UNPROMOTED
Definition common.h:96
GHashTable * pe_rsc_params(pe_resource_t *rsc, const pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters.
Definition complex.c:436
char data[0]
Definition cpg.c:10
#define RSC_PROMOTE
Definition crm.h:205
#define RSC_DEMOTE
Definition crm.h:207
#define RSC_STARTED
Definition crm.h:200
#define RSC_STOPPED
Definition crm.h:203
#define RSC_START
Definition crm.h:199
#define INFINITY
Definition crm.h:99
#define RSC_STOP
Definition crm.h:202
#define RSC_PROMOTED
Definition crm.h:206
#define RSC_STATUS
Definition crm.h:213
#define RSC_DEMOTED
Definition crm.h:208
G_GNUC_INTERNAL void pcmk__new_colocation(const char *id, const char *node_attr, int score, pe_resource_t *dependent, pe_resource_t *primary, const char *dependent_role, const char *primary_role, bool influence, pe_working_set_t *data_set)
#define pcmk__order_starts(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition)
G_GNUC_INTERNAL void pcmk__add_collective_constraints(GList **list, const pe_resource_t *instance, const pe_resource_t *collective, bool with_this)
G_GNUC_INTERNAL bool pcmk__instance_matches(const pe_resource_t *instance, const pe_node_t *node, enum rsc_role_e role, bool current)
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
G_GNUC_INTERNAL void pcmk__assign_instances(pe_resource_t *collective, GList *instances, int max_total, int max_per_node)
G_GNUC_INTERNAL GList * pcmk__sort_nodes(GList *nodes, pe_node_t *active_node)
G_GNUC_INTERNAL void pcmk__create_instance_actions(pe_resource_t *rsc, GList *instances)
G_GNUC_INTERNAL gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
G_GNUC_INTERNAL bool pcmk__assign_resource(pe_resource_t *rsc, pe_node_t *node, bool force)
G_GNUC_INTERNAL enum pe_action_flags pcmk__collective_action_flags(pe_action_t *action, const GList *instances, const pe_node_t *node)
G_GNUC_INTERNAL void pcmk__promotable_restart_ordering(pe_resource_t *rsc)
#define pcmk__order_stops(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__add_this_with_list(GList **list, GList *addition)
G_GNUC_INTERNAL void pcmk__apply_location(pe_resource_t *rsc, pe__location_t *constraint)
G_GNUC_INTERNAL bool pcmk__threshold_reached(pe_resource_t *rsc, const pe_node_t *node, pe_resource_t **failed)
G_GNUC_INTERNAL void pcmk__new_ordering(pe_resource_t *first_rsc, char *first_task, pe_action_t *first_action, pe_resource_t *then_rsc, char *then_task, pe_action_t *then_action, uint32_t flags, pe_working_set_t *data_set)
#define crm_info(fmt, args...)
Definition logging.h:378
#define crm_notice(fmt, args...)
Definition logging.h:377
#define CRM_CHECK(expr, failure_action)
Definition logging.h:235
#define crm_trace(fmt, args...)
Definition logging.h:381
#define XML_RSC_ATTR_REMOTE_RA_ADDR
Definition msg_xml.h:263
#define XML_RSC_ATTR_INCARNATION_NODEMAX
Definition msg_xml.h:244
pe_working_set_t * data_set
const char * action
Definition pcmk_fence.c:30
bool pcmk__bundle_create_probe(pe_resource_t *rsc, pe_node_t *node)
void pcmk__bundle_create_actions(pe_resource_t *rsc)
void pcmk__bundle_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
enum pe_action_flags pcmk__bundle_action_flags(pe_action_t *action, const pe_node_t *node)
void pcmk__output_bundle_actions(pe_resource_t *rsc)
void pcmk__bundle_add_utilization(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void pcmk__bundle_expand(pe_resource_t *rsc)
void pcmk__bundle_apply_coloc_score(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void pcmk__bundle_shutdown_lock(pe_resource_t *rsc)
int copies_per_node(pe_resource_t *rsc)
void pcmk__bundle_internal_constraints(pe_resource_t *rsc)
void pcmk__bundle_with_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
void pcmk__with_bundle_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
const pe_resource_t * pcmk__get_rsc_in_container(const pe_resource_t *instance)
pe_node_t * pcmk__bundle_allocate(pe_resource_t *rsc, const pe_node_t *prefer)
#define pe_rsc_replica_container
Definition pe_types.h:307
#define pe_rsc_block
Definition pe_types.h:274
@ pe_order_implies_first_printed
Definition pe_types.h:535
@ pe_order_same_node
Definition pe_types.h:533
@ pe_order_preserve
Definition pe_types.h:543
@ pe_order_implies_then_printed
Definition pe_types.h:536
@ pe_order_optional
Definition pe_types.h:508
@ pe_order_implies_first
Definition pe_types.h:511
@ pe_order_runnable_left
Definition pe_types.h:518
@ pe_order_probe
Definition pe_types.h:525
#define pe_rsc_provisional
Definition pe_types.h:282
#define pe_rsc_allocating
Definition pe_types.h:283
#define pe_flag_show_scores
Definition pe_types.h:150
pe_action_flags
Definition pe_types.h:316
@ pe_group
Definition pe_types.h:39
@ pe_container
Definition pe_types.h:41
@ pe_unknown
Definition pe_types.h:37
@ pe_native
Definition pe_types.h:38
@ pe_clone
Definition pe_types.h:40
#define pe_rsc_promotable
Definition pe_types.h:280
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
Definition internal.h:385
enum action_tasks get_complex_task(const pe_resource_t *rsc, const char *name)
void node_list_exclude(GHashTable *list, GList *list2, gboolean merge_scores)
Definition utils.c:108
const char * pe__add_bundle_remote_name(pe_resource_t *rsc, pe_working_set_t *data_set, xmlNode *xml, const char *field)
Definition bundle.c:743
bool is_set_recursive(const pe_resource_t *rsc, long long flag, bool any)
Definition clone.c:555
pe_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pe_node_t *on_node)
GList * pe__bundle_containers(const pe_resource_t *bundle)
Definition bundle.c:1916
bool pe__bundle_needs_remote_name(pe_resource_t *rsc)
Definition bundle.c:725
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition internal.h:83
#define pe_rsc_debug(rsc, fmt, args...)
Definition internal.h:49
pe_action_t * pe__new_rsc_pseudo_action(pe_resource_t *rsc, const char *task, bool optional, bool runnable)
#define pe_rsc_trace(rsc, fmt, args...)
Definition internal.h:50
#define pe__set_resource_flags(resource, flags_to_set)
Definition internal.h:77
const pe_resource_t * pe__const_top_resource(const pe_resource_t *rsc, bool include_bundle)
Definition complex.c:947
bool pe__is_guest_or_remote_node(const pe_node_t *node)
Definition remote.c:41
#define CRM_ASSERT(expr)
Definition results.h:42
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition strings.c:127
pe_resource_t * dependent
enum rsc_role_e role_filter
Definition internal.h:194
int weight
Definition pe_types.h:265
struct pe_node_shared_s * details
Definition pe_types.h:268
pe_resource_t * remote_rsc
Definition pe_types.h:253
enum pe_obj_types variant
Definition pe_types.h:356
GHashTable * meta
Definition pe_types.h:405
GList * rsc_cons
Definition pe_types.h:389
GList * rsc_cons_lhs
Definition pe_types.h:388
pe_working_set_t * cluster
Definition pe_types.h:353
pe_resource_t * container
Definition pe_types.h:412
GHashTable * allowed_nodes
Definition pe_types.h:400
unsigned long long flags
Definition pe_types.h:373
resource_alloc_functions_t * cmds
Definition pe_types.h:359
resource_object_functions_t * fns
Definition pe_types.h:358
unsigned long long flags
Definition pe_types.h:169
void(* apply_coloc_score)(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition pe_types.h:55
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition xpath.c:214