pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_sched_clone.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 <crm/common/xml.h>
13#include <pacemaker-internal.h>
14
16
38 bool stop_if_fail)
39{
40 GList *colocations = NULL;
41
42 pcmk__assert(pcmk__is_clone(rsc));
43
45 return NULL; // Assignment has already been done
46 }
47
48 // Detect assignment loops
50 pcmk__rsc_debug(rsc, "Breaking assignment loop involving %s", rsc->id);
51 return NULL;
52 }
54
55 // If this clone is promotable, consider nodes' promotion scores
58 }
59
60 // If this clone is colocated with any other resources, assign those first
61 colocations = pcmk__this_with_colocations(rsc);
62 for (GList *iter = colocations; iter != NULL; iter = iter->next) {
63 pcmk__colocation_t *constraint = (pcmk__colocation_t *) iter->data;
64 pcmk_resource_t *primary = constraint->primary;
65
66 pcmk__rsc_trace(rsc, "%s: Assigning colocation %s primary %s first",
67 rsc->id, constraint->id, primary->id);
68 primary->priv->cmds->assign(primary, prefer, stop_if_fail);
69 }
70 g_list_free(colocations);
71
72 // If any resources are colocated with this one, consider their preferences
73 colocations = pcmk__with_this_colocations(rsc);
74 g_list_foreach(colocations, pcmk__add_dependent_scores, rsc);
75 g_list_free(colocations);
76
79 rsc, __func__, rsc->priv->allowed_nodes,
80 rsc->priv->scheduler);
81
82 rsc->priv->children = g_list_sort(rsc->priv->children, pcmk__cmp_instance);
85
88 }
89
91 pcmk__rsc_trace(rsc, "Assigned clone %s", rsc->id);
92 return NULL;
93}
94
101void
103{
104 pcmk__assert(pcmk__is_clone(rsc));
105
106 pcmk__rsc_trace(rsc, "Creating actions for clone %s", rsc->id);
110 }
111}
112
119void
121{
122 bool ordered = false;
123
124 pcmk__assert(pcmk__is_clone(rsc));
125
126 pcmk__rsc_trace(rsc, "Creating internal constraints for clone %s", rsc->id);
127
128 // Restart ordering: Stop -> stopped -> start -> started
138
139 // Demoted -> stop and started -> promote
142 rsc, PCMK_ACTION_STOP,
147 }
148
149 ordered = pe__clone_is_ordered(rsc);
150 if (ordered) {
151 /* Ordered clone instances must start and stop by instance number. The
152 * instances might have been previously shuffled for assignment or
153 * promotion purposes, so re-sort them.
154 */
155 rsc->priv->children = g_list_sort(rsc->priv->children,
157 }
158 for (GList *iter = rsc->priv->children;
159 iter != NULL; iter = iter->next) {
160
161 pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
162
163 instance->priv->cmds->internal_constraints(instance);
164
165 // Start clone -> start instance -> clone started
171
172 // Stop clone -> stop instance -> clone stopped
177
178 /* Instances of ordered clones must be started and stopped by instance
179 * number. Since only some instances may be starting or stopping, order
180 * each instance relative to every later instance.
181 */
182 if (ordered) {
183 for (GList *later = iter->next;
184 later != NULL; later = later->next) {
185 pcmk__order_starts(instance, (pcmk_resource_t *) later->data,
187 pcmk__order_stops((pcmk_resource_t *) later->data, instance,
189 }
190 }
191 }
194 }
195}
196
205static bool
206can_interleave(const pcmk__colocation_t *colocation)
207{
208 const pcmk_resource_t *primary = colocation->primary;
209 const pcmk_resource_t *dependent = colocation->dependent;
210
211 // Only colocations between clone or bundle resources use interleaving
212 if (dependent->priv->variant <= pcmk__rsc_variant_group) {
213 return false;
214 }
215
216 // Only the dependent needs to be marked for interleaving
217 if (!crm_is_true(g_hash_table_lookup(dependent->priv->meta,
219 return false;
220 }
221
222 /* @TODO Do we actually care about multiple primary instances sharing a
223 * dependent instance?
224 */
225 if (dependent->priv->fns->max_per_node(dependent)
226 != primary->priv->fns->max_per_node(primary)) {
227 pcmk__config_err("Cannot interleave %s and %s because they do not "
228 "support the same number of instances per node",
229 dependent->id, primary->id);
230 return false;
231 }
232
233 return true;
234}
235
251int
253 const pcmk_resource_t *primary,
254 const pcmk__colocation_t *colocation,
255 bool for_dependent)
256{
257 const GList *iter = NULL;
258 int priority_delta = 0;
259
260 /* This should never be called for the clone itself as a dependent. Instead,
261 * we add its colocation constraints to its instances and call the
262 * apply_coloc_score() method for the instances as dependents.
263 */
264 pcmk__assert(!for_dependent && (colocation != NULL)
265 && pcmk__is_clone(primary) && pcmk__is_primitive(dependent));
266
267 if (pcmk_is_set(primary->flags, pcmk__rsc_unassigned)) {
268 pcmk__rsc_trace(primary,
269 "Delaying processing colocation %s "
270 "because cloned primary %s is still provisional",
271 colocation->id, primary->id);
272 return 0;
273 }
274
275 pcmk__rsc_trace(primary, "Processing colocation %s (%s with clone %s @%s)",
276 colocation->id, dependent->id, primary->id,
277 pcmk_readable_score(colocation->score));
278
279 // Apply role-specific colocations
281 && (colocation->primary_role != pcmk_role_unknown)) {
282
283 if (pcmk_is_set(dependent->flags, pcmk__rsc_unassigned)) {
284 // We're assigning the dependent to a node
286 colocation);
287 return 0;
288 }
289
290 if (colocation->dependent_role == pcmk_role_promoted) {
291 // We're choosing a role for the dependent
293 dependent,
294 colocation);
295 }
296 }
297
298 // Apply interleaved colocations
299 if (can_interleave(colocation)) {
300 const pcmk_resource_t *primary_instance = NULL;
301
302 primary_instance = pcmk__find_compatible_instance(dependent, primary,
304 false);
305 if (primary_instance != NULL) {
306 pcmk__rsc_debug(primary, "Interleaving %s with %s",
307 dependent->id, primary_instance->id);
308
309 return dependent->priv->cmds->apply_coloc_score(dependent,
310 primary_instance,
311 colocation, true);
312 }
313
314 if (colocation->score >= PCMK_SCORE_INFINITY) {
315 crm_notice("%s cannot run because it cannot interleave with "
316 "any instance of %s", dependent->id, primary->id);
317 pcmk__assign_resource(dependent, NULL, true, true);
318
319 } else {
320 pcmk__rsc_debug(primary,
321 "%s will not colocate with %s "
322 "because no instance can interleave with it",
323 dependent->id, primary->id);
324 }
325
326 return 0;
327 }
328
329 // Apply mandatory colocations
330 if (colocation->score >= PCMK_SCORE_INFINITY) {
331 GList *primary_nodes = NULL;
332
333 // Dependent can run only where primary will have unblocked instances
334 for (iter = primary->priv->children;
335 iter != NULL; iter = iter->next) {
336
337 const pcmk_resource_t *instance = iter->data;
338 pcmk_node_t *chosen = NULL;
339
340 chosen = instance->priv->fns->location(instance, NULL,
342 if ((chosen != NULL)
343 && !is_set_recursive(instance, pcmk__rsc_blocked, TRUE)) {
344 pcmk__rsc_trace(primary, "Allowing %s: %s %d",
345 colocation->id, pcmk__node_name(chosen),
346 chosen->assign->score);
347 primary_nodes = g_list_prepend(primary_nodes, chosen);
348 }
349 }
350 pcmk__colocation_intersect_nodes(dependent, primary, colocation,
351 primary_nodes, false);
352 g_list_free(primary_nodes);
353 return 0;
354 }
355
356 // Apply optional colocations
357 for (iter = primary->priv->children; iter != NULL; iter = iter->next) {
358 const pcmk_resource_t *instance = iter->data;
359 int instance_delta = instance->priv->cmds->apply_coloc_score(dependent,
360 instance,
361 colocation,
362 false);
363
364 priority_delta = pcmk__add_scores(priority_delta, instance_delta);
365 }
366 return priority_delta;
367}
368
369// Clone implementation of pcmk__assignment_methods_t:with_this_colocations()
370void
372 const pcmk_resource_t *orig_rsc, GList **list)
373{
374 const pcmk_resource_t *parent = NULL;
375
376 CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
377 parent = rsc->priv->parent;
378
380 orig_rsc);
381
382 if (parent != NULL) {
383 parent->priv->cmds->with_this_colocations(parent, orig_rsc, list);
384 }
385}
386
387// Clone implementation of pcmk__assignment_methods_t:this_with_colocations()
388void
390 const pcmk_resource_t *orig_rsc, GList **list)
391{
392 const pcmk_resource_t *parent = NULL;
393
394 CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
395 parent = rsc->priv->parent;
396
398 orig_rsc);
399
400 if (parent != NULL) {
401 parent->priv->cmds->this_with_colocations(parent, orig_rsc, list);
402 }
403}
404
414uint32_t
416{
417 pcmk__assert((action != NULL) && pcmk__is_clone(action->rsc));
418
419 return pcmk__collective_action_flags(action, action->rsc->priv->children,
420 node);
421}
422
430void
432{
433 CRM_CHECK((location != NULL) && pcmk__is_clone(rsc), return);
434
435 pcmk__apply_location(rsc, location);
436
437 for (GList *iter = rsc->priv->children;
438 iter != NULL; iter = iter->next) {
439
440 pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
441
442 instance->priv->cmds->apply_location(instance, location);
443 }
444}
445
446// GFunc wrapper for calling the action_flags() resource method
447static void
448call_action_flags(gpointer data, gpointer user_data)
449{
450 pcmk_resource_t *rsc = user_data;
451
452 rsc->priv->cmds->action_flags((pcmk_action_t *) data, NULL);
453}
454
461void
463{
464 pcmk__assert(pcmk__is_clone(rsc));
465
466 g_list_foreach(rsc->priv->actions, call_action_flags, rsc);
468
469 for (GList *iter = rsc->priv->children;
470 iter != NULL; iter = iter->next) {
471
472 pcmk_resource_t *child_rsc = (pcmk_resource_t *) iter->data;
473
474 child_rsc->priv->cmds->add_actions_to_graph(child_rsc);
475 }
476
479}
480
491static bool
492rsc_probed_on(const pcmk_resource_t *rsc, const pcmk_node_t *node)
493{
494 if (rsc->priv->children != NULL) {
495 for (GList *child_iter = rsc->priv->children;
496 child_iter != NULL; child_iter = child_iter->next) {
497
498 pcmk_resource_t *child = (pcmk_resource_t *) child_iter->data;
499
500 if (rsc_probed_on(child, node)) {
501 return true;
502 }
503 }
504 return false;
505 }
506
507 if (rsc->priv->probed_nodes != NULL) {
508 GHashTableIter iter;
509 pcmk_node_t *known_node = NULL;
510
511 g_hash_table_iter_init(&iter, rsc->priv->probed_nodes);
512 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &known_node)) {
513 if (pcmk__same_node(node, known_node)) {
514 return true;
515 }
516 }
517 }
518 return false;
519}
520
531static pcmk_resource_t *
532find_probed_instance_on(const pcmk_resource_t *clone, const pcmk_node_t *node)
533{
534 for (GList *iter = clone->priv->children;
535 iter != NULL; iter = iter->next) {
536
537 pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
538
539 if (rsc_probed_on(instance, node)) {
540 return instance;
541 }
542 }
543 return NULL;
544}
545
553static bool
554probe_anonymous_clone(pcmk_resource_t *clone, pcmk_node_t *node)
555{
556 // Check whether we already probed an instance on this node
557 pcmk_resource_t *child = find_probed_instance_on(clone, node);
558
559 // Otherwise, check if we plan to start an instance on this node
560 for (GList *iter = clone->priv->children;
561 (iter != NULL) && (child == NULL); iter = iter->next) {
562
563 pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
564 const pcmk_node_t *instance_node = NULL;
565
566 instance_node = instance->priv->fns->location(instance, NULL,
568 if (pcmk__same_node(instance_node, node)) {
569 child = instance;
570 }
571 }
572
573 // Otherwise, use the first clone instance
574 if (child == NULL) {
575 child = clone->priv->children->data;
576 }
577
578 // Anonymous clones only need to probe a single instance
579 return child->priv->cmds->create_probe(child, node);
580}
581
591bool
593{
594 pcmk__assert((node != NULL) && pcmk__is_clone(rsc));
595
597 /* The clone is configured to be probed only where a location constraint
598 * exists with PCMK_XA_RESOURCE_DISCOVERY set to exclusive.
599 *
600 * This check is not strictly necessary here since the instance's
601 * create_probe() method would also check, but doing it here is more
602 * efficient (especially for unique clones with a large number of
603 * instances), and affects the CRM_meta_notify_available_uname variable
604 * passed with notify actions.
605 */
606 pcmk_node_t *allowed = g_hash_table_lookup(rsc->priv->allowed_nodes,
607 node->priv->id);
608
609 if ((allowed == NULL)
610 || (allowed->assign->probe_mode != pcmk__probe_exclusive)) {
611 /* This node is not marked for resource discovery. Remove it from
612 * allowed nodes so that notifications contain only nodes that the
613 * clone can possibly run on.
614 */
615 pcmk__rsc_trace(rsc,
616 "Skipping probe for %s on %s because resource has "
617 "exclusive discovery but is not allowed on node",
618 rsc->id, pcmk__node_name(node));
619 g_hash_table_remove(rsc->priv->allowed_nodes, node->priv->id);
620 return false;
621 }
622 }
623
624 rsc->priv->children = g_list_sort(rsc->priv->children,
627 return pcmk__probe_resource_list(rsc->priv->children, node);
628 } else {
629 return probe_anonymous_clone(rsc, node);
630 }
631}
632
642void
644{
645 char *name = NULL;
646
647 pcmk__assert(pcmk__is_clone(rsc) && (xml != NULL));
648
650 crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk__rsc_unique));
651 free(name);
652
654 crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk__rsc_notify));
655 free(name);
656
659 free(name);
660
663 free(name);
664
666 int promoted_max = pe__clone_promoted_max(rsc);
667 int promoted_node_max = pe__clone_promoted_node_max(rsc);
668
670 crm_xml_add_int(xml, name, promoted_max);
671 free(name);
672
674 crm_xml_add_int(xml, name, promoted_node_max);
675 free(name);
676
677 /* @COMPAT Maintain backward compatibility with resource agents that
678 * expect the old names (deprecated since 2.0.0).
679 */
681 crm_xml_add_int(xml, name, promoted_max);
682 free(name);
683
685 crm_xml_add_int(xml, name, promoted_node_max);
686 free(name);
687 }
688}
689
690// Clone implementation of pcmk__assignment_methods_t:add_utilization()
691void
693 const pcmk_resource_t *orig_rsc, GList *all_rscs,
694 GHashTable *utilization)
695{
696 bool existing = false;
697 pcmk_resource_t *child = NULL;
698
699 pcmk__assert(pcmk__is_clone(rsc) && (orig_rsc != NULL)
700 && (utilization != NULL));
701
703 return;
704 }
705
706 // Look for any child already existing in the list
707 for (GList *iter = rsc->priv->children;
708 iter != NULL; iter = iter->next) {
709
710 child = (pcmk_resource_t *) iter->data;
711 if (g_list_find(all_rscs, child)) {
712 existing = true; // Keep checking remaining children
713 } else {
714 // If this is a clone of a group, look for group's members
715 for (GList *member_iter = child->priv->children;
716 member_iter != NULL; member_iter = member_iter->next) {
717
718 pcmk_resource_t *member = (pcmk_resource_t *) member_iter->data;
719
720 if (g_list_find(all_rscs, member) != NULL) {
721 // Add *child's* utilization, not group member's
722 child->priv->cmds->add_utilization(child, orig_rsc,
723 all_rscs, utilization);
724 existing = true;
725 break;
726 }
727 }
728 }
729 }
730
731 if (!existing && (rsc->priv->children != NULL)) {
732 // If nothing was found, still add first child's utilization
733 child = (pcmk_resource_t *) rsc->priv->children->data;
734
735 child->priv->cmds->add_utilization(child, orig_rsc, all_rscs,
736 utilization);
737 }
738}
739
740// Clone implementation of pcmk__assignment_methods_t:shutdown_lock()
741void
743{
744 pcmk__assert(pcmk__is_clone(rsc));
745 return; // Clones currently don't support shutdown locks
746}
@ 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_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)
#define PCMK_ACTION_STOP
Definition actions.h:66
#define PCMK_ACTION_RUNNING
Definition actions.h:62
#define PCMK_ACTION_PROMOTE
Definition actions.h:57
#define PCMK_ACTION_START
Definition actions.h:63
#define PCMK_ACTION_STOPPED
Definition actions.h:67
#define PCMK_ACTION_DEMOTED
Definition actions.h:41
const char * parent
Definition cib.c:27
const char * name
Definition cib.c:26
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:80
char data[0]
Definition cpg.c:10
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__colocation_intersect_nodes(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, const GList *primary_nodes, bool merge_scores)
#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)
G_GNUC_INTERNAL gint pcmk__cmp_instance_number(gconstpointer a, gconstpointer b)
G_GNUC_INTERNAL bool pcmk__assign_resource(pcmk_resource_t *rsc, pcmk_node_t *node, bool force, bool stop_if_fail)
G_GNUC_INTERNAL void pcmk__create_promotable_actions(pcmk_resource_t *clone)
G_GNUC_INTERNAL pcmk_resource_t * pcmk__find_compatible_instance(const pcmk_resource_t *match_rsc, const pcmk_resource_t *rsc, enum rsc_role_e role, bool current)
G_GNUC_INTERNAL GList * pcmk__with_this_colocations(const pcmk_resource_t *rsc)
G_GNUC_INTERNAL gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
G_GNUC_INTERNAL void pcmk__order_promotable_instances(pcmk_resource_t *clone)
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL int pcmk__update_promotable_dependent_priority(const pcmk_resource_t *primary, pcmk_resource_t *dependent, const pcmk__colocation_t *colocation)
G_GNUC_INTERNAL bool pcmk__probe_resource_list(GList *rscs, pcmk_node_t *node)
G_GNUC_INTERNAL void pcmk__add_dependent_scores(gpointer data, gpointer user_data)
G_GNUC_INTERNAL GList * pcmk__this_with_colocations(const pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__set_instance_roles(pcmk_resource_t *rsc)
#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)
G_GNUC_INTERNAL void pcmk__add_promotion_scores(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__add_rsc_actions_to_graph(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__update_dependent_with_promotable(const pcmk_resource_t *primary, pcmk_resource_t *dependent, const pcmk__colocation_t *colocation)
Update dependent for a colocation with a promotable clone.
#define crm_notice(fmt, args...)
Definition logging.h:363
#define CRM_CHECK(expr, failure_action)
Definition logging.h:213
#define pcmk__config_err(fmt...)
@ pcmk__probe_exclusive
char * crm_meta_name(const char *field)
Get the environment variable equivalent of a meta-attribute name.
Definition nvpair.c:525
#define PCMK_META_CLONE_NODE_MAX
Definition options.h:85
#define PCMK_META_PROMOTED_MAX
Definition options.h:103
#define PCMK_META_CLONE_MAX
Definition options.h:83
#define PCMK_META_INTERLEAVE
Definition options.h:91
#define PCMK_META_NOTIFY
Definition options.h:98
#define PCMK_META_GLOBALLY_UNIQUE
Definition options.h:90
#define PCMK_META_PROMOTED_NODE_MAX
Definition options.h:104
#define PCMK__META_PROMOTED_MAX_LEGACY
#define PCMK__META_PROMOTED_NODE_MAX_LEGACY
const char * action
Definition pcmk_fence.c:32
void pcmk__clone_add_graph_meta(const pcmk_resource_t *rsc, xmlNode *xml)
void pcmk__clone_create_actions(pcmk_resource_t *rsc)
void pcmk__clone_internal_constraints(pcmk_resource_t *rsc)
uint32_t pcmk__clone_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
void pcmk__clone_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
int pcmk__clone_apply_coloc_score(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void pcmk__with_clone_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void pcmk__clone_shutdown_lock(pcmk_resource_t *rsc)
pcmk_node_t * pcmk__clone_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
bool pcmk__clone_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
void pcmk__clone_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
void pcmk__clone_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void pcmk__clone_add_actions_to_graph(pcmk_resource_t *rsc)
bool is_set_recursive(const pcmk_resource_t *rsc, long long flag, bool any)
Definition clone.c:500
void pe__create_clone_notifications(pcmk_resource_t *clone)
Definition clone.c:1169
int pe__clone_promoted_node_max(const pcmk_resource_t *clone)
Definition clone.c:107
#define pe__show_node_scores(level, rsc, text, nodes, scheduler)
Definition internal.h:158
int pe__clone_max(const pcmk_resource_t *clone)
Definition clone.c:56
bool pe__clone_is_ordered(const pcmk_resource_t *clone)
Definition clone.c:1043
int pe__clone_node_max(const pcmk_resource_t *clone)
Definition clone.c:73
int pe__clone_promoted_max(const pcmk_resource_t *clone)
Definition clone.c:90
void pe__free_clone_notification_data(pcmk_resource_t *clone)
Definition clone.c:1188
@ pcmk__rsc_assigning
@ pcmk__rsc_unassigned
@ pcmk__rsc_blocked
@ pcmk__rsc_unique
@ pcmk__rsc_promotable
@ pcmk__rsc_exclusive_probes
@ pcmk__rsc_notify
#define pcmk__set_rsc_flags(resource, flags_to_set)
@ pcmk__rsc_variant_group
Group resource.
@ pcmk__rsc_node_assigned
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
#define pcmk__assert(expr)
@ pcmk_role_unknown
Resource role is unknown.
Definition roles.h:35
@ pcmk_role_promoted
Promoted.
Definition roles.h:39
#define pcmk__rsc_trace(rsc, fmt, args...)
#define pcmk__rsc_debug(rsc, fmt, args...)
@ pcmk__sched_output_scores
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition scores.c:102
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition scores.h:26
int pcmk__add_scores(int score1, int score2)
Definition scores.c:159
gboolean crm_is_true(const char *s)
Definition strings.c:490
uint32_t(* action_flags)(pcmk_action_t *action, const pcmk_node_t *node)
pcmk_node_t *(* assign)(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
int(* apply_coloc_score)(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void(* internal_constraints)(pcmk_resource_t *rsc)
bool(* create_probe)(pcmk_resource_t *rsc, pcmk_node_t *node)
void(* add_actions_to_graph)(pcmk_resource_t *rsc)
void(* add_utilization)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void(* apply_location)(pcmk_resource_t *rsc, pcmk__location_t *location)
pcmk_resource_t * primary
pcmk_resource_t * dependent
Location constraint object.
enum pcmk__probe_mode probe_mode
pcmk_scheduler_t * scheduler
enum pcmk__rsc_variant variant
const pcmk__assignment_methods_t * cmds
const pcmk__rsc_methods_t * fns
unsigned long long flags
Definition resources.h:69
pcmk__resource_private_t * priv
Definition resources.h:61
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, uint32_t target)
unsigned int(* max_per_node)(const pcmk_resource_t *rsc)
uint64_t flags
Definition scheduler.h:89
pcmk__node_private_t * priv
Definition nodes.h:85
struct pcmk__node_assignment * assign
Definition nodes.h:79
Wrappers for and extensions to libxml2.
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.