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)
144 cmp_primary_priority);
158 cmp_dependent_priority);
166 anti_colocation_order(
pe_resource_t *first_rsc,
int first_role,
170 const char *first_tasks[] = { NULL, NULL };
171 const char *then_tasks[] = { NULL, NULL };
197 for (
int first_lpc = 0;
198 (first_lpc <= 1) && (first_tasks[first_lpc] != NULL); first_lpc++) {
200 for (
int then_lpc = 0;
201 (then_lpc <= 1) && (then_tasks[then_lpc] != NULL); then_lpc++) {
204 then_rsc, then_tasks[then_lpc],
227 const char *dependent_role,
const char *primary_role,
233 crm_trace(
"Ignoring colocation '%s' because score is 0",
id);
236 if ((dependent == NULL) || (primary == NULL)) {
238 "does not exist",
id);
243 if (new_con == NULL) {
260 new_con->
score = score;
266 if (node_attr == NULL) {
271 dependent->
id, primary->
id, node_attr, score);
280 anti_colocation_order(dependent, new_con->
dependent_role, primary,
282 anti_colocation_order(primary, new_con->
primary_role, dependent,
299 unpack_influence(
const char *coloc_id,
const pe_resource_t *rsc,
300 const char *influence_s)
302 if (influence_s != NULL) {
310 return (influence_i != 0);
317 unpack_colocation_set(xmlNode *
set,
int score,
const char *coloc_id,
320 xmlNode *xml_rsc = NULL;
323 const char *set_id =
ID(
set);
326 int local_score = score;
327 bool sequential =
false;
334 if (local_score == 0) {
335 crm_trace(
"Ignoring colocation '%s' for set '%s' because score is 0",
340 if (ordering == NULL) {
347 }
else if ((local_score > 0)
357 unpack_influence(coloc_id, resource,
363 }
else if (local_score > 0) {
372 last->
id, resource->
id);
374 resource, role, role,
375 unpack_influence(coloc_id, last,
391 xmlNode *xml_rsc_with = NULL;
392 bool influence =
true;
395 influence = unpack_influence(coloc_id, resource, influence_s);
398 xml_rsc_with != NULL;
401 if (pcmk__str_eq(resource->
id,
ID(xml_rsc_with),
406 pe_rsc_trace(resource,
"Anti-Colocating %s with %s", resource->
id,
409 resource, with, role, role,
417 colocate_rsc_sets(
const char *
id, xmlNode *set1, xmlNode *set2,
int score,
420 xmlNode *xml_rsc = NULL;
428 bool sequential =
false;
431 crm_trace(
"Ignoring colocation '%s' between sets because score is 0",
440 if (xml_rsc != NULL) {
448 const char *rid = NULL;
458 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
460 unpack_influence(
id, rsc_1, influence_s),
463 }
else if (rsc_1 != NULL) {
464 bool influence = unpack_influence(
id, rsc_1, influence_s);
474 }
else if (rsc_2 != NULL) {
481 unpack_influence(
id, rsc_1, influence_s),
489 xmlNode *xml_rsc_2 = NULL;
490 bool influence =
true;
493 influence = unpack_influence(
id, rsc_1, influence_s);
501 role_1, role_2, influence,
509 unpack_simple_colocation(xmlNode *xml_obj,
const char *
id,
536 if (dependent_instance != NULL) {
539 "deprecated and will be removed in a future release.");
542 if (primary_instance != NULL) {
545 "deprecated and will be removed in a future release.");
548 if (dependent == NULL) {
550 "does not exist",
id, dependent_id);
553 }
else if (primary == NULL) {
555 "does not exist",
id, primary_id);
558 }
else if ((dependent_instance != NULL) && !pe_rsc_is_clone(dependent)) {
560 "is not a clone but instance '%s' was requested",
561 id, dependent_id, dependent_instance);
564 }
else if ((primary_instance != NULL) && !pe_rsc_is_clone(primary)) {
566 "is not a clone but instance '%s' was requested",
567 id, primary_id, primary_instance);
571 if (dependent_instance != NULL) {
573 if (dependent == NULL) {
575 "does not have an instance '%s'",
576 id, dependent_id, dependent_instance);
581 if (primary_instance != NULL) {
583 if (primary == NULL) {
585 "does not have an instance '%s'",
586 "'%s'",
id, primary_id, primary_instance);
594 "' attribute has been removed");
602 dependent_role, primary_role,
603 unpack_influence(
id, dependent, influence_s),
data_set);
608 unpack_colocation_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
611 const char *
id = NULL;
612 const char *dependent_id = NULL;
613 const char *primary_id = NULL;
614 const char *dependent_role = NULL;
615 const char *primary_role = NULL;
623 xmlNode *dependent_set = NULL;
624 xmlNode *primary_set = NULL;
625 bool any_sets =
false;
627 *expanded_xml = NULL;
629 CRM_CHECK(xml_obj != NULL,
return EINVAL);
634 crm_element_name(xml_obj));
640 if (*expanded_xml != NULL) {
647 if ((dependent_id == NULL) || (primary_id == NULL)) {
654 "valid resource or tag",
id, dependent_id);
661 "valid resource or tag",
id, primary_id);
665 if ((dependent != NULL) && (primary != NULL)) {
670 if ((dependent_tag != NULL) && (primary_tag != NULL)) {
673 "tags cannot be colocated",
id);
686 *expanded_xml = NULL;
690 if (dependent_set != NULL) {
691 if (dependent_role != NULL) {
693 crm_xml_add(dependent_set,
"role", dependent_role);
703 *expanded_xml = NULL;
707 if (primary_set != NULL) {
708 if (primary_role != NULL) {
720 *expanded_xml = NULL;
738 xmlNode *last = NULL;
740 xmlNode *orig_xml = NULL;
741 xmlNode *expanded_xml = NULL;
752 if (unpack_colocation_tags(xml_obj, &expanded_xml,
758 xml_obj = expanded_xml;
766 if (expanded_xml != NULL) {
772 unpack_colocation_set(
set, score_i,
id, influence_s,
data_set);
775 colocate_rsc_sets(
id, last,
set, score_i, influence_s,
data_set);
786 unpack_simple_colocation(xml_obj,
id, influence_s,
data_set);
804 for (GList *gIter = rsc->
actions; gIter != NULL; gIter = gIter->next) {
818 for (GList *iter = rsc->
children; iter != NULL; iter = iter->next) {
819 mark_action_blocked((
pe_resource_t *) (iter->data), task, reason);
841 bool is_start =
false;
859 if (rsc->
parent != NULL) {
868 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
873 if ((child_action == NULL)
875 crm_trace(
"Not blocking %s colocation dependents because " 876 "at least %s has runnable %s",
882 crm_trace(
"Blocking %s colocation dependents due to unrunnable %s %s",
886 for (gIter = rsc->
rsc_cons_lhs; gIter != NULL; gIter = gIter->next) {
942 && (dependent->
parent != NULL)
962 crm_trace(
"Skipping colocation '%s': %s will not run anywhere",
963 colocation->
id, dependent->
id);
968 if ((primary_node == NULL) ||
970 crm_err(
"%s must be colocated with %s but is not (%s vs. %s)",
971 dependent->
id, primary->
id,
973 pe__node_name(primary_node));
979 if ((primary_node != NULL) &&
981 crm_err(
"%s and %s must be anti-colocated but are allocated " 982 "to the same node (%s)",
983 dependent->
id, primary->
id, pe__node_name(primary_node));
989 if ((colocation->
score > 0)
993 crm_trace(
"Skipping colocation '%s': dependent limited to %s role " 994 "but %s next role is %s",
1000 if ((colocation->
score > 0)
1004 crm_trace(
"Skipping colocation '%s': primary limited to %s role " 1005 "but %s next role is %s",
1011 if ((colocation->
score < 0)
1014 crm_trace(
"Skipping anti-colocation '%s': dependent role %s matches",
1019 if ((colocation->
score < 0)
1022 crm_trace(
"Skipping anti-colocation '%s': primary role %s matches",
1047 const char *value = NULL;
1048 GHashTable *work = NULL;
1049 GHashTableIter iter;
1059 }
else if (colocation->
score < 0) {
1066 g_hash_table_iter_init(&iter, work);
1067 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1069 pe_rsc_trace(dependent,
"%s: %s@%s -= %d (%s inactive)",
1070 colocation->
id, dependent->
id, pe__node_name(node),
1071 colocation->
score, primary->
id);
1078 colocation->
id, dependent->
id,
1079 pe__node_name(node), colocation->
score);
1085 pe_rsc_trace(dependent,
"%s: %s@%s -= %d (%s mismatch)",
1086 colocation->
id, dependent->
id, pe__node_name(node),
1087 colocation->
score, attribute);
1101 "%s: Rolling back scores from %s (no available nodes)",
1102 dependent->
id, primary->
id);
1106 g_hash_table_destroy(work);
1126 const char *dependent_value = NULL;
1127 const char *primary_value = NULL;
1129 int score_multiplier = 1;
1156 score_multiplier = -1;
1172 best_node_score_matching_attr(
const pe_resource_t *rsc,
const char *attr,
1175 GHashTableIter iter;
1178 const char *best_node = NULL;
1182 while (g_hash_table_iter_next(&iter, NULL, (
void **) &node)) {
1187 best_score = node->weight;
1188 best_node = node->details->uname;
1193 if (best_node == NULL) {
1194 crm_info(
"No allowed node for %s matches node attribute %s=%s",
1195 rsc->
id, attr, value);
1197 crm_info(
"Allowed node %s for %s had best score (%d) " 1198 "of those matching node attribute %s=%s",
1199 best_node, rsc->
id, best_score, attr, value);
1220 add_node_scores_matching_attr(GHashTable *nodes,
const pe_resource_t *rsc,
1221 const char *attr,
float factor,
1224 GHashTableIter iter;
1232 g_hash_table_iter_init(&iter, nodes);
1233 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1239 score = best_node_score_matching_attr(rsc, attr,
1242 if ((factor < 0) && (score < 0)) {
1248 crm_trace(
"%s: Filtering %d + %f * %d (double negative disallowed)",
1249 pe__node_name(node), node->weight, factor, score);
1254 crm_trace(
"%s: Filtering %d + %f * %d (node was marked unusable)",
1255 pe__node_name(node), node->weight, factor, score);
1259 weight_f = factor * score;
1262 weight = (int) ((weight_f < 0)? (weight_f - 0.5) : (weight_f + 0.5));
1268 if ((weight == 0) && (score != 0)) {
1271 }
else if (factor < 0.0) {
1278 if (only_positive && (new_score < 0) && (node->weight > 0)) {
1279 crm_trace(
"%s: Filtering %d + %f * %d = %d " 1280 "(negative disallowed, marking node unusable)",
1281 pe__node_name(node), node->weight, factor, score,
1287 if (only_positive && (new_score < 0) && (node->weight == 0)) {
1288 crm_trace(
"%s: Filtering %d + %f * %d = %d (negative disallowed)",
1289 pe__node_name(node), node->weight, factor, score,
1294 crm_trace(
"%s: %d + %f * %d = %d", pe__node_name(node),
1295 node->weight, factor, score, new_score);
1296 node->weight = new_score;
1317 init_group_colocated_nodes(
const pe_resource_t *rsc,
const char *log_id,
1318 GHashTable **nodes,
const char *attr,
float factor,
1321 GHashTable *work = NULL;
1329 if (*nodes == NULL) {
1346 pe_rsc_trace(rsc,
"%s: Merging scores from group %s using member %s " 1347 "(at %.6f)", log_id, rsc->
id, member->
id, factor);
1370 init_nongroup_colocated_nodes(
const pe_resource_t *rsc,
const char *log_id,
1371 GHashTable **nodes,
const char *attr,
1372 float factor, uint32_t
flags)
1374 GHashTable *work = NULL;
1376 if (*nodes == NULL) {
1383 pe_rsc_trace(rsc,
"%s: Merging scores from %s (at %.6f)",
1384 log_id, rsc->
id, factor);
1386 add_node_scores_matching_attr(work, rsc, attr, factor,
1412 GHashTable **nodes,
const char *attr,
1413 float factor, uint32_t
flags)
1415 GHashTable *work = NULL;
1417 CRM_CHECK((rsc != NULL) && (nodes != NULL),
return);
1419 if (log_id == NULL) {
1425 pe_rsc_info(rsc,
"%s: Breaking dependency loop at %s",
1432 work = init_group_colocated_nodes(rsc, log_id, nodes, attr, factor,
1435 work = init_nongroup_colocated_nodes(rsc, log_id, nodes, attr, factor,
1444 GList *gIter = NULL;
1445 float multiplier = (factor < 0.0)? -1.0 : 1.0;
1450 "Checking additional %d optional '%s with' constraints",
1451 g_list_length(gIter), rsc->
id);
1457 pe_rsc_trace(rsc,
"Checking additional %d optional 'with group %s' " 1458 "constraints using last member %s",
1459 g_list_length(gIter), rsc->
id, last_rsc->
id);
1464 "Checking additional %d optional 'with %s' constraints",
1465 g_list_length(gIter), rsc->
id);
1468 for (; gIter != NULL; gIter = gIter->next) {
1474 }
else if (!pcmk__colocation_has_influence(constraint, NULL)) {
1480 pe_rsc_trace(rsc,
"Optionally merging score of '%s' constraint (%s with %s)",
1491 pe_rsc_info(rsc,
"%s: Rolling back optional scores from %s",
1493 g_hash_table_destroy(work);
1501 GHashTableIter iter;
1503 g_hash_table_iter_init(&iter, work);
1504 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1511 if (*nodes != NULL) {
1512 g_hash_table_destroy(*nodes);
#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)
#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
#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...)
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
void pcmk__add_this_with(pe_resource_t *rsc, pcmk__colocation_t *colocation)
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
#define XML_COLOC_ATTR_TARGET_ROLE
#define CRM_SCORE_INFINITY
#define XML_CONS_TAG_RSC_SET
#define pe__set_resource_flags(resource, flags_to_set)
#define CRMD_ACTION_START
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, pe_working_set_t *data_set)
xmlNode * copy_xml(xmlNode *src_node)
#define pe_rsc_provisional
const char * role2text(enum rsc_role_e role)
#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)
pe_resource_t * find_clone_instance(pe_resource_t *rsc, const char *sub_id, 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
void free_xml(xmlNode *child)
enum rsc_role_e text2role(const char *role)
enum pe_obj_types variant
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
int crm_str_to_boolean(const char *s, int *ret)
pe_resource_t * pe__last_group_member(const pe_resource_t *group)
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 pcmk__add_with_this(pe_resource_t *rsc, pcmk__colocation_t *colocation)
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)
#define pe_rsc_trace(rsc, fmt, args...)
#define XML_CONS_ATTR_SYMMETRICAL
#define crm_info(fmt, args...)
#define XML_COLOC_ATTR_SOURCE
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(pe_working_set_t *data_set, const char *id, pe_resource_t **rsc, pe_tag_t **tag)
#define pe_rsc_info(rsc, fmt, args...)
G_GNUC_INTERNAL bool pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr, bool convert_rsc, pe_working_set_t *data_set)
GHashTable * allowed_nodes
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.