24 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \ 25 __rsc = pcmk__find_constraint_resource(data_set->resources, __name); \ 26 if (__rsc == NULL) { \ 27 pcmk__config_err("%s: No resource found for %s", __set, __name); \ 33 #define INFINITY_HACK (INFINITY * -100) 36 cmp_dependent_priority(gconstpointer a, gconstpointer b)
86 cmp_primary_priority(gconstpointer a, gconstpointer b)
145 CRM_ASSERT((list != NULL) && (colocation != NULL));
147 crm_trace(
"Adding colocation %s (%s with %s%s%s @%d) " 148 "to 'this with' list",
154 *list = g_list_insert_sorted(*list, (gpointer) colocation,
155 cmp_primary_priority);
173 crm_trace(
"Copying %u 'this with' colocations to new list",
174 g_list_length(addition));
175 *list = g_list_copy(addition);
177 while (addition != NULL) {
179 addition = addition->next;
196 CRM_ASSERT((list != NULL) && (colocation != NULL));
198 crm_trace(
"Adding colocation %s (%s with %s%s%s @%d) " 199 "to 'with this' list",
205 *list = g_list_insert_sorted(*list, (gpointer) colocation,
206 cmp_dependent_priority);
224 crm_trace(
"Copying %u 'with this' colocations to new list",
225 g_list_length(addition));
226 *list = g_list_copy(addition);
228 while (addition != NULL) {
230 addition = addition->next;
245 anti_colocation_order(
pe_resource_t *first_rsc,
int first_role,
248 const char *first_tasks[] = { NULL, NULL };
249 const char *then_tasks[] = { NULL, NULL };
275 for (
int first_lpc = 0;
276 (first_lpc <= 1) && (first_tasks[first_lpc] != NULL); first_lpc++) {
278 for (
int then_lpc = 0;
279 (then_lpc <= 1) && (then_tasks[then_lpc] != NULL); then_lpc++) {
282 then_rsc, then_tasks[then_lpc],
305 const char *dependent_role,
const char *primary_role,
311 crm_trace(
"Ignoring colocation '%s' because score is 0",
id);
314 if ((dependent == NULL) || (primary == NULL)) {
316 "does not exist",
id);
321 if (new_con == NULL) {
338 new_con->
score = score;
344 if (node_attr == NULL) {
349 dependent->
id, primary->
id, node_attr, score);
358 anti_colocation_order(dependent, new_con->
dependent_role, primary,
360 anti_colocation_order(primary, new_con->
primary_role, dependent,
377 unpack_influence(
const char *coloc_id,
const pe_resource_t *rsc,
378 const char *influence_s)
380 if (influence_s != NULL) {
388 return (influence_i != 0);
395 unpack_colocation_set(xmlNode *
set,
int score,
const char *coloc_id,
398 xmlNode *xml_rsc = NULL;
401 const char *set_id =
ID(
set);
404 int local_score = score;
405 bool sequential =
false;
412 if (local_score == 0) {
413 crm_trace(
"Ignoring colocation '%s' for set '%s' because score is 0",
418 if (ordering == NULL) {
425 }
else if ((local_score > 0)
435 unpack_influence(coloc_id, resource,
441 }
else if (local_score > 0) {
450 last->
id, resource->
id);
452 resource, role, role,
453 unpack_influence(coloc_id, last,
469 xmlNode *xml_rsc_with = NULL;
470 bool influence =
true;
473 influence = unpack_influence(coloc_id, resource, influence_s);
476 xml_rsc_with != NULL;
479 if (pcmk__str_eq(resource->
id,
ID(xml_rsc_with),
484 pe_rsc_trace(resource,
"Anti-Colocating %s with %s", resource->
id,
487 resource, with, role, role,
495 colocate_rsc_sets(
const char *
id, xmlNode *set1, xmlNode *set2,
int score,
498 xmlNode *xml_rsc = NULL;
506 bool sequential =
false;
509 crm_trace(
"Ignoring colocation '%s' between sets because score is 0",
518 if (xml_rsc != NULL) {
526 const char *rid = NULL;
536 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
538 unpack_influence(
id, rsc_1, influence_s),
541 }
else if (rsc_1 != NULL) {
542 bool influence = unpack_influence(
id, rsc_1, influence_s);
552 }
else if (rsc_2 != NULL) {
559 unpack_influence(
id, rsc_1, influence_s),
567 xmlNode *xml_rsc_2 = NULL;
568 bool influence =
true;
571 influence = unpack_influence(
id, rsc_1, influence_s);
579 role_1, role_2, influence,
587 unpack_simple_colocation(xmlNode *xml_obj,
const char *
id,
614 if (dependent_instance != NULL) {
617 "deprecated and will be removed in a future release.");
620 if (primary_instance != NULL) {
623 "deprecated and will be removed in a future release.");
626 if (dependent == NULL) {
628 "does not exist",
id, dependent_id);
631 }
else if (primary == NULL) {
633 "does not exist",
id, primary_id);
636 }
else if ((dependent_instance != NULL) && !pe_rsc_is_clone(dependent)) {
638 "is not a clone but instance '%s' was requested",
639 id, dependent_id, dependent_instance);
642 }
else if ((primary_instance != NULL) && !pe_rsc_is_clone(primary)) {
644 "is not a clone but instance '%s' was requested",
645 id, primary_id, primary_instance);
649 if (dependent_instance != NULL) {
651 if (dependent == NULL) {
653 "does not have an instance '%s'",
654 id, dependent_id, dependent_instance);
659 if (primary_instance != NULL) {
661 if (primary == NULL) {
663 "does not have an instance '%s'",
664 "'%s'",
id, primary_id, primary_instance);
672 "' attribute has been removed");
680 dependent_role, primary_role,
681 unpack_influence(
id, dependent, influence_s),
data_set);
686 unpack_colocation_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
689 const char *
id = NULL;
690 const char *dependent_id = NULL;
691 const char *primary_id = NULL;
692 const char *dependent_role = NULL;
693 const char *primary_role = NULL;
701 xmlNode *dependent_set = NULL;
702 xmlNode *primary_set = NULL;
703 bool any_sets =
false;
705 *expanded_xml = NULL;
707 CRM_CHECK(xml_obj != NULL,
return EINVAL);
712 crm_element_name(xml_obj));
718 if (*expanded_xml != NULL) {
725 if ((dependent_id == NULL) || (primary_id == NULL)) {
732 "valid resource or tag",
id, dependent_id);
739 "valid resource or tag",
id, primary_id);
743 if ((dependent != NULL) && (primary != NULL)) {
748 if ((dependent_tag != NULL) && (primary_tag != NULL)) {
751 "tags cannot be colocated",
id);
764 *expanded_xml = NULL;
768 if (dependent_set != NULL) {
769 if (dependent_role != NULL) {
771 crm_xml_add(dependent_set,
"role", dependent_role);
781 *expanded_xml = NULL;
785 if (primary_set != NULL) {
786 if (primary_role != NULL) {
798 *expanded_xml = NULL;
816 xmlNode *last = NULL;
818 xmlNode *orig_xml = NULL;
819 xmlNode *expanded_xml = NULL;
830 if (unpack_colocation_tags(xml_obj, &expanded_xml,
836 xml_obj = expanded_xml;
844 if (expanded_xml != NULL) {
850 unpack_colocation_set(
set, score_i,
id, influence_s,
data_set);
853 colocate_rsc_sets(
id, last,
set, score_i, influence_s,
data_set);
864 unpack_simple_colocation(xml_obj,
id, influence_s,
data_set);
882 for (GList *gIter = rsc->
actions; gIter != NULL; gIter = gIter->next) {
896 for (GList *iter = rsc->
children; iter != NULL; iter = iter->next) {
897 mark_action_blocked((
pe_resource_t *) (iter->data), task, reason);
918 GList *colocations = NULL;
920 bool is_start =
false;
938 if (rsc->
parent != NULL) {
943 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
948 if ((child_action == NULL)
950 crm_trace(
"Not blocking %s colocation dependents because " 951 "at least %s has runnable %s",
957 crm_trace(
"Blocking %s colocation dependents due to unrunnable %s %s",
962 for (gIter = colocations; gIter != NULL; gIter = gIter->next) {
987 g_list_free(colocations);
1019 && (dependent->
parent != NULL)
1039 crm_trace(
"Skipping colocation '%s': %s will not run anywhere",
1040 colocation->
id, dependent->
id);
1045 if ((primary_node == NULL) ||
1047 crm_err(
"%s must be colocated with %s but is not (%s vs. %s)",
1048 dependent->
id, primary->
id,
1050 pe__node_name(primary_node));
1056 if ((primary_node != NULL) &&
1058 crm_err(
"%s and %s must be anti-colocated but are allocated " 1059 "to the same node (%s)",
1060 dependent->
id, primary->
id, pe__node_name(primary_node));
1066 if ((colocation->
score > 0)
1070 crm_trace(
"Skipping colocation '%s': dependent limited to %s role " 1071 "but %s next role is %s",
1077 if ((colocation->
score > 0)
1081 crm_trace(
"Skipping colocation '%s': primary limited to %s role " 1082 "but %s next role is %s",
1088 if ((colocation->
score < 0)
1091 crm_trace(
"Skipping anti-colocation '%s': dependent role %s matches",
1096 if ((colocation->
score < 0)
1099 crm_trace(
"Skipping anti-colocation '%s': primary role %s matches",
1124 const char *value = NULL;
1125 GHashTable *work = NULL;
1126 GHashTableIter iter;
1136 }
else if (colocation->
score < 0) {
1143 g_hash_table_iter_init(&iter, work);
1144 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1148 "Applied %s to %s score on %s (now %s after " 1149 "subtracting %s because primary %s inactive)",
1150 colocation->
id, dependent->
id, pe__node_name(node),
1166 "Applied %s to %s score on %s (now %s after " 1168 colocation->
id, dependent->
id, pe__node_name(node),
1181 "Banned %s from %s because colocation %s attribute %s " 1183 dependent->
id, pe__node_name(node), colocation->
id,
1197 "%s: Rolling back scores from %s (no available nodes)",
1198 dependent->
id, primary->
id);
1202 g_hash_table_destroy(work);
1222 const char *dependent_value = NULL;
1223 const char *primary_value = NULL;
1225 int score_multiplier = 1;
1252 score_multiplier = -1;
1258 "Applied %s to %s promotion priority (now %s after %s %s)",
1259 colocation->
id, dependent->
id,
1261 ((score_multiplier == 1)?
"adding" :
"subtracting"),
1274 best_node_score_matching_attr(
const pe_resource_t *rsc,
const char *attr,
1277 GHashTableIter iter;
1280 const char *best_node = NULL;
1284 while (g_hash_table_iter_next(&iter, NULL, (
void **) &node)) {
1289 best_score = node->weight;
1290 best_node = node->details->uname;
1295 if (best_node == NULL) {
1296 crm_info(
"No allowed node for %s matches node attribute %s=%s",
1297 rsc->
id, attr, value);
1299 crm_info(
"Allowed node %s for %s had best score (%d) " 1300 "of those matching node attribute %s=%s",
1301 best_node, rsc->
id, best_score, attr, value);
1322 add_node_scores_matching_attr(GHashTable *nodes,
const pe_resource_t *rsc,
1323 const char *attr,
float factor,
1326 GHashTableIter iter;
1334 g_hash_table_iter_init(&iter, nodes);
1335 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1341 score = best_node_score_matching_attr(rsc, attr,
1344 if ((factor < 0) && (score < 0)) {
1350 crm_trace(
"%s: Filtering %d + %f * %d (double negative disallowed)",
1351 pe__node_name(node), node->weight, factor, score);
1356 crm_trace(
"%s: Filtering %d + %f * %d (node was marked unusable)",
1357 pe__node_name(node), node->weight, factor, score);
1361 weight_f = factor * score;
1364 weight = (int) ((weight_f < 0)? (weight_f - 0.5) : (weight_f + 0.5));
1370 if ((weight == 0) && (score != 0)) {
1373 }
else if (factor < 0.0) {
1380 if (only_positive && (new_score < 0) && (node->weight > 0)) {
1381 crm_trace(
"%s: Filtering %d + %f * %d = %d " 1382 "(negative disallowed, marking node unusable)",
1383 pe__node_name(node), node->weight, factor, score,
1389 if (only_positive && (new_score < 0) && (node->weight == 0)) {
1390 crm_trace(
"%s: Filtering %d + %f * %d = %d (negative disallowed)",
1391 pe__node_name(node), node->weight, factor, score,
1396 crm_trace(
"%s: %d + %f * %d = %d", pe__node_name(node),
1397 node->weight, factor, score, new_score);
1398 node->weight = new_score;
1421 GHashTable **nodes,
const char *attr,
1422 float factor, uint32_t
flags)
1424 GHashTable *work = NULL;
1426 CRM_CHECK((rsc != NULL) && (nodes != NULL),
return);
1428 if (log_id == NULL) {
1434 pe_rsc_info(rsc,
"%s: Breaking dependency loop at %s",
1440 if (*nodes == NULL) {
1446 pe_rsc_trace(rsc,
"%s: Merging scores from %s (at %.6f)",
1447 log_id, rsc->
id, factor);
1449 add_node_scores_matching_attr(work, rsc, attr, factor,
1460 GList *colocations = NULL;
1465 "Checking additional %d optional '%s with' constraints",
1466 g_list_length(colocations), rsc->
id);
1470 "Checking additional %d optional 'with %s' constraints",
1471 g_list_length(colocations), rsc->
id);
1475 for (GList *iter = colocations; iter != NULL; iter = iter->next) {
1479 float other_factor = factor * constraint->
score / (
float)
INFINITY;
1483 }
else if (!pcmk__colocation_has_influence(constraint, NULL)) {
1489 pe_rsc_trace(rsc,
"Optionally merging score of '%s' constraint (%s with %s)",
1492 other->cmds->add_colocated_node_scores(other, log_id, &work,
1494 other_factor,
flags);
1497 g_list_free(colocations);
1500 pe_rsc_info(rsc,
"%s: Rolling back optional scores from %s",
1502 g_hash_table_destroy(work);
1510 GHashTableIter iter;
1512 g_hash_table_iter_init(&iter, work);
1513 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1520 if (*nodes != NULL) {
1521 g_hash_table_destroy(*nodes);
1545 if (!pcmk__colocation_has_influence(colocation, NULL)) {
1552 "%s: Incorporating attenuated %s assignment scores due " 1553 "to colocation %s", rsc->
id, other->
id, colocation->
id);
#define CRM_CHECK(expr, failure_action)
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
void pcmk__unpack_colocation(xmlNode *xml_obj, pe_working_set_t *data_set)
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
#define XML_COLOC_ATTR_TARGET_INSTANCE
G_GNUC_INTERNAL bool pcmk__any_node_available(GHashTable *nodes)
#define pcmk__config_warn(fmt...)
#define RSC_ROLE_STARTED_S
void pcmk__add_with_this_list(GList **list, GList *addition)
resource_alloc_functions_t * cmds
#define XML_RULE_ATTR_SCORE
xmlNode * first_named_child(const xmlNode *parent, const char *name)
enum rsc_role_e next_role
pe_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pe_node_t *on_node)
int char2score(const char *score)
Get the integer value of a score string.
#define pcmk__config_err(fmt...)
void(* with_this_colocations)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
#define CRMD_ACTION_PROMOTE
pe_resource_t * dependent
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
void pcmk__add_with_this(GList **list, const pcmk__colocation_t *colocation)
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pe_working_set_t *data_set)
#define XML_COLOC_ATTR_TARGET_ROLE
#define CRM_SCORE_INFINITY
#define XML_CONS_TAG_RSC_SET
G_GNUC_INTERNAL bool pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr, bool convert_rsc, const pe_working_set_t *data_set)
#define pe__set_resource_flags(resource, flags_to_set)
#define CRMD_ACTION_START
xmlNode * copy_xml(xmlNode *src_node)
#define pe_rsc_provisional
const char * role2text(enum rsc_role_e role)
GList * pcmk__with_this_colocations(const pe_resource_t *rsc)
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(const pe_working_set_t *data_set, const char *id, pe_resource_t **rsc, pe_tag_t **tag)
GList * pcmk__this_with_colocations(const pe_resource_t *rsc)
#define CRMD_ACTION_DEMOTE
#define XML_COLOC_ATTR_TARGET
void pe_action_set_reason(pe_action_t *action, const char *reason, bool overwrite)
void pcmk__add_colocated_node_scores(pe_resource_t *rsc, const char *log_id, GHashTable **nodes, const char *attr, float factor, uint32_t flags)
G_GNUC_INTERNAL bool pcmk__node_available(const pe_node_t *node, bool consider_score, bool consider_guest)
pe_resource_t * uber_parent(pe_resource_t *rsc)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
const char * pe_node_attribute_raw(const pe_node_t *node, const char *name)
void pcmk__apply_coloc_to_priority(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation)
#define pe_warn_once(pe_wo_bit, fmt...)
#define pe__clear_action_flags(action, flags_to_clear)
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
void pcmk__apply_coloc_to_weights(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation)
struct pe_node_shared_s * details
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
void pcmk__block_colocation_dependents(pe_action_t *action, pe_working_set_t *data_set)
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
#define pe_rsc_promotable
pe_working_set_t * data_set
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 XML_COLOC_ATTR_SOURCE_INSTANCE
#define XML_TAG_RESOURCE_REF
pe_resource_t * find_clone_instance(const pe_resource_t *rsc, const char *sub_id)
void free_xml(xmlNode *child)
enum rsc_role_e text2role(const char *role)
enum pe_obj_types variant
void(* this_with_colocations)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
G_GNUC_INTERNAL pe_resource_t * pcmk__find_constraint_resource(GList *rsc_list, const char *id)
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
#define XML_COLOC_ATTR_SOURCE_ROLE
#define XML_COLOC_ATTR_NODE_ATTR
void pcmk__add_this_with(GList **list, const pcmk__colocation_t *colocation)
int crm_str_to_boolean(const char *s, int *ret)
void pcmk__add_this_with_list(GList **list, GList *addition)
G_GNUC_INTERNAL void pcmk__update_action_for_orderings(pe_action_t *action, pe_working_set_t *data_set)
Cluster status and scheduling.
#define XML_COLOC_ATTR_INFLUENCE
G_GNUC_INTERNAL GHashTable * pcmk__copy_node_table(GHashTable *nodes)
#define crm_err(fmt, args...)
#define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name)
GList * colocation_constraints
void xml_remove_prop(xmlNode *obj, const char *name)
#define pe__clear_resource_flags(resource, flags_to_clear)
enum pcmk__coloc_affects pcmk__colocation_affects(const pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool preview)
pe_working_set_t * cluster
const char * node_attribute
int pcmk__add_scores(int score1, int score2)
#define RSC_ROLE_UNKNOWN_S
#define crm_log_xml_trace(xml, text)
void pcmk__add_dependent_scores(gpointer data, gpointer user_data)
#define pe_rsc_trace(rsc, fmt, args...)
#define XML_CONS_ATTR_SYMMETRICAL
#define crm_info(fmt, args...)
#define XML_COLOC_ATTR_SOURCE
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
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.