33 int available_nodes = 0;
34 int max_instances = 0;
48 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
50 && (max_instances < ++available_nodes)) {
75 instance->
id, pe__node_name(node));
81 "%s cannot run on %s: node cannot run resources",
82 instance->
id, pe__node_name(node));
87 if (allowed_node == NULL) {
88 crm_warn(
"%s cannot run on %s: node not allowed",
89 instance->
id, pe__node_name(node));
93 if (allowed_node->
weight < 0) {
94 pe_rsc_trace(instance,
"%s cannot run on %s: parent score is %s there",
95 instance->
id, pe__node_name(node),
100 if (allowed_node->
count >= max_per_node) {
102 "%s cannot run on %s: node already has %d instance%s",
103 instance->
id, pe__node_name(node), max_per_node,
108 pe_rsc_trace(instance,
"%s can run on %s (%d already running)",
109 instance->
id, pe__node_name(node), allowed_node->
count);
121 ban_unavailable_allowed_nodes(
pe_resource_t *instance,
int max_per_node)
128 while (g_hash_table_iter_next(&iter, NULL, (
void **) &node)) {
129 if (!can_run_instance(instance, node, max_per_node)) {
130 pe_rsc_trace(instance,
"Banning %s from unavailable node %s",
131 instance->
id, pe__node_name(node));
133 for (GList *child_iter = instance->
children;
134 child_iter != NULL; child_iter = child_iter->next) {
140 if (child_node != NULL) {
142 "Banning %s child %s " 143 "from unavailable node %s",
144 instance->
id, child->
id,
145 pe__node_name(node));
170 g_hash_table_insert(table, (gpointer) node->
details->
id, node);
182 apply_parent_colocations(
const pe_resource_t *rsc, GHashTable **nodes)
193 for (iter = rsc->
parent->
rsc_cons; iter != NULL; iter = iter->next) {
204 if (!pcmk__colocation_has_influence(colocation, rsc)) {
238 pe_node_t *current_node1 = pe__current_node(instance1);
239 pe_node_t *current_node2 = pe__current_node(instance2);
240 GHashTable *colocated_scores1 = NULL;
241 GHashTable *colocated_scores2 = NULL;
244 && (instance2 != NULL) && (instance2->
parent != NULL)
245 && (current_node1 != NULL) && (current_node2 != NULL));
248 colocated_scores1 = new_node_table(current_node1);
249 colocated_scores2 = new_node_table(current_node2);
252 apply_parent_colocations(instance1, &colocated_scores1);
253 apply_parent_colocations(instance2, &colocated_scores2);
256 node1 = g_hash_table_lookup(colocated_scores1, current_node1->
details->
id);
257 node2 = g_hash_table_lookup(colocated_scores2, current_node2->
details->
id);
261 crm_trace(
"Assign %s (%d on %s) after %s (%d on %s)",
267 crm_trace(
"Assign %s (%d on %s) before %s (%d on %s)",
273 g_hash_table_destroy(colocated_scores1);
274 g_hash_table_destroy(colocated_scores2);
292 for (GList *iter = rsc->
children; iter != NULL; iter = iter->next) {
314 (*node)->details->id);
315 if ((allowed == NULL) || (allowed->
weight < 0)) {
316 pe_rsc_trace(rsc,
"%s: current location (%s) is unavailable",
317 rsc->
id, pe__node_name(*node));
344 CRM_ASSERT((instance1 != NULL) && (instance2 != NULL));
347 div1 = strrchr(instance1->
id,
':');
349 div1 = strrchr(instance1->
id,
'-');
351 div2 = strrchr(instance2->
id,
':');
353 div2 = strrchr(instance2->
id,
'-');
357 return (gint) (strtol(div1 + 1, NULL, 10) - strtol(div2 + 1, NULL, 10));
391 unsigned int nnodes1 = 0;
392 unsigned int nnodes2 = 0;
400 CRM_ASSERT((instance1 != NULL) && (instance2 != NULL));
408 if ((nnodes1 > 0) && (nnodes2 > 0)) {
409 if (nnodes1 < nnodes2) {
410 crm_trace(
"Assign %s (active on %d) before %s (active on %d): " 411 "less multiply active",
412 instance1->
id, nnodes1, instance2->
id, nnodes2);
415 }
else if (nnodes1 > nnodes2) {
416 crm_trace(
"Assign %s (active on %d) after %s (active on %d): " 417 "more multiply active",
418 instance1->
id, nnodes1, instance2->
id, nnodes2);
426 can1 = node_is_allowed(instance1, &
node1);
427 can2 = node_is_allowed(instance2, &
node2);
429 crm_trace(
"Assign %s before %s: not active on a disallowed node",
430 instance1->
id, instance2->
id);
433 }
else if (!can1 && can2) {
434 crm_trace(
"Assign %s after %s: active on a disallowed node",
435 instance1->
id, instance2->
id);
441 crm_trace(
"Assign %s before %s: priority (%d > %d)",
442 instance1->
id, instance2->
id,
447 crm_trace(
"Assign %s after %s: priority (%d < %d)",
448 instance1->
id, instance2->
id,
455 crm_trace(
"No assignment preference for %s vs. %s: inactive",
456 instance1->
id, instance2->
id);
459 }
else if (
node1 == NULL) {
460 crm_trace(
"Assign %s after %s: active", instance1->
id, instance2->
id);
463 }
else if (
node2 == NULL) {
464 crm_trace(
"Assign %s before %s: active", instance1->
id, instance2->
id);
472 crm_trace(
"Assign %s before %s: current node can run resources",
473 instance1->
id, instance2->
id);
476 }
else if (!can1 && can2) {
477 crm_trace(
"Assign %s after %s: current node can't run resources",
478 instance1->
id, instance2->
id);
486 crm_trace(
"No assignment preference for %s vs. %s: " 487 "parent not allowed on either instance's current node",
488 instance1->
id, instance2->
id);
491 }
else if (
node1 == NULL) {
492 crm_trace(
"Assign %s after %s: parent not allowed on current node",
493 instance1->
id, instance2->
id);
496 }
else if (
node2 == NULL) {
497 crm_trace(
"Assign %s before %s: parent allowed on current node",
498 instance1->
id, instance2->
id);
504 crm_trace(
"Assign %s before %s: fewer active instances on current node",
505 instance1->
id, instance2->
id);
509 crm_trace(
"Assign %s after %s: more active instances on current node",
510 instance1->
id, instance2->
id);
515 can1 = did_fail(instance1);
516 can2 = did_fail(instance2);
518 crm_trace(
"Assign %s before %s: not failed",
519 instance1->
id, instance2->
id);
521 }
else if (can1 && !can2) {
523 instance1->
id, instance2->
id);
528 rc = cmp_instance_by_colocation(instance1, instance2);
536 crm_trace(
"Assign %s before %s: instance number",
537 instance1->
id, instance2->
id);
539 crm_trace(
"Assign %s after %s: instance number",
540 instance1->
id, instance2->
id);
542 crm_trace(
"No assignment preference for %s vs. %s",
543 instance1->
id, instance2->
id);
568 pe_rsc_trace(instance,
"Assigning %s (preferring %s)", instance->
id,
569 ((prefer == NULL)?
"no node" : prefer->
details->
uname));
573 return instance->
fns->
location(instance, NULL, FALSE) != NULL;
578 "Assignment loop detected involving %s colocations",
583 if (prefer != NULL) {
589 if ((allowed == NULL) || (allowed->
weight < 0)) {
591 "Not assigning %s to preferred node %s: unavailable",
592 instance->
id, pe__node_name(prefer));
597 ban_unavailable_allowed_nodes(instance, max_per_node);
599 if (prefer == NULL) {
600 chosen = instance->
cmds->
assign(instance, NULL);
605 chosen = instance->
cmds->
assign(instance, prefer);
609 crm_info(
"Not assigning %s to preferred node %s: %s is better",
610 instance->
id, pe__node_name(prefer),
611 pe__node_name(chosen));
616 }
else if (backup != NULL) {
617 g_hash_table_destroy(backup);
622 if (chosen != NULL) {
624 if (allowed == NULL) {
635 return chosen != NULL;
649 unsigned int available_nodes = 0;
654 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
660 return available_nodes;
675 int optimal_per_node)
688 node = pe__current_node(instance);
690 pe_rsc_trace(rsc,
"Not assigning %s to %s early (unavailable)",
691 instance->
id, pe__node_name(node));
697 if ((parent_node != NULL) && (parent_node->
count >= optimal_per_node)) {
699 "Not assigning %s to %s early " 700 "(optimal instances already assigned)",
701 instance->
id, pe__node_name(node));
719 int max_total,
int max_per_node)
722 unsigned int available_nodes = reset_allowed_node_counts(collective);
724 int optimal_per_node = 0;
730 if (available_nodes > 0) {
731 optimal_per_node = max_total / available_nodes;
733 if (optimal_per_node < 1) {
734 optimal_per_node = 1;
738 "Assigning up to %d %s instance%s to up to %u node%s " 739 "(at most %d per host, %d optimal)",
742 max_per_node, optimal_per_node);
745 for (iter = instances; (iter != NULL) && (assigned < max_total);
749 current = preferred_node(collective, instance, optimal_per_node);
750 if ((current != NULL)
751 && assign_instance(instance, current, max_per_node)) {
752 pe_rsc_trace(collective,
"Assigned %s to current node %s",
753 instance->
id, pe__node_name(current));
758 pe_rsc_trace(collective,
"Assigned %d of %d instance%s to current node",
761 for (iter = instances; iter != NULL; iter = iter->next) {
769 current = pe__current_node(instance);
771 const char *unmanaged =
"";
774 unmanaged =
"Unmanaged resource ";
776 crm_notice(
"%s%s is running on %s which is no longer allowed",
777 unmanaged, instance->
id, pe__node_name(current));
781 if (assigned >= max_total) {
783 "Not assigning %s because maximum %d instances " 785 instance->
id, max_total);
787 "collective_limit_reached", collective->
cluster);
789 }
else if (assign_instance(instance, NULL, max_per_node)) {
794 pe_rsc_debug(collective,
"Assigned %d of %d possible instance%s of %s",
824 check_instance_state(
const pe_resource_t *instance, uint32_t *state)
826 const GList *iter = NULL;
837 (iter != NULL) && !pcmk_all_flags_set(*state,
instance_all);
839 check_instance_state((
const pe_resource_t *) iter->data, state);
862 pe_rsc_trace(instance,
"Instance is starting due to %s",
866 pe_rsc_trace(instance,
"%s doesn't affect %s state (%s)",
868 (optional?
"optional" :
"unrunnable"));
877 && pcmk_any_flags_set(
action->flags,
879 pe_rsc_trace(instance,
"Instance is stopping due to %s",
883 pe_rsc_trace(instance,
"%s doesn't affect %s state (%s)",
885 (optional?
"optional" :
"unrunnable"));
915 pe_rsc_trace(collective,
"Creating collective instance actions for %s",
919 for (GList *iter = instances; iter != NULL; iter = iter->next) {
923 check_instance_state(instance, &state);
967 static inline GList *
1011 CRM_CHECK((instance != NULL) && (node != NULL),
return false);
1014 && (role != instance->
fns->
state(instance, current))) {
1016 "%s is not a compatible instance (role is not %s)",
1023 instance_node = instance->
fns->
location(instance, NULL, current);
1026 if (instance_node == NULL) {
1028 "%s is not a compatible instance (not assigned to a node)",
1035 "%s is not a compatible instance (assigned to %s not %s)",
1036 instance->
id, pe__node_name(instance_node),
1037 pe__node_name(node));
1058 find_compatible_instance_on_node(
const pe_resource_t *match_rsc,
1063 GList *instances = NULL;
1065 instances = get_instance_list(rsc);
1066 for (GList *iter = instances; iter != NULL; iter = iter->next) {
1070 pe_rsc_trace(match_rsc,
"Found %s %s instance %s compatible with %s on %s",
1072 rsc->
id, instance->
id, match_rsc->
id,
1073 pe__node_name(node));
1074 free_instance_list(rsc, instances);
1078 free_instance_list(rsc, instances);
1080 pe_rsc_trace(match_rsc,
"No %s %s instance found compatible with %s on %s",
1082 rsc->
id, match_rsc->
id, pe__node_name(node));
1105 GList *nodes = NULL;
1110 return find_compatible_instance_on_node(match_rsc, rsc, node, role,
1117 for (GList *iter = nodes; (iter != NULL) && (instance == NULL);
1118 iter = iter->next) {
1119 instance = find_compatible_instance_on_node(match_rsc, rsc,
1124 if (instance == NULL) {
1125 pe_rsc_debug(rsc,
"No %s instance found compatible with %s",
1126 rsc->
id, match_rsc->
id);
1151 "%s has no instance to order before stopping " 1153 first->
rsc->
id, then_instance->
id);
1161 "Inhibiting %s from being active " 1162 "because there is no %s instance to interleave",
1163 then_instance->
id, first->
rsc->
id);
1186 const char *action_name,
const pe_node_t *node,
1224 if (matching_action != NULL) {
1225 return matching_action;
1230 crm_trace(
"No %s action found for %s%s",
1235 crm_err(
"No %s action found for %s to interleave (bug?)",
1236 action_name, instance->
id);
1258 char *action_type = NULL;
1259 const char *action_name =
action->task;
1267 action_name = strstr(action_type,
"_notify_");
1269 action_name += strlen(
"_notify_");
1301 GList *instances = NULL;
1303 const char *orig_first_task = orig_action_name(first);
1311 instances = get_instance_list(then->
rsc);
1312 for (GList *iter = instances; iter != NULL; iter = iter->next) {
1325 if (first_instance == NULL) {
1326 if (unassign_if_mandatory(first, then, then_instance,
type,
1333 first_action = find_instance_action(first, first_instance,
1334 orig_first_task, node,
true);
1335 if (first_action == NULL) {
1339 then_action = find_instance_action(then, then_instance, then->
task,
1341 if (then_action == NULL) {
1351 first_action, then_action, node,
1355 free_instance_list(then->
rsc, instances);
1371 bool interleave =
false;
1374 if ((first->
rsc == NULL) || (then->
rsc == NULL)) {
1375 crm_trace(
"Not interleaving %s with %s: not resource actions",
1380 if (first->
rsc == then->
rsc) {
1381 crm_trace(
"Not interleaving %s with %s: same resource",
1387 crm_trace(
"Not interleaving %s with %s: not clones or bundles",
1401 pe_rsc_trace(rsc,
"'%s then %s' will %sbe interleaved (based on %s)",
1402 first->
uuid, then->
uuid, (interleave?
"" :
"not "), rsc->
id);
1431 uint32_t
flags, uint32_t filter, uint32_t
type)
1434 uint32_t instance_flags = 0;
1440 if (instance_action == NULL) {
1458 after_iter != NULL; after_iter = after_iter->next) {
1494 uint32_t filter, uint32_t
type,
1497 if (then->
rsc == NULL) {
1500 }
else if (can_interleave_actions(first, then)) {
1501 return update_interleaved_actions(first, then, node, filter,
type);
1505 GList *instances = get_instance_list(then->
rsc);
1512 for (GList *iter = instances; iter != NULL; iter = iter->next) {
1515 changed |= update_noninterleaved_actions(instance, first, then,
1518 free_instance_list(then->
rsc, instances);
1523 #define pe__clear_action_summary_flags(flags, action, flag) do { \ 1524 flags = pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, \ 1525 "Action summary", action->rsc->id, \ 1526 flags, flag, #flag); \ 1543 bool any_runnable =
false;
1545 const char *action_name = orig_action_name(
action);
1550 for (
const GList *iter = instances; iter != NULL; iter = iter->next) {
1558 instance_node = node;
1562 action_name, instance_node);
1563 if (instance_action == NULL) {
1565 instance->
id, action_name, pe__node_name(node));
1570 instance->
id, instance_action->
uuid, action_name,
1571 pe__node_name(node));
1578 pe_rsc_trace(instance,
"%s is mandatory because %s is",
1586 any_runnable =
true;
1590 if (!any_runnable) {
1592 "%s is not runnable because no instance can run %s",
1593 action->uuid, action_name);
1618 const GList *colocations = NULL;
1619 bool everywhere =
false;
1621 CRM_CHECK((list != NULL) && (instance != NULL),
return);
1623 if (collective == NULL) {
1626 switch (collective->
variant) {
1634 everywhere = can_run_everywhere(collective);
1639 colocations = collective->
rsc_cons;
1642 for (
const GList *iter = colocations; iter != NULL; iter = iter->next) {
1646 && !pcmk__colocation_has_influence(colocation, instance)) {
1649 if (!everywhere || (colocation->
score < 0)
#define CRM_CHECK(expr, failure_action)
const char * task2text(enum action_tasks task)
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
#define crm_notice(fmt, args...)
#define pe_rsc_debug(rsc, fmt, args...)
#define pe__set_action_flags(action, flags_to_set)
G_GNUC_INTERNAL uint32_t pcmk__update_ordered_actions(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
resource_alloc_functions_t * cmds
pe_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pe_node_t *on_node)
#define CRMD_ACTION_NOTIFY
resource_object_functions_t * fns
pe_node_t * pe__copy_node(const pe_node_t *this_node)
#define CRMD_ACTION_PROMOTE
pe_resource_t * dependent
G_GNUC_INTERNAL GList * pcmk__sort_nodes(GList *nodes, pe_node_t *active_node)
#define CRM_LOG_ASSERT(expr)
gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
pe_action_t * pe__new_rsc_pseudo_action(pe_resource_t *rsc, const char *task, bool optional, bool runnable)
enum crm_ais_msg_types type
void resource_location(pe_resource_t *rsc, const pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
bool pcmk__ends_with(const char *s, const char *match)
int pe__clone_max(const pe_resource_t *clone)
pe_node_t *(* assign)(pe_resource_t *rsc, const pe_node_t *prefer)
enum pe_action_flags(* action_flags)(pe_action_t *action, const pe_node_t *node)
gint pcmk__cmp_instance_number(gconstpointer a, gconstpointer b)
pe_node_t *(* active_node)(const pe_resource_t *rsc, unsigned int *count_all, unsigned int *count_clean)
#define pe_rsc_provisional
GList * pe__bundle_containers(const pe_resource_t *bundle)
void pcmk__add_collective_constraints(GList **list, const pe_resource_t *instance, const pe_resource_t *collective, bool with_this)
bool pcmk__instance_matches(const pe_resource_t *instance, const pe_node_t *node, enum rsc_role_e role, bool current)
const char * role2text(enum rsc_role_e role)
#define CRMD_ACTION_DEMOTED
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
void pcmk__assign_instances(pe_resource_t *collective, GList *instances, int max_total, int max_per_node)
G_GNUC_INTERNAL void pcmk__add_with_this(GList **list, const pcmk__colocation_t *colocation)
#define crm_warn(fmt, args...)
#define CRMD_ACTION_DEMOTE
G_GNUC_INTERNAL bool pcmk__node_available(const pe_node_t *node, bool consider_score, bool consider_guest)
enum pe_action_flags pcmk__collective_action_flags(pe_action_t *action, const GList *instances, const pe_node_t *node)
G_GNUC_INTERNAL const pe_resource_t * pcmk__get_rsc_in_container(const pe_resource_t *instance)
#define pe__clear_action_flags(action, flags_to_clear)
#define pe__clear_action_summary_flags(flags, action, flag)
#define crm_trace(fmt, args...)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
struct pe_node_shared_s * details
void pcmk__create_instance_actions(pe_resource_t *collective, GList *instances)
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
pe_working_set_t * data_set
void(* create_actions)(pe_resource_t *rsc)
uint32_t pcmk__instance_update_ordered_actions(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
void pe__create_clone_notif_pseudo_ops(pe_resource_t *clone, pe_action_t *start, pe_action_t *started, pe_action_t *stop, pe_action_t *stopped)
#define CRMD_ACTION_PROMOTED
bool is_set_recursive(const pe_resource_t *rsc, long long flag, bool any)
#define pe_rsc_allocating
enum pe_obj_types variant
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
G_GNUC_INTERNAL void pcmk__unassign_resource(pe_resource_t *rsc)
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)
#define CRMD_ACTION_STOPPED
enum rsc_role_e(* state)(const pe_resource_t *, gboolean)
G_GNUC_INTERNAL void pcmk__update_action_for_orderings(pe_action_t *action, pe_working_set_t *data_set)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
G_GNUC_INTERNAL GHashTable * pcmk__copy_node_table(GHashTable *nodes)
#define pcmk__set_updated_flags(au_flags, action, flags_to_set)
#define crm_err(fmt, args...)
G_GNUC_INTERNAL pe_node_t * pcmk__top_allowed_node(const pe_resource_t *rsc, const pe_node_t *node)
G_GNUC_INTERNAL void pcmk__add_this_with(GList **list, const pcmk__colocation_t *colocation)
G_GNUC_INTERNAL bool pcmk__assign_resource(pe_resource_t *rsc, pe_node_t *node, bool force)
int pe__bundle_max(const pe_resource_t *rsc)
#define pcmk__plural_s(i)
rsc_role_e
Possible roles that a resource can be in.
pe_working_set_t * cluster
const char * node_attribute
enum action_tasks get_complex_task(const pe_resource_t *rsc, const char *name)
gboolean crm_is_true(const char *s)
#define CRMD_ACTION_NOTIFIED
#define pe_rsc_trace(rsc, fmt, args...)
uint32_t(* update_ordered_actions)(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
#define XML_RSC_ATTR_INTERLEAVE
#define crm_info(fmt, args...)
void(* add_colocated_node_scores)(pe_resource_t *rsc, const char *log_id, GHashTable **nodes, const char *attr, float factor, uint32_t flags)
#define pe_rsc_info(rsc, fmt, args...)
GHashTable * allowed_nodes