37 instance->
id, pcmk__node_name(node));
43 "%s cannot run on %s: node cannot run resources",
44 instance->
id, pcmk__node_name(node));
49 if (allowed_node == NULL) {
50 crm_warn(
"%s cannot run on %s: node not allowed",
51 instance->
id, pcmk__node_name(node));
57 "%s cannot run on %s: parent score is %s there",
58 instance->
id, pcmk__node_name(node),
65 "%s cannot run on %s: node already has %d instance%s",
66 instance->
id, pcmk__node_name(node), max_per_node,
72 instance->
id, pcmk__node_name(node),
85ban_unavailable_allowed_nodes(
pcmk_resource_t *instance,
int max_per_node)
92 while (g_hash_table_iter_next(&iter, NULL, (
void **) &node)) {
93 if (!can_run_instance(instance, node, max_per_node)) {
95 instance->
id, pcmk__node_name(node));
99 child_iter != NULL; child_iter = child_iter->next) {
107 if (child_node != NULL) {
109 "Banning %s child %s "
110 "from unavailable node %s",
111 instance->
id, child->
id,
112 pcmk__node_name(node));
137 g_hash_table_insert(table, (gpointer) node->
priv->
id, node);
149apply_parent_colocations(
const pcmk_resource_t *rsc, GHashTable **nodes)
153 for (
const GList *iter = colocations; iter != NULL; iter = iter->next) {
159 nodes, colocation, factor,
162 g_list_free(colocations);
165 for (
const GList *iter = colocations; iter != NULL; iter = iter->next) {
174 nodes, colocation, factor,
177 g_list_free(colocations);
202 pcmk_node_t *current_node1 = pcmk__current_node(instance1);
203 pcmk_node_t *current_node2 = pcmk__current_node(instance2);
204 GHashTable *colocated_scores1 = NULL;
205 GHashTable *colocated_scores2 = NULL;
208 && (instance2 != NULL) && (instance2->
priv->
parent != NULL)
209 && (current_node1 != NULL) && (current_node2 != NULL));
212 colocated_scores1 = new_node_table(current_node1);
213 colocated_scores2 = new_node_table(current_node2);
216 apply_parent_colocations(instance1, &colocated_scores1);
217 apply_parent_colocations(instance2, &colocated_scores2);
220 node1 = g_hash_table_lookup(colocated_scores1, current_node1->
priv->
id);
221 node2 = g_hash_table_lookup(colocated_scores2, current_node2->
priv->
id);
225 crm_trace(
"Assign %s (%d on %s) after %s (%d on %s)",
231 crm_trace(
"Assign %s (%d on %s) before %s (%d on %s)",
237 g_hash_table_destroy(colocated_scores1);
238 g_hash_table_destroy(colocated_scores2);
258 iter != NULL; iter = iter->next) {
283 if ((allowed == NULL) || (allowed->
assign->
score < 0)) {
285 rsc->
id, pcmk__node_name(*node));
312 pcmk__assert((instance1 != NULL) && (instance2 != NULL));
315 div1 = strrchr(instance1->
id,
':');
317 div1 = strrchr(instance1->
id,
'-');
319 div2 = strrchr(instance2->
id,
':');
321 div2 = strrchr(instance2->
id,
'-');
325 return (gint) (strtol(div1 + 1, NULL, 10) - strtol(div2 + 1, NULL, 10));
359 unsigned int nnodes1 = 0;
360 unsigned int nnodes2 = 0;
368 pcmk__assert((instance1 != NULL) && (instance2 != NULL));
376 if ((nnodes1 > 0) && (nnodes2 > 0)) {
377 if (nnodes1 < nnodes2) {
378 crm_trace(
"Assign %s (active on %d) before %s (active on %d): "
379 "less multiply active",
380 instance1->
id, nnodes1, instance2->
id, nnodes2);
383 }
else if (nnodes1 > nnodes2) {
384 crm_trace(
"Assign %s (active on %d) after %s (active on %d): "
385 "more multiply active",
386 instance1->
id, nnodes1, instance2->
id, nnodes2);
394 can1 = node_is_allowed(instance1, &
node1);
395 can2 = node_is_allowed(instance2, &
node2);
397 crm_trace(
"Assign %s before %s: not active on a disallowed node",
398 instance1->
id, instance2->
id);
401 }
else if (!can1 && can2) {
402 crm_trace(
"Assign %s after %s: active on a disallowed node",
403 instance1->
id, instance2->
id);
409 crm_trace(
"Assign %s before %s: priority (%d > %d)",
410 instance1->
id, instance2->
id,
415 crm_trace(
"Assign %s after %s: priority (%d < %d)",
416 instance1->
id, instance2->
id,
423 crm_trace(
"No assignment preference for %s vs. %s: inactive",
424 instance1->
id, instance2->
id);
427 }
else if (
node1 == NULL) {
428 crm_trace(
"Assign %s after %s: active", instance1->
id, instance2->
id);
431 }
else if (
node2 == NULL) {
432 crm_trace(
"Assign %s before %s: active", instance1->
id, instance2->
id);
440 crm_trace(
"Assign %s before %s: current node can run resources",
441 instance1->
id, instance2->
id);
444 }
else if (!can1 && can2) {
445 crm_trace(
"Assign %s after %s: current node can't run resources",
446 instance1->
id, instance2->
id);
454 crm_trace(
"No assignment preference for %s vs. %s: "
455 "parent not allowed on either instance's current node",
456 instance1->
id, instance2->
id);
459 }
else if (
node1 == NULL) {
460 crm_trace(
"Assign %s after %s: parent not allowed on current node",
461 instance1->
id, instance2->
id);
464 }
else if (
node2 == NULL) {
465 crm_trace(
"Assign %s before %s: parent allowed on current node",
466 instance1->
id, instance2->
id);
472 crm_trace(
"Assign %s before %s: fewer active instances on current node",
473 instance1->
id, instance2->
id);
477 crm_trace(
"Assign %s after %s: more active instances on current node",
478 instance1->
id, instance2->
id);
483 can1 = did_fail(instance1);
484 can2 = did_fail(instance2);
486 crm_trace(
"Assign %s before %s: not failed",
487 instance1->
id, instance2->
id);
489 }
else if (can1 && !can2) {
491 instance1->
id, instance2->
id);
496 rc = cmp_instance_by_colocation(instance1, instance2);
504 crm_trace(
"Assign %s before %s: instance number",
505 instance1->
id, instance2->
id);
507 crm_trace(
"Assign %s after %s: instance number",
508 instance1->
id, instance2->
id);
510 crm_trace(
"No assignment preference for %s vs. %s",
511 instance1->
id, instance2->
id);
533 if (assigned_to == NULL) {
538 if (allowed == NULL) {
569 ((prefer == NULL)?
"no node" : prefer->
priv->
name));
573 "Assignment loop detected involving %s colocations",
577 ban_unavailable_allowed_nodes(instance, max_per_node);
580 chosen = instance->
priv->
cmds->
assign(instance, prefer, (prefer == NULL));
581 increment_parent_count(instance, chosen);
607 GHashTable *allowed_orig = NULL;
611 pcmk__rsc_trace(instance,
"Trying to assign %s to its current node %s",
612 instance->
id, pcmk__node_name(current));
618 "Not assigning %s to current node %s: unavailable",
619 instance->
id, pcmk__node_name(current));
647 while (reserved < available) {
648 chosen = assign_instance(instance, current, max_per_node);
650 if (pcmk__same_node(chosen, current)) {
660 if (chosen == NULL) {
663 "Not assigning %s to current node %s: unavailable",
664 instance->
id, pcmk__node_name(current));
671 "Not assigning %s to current node %s: %s is better",
672 instance->
id, pcmk__node_name(current),
673 pcmk__node_name(chosen));
676 if (++reserved >= available) {
678 "Not assigning %s to current node %s: "
679 "other assignments are more important",
680 instance->
id, pcmk__node_name(current));
684 "Reserved an instance of %s for %s. Retrying "
685 "assignment of %s to %s",
686 rsc->
id, pcmk__node_name(chosen), instance->
id,
687 pcmk__node_name(current));
695 g_hash_table_destroy(allowed_orig);
698 g_hash_table_destroy(
parent->priv->allowed_nodes);
699 parent->priv->allowed_nodes = allowed_orig_parent;
701 if (chosen == NULL) {
706 instance->
id, pcmk__node_name(current));
707 increment_parent_count(instance, chosen);
722 unsigned int available_nodes = 0;
727 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
728 node->assign->count = 0;
733 return available_nodes;
759 node = pcmk__current_node(instance);
761 pcmk__rsc_trace(instance,
"Not assigning %s to %s early (unavailable)",
762 instance->
id, pcmk__node_name(node));
768 if ((parent_node != NULL)
769 && (parent_node->
assign->
count >= optimal_per_node)) {
771 "Not assigning %s to %s early "
772 "(optimal instances already assigned)",
773 instance->
id, pcmk__node_name(node));
791 int max_total,
int max_per_node)
794 unsigned int available_nodes = reset_allowed_node_counts(collective);
796 int optimal_per_node = 0;
802 if (available_nodes > 0) {
803 optimal_per_node = max_total / available_nodes;
805 if (optimal_per_node < 1) {
806 optimal_per_node = 1;
810 "Assigning up to %d %s instance%s to up to %u node%s "
811 "(at most %d per host, %d optimal)",
814 max_per_node, optimal_per_node);
817 for (iter = instances; (iter != NULL) && (assigned < max_total);
819 int available = max_total - assigned;
821 instance = iter->data;
826 current = preferred_node(instance, optimal_per_node);
827 if ((current != NULL)
828 && assign_instance_early(collective, instance, current,
829 max_per_node, available)) {
834 pcmk__rsc_trace(collective,
"Assigned %d of %d instance%s to current node",
837 for (iter = instances; iter != NULL; iter = iter->next) {
845 current = pcmk__current_node(instance);
847 const char *unmanaged =
"";
850 unmanaged =
"Unmanaged resource ";
852 crm_notice(
"%s%s is running on %s which is no longer allowed",
853 unmanaged, instance->
id, pcmk__node_name(current));
857 if (assigned >= max_total) {
859 "Not assigning %s because maximum %d instances "
861 instance->
id, max_total);
863 "collective_limit_reached",
866 }
else if (assign_instance(instance, NULL, max_per_node) != NULL) {
871 pcmk__rsc_debug(collective,
"Assigned %d of %d possible instance%s of %s",
903 const GList *iter = NULL;
914 (iter != NULL) && !pcmk_all_flags_set(*state,
instance_all);
947 (optional?
"optional" :
"unrunnable"));
965 (optional?
"optional" :
"unrunnable"));
995 pcmk__rsc_trace(collective,
"Creating collective instance actions for %s",
999 for (GList *iter = instances; iter != NULL; iter = iter->next) {
1003 check_instance_state(instance, &state);
1030 if (pcmk__is_clone(collective)) {
1047static inline GList *
1050 if (pcmk__is_bundle(rsc)) {
1091 CRM_CHECK((instance != NULL) && (node != NULL),
return false);
1094 && (role != instance->
priv->
fns->
state(instance, current))) {
1096 "%s is not a compatible instance (role is not %s)",
1112 if (instance_node == NULL) {
1114 "%s is not a compatible instance "
1115 "(not assigned to a node)",
1120 if (!pcmk__same_node(instance_node, node)) {
1122 "%s is not a compatible instance "
1123 "(assigned to %s not %s)",
1124 instance->
id, pcmk__node_name(instance_node),
1125 pcmk__node_name(node));
1132#define display_role(r) \
1133 (((r) == pcmk_role_unknown)? "matching" : pcmk_role_text(r))
1154 GList *instances = NULL;
1156 instances = get_instance_list(rsc);
1157 for (GList *iter = instances; iter != NULL; iter = iter->next) {
1162 "Found %s %s instance %s compatible with %s on %s",
1164 match_rsc->
id, pcmk__node_name(node));
1165 free_instance_list(rsc, instances);
1169 free_instance_list(rsc, instances);
1172 "No %s %s instance found compatible with %s on %s",
1174 pcmk__node_name(node));
1197 GList *nodes = NULL;
1209 return find_compatible_instance_on_node(match_rsc, rsc, node, role,
1215 for (GList *iter = nodes; (iter != NULL) && (instance == NULL);
1216 iter = iter->next) {
1217 instance = find_compatible_instance_on_node(match_rsc, rsc,
1222 if (instance == NULL) {
1224 rsc->
id, match_rsc->
id);
1250 "%s has no instance to order before stopping "
1252 first->
rsc->
id, then_instance->
id);
1260 "Inhibiting %s from being active "
1261 "because there is no %s instance to interleave",
1262 then_instance->
id, first->
rsc->
id);
1324 if (matching_action != NULL) {
1325 return matching_action;
1329 || pcmk__is_down_action(action_name)) {
1330 crm_trace(
"No %s action found for %s%s",
1335 crm_err(
"No %s action found for %s to interleave (bug?)",
1336 action_name, instance->
id);
1360 char *action_type = NULL;
1361 const char *action_name =
action->task;
1369 action_name = strstr(action_type,
"_notify_");
1372 action_name += strlen(
"_notify_");
1404 GList *instances = NULL;
1406 const char *orig_first_task = orig_action_name(first);
1414 instances = get_instance_list(then->
rsc);
1415 for (GList *iter = instances; iter != NULL; iter = iter->next) {
1428 if (first_instance == NULL) {
1429 if (unassign_if_mandatory(first, then, then_instance,
type,
1436 first_action = find_instance_action(first, first_instance,
1437 orig_first_task, node,
true);
1438 if (first_action == NULL) {
1442 then_action = find_instance_action(then, then_instance, then->
task,
1444 if (then_action == NULL) {
1454 first_action, then_action, node,
1458 free_instance_list(then->
rsc, instances);
1474 bool interleave =
false;
1477 if ((first->
rsc == NULL) || (then->
rsc == NULL)) {
1478 crm_trace(
"Not interleaving %s with %s: not resource actions",
1483 if (first->
rsc == then->
rsc) {
1484 crm_trace(
"Not interleaving %s with %s: same resource",
1491 crm_trace(
"Not interleaving %s with %s: not clones or bundles",
1505 pcmk__rsc_trace(rsc,
"'%s then %s' will %sbe interleaved (based on %s)",
1506 first->
uuid, then->
uuid, (interleave?
"" :
"not "),
1536 uint32_t
flags, uint32_t filter, uint32_t
type)
1540 uint32_t instance_flags = 0;
1546 if (instance_action == NULL) {
1559 node,
flags, filter,
1565 after_iter != NULL; after_iter = after_iter->next) {
1601 uint32_t filter, uint32_t
type,
1606 if (then->
rsc == NULL) {
1609 }
else if (can_interleave_actions(first, then)) {
1610 return update_interleaved_actions(first, then, node, filter,
type);
1614 GList *instances = get_instance_list(then->
rsc);
1621 for (GList *iter = instances; iter != NULL; iter = iter->next) {
1624 changed |= update_noninterleaved_actions(instance, first, then,
1627 free_instance_list(then->
rsc, instances);
1632#define pe__clear_action_summary_flags(flags, action, flag) do { \
1633 flags = pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, \
1634 "Action summary", action->rsc->id, \
1635 flags, flag, #flag); \
1652 bool any_runnable =
false;
1653 const char *action_name = orig_action_name(
action);
1660 for (
const GList *iter = instances; iter != NULL; iter = iter->next) {
1664 uint32_t instance_flags;
1667 if (pcmk__is_primitive(instance)) {
1668 instance_node = node;
1672 action_name, instance_node);
1673 if (instance_action == NULL) {
1675 instance->
id, action_name, pcmk__node_name(node));
1680 instance->
id, instance_action->
uuid, action_name,
1681 pcmk__node_name(node));
1698 any_runnable =
true;
1702 if (!any_runnable) {
1704 "%s is not runnable because no instance can run %s",
1705 action->uuid, action_name);
@ pcmk__ar_first_implies_then
@ pcmk__ar_unrunnable_first_blocks
'then' is runnable (and migratable) only if 'first' is runnable
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
#define PCMK_ACTION_PROMOTED
#define PCMK_ACTION_RUNNING
#define PCMK_ACTION_PROMOTE
#define PCMK_ACTION_START
#define PCMK_ACTION_NOTIFIED
#define PCMK_ACTION_STOPPED
#define PCMK_ACTION_DEMOTED
#define PCMK_ACTION_DEMOTE
#define PCMK_ACTION_NOTIFY
@ pcmk__action_migratable
#define pcmk__set_action_flags(action, flags_to_set)
const char * pcmk__action_text(enum pcmk__action_type action)
#define pcmk__clear_action_flags(action, flags_to_clear)
@ pcmk__action_unspecified
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
enum pcmk_ipc_server type
@ pcmk__coloc_select_nonnegative
@ pcmk__coloc_select_default
G_GNUC_INTERNAL void pcmk__unassign_resource(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__update_action_for_orderings(pcmk_action_t *action, pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL uint32_t pcmk__update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL bool pcmk__assign_resource(pcmk_resource_t *rsc, pcmk_node_t *node, bool force, bool stop_if_fail)
#define pcmk__set_updated_flags(au_flags, action, flags_to_set)
G_GNUC_INTERNAL GList * pcmk__with_this_colocations(const pcmk_resource_t *rsc)
G_GNUC_INTERNAL bool pcmk__colocation_has_influence(const pcmk__colocation_t *colocation, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL GList * pcmk__sort_nodes(GList *nodes, pcmk_node_t *active_node)
G_GNUC_INTERNAL void pcmk__restore_node_tables(pcmk_resource_t *rsc, GHashTable *backup)
G_GNUC_INTERNAL GList * pcmk__this_with_colocations(const pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__copy_node_tables(const pcmk_resource_t *rsc, GHashTable **copy)
G_GNUC_INTERNAL pcmk_node_t * pcmk__top_allowed_node(const pcmk_resource_t *rsc, const pcmk_node_t *node)
G_GNUC_INTERNAL bool pcmk__node_available(const pcmk_node_t *node, bool consider_score, bool consider_guest)
G_GNUC_INTERNAL GHashTable * pcmk__copy_node_table(GHashTable *nodes)
#define crm_warn(fmt, args...)
#define CRM_LOG_ASSERT(expr)
#define crm_notice(fmt, args...)
#define CRM_CHECK(expr, failure_action)
#define crm_err(fmt, args...)
#define crm_trace(fmt, args...)
pcmk_scheduler_t * scheduler
void pcmk__free_node_copy(void *data)
#define PCMK_META_INTERLEAVE
void pcmk__create_instance_actions(pcmk_resource_t *collective, GList *instances)
#define pe__clear_action_summary_flags(flags, action, flag)
bool pcmk__instance_matches(const pcmk_resource_t *instance, const pcmk_node_t *node, enum rsc_role_e role, bool current)
gint pcmk__cmp_instance_number(gconstpointer a, gconstpointer b)
uint32_t pcmk__instance_update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
void pcmk__assign_instances(pcmk_resource_t *collective, GList *instances, int max_total, int max_per_node)
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)
uint32_t pcmk__collective_action_flags(pcmk_action_t *action, const GList *instances, const pcmk_node_t *node)
gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
bool is_set_recursive(const pcmk_resource_t *rsc, long long flag, bool any)
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
pcmk_action_t * pe__new_rsc_pseudo_action(pcmk_resource_t *rsc, const char *task, bool optional, bool runnable)
const pcmk_resource_t * pe__get_rsc_in_container(const pcmk_resource_t *instance)
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
void pe__create_clone_notif_pseudo_ops(pcmk_resource_t *clone, pcmk_action_t *start, pcmk_action_t *started, pcmk_action_t *stop, pcmk_action_t *stopped)
pcmk_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pcmk_node_t *on_node)
GList * pe__bundle_containers(const pcmk_resource_t *bundle)
enum pcmk__action_type get_complex_task(const pcmk_resource_t *rsc, const char *name)
#define pcmk__set_rsc_flags(resource, flags_to_set)
@ pcmk__rsc_variant_clone
Clone resource.
@ pcmk__rsc_variant_primitive
Primitive resource.
@ pcmk__rsc_node_assigned
#define pcmk__assert(expr)
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
@ pcmk_role_unknown
Resource role is unknown.
#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.
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
gboolean crm_is_true(const char *s)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
#define pcmk__plural_s(i)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
bool pcmk__ends_with(const char *s, const char *match)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
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)
uint32_t(* update_ordered_actions)(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
void(* create_actions)(pcmk_resource_t *rsc)
void(* add_colocated_node_scores)(pcmk_resource_t *source_rsc, const pcmk_resource_t *target_rsc, const char *log_id, GHashTable **nodes, const pcmk__colocation_t *colocation, float factor, uint32_t flags)
pcmk_resource_t * primary
pcmk_resource_t * dependent
pcmk_scheduler_t * scheduler
enum pcmk__rsc_variant variant
const pcmk__assignment_methods_t * cmds
const pcmk__rsc_methods_t * fns
GHashTable * allowed_nodes
pcmk__resource_private_t * priv
enum rsc_role_e(* state)(const pcmk_resource_t *rsc, bool current)
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, uint32_t target)
pcmk_node_t *(* active_node)(const pcmk_resource_t *rsc, unsigned int *count_all, unsigned int *count_clean)
pcmk__node_private_t * priv
struct pcmk__node_assignment * assign
Wrappers for and extensions to libxml2.