pacemaker 2.1.6-6fdc9deea29
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-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 <crm/msg_xml.h>
13#include <pacemaker-internal.h>
14
16
28{
29 CRM_ASSERT(pe_rsc_is_clone(rsc));
30
32 return NULL; // Assignment has already been done
33 }
34
35 // Detect assignment loops
37 pe_rsc_debug(rsc, "Breaking assignment loop involving %s", rsc->id);
38 return NULL;
39 }
41
42 // If this clone is promotable, consider nodes' promotion scores
45 }
46
47 /* If this clone is colocated with any other resources, assign those first.
48 * Since the this_with_colocations() method boils down to a copy of rsc_cons
49 * for clones, we can use that here directly for efficiency.
50 */
51 for (GList *iter = rsc->rsc_cons; iter != NULL; iter = iter->next) {
52 pcmk__colocation_t *constraint = (pcmk__colocation_t *) iter->data;
53
54 pe_rsc_trace(rsc, "%s: Assigning colocation %s primary %s first",
55 rsc->id, constraint->id, constraint->primary->id);
56 constraint->primary->cmds->assign(constraint->primary, prefer);
57 }
58
59 /* If any resources are colocated with this one, consider their preferences.
60 * Because the with_this_colocations() method boils down to a copy of
61 * rsc_cons_lhs for clones, we can use that here directly for efficiency.
62 */
63 g_list_foreach(rsc->rsc_cons_lhs, pcmk__add_dependent_scores, rsc);
64
66 rsc, __func__, rsc->allowed_nodes, rsc->cluster);
67
68 rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance);
71
74 }
75
77 pe_rsc_trace(rsc, "Assigned clone %s", rsc->id);
78 return NULL;
79}
80
81static pe_action_t *
82find_rsc_action(pe_resource_t *rsc, const char *task)
83{
84 pe_action_t *match = NULL;
85 GList *actions = pe__resource_actions(rsc, NULL, task, FALSE);
86
87 for (GList *item = actions; item != NULL; item = item->next) {
88 pe_action_t *op = (pe_action_t *) item->data;
89
90 if (!pcmk_is_set(op->flags, pe_action_optional)) {
91 if (match != NULL) {
92 // More than one match, don't return any
93 match = NULL;
94 break;
95 }
96 match = op;
97 }
98 }
99 g_list_free(actions);
100 return match;
101}
102
109static void
110order_instance_starts_stops(pe_resource_t *rsc)
111{
112 pe_action_t *last_stop = NULL;
113 pe_action_t *last_start = NULL;
114
115 // Instances must be ordered by ascending instance number, so sort them
116 rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
117
118 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
119 pe_resource_t *child = (pe_resource_t *) iter->data;
120 pe_action_t *action = NULL;
121
122 // Order this instance's stop after previous instance's stop
123 // @TODO: Should instances be stopped in reverse order instead?
124 action = find_rsc_action(child, RSC_STOP);
125 if (action != NULL) {
126 if (last_stop != NULL) {
128 }
129 last_stop = action;
130 }
131
132 // Order this instance's start after previous instance's start
133 action = find_rsc_action(child, RSC_START);
134 if (action != NULL) {
135 if (last_start != NULL) {
137 }
138 last_start = action;
139 }
140 }
141}
142
143void
145{
146 pe_rsc_debug(rsc, "Creating actions for clone %s", rsc->id);
148 if (pe__clone_is_ordered(rsc)) {
149 order_instance_starts_stops(rsc);
150 }
153 }
154}
155
156void
158{
159 pe_resource_t *last_rsc = NULL;
160 GList *gIter;
161 bool ordered = pe__clone_is_ordered(rsc);
162
163 pe_rsc_trace(rsc, "Internal constraints for %s", rsc->id);
170
176 }
177
178 if (ordered) {
179 /* we have to maintain a consistent sorted child list when building order constraints */
180 rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
181 }
182 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
183 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
184
185 child_rsc->cmds->internal_constraints(child_rsc);
186
187 pcmk__order_starts(rsc, child_rsc,
191 if (ordered && (last_rsc != NULL)) {
192 pcmk__order_starts(last_rsc, child_rsc, pe_order_optional);
193 }
194
198 if (ordered && (last_rsc != NULL)) {
199 pcmk__order_stops(child_rsc, last_rsc, pe_order_optional);
200 }
201
202 last_rsc = child_rsc;
203 }
206 }
207}
208
222void
224 const pe_resource_t *primary,
225 const pcmk__colocation_t *colocation,
226 bool for_dependent)
227{
228 GList *gIter = NULL;
229 gboolean do_interleave = FALSE;
230 const char *interleave_s = NULL;
231
232 /* This should never be called for the clone itself as a dependent. Instead,
233 * we add its colocation constraints to its instances and call the
234 * apply_coloc_score() for the instances as dependents.
235 */
236 CRM_ASSERT(!for_dependent);
237
238 CRM_CHECK((colocation != NULL) && (dependent != NULL) && (primary != NULL),
239 return);
240 CRM_CHECK(dependent->variant == pe_native, return);
241
242 pe_rsc_trace(primary, "Processing constraint %s: %s -> %s %d",
243 colocation->id, dependent->id, primary->id, colocation->score);
244
245 if (pcmk_is_set(primary->flags, pe_rsc_promotable)) {
246 if (pcmk_is_set(primary->flags, pe_rsc_provisional)) {
247 // We haven't placed the primary yet, so we can't apply colocation
248 pe_rsc_trace(primary, "%s is still provisional", primary->id);
249 return;
250
251 } else if (colocation->primary_role == RSC_ROLE_UNKNOWN) {
252 // This isn't a role-specfic colocation, so handle normally
253 pe_rsc_trace(primary, "Handling %s as a clone colocation",
254 colocation->id);
255
256 } else if (pcmk_is_set(dependent->flags, pe_rsc_provisional)) {
257 // We're placing the dependent
259 colocation);
260 return;
261
262 } else if (colocation->dependent_role == RSC_ROLE_PROMOTED) {
263 // We're choosing roles for the dependent
265 colocation);
266 return;
267 }
268 }
269
270 // Only the dependent needs to be marked for interleave
271 interleave_s = g_hash_table_lookup(colocation->dependent->meta,
273 if (crm_is_true(interleave_s)
274 && (colocation->dependent->variant > pe_group)) {
275 /* @TODO Do we actually care about multiple primary copies sharing a
276 * dependent copy anymore?
277 */
278 if (copies_per_node(colocation->dependent) != copies_per_node(colocation->primary)) {
279 pcmk__config_err("Cannot interleave %s and %s because they do not "
280 "support the same number of instances per node",
281 colocation->dependent->id,
282 colocation->primary->id);
283
284 } else {
285 do_interleave = TRUE;
286 }
287 }
288
289 if (pcmk_is_set(primary->flags, pe_rsc_provisional)) {
290 pe_rsc_trace(primary, "%s is still provisional", primary->id);
291 return;
292
293 } else if (do_interleave) {
294 pe_resource_t *primary_instance = NULL;
295
296 primary_instance = pcmk__find_compatible_instance(dependent, primary,
298 false);
299 if (primary_instance != NULL) {
300 pe_rsc_debug(primary, "Pairing %s with %s",
301 dependent->id, primary_instance->id);
302 dependent->cmds->apply_coloc_score(dependent, primary_instance,
303 colocation, true);
304
305 } else if (colocation->score >= INFINITY) {
306 crm_notice("Cannot pair %s with instance of %s",
307 dependent->id, primary->id);
308 pcmk__assign_resource(dependent, NULL, true);
309
310 } else {
311 pe_rsc_debug(primary, "Cannot pair %s with instance of %s",
312 dependent->id, primary->id);
313 }
314
315 return;
316
317 } else if (colocation->score >= INFINITY) {
318 GList *affected_nodes = NULL;
319
320 gIter = primary->children;
321 for (; gIter != NULL; gIter = gIter->next) {
322 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
323 pe_node_t *chosen = child_rsc->fns->location(child_rsc, NULL, FALSE);
324
325 if (chosen != NULL && is_set_recursive(child_rsc, pe_rsc_block, TRUE) == FALSE) {
326 pe_rsc_trace(primary, "Allowing %s: %s %d",
327 colocation->id, pe__node_name(chosen),
328 chosen->weight);
329 affected_nodes = g_list_prepend(affected_nodes, chosen);
330 }
331 }
332
333 node_list_exclude(dependent->allowed_nodes, affected_nodes, FALSE);
334 g_list_free(affected_nodes);
335 return;
336 }
337
338 gIter = primary->children;
339 for (; gIter != NULL; gIter = gIter->next) {
340 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
341
342 child_rsc->cmds->apply_coloc_score(dependent, child_rsc, colocation,
343 false);
344 }
345}
346
347// Clone implementation of resource_alloc_functions_t:with_this_colocations()
348void
350 const pe_resource_t *orig_rsc, GList **list)
351{
352 CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
353
354 if (rsc == orig_rsc) { // Colocations are wanted for clone itself
356 } else {
357 pcmk__add_collective_constraints(list, orig_rsc, rsc, true);
358 }
359}
360
361// Clone implementation of resource_alloc_functions_t:this_with_colocations()
362void
364 const pe_resource_t *orig_rsc, GList **list)
365{
366 CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
367
368 if (rsc == orig_rsc) { // Colocations are wanted for clone itself
370 } else {
371 pcmk__add_collective_constraints(list, orig_rsc, rsc, false);
372 }
373}
374
377{
378 return pcmk__collective_action_flags(action, action->rsc->children, node);
379}
380
381void
383{
384 GList *gIter = rsc->children;
385
386 pe_rsc_trace(rsc, "Processing location constraint %s for %s", constraint->id, rsc->id);
387
388 pcmk__apply_location(rsc, constraint);
389
390 for (; gIter != NULL; gIter = gIter->next) {
391 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
392
393 child_rsc->cmds->apply_location(child_rsc, constraint);
394 }
395}
396
403void
405{
406 GList *gIter = NULL;
407
408 g_list_foreach(rsc->actions, (GFunc) rsc->cmds->action_flags, NULL);
409
411
412 /* Now that the notifcations have been created we can expand the children */
413
414 gIter = rsc->children;
415 for (; gIter != NULL; gIter = gIter->next) {
416 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
417
418 child_rsc->cmds->add_actions_to_graph(child_rsc);
419 }
420
422
423 /* The notifications are in the graph now, we can destroy the notify_data */
425}
426
427// Check whether a resource or any of its children is known on node
428static bool
429rsc_known_on(const pe_resource_t *rsc, const pe_node_t *node)
430{
431 if (rsc->children) {
432 for (GList *child_iter = rsc->children; child_iter != NULL;
433 child_iter = child_iter->next) {
434
435 pe_resource_t *child = (pe_resource_t *) child_iter->data;
436
437 if (rsc_known_on(child, node)) {
438 return TRUE;
439 }
440 }
441
442 } else if (rsc->known_on) {
443 GHashTableIter iter;
444 pe_node_t *known_node = NULL;
445
446 g_hash_table_iter_init(&iter, rsc->known_on);
447 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &known_node)) {
448 if (node->details == known_node->details) {
449 return TRUE;
450 }
451 }
452 }
453 return FALSE;
454}
455
456// Look for an instance of clone that is known on node
457static pe_resource_t *
458find_instance_on(const pe_resource_t *clone, const pe_node_t *node)
459{
460 for (GList *gIter = clone->children; gIter != NULL; gIter = gIter->next) {
461 pe_resource_t *child = (pe_resource_t *) gIter->data;
462
463 if (rsc_known_on(child, node)) {
464 return child;
465 }
466 }
467 return NULL;
468}
469
470// For anonymous clones, only a single instance needs to be probed
471static bool
472probe_anonymous_clone(pe_resource_t *rsc, pe_node_t *node,
474{
475 // First, check if we probed an instance on this node last time
476 pe_resource_t *child = find_instance_on(rsc, node);
477
478 // Otherwise, check if we plan to start an instance on this node
479 if (child == NULL) {
480 for (GList *child_iter = rsc->children; child_iter && !child;
481 child_iter = child_iter->next) {
482
483 pe_node_t *local_node = NULL;
484 pe_resource_t *child_rsc = (pe_resource_t *) child_iter->data;
485
486 if (child_rsc) { /* make clang analyzer happy */
487 local_node = child_rsc->fns->location(child_rsc, NULL, FALSE);
488 if (local_node && (local_node->details == node->details)) {
489 child = child_rsc;
490 }
491 }
492 }
493 }
494
495 // Otherwise, use the first clone instance
496 if (child == NULL) {
497 child = rsc->children->data;
498 }
499 CRM_ASSERT(child);
500 return child->cmds->create_probe(child, node);
501}
502
513bool
515{
516 CRM_ASSERT(rsc);
517
518 rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
519 if (rsc->children == NULL) {
520 pe_warn("Clone %s has no children", rsc->id);
521 return false;
522 }
523
524 if (rsc->exclusive_discover) {
525 pe_node_t *allowed = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
526 if (allowed && allowed->rsc_discover_mode != pe_discover_exclusive) {
527 /* exclusive discover is enabled and this node is not marked
528 * as a node this resource should be discovered on
529 *
530 * remove the node from allowed_nodes so that the
531 * notification contains only nodes that we might ever run
532 * on
533 */
534 g_hash_table_remove(rsc->allowed_nodes, node->details->id);
535
536 /* Bit of a shortcut - might as well take it */
537 return false;
538 }
539 }
540
541 if (pcmk_is_set(rsc->flags, pe_rsc_unique)) {
542 return pcmk__probe_resource_list(rsc->children, node);
543 } else {
544 return probe_anonymous_clone(rsc, node, rsc->cluster);
545 }
546}
547
548void
549clone_append_meta(const pe_resource_t *rsc, xmlNode *xml)
550{
551 char *name = NULL;
552
554 crm_xml_add(xml, name, pe__rsc_bool_str(rsc, pe_rsc_unique));
555 free(name);
556
558 crm_xml_add(xml, name, pe__rsc_bool_str(rsc, pe_rsc_notify));
559 free(name);
560
563 free(name);
564
567 free(name);
568
570 int promoted_max = pe__clone_promoted_max(rsc);
571 int promoted_node_max = pe__clone_promoted_node_max(rsc);
572
574 crm_xml_add_int(xml, name, promoted_max);
575 free(name);
576
578 crm_xml_add_int(xml, name, promoted_node_max);
579 free(name);
580
581 /* @COMPAT Maintain backward compatibility with resource agents that
582 * expect the old names (deprecated since 2.0.0).
583 */
585 crm_xml_add_int(xml, name, promoted_max);
586 free(name);
587
589 crm_xml_add_int(xml, name, promoted_node_max);
590 free(name);
591 }
592}
593
594// Clone implementation of resource_alloc_functions_t:add_utilization()
595void
597 const pe_resource_t *orig_rsc, GList *all_rscs,
598 GHashTable *utilization)
599{
600 bool existing = false;
601 pe_resource_t *child = NULL;
602
604 return;
605 }
606
607 // Look for any child already existing in the list
608 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
609 child = (pe_resource_t *) iter->data;
610 if (g_list_find(all_rscs, child)) {
611 existing = true; // Keep checking remaining children
612 } else {
613 // If this is a clone of a group, look for group's members
614 for (GList *member_iter = child->children; member_iter != NULL;
615 member_iter = member_iter->next) {
616
617 pe_resource_t *member = (pe_resource_t *) member_iter->data;
618
619 if (g_list_find(all_rscs, member) != NULL) {
620 // Add *child's* utilization, not group member's
621 child->cmds->add_utilization(child, orig_rsc, all_rscs,
622 utilization);
623 existing = true;
624 break;
625 }
626 }
627 }
628 }
629
630 if (!existing && (rsc->children != NULL)) {
631 // If nothing was found, still add first child's utilization
632 child = (pe_resource_t *) rsc->children->data;
633
634 child->cmds->add_utilization(child, orig_rsc, all_rscs, utilization);
635 }
636}
637
638// Clone implementation of resource_alloc_functions_t:shutdown_lock()
639void
641{
642 return; // Clones currently don't support shutdown locks
643}
const char * name
Definition cib.c:24
char * crm_meta_name(const char *field)
Definition utils.c:468
gboolean crm_is_true(const char *s)
Definition strings.c:416
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:121
@ RSC_ROLE_PROMOTED
Definition common.h:97
@ RSC_ROLE_UNKNOWN
Definition common.h:93
#define RSC_PROMOTE
Definition crm.h:205
#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_DEMOTED
Definition crm.h:208
#define pcmk__order_starts(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__set_instance_roles(pe_resource_t *rsc)
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)
#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 gint pcmk__cmp_instance_number(gconstpointer a, gconstpointer b)
G_GNUC_INTERNAL void pcmk__add_promotion_scores(pe_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__order_promotable_instances(pe_resource_t *clone)
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 void pcmk__add_rsc_actions_to_graph(pe_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__update_dependent_with_promotable(const pe_resource_t *primary, pe_resource_t *dependent, const pcmk__colocation_t *colocation)
Update dependent for a colocation with a promotable clone.
G_GNUC_INTERNAL bool pcmk__probe_resource_list(GList *rscs, pe_node_t *node)
G_GNUC_INTERNAL pe_resource_t * pcmk__find_compatible_instance(const pe_resource_t *match_rsc, const pe_resource_t *rsc, enum rsc_role_e role, bool current)
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__update_promotable_dependent_priority(const pe_resource_t *primary, pe_resource_t *dependent, const pcmk__colocation_t *colocation)
G_GNUC_INTERNAL void pcmk__add_dependent_scores(gpointer data, gpointer user_data)
G_GNUC_INTERNAL void pcmk__create_promotable_actions(pe_resource_t *clone)
#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)
#define crm_notice(fmt, args...)
Definition logging.h:377
#define CRM_CHECK(expr, failure_action)
Definition logging.h:235
#define pcmk__config_err(fmt...)
#define XML_RSC_ATTR_PROMOTED_MAX
Definition msg_xml.h:246
#define XML_RSC_ATTR_NOTIFY
Definition msg_xml.h:251
#define XML_RSC_ATTR_INCARNATION_MAX
Definition msg_xml.h:242
#define XML_RSC_ATTR_PROMOTED_NODEMAX
Definition msg_xml.h:247
#define PCMK_XA_PROMOTED_NODE_MAX_LEGACY
Definition msg_xml.h:55
#define XML_RSC_ATTR_UNIQUE
Definition msg_xml.h:250
#define XML_RSC_ATTR_INTERLEAVE
Definition msg_xml.h:240
#define XML_RSC_ATTR_INCARNATION_NODEMAX
Definition msg_xml.h:244
#define PCMK_XA_PROMOTED_MAX_LEGACY
Definition msg_xml.h:54
pe_working_set_t * data_set
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition nvpair.c:398
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition nvpair.c:302
const char * action
Definition pcmk_fence.c:30
enum pe_action_flags clone_action_flags(pe_action_t *action, const pe_node_t *node)
void pcmk__clone_with_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
void pcmk__clone_shutdown_lock(pe_resource_t *rsc)
void clone_create_actions(pe_resource_t *rsc)
void pcmk__clone_apply_coloc_score(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void pcmk__with_clone_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
void clone_append_meta(const pe_resource_t *rsc, xmlNode *xml)
pe_node_t * pcmk__clone_assign(pe_resource_t *rsc, const pe_node_t *prefer)
void clone_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
bool clone_create_probe(pe_resource_t *rsc, pe_node_t *node)
void pcmk__clone_add_utilization(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void clone_expand(pe_resource_t *rsc)
void clone_internal_constraints(pe_resource_t *rsc)
int copies_per_node(pe_resource_t *rsc)
#define pe_rsc_notify
Definition pe_types.h:277
#define pe_rsc_block
Definition pe_types.h:274
@ pe_order_implies_first_printed
Definition pe_types.h:535
@ pe_order_implies_then_printed
Definition pe_types.h:536
@ pe_order_optional
Definition pe_types.h:508
@ pe_order_runnable_left
Definition pe_types.h:518
#define pe_rsc_provisional
Definition pe_types.h:282
#define pe_rsc_unique
Definition pe_types.h:278
#define pe_rsc_allocating
Definition pe_types.h:283
@ pe_discover_exclusive
Definition pe_types.h:502
#define pe_flag_show_scores
Definition pe_types.h:150
pe_action_flags
Definition pe_types.h:316
@ pe_action_optional
Definition pe_types.h:319
@ pe_group
Definition pe_types.h:39
@ pe_native
Definition pe_types.h:38
#define pe_rsc_promotable
Definition pe_types.h:280
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
Definition internal.h:385
void node_list_exclude(GHashTable *list, GList *list2, gboolean merge_scores)
Definition utils.c:108
bool pe__clone_is_ordered(const pe_resource_t *clone)
Definition clone.c:1289
bool is_set_recursive(const pe_resource_t *rsc, long long flag, bool any)
Definition clone.c:555
void pe__create_clone_notifications(pe_resource_t *clone)
Definition clone.c:1399
int pe__clone_node_max(const pe_resource_t *clone)
Definition clone.c:79
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition internal.h:83
#define pe_rsc_debug(rsc, fmt, args...)
Definition internal.h:49
#define pe_warn(fmt...)
Definition internal.h:57
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition utils.c:488
#define pe_rsc_trace(rsc, fmt, args...)
Definition internal.h:50
#define pe__set_resource_flags(resource, flags_to_set)
Definition internal.h:77
int pe__clone_max(const pe_resource_t *clone)
Definition clone.c:62
int pe__clone_promoted_node_max(const pe_resource_t *clone)
Definition clone.c:113
void pe__free_clone_notification_data(pe_resource_t *clone)
Definition clone.c:1418
int pe__clone_promoted_max(const pe_resource_t *clone)
Definition clone.c:96
#define CRM_ASSERT(expr)
Definition results.h:42
pe_resource_t * primary
pe_resource_t * dependent
int weight
Definition pe_types.h:265
int rsc_discover_mode
Definition pe_types.h:269
struct pe_node_shared_s * details
Definition pe_types.h:268
const char * id
Definition pe_types.h:231
GList * actions
Definition pe_types.h:391
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
GList * children
Definition pe_types.h:409
gboolean exclusive_discover
Definition pe_types.h:377
GHashTable * known_on
Definition pe_types.h:399
pe_working_set_t * cluster
Definition pe_types.h:353
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_location)(pe_resource_t *rsc, pe__location_t *location)
void(* apply_coloc_score)(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
bool(* create_probe)(pe_resource_t *rsc, pe_node_t *node)
void(* add_utilization)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
enum pe_action_flags(* action_flags)(pe_action_t *action, const pe_node_t *node)
void(* add_actions_to_graph)(pe_resource_t *rsc)
void(* internal_constraints)(pe_resource_t *rsc)
pe_node_t *(* assign)(pe_resource_t *rsc, const pe_node_t *prefer)
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition pe_types.h:55