12 #include <sys/param.h>
13 #include <sys/types.h>
35 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \
36 __rsc = pe_find_constraint_resource(data_set->resources, __name); \
38 pcmk__config_err("%s: No resource found for %s", __set, __name); \
44 const char *action_first,
const char *action_then, gboolean invert);
48 const char *discovery,
53 static void unpack_rsc_colocation(xmlNode *xml_obj,
pe_working_set_t *data_set);
74 xmlNode *xml_obj = NULL;
75 xmlNode *lifetime = NULL;
77 for (xml_obj = pcmk__xe_first_child(xml_constraints); xml_obj != NULL;
78 xml_obj = pcmk__xe_next(xml_obj)) {
80 const char *tag = crm_element_name(xml_obj);
88 crm_trace(
"Processing constraint %s %s", tag,
id);
93 "deprecated (the rules it contains should "
94 "instead be direct descendents of the "
95 "constraint object)",
id);
98 if (lifetime && !evaluate_lifetime(lifetime, data_set)) {
99 crm_info(
"Constraint %s %s is not active", tag,
id);
105 unpack_rsc_colocation(xml_obj, data_set);
108 unpack_location(xml_obj, data_set);
114 pe_err(
"Unsupported constraint type: %s", tag);
122 invert_action(
const char *
action)
148 crm_warn(
"Unknown action '%s' specified in order constraint", action);
153 get_ordering_type(xmlNode * xml_obj)
171 "Support for 'score' in rsc_order is deprecated "
172 "and will be removed in a future release (use 'kind' instead)");
186 "'%s' to Mandatory because '%s' is not valid",
193 pe_find_constraint_resource(GList *rsc_list,
const char *
id)
197 for (rIter = rsc_list;
id && rIter; rIter = rIter->next) {
222 NULL, (gpointer*) tag);
225 rc = g_hash_table_lookup_extended(data_set->
tags,
id,
226 NULL, (gpointer*) tag);
229 crm_warn(
"No template or tag named '%s'",
id);
232 }
else if (*tag == NULL) {
233 crm_warn(
"No resource is tagged with '%s'",
id);
237 }
else if (*tag == NULL) {
238 crm_warn(
"No resource is derived from template '%s'",
id);
253 *rsc = pe_find_constraint_resource(data_set->
resources,
id);
261 rc = pe_find_constraint_tag(data_set,
id, tag);
268 order_is_symmetrical(xmlNode * xml_obj,
269 enum pe_order_kind parent_kind,
const char * parent_symmetrical_s)
277 if (kind_s || score_s) {
278 kind = get_ordering_type(xml_obj);
281 if (symmetrical_s == NULL) {
282 symmetrical_s = parent_symmetrical_s;
290 " for '%s' because not valid with "
313 gboolean invert_bool = TRUE;
314 int min_required_before = 0;
318 const char *id_first = NULL;
319 const char *id_then = NULL;
320 const char *action_then = NULL;
321 const char *action_first = NULL;
322 const char *instance_then = NULL;
323 const char *instance_first = NULL;
325 const char *
id = NULL;
327 CRM_CHECK(xml_obj != NULL,
return FALSE);
332 crm_element_name(xml_obj));
336 invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
347 if (action_first == NULL) {
350 if (action_then == NULL) {
351 action_then = action_first;
354 if (id_first == NULL) {
359 if (id_then == NULL) {
365 rsc_then = pe_find_constraint_resource(data_set->
resources, id_then);
366 rsc_first = pe_find_constraint_resource(data_set->
resources, id_first);
368 if (rsc_then == NULL) {
370 "does not exist",
id, id_then);
373 }
else if (rsc_first == NULL) {
375 "does not exist",
id, id_first);
378 }
else if (instance_then && pe_rsc_is_clone(rsc_then) == FALSE) {
380 "is not a clone but instance '%s' was requested",
381 id, id_then, instance_then);
384 }
else if (instance_first && pe_rsc_is_clone(rsc_first) == FALSE) {
386 "is not a clone but instance '%s' was requested",
387 id, id_first, instance_first);
393 if (rsc_then == NULL) {
395 "does not have an instance '%s'",
396 id, id_then, instance_then);
401 if (instance_first) {
403 if (rsc_first == NULL) {
405 "does not have an instance '%s'",
406 "'%s'",
id, id_first, instance_first);
412 kind = get_ordering_type(xml_obj);
415 crm_trace(
"Upgrade : recovery - implies right");
419 if (invert_bool == FALSE) {
423 get_flags(
id, kind, action_first, action_then, FALSE));
426 if (pe_rsc_is_clone(rsc_first)) {
430 const char *min_clones_s = g_hash_table_lookup(rsc_first->
meta,
439 }
else if (require_all_s) {
441 "Support for require-all in ordering constraints "
442 "is deprecated and will be removed in a future release"
443 " (use clone-min clone meta-attribute instead)");
446 min_required_before = 1;
454 if (min_required_before) {
467 for (rIter = rsc_first->
children;
id && rIter; rIter = rIter->next) {
471 NULL, NULL, NULL, unordered_action,
483 order_id =
new_rsc_order(rsc_first, action_first, rsc_then, action_then, cons_weight, data_set);
486 pe_rsc_trace(rsc_first,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
487 order_id,
id, rsc_first->
id, action_first, rsc_then->
id, action_then, cons_weight);
489 if (invert_bool == FALSE) {
493 action_then = invert_action(action_then);
494 action_first = invert_action(action_first);
495 if (action_then == NULL || action_first == NULL) {
497 "(please specify inverse manually)",
id);
503 crm_trace(
"Upgrade : recovery - implies left");
508 get_flags(
id, kind, action_first, action_then, TRUE));
510 order_id =
new_rsc_order(rsc_then, action_then, rsc_first, action_first, cons_weight, data_set);
512 pe_rsc_trace(rsc_then,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
513 order_id,
id, rsc_then->
id, action_then, rsc_first->
id, action_first, cons_weight);
519 expand_tags_in_sets(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
521 xmlNode *new_xml = NULL;
523 gboolean any_refs = FALSE;
524 const char *cons_id = NULL;
526 *expanded_xml = NULL;
528 CRM_CHECK(xml_obj != NULL,
return FALSE);
531 cons_id =
ID(new_xml);
533 for (set = pcmk__xe_first_child(new_xml); set != NULL;
534 set = pcmk__xe_next(set)) {
536 xmlNode *xml_rsc = NULL;
537 GList *tag_refs = NULL;
544 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
545 xml_rsc = pcmk__xe_next(xml_rsc)) {
549 const char *
id =
ID(xml_rsc);
555 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
557 "because '%s' is not a valid resource or tag",
567 xmlNode *last_ref = xml_rsc;
591 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
592 const char *obj_ref = (
const char *) gIter->data;
593 xmlNode *new_rsc_ref = NULL;
595 new_rsc_ref = xmlNewDocRawNode(
getDocPtr(set), NULL,
598 xmlAddNextSibling(last_ref, new_rsc_ref);
600 last_ref = new_rsc_ref;
610 tag_refs = g_list_append(tag_refs, xml_rsc);
624 for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
625 xmlNode *tag_ref = gIter->data;
629 g_list_free(tag_refs);
633 *expanded_xml = new_xml;
642 tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set,
const char * attr,
645 const char *cons_id = NULL;
646 const char *
id = NULL;
653 CRM_CHECK((xml_obj != NULL) && (attr != NULL),
return FALSE);
655 cons_id =
ID(xml_obj);
656 if (cons_id == NULL) {
658 crm_element_name(xml_obj));
667 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
669 "valid resource or tag", cons_id,
id);
681 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
682 const char *obj_ref = (
const char *) gIter->data;
683 xmlNode *rsc_ref = NULL;
692 }
else if (rsc && convert_rsc) {
695 xmlNode *rsc_ref = NULL;
715 static void unpack_rsc_location(xmlNode *xml_obj,
pe_resource_t *rsc_lh,
716 const char *role,
const char *score,
729 unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
734 regex_t *r_patt = calloc(1,
sizeof(regex_t));
738 if(value[0] ==
'!') {
743 if (regcomp(r_patt, value, REG_EXTENDED)) {
746 " has invalid value '%s'",
id, value);
752 for (rIter = data_set->
resources; rIter; rIter = rIter->next) {
755 regmatch_t *pmatch = NULL;
758 if(r_patt->re_nsub > 0) {
759 nregs = r_patt->re_nsub + 1;
763 pmatch = calloc(nregs,
sizeof(regmatch_t));
765 status = regexec(r_patt, r->
id, nregs, pmatch, 0);
767 if(invert == FALSE && status == 0) {
774 crm_debug(
"'%s' matched '%s' for %s", r->
id, value,
id);
775 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, &re_match_data);
777 }
else if (invert && (status != 0)) {
778 crm_debug(
"'%s' is an inverted match of '%s' for %s", r->
id, value,
id);
779 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, NULL);
782 crm_trace(
"'%s' does not match '%s' for %s", r->
id, value,
id);
794 unpack_rsc_location(xmlNode *xml_obj,
pe_resource_t *rsc_lh,
const char *role,
804 if (rsc_lh == NULL) {
806 "does not exist",
id, id_lh);
814 if (node != NULL && score != NULL) {
821 location =
rsc2node_new(
id, rsc_lh, score_i, discovery, match, data_set);
835 generate_location_rule(rsc_lh, rule_xml, discovery, next_change,
836 data_set, re_match_data);
860 if (location && role) {
862 pe_err(
"Invalid constraint %s: Bad role %s",
id, role);
883 unpack_location_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
885 const char *
id = NULL;
886 const char *id_lh = NULL;
887 const char *state_lh = NULL;
893 xmlNode *new_xml = NULL;
894 xmlNode *rsc_set_lh = NULL;
896 *expanded_xml = NULL;
898 CRM_CHECK(xml_obj != NULL,
return FALSE);
903 crm_element_name(xml_obj));
908 expand_tags_in_sets(xml_obj, &new_xml, data_set);
912 *expanded_xml = new_xml;
921 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
923 "valid resource or tag",
id, id_lh);
949 *expanded_xml = new_xml;
960 unpack_location_set(xmlNode * location, xmlNode * set,
pe_working_set_t * data_set)
962 xmlNode *xml_rsc = NULL;
966 const char *local_score;
971 if (set_id == NULL) {
981 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
982 xml_rsc = pcmk__xe_next(xml_rsc)) {
986 unpack_rsc_location(location, resource, role, local_score, data_set, NULL);
997 gboolean any_sets = FALSE;
999 xmlNode *orig_xml = NULL;
1000 xmlNode *expanded_xml = NULL;
1002 if (unpack_location_tags(xml_obj, &expanded_xml, data_set) == FALSE) {
1008 xml_obj = expanded_xml;
1011 for (set = pcmk__xe_first_child(xml_obj); set != NULL;
1012 set = pcmk__xe_next(set)) {
1017 if (unpack_location_set(xml_obj, set, data_set) == FALSE) {
1031 if (any_sets == FALSE) {
1032 unpack_simple_location(xml_obj, data_set);
1041 if (score == NULL) {
1042 pe_err(
"Rule %s: no score specified. Assuming 0.", rule);
1050 if (attr_score == NULL) {
1051 crm_debug(
"Rule %s: node %s did not have a value for %s",
1056 crm_debug(
"Rule %s: node %s had value %s for %s",
1065 generate_location_rule(
pe_resource_t *rsc, xmlNode *rule_xml,
1066 const char *discovery,
crm_time_t *next_change,
1070 const char *rule_id = NULL;
1071 const char *score = NULL;
1072 const char *
boolean = NULL;
1073 const char *role = NULL;
1075 GList *gIter = NULL;
1076 GList *match_L = NULL;
1078 gboolean do_and = TRUE;
1079 gboolean accept = TRUE;
1080 gboolean raw_score = TRUE;
1081 gboolean score_allocated = FALSE;
1090 crm_trace(
"Processing rule: %s", rule_id);
1093 pe_err(
"Bad role specified for %s: %s", rule_id, role);
1098 if (score == NULL) {
1100 if (score != NULL) {
1108 location_rule =
rsc2node_new(rule_id, rsc, 0, discovery, NULL, data_set);
1110 if (location_rule == NULL) {
1114 if ((re_match_data != NULL) && (re_match_data->
nregs > 0)
1115 && (re_match_data->
pmatch[0].rm_so != -1) && !raw_score) {
1119 if (result != NULL) {
1121 score_allocated = TRUE;
1126 crm_trace(
"Setting role filter: %s", role);
1137 GList *gIter = NULL;
1140 for (gIter = match_L; gIter != NULL; gIter = gIter->next) {
1143 node->
weight = get_node_score(rule_id, score, raw_score, node, rsc);
1147 for (gIter = data_set->
nodes; gIter != NULL; gIter = gIter->next) {
1151 .
re = re_match_data,
1157 data_set->
now, next_change, &match_data);
1159 crm_trace(
"Rule %s %s on %s",
ID(rule_xml), accept ?
"passed" :
"failed",
1162 score_f = get_node_score(rule_id, score, raw_score, node, rsc);
1170 if (local == NULL && do_and) {
1173 }
else if (local == NULL) {
1175 match_L = g_list_append(match_L, local);
1178 if (do_and == FALSE) {
1183 }
else if (do_and && !accept) {
1187 if (
delete != NULL) {
1188 match_L = g_list_remove(match_L,
delete);
1195 if (score_allocated == TRUE) {
1196 free((
char *)score);
1201 crm_trace(
"No matching nodes for rule %s", rule_id);
1206 return location_rule;
1210 sort_cons_priority_lh(gconstpointer a, gconstpointer b)
1258 sort_cons_priority_rh(gconstpointer a, gconstpointer b)
1306 anti_colocation_order(
pe_resource_t * first_rsc,
int first_role,
1310 const char *first_tasks[] = { NULL, NULL };
1311 const char *then_tasks[] = { NULL, NULL };
1339 for (first_lpc = 0; first_lpc <= 1 && first_tasks[first_lpc] != NULL; first_lpc++) {
1340 for (then_lpc = 0; then_lpc <= 1 && then_tasks[then_lpc] != NULL; then_lpc++) {
1341 new_rsc_order(first_rsc, first_tasks[first_lpc], then_rsc, then_tasks[then_lpc],
1350 const char *state_lh,
const char *state_rh,
1356 crm_trace(
"Ignoring colocation '%s' because score is 0",
id);
1359 if ((rsc_lh == NULL) || (rsc_rh == NULL)) {
1361 "does not exist",
id);
1366 if (new_con == NULL) {
1379 new_con->
rsc_lh = rsc_lh;
1380 new_con->
rsc_rh = rsc_rh;
1381 new_con->
score = score;
1387 if (node_attr == NULL) {
1391 pe_rsc_trace(rsc_lh,
"%s ==> %s (%s %d)", rsc_lh->
id, rsc_rh->
id, node_attr, score);
1393 rsc_lh->
rsc_cons = g_list_insert_sorted(rsc_lh->
rsc_cons, new_con, sort_cons_priority_rh);
1396 g_list_insert_sorted(rsc_rh->
rsc_cons_lhs, new_con, sort_cons_priority_lh);
1401 anti_colocation_order(rsc_lh, new_con->
role_lh, rsc_rh, new_con->
role_rh, data_set);
1402 anti_colocation_order(rsc_rh, new_con->
role_rh, rsc_lh, new_con->
role_lh, data_set);
1412 char *lh_key = NULL;
1413 char *rh_key = NULL;
1424 if (validate_order_resources(lh_rsc, lh_task, rh_rsc, rh_task)) {
1436 task_from_action_or_key(
pe_action_t *action,
const char *key)
1441 res = strdup(action->
task);
1455 char *lh_task = NULL;
1456 char *rh_task = NULL;
1457 gboolean rh_migratable;
1458 gboolean lh_migratable;
1477 if (lh_migratable == FALSE && rh_migratable == FALSE) {
1487 if (lh_task == NULL || rh_task == NULL) {
1494 if (lh_migratable && rh_migratable) {
1501 NULL, flags, data_set);
1504 if (rh_migratable) {
1505 if (lh_migratable) {
1515 NULL, flags, data_set);
1521 if (lh_migratable) {
1532 NULL, flags, data_set);
1541 NULL, flags, data_set);
1547 if (rh_migratable) {
1554 NULL, flags, data_set);
1560 if (rh_migratable) {
1574 NULL, flags, data_set);
1592 if (lh_rsc == NULL && lh_action) {
1593 lh_rsc = lh_action->
rsc;
1595 if (rh_rsc == NULL && rh_action) {
1596 rh_rsc = rh_action->
rsc;
1599 if ((lh_action == NULL && lh_rsc == NULL)
1600 || (rh_action == NULL && rh_rsc == NULL)) {
1601 crm_err(
"Invalid ordering (bug?)");
1602 free(lh_action_task);
1603 free(rh_action_task);
1610 lh_rsc?lh_rsc->
id:
"NA", lh_action_task?lh_action_task:
"NA", lh_action?lh_action->
uuid:
"NA",
1611 rh_rsc?rh_rsc->
id:
"NA", rh_action_task?rh_action_task:
"NA", rh_action?rh_action->
uuid:
"NA");
1632 if (order->
lh_rsc == NULL && lh_action) {
1636 if (order->
rh_rsc == NULL && rh_action) {
1641 handle_migration_ordering(order, data_set);
1661 const char *action_first,
const char *action_then, gboolean invert)
1666 crm_trace(
"Upgrade %s: implies left",
id);
1670 crm_trace(
"Upgrade %s: implies right",
id);
1687 pe_action_t ** inv_end,
const char *parent_symmetrical_s,
1690 xmlNode *xml_rsc = NULL;
1691 GList *set_iter = NULL;
1692 GList *resources = NULL;
1697 int local_kind = parent_kind;
1698 gboolean sequential = FALSE;
1700 gboolean symmetrical = TRUE;
1703 const char *
id =
ID(set);
1714 if (action == NULL) {
1719 local_kind = get_ordering_type(set);
1721 if (sequential_s == NULL) {
1727 symmetrical = order_is_symmetrical(set, parent_kind, parent_symmetrical_s);
1729 flags =
get_flags(
id, local_kind, action, action, FALSE);
1734 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
1735 xml_rsc = pcmk__xe_next(xml_rsc)) {
1739 resources = g_list_append(resources, resource);
1743 if (pcmk__list_of_1(resources)) {
1769 set_iter = resources;
1770 while (set_iter != NULL) {
1772 set_iter = set_iter->next;
1787 GList *gIter = NULL;
1789 for (gIter = set_iter; gIter != NULL; gIter = gIter->next) {
1797 }
else if (sequential) {
1799 new_rsc_order(last, action, resource, action, flags, data_set);
1806 if (symmetrical == FALSE) {
1811 action = invert_action(action);
1826 flags =
get_flags(
id, local_kind, action, action, TRUE);
1828 set_iter = resources;
1829 while (set_iter != NULL) {
1831 set_iter = set_iter->next;
1845 new_rsc_order(resource, action, last, action, flags, data_set);
1852 g_list_free(resources);
1857 order_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
enum pe_order_kind kind,
1861 xmlNode *xml_rsc = NULL;
1862 xmlNode *xml_rsc_2 = NULL;
1874 gboolean require_all = require_all_s ?
crm_is_true(require_all_s) : TRUE;
1878 if (action_1 == NULL) {
1882 if (action_2 == NULL) {
1887 action_1 = invert_action(action_1);
1888 action_2 = invert_action(action_2);
1899 if (symmetrical == FALSE) {
1902 flags =
get_flags(
id, kind, action_2, action_1, invert);
1912 __func__, __LINE__);
1914 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1915 xml_rsc = pcmk__xe_next(xml_rsc)) {
1926 NULL, NULL, NULL, unordered_action,
1930 for (xml_rsc_2 = pcmk__xe_first_child(set2); xml_rsc_2 != NULL;
1931 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
1950 if (invert == FALSE) {
1952 const char *rid = NULL;
1954 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1955 xml_rsc = pcmk__xe_next(xml_rsc)) {
1965 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1966 xml_rsc = pcmk__xe_next(xml_rsc)) {
1977 if (invert == FALSE) {
1979 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
1980 xml_rsc = pcmk__xe_next(xml_rsc)) {
1990 const char *rid = NULL;
1992 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
1993 xml_rsc = pcmk__xe_next(xml_rsc)) {
2003 if (rsc_1 != NULL && rsc_2 != NULL) {
2004 new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set);
2006 }
else if (rsc_1 != NULL) {
2007 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2008 xml_rsc = pcmk__xe_next(xml_rsc)) {
2012 new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set);
2016 }
else if (rsc_2 != NULL) {
2017 xmlNode *xml_rsc = NULL;
2019 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2020 xml_rsc = pcmk__xe_next(xml_rsc)) {
2024 new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set);
2029 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2030 xml_rsc = pcmk__xe_next(xml_rsc)) {
2033 xmlNode *xml_rsc_2 = NULL;
2037 for (xml_rsc_2 = pcmk__xe_first_child(set2);
2039 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
2043 new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set);
2054 unpack_order_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2056 const char *
id = NULL;
2057 const char *id_first = NULL;
2058 const char *id_then = NULL;
2059 const char *action_first = NULL;
2060 const char *action_then = NULL;
2067 xmlNode *new_xml = NULL;
2068 xmlNode *rsc_set_first = NULL;
2069 xmlNode *rsc_set_then = NULL;
2070 gboolean any_sets = FALSE;
2072 *expanded_xml = NULL;
2074 CRM_CHECK(xml_obj != NULL,
return FALSE);
2079 crm_element_name(xml_obj));
2084 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2088 *expanded_xml = new_xml;
2094 if (id_first == NULL || id_then == NULL) {
2098 if (valid_resource_or_tag(data_set, id_first, &rsc_first, &tag_first) == FALSE) {
2100 "valid resource or tag",
id, id_first);
2104 if (valid_resource_or_tag(data_set, id_then, &rsc_then, &tag_then) == FALSE) {
2106 "valid resource or tag",
id, id_then);
2110 if (rsc_first && rsc_then) {
2126 if (rsc_set_first) {
2130 crm_xml_add(rsc_set_first,
"action", action_first);
2154 *expanded_xml = new_xml;
2165 gboolean any_sets = FALSE;
2179 xmlNode *set = NULL;
2180 xmlNode *last = NULL;
2182 xmlNode *orig_xml = NULL;
2183 xmlNode *expanded_xml = NULL;
2196 gboolean invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
2199 rc = unpack_order_tags(xml_obj, &expanded_xml, data_set);
2202 xml_obj = expanded_xml;
2204 }
else if (rc == FALSE) {
2208 for (set = pcmk__xe_first_child(xml_obj); set != NULL;
2209 set = pcmk__xe_next(set)) {
2214 if (unpack_order_set(set, kind, &rsc, &set_begin, &set_end,
2215 &set_inv_begin, &set_inv_end, invert, data_set) == FALSE) {
2256 if (order_rsc_sets(
id, last, set, kind, data_set, FALSE, invert_bool) == FALSE) {
2261 && order_rsc_sets(
id, set, last, kind, data_set, TRUE, invert_bool) == FALSE) {
2282 if (any_sets == FALSE) {
2283 return unpack_simple_rsc_order(xml_obj, data_set);
2301 unpack_influence(
const char *coloc_id,
const pe_resource_t *rsc,
2302 const char *influence_s)
2304 if (influence_s != NULL) {
2305 int influence_i = 0;
2312 return (influence_i == TRUE);
2319 unpack_colocation_set(xmlNode *set,
int score,
const char *coloc_id,
2322 xmlNode *xml_rsc = NULL;
2325 const char *set_id =
ID(set);
2329 int local_score = score;
2336 if (local_score == 0) {
2337 crm_trace(
"Ignoring colocation '%s' for set '%s' because score is 0",
2342 if(ordering == NULL) {
2346 if (sequential != NULL &&
crm_is_true(sequential) == FALSE) {
2349 }
else if ((local_score > 0)
2351 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
2352 xml_rsc = pcmk__xe_next(xml_rsc)) {
2360 unpack_influence(coloc_id, resource,
2368 }
else if (local_score > 0) {
2370 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
2371 xml_rsc = pcmk__xe_next(xml_rsc)) {
2378 resource, role, role,
2379 unpack_influence(coloc_id, last,
2394 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
2395 xml_rsc = pcmk__xe_next(xml_rsc)) {
2398 xmlNode *xml_rsc_with = NULL;
2399 bool influence =
true;
2402 influence = unpack_influence(coloc_id, resource, influence_s);
2404 for (xml_rsc_with = pcmk__xe_first_child(set);
2405 xml_rsc_with != NULL;
2406 xml_rsc_with = pcmk__xe_next(xml_rsc_with)) {
2413 pe_rsc_trace(resource,
"Anti-Colocating %s with %s", resource->
id,
2416 resource, with, role, role,
2417 influence, data_set);
2428 colocate_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
int score,
2431 xmlNode *xml_rsc = NULL;
2442 crm_trace(
"Ignoring colocation '%s' between sets because score is 0",
2446 if (sequential_1 == NULL ||
crm_is_true(sequential_1)) {
2448 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2449 xml_rsc = pcmk__xe_next(xml_rsc)) {
2458 if (sequential_2 == NULL ||
crm_is_true(sequential_2)) {
2460 const char *rid = NULL;
2462 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2463 xml_rsc = pcmk__xe_next(xml_rsc)) {
2472 if (rsc_1 != NULL && rsc_2 != NULL) {
2474 unpack_influence(
id, rsc_1, influence_s),
2477 }
else if (rsc_1 != NULL) {
2478 bool influence = unpack_influence(
id, rsc_1, influence_s);
2480 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2481 xml_rsc = pcmk__xe_next(xml_rsc)) {
2486 role_2, influence, data_set);
2490 }
else if (rsc_2 != NULL) {
2491 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2492 xml_rsc = pcmk__xe_next(xml_rsc)) {
2498 unpack_influence(
id, rsc_1, influence_s),
2504 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2505 xml_rsc = pcmk__xe_next(xml_rsc)) {
2508 xmlNode *xml_rsc_2 = NULL;
2509 bool influence =
true;
2512 influence = unpack_influence(
id, rsc_1, influence_s);
2514 for (xml_rsc_2 = pcmk__xe_first_child(set2);
2516 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
2521 role_1, role_2, influence,
2533 unpack_simple_colocation(xmlNode *xml_obj,
const char *
id,
2553 if (rsc_lh == NULL) {
2555 "does not exist",
id, id_lh);
2558 }
else if (rsc_rh == NULL) {
2560 "does not exist",
id, id_rh);
2563 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2565 "is not a clone but instance '%s' was requested",
2566 id, id_lh, instance_lh);
2569 }
else if (instance_rh && pe_rsc_is_clone(rsc_rh) == FALSE) {
2571 "is not a clone but instance '%s' was requested",
2572 id, id_rh, instance_rh);
2578 if (rsc_lh == NULL) {
2580 "does not have an instance '%s'",
2581 id, id_lh, instance_lh);
2588 if (rsc_rh == NULL) {
2590 "does not have an instance '%s'",
2591 "'%s'",
id, id_rh, instance_rh);
2599 "' attribute has been removed");
2607 unpack_influence(
id, rsc_lh, influence_s), data_set);
2611 unpack_colocation_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2613 const char *
id = NULL;
2614 const char *id_lh = NULL;
2615 const char *id_rh = NULL;
2616 const char *state_lh = NULL;
2617 const char *state_rh = NULL;
2625 xmlNode *new_xml = NULL;
2626 xmlNode *rsc_set_lh = NULL;
2627 xmlNode *rsc_set_rh = NULL;
2628 gboolean any_sets = FALSE;
2630 *expanded_xml = NULL;
2632 CRM_CHECK(xml_obj != NULL,
return FALSE);
2637 crm_element_name(xml_obj));
2642 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2646 *expanded_xml = new_xml;
2652 if (id_lh == NULL || id_rh == NULL) {
2656 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
2658 "valid resource or tag",
id, id_lh);
2662 if (valid_resource_or_tag(data_set, id_rh, &rsc_rh, &tag_rh) == FALSE) {
2664 "valid resource or tag",
id, id_rh);
2668 if (rsc_lh && rsc_rh) {
2673 if (tag_lh && tag_rh) {
2676 "tags cannot be colocated",
id);
2719 *expanded_xml = new_xml;
2731 xmlNode *set = NULL;
2732 xmlNode *last = NULL;
2733 gboolean any_sets = FALSE;
2735 xmlNode *orig_xml = NULL;
2736 xmlNode *expanded_xml = NULL;
2747 if (!unpack_colocation_tags(xml_obj, &expanded_xml, data_set)) {
2752 xml_obj = expanded_xml;
2755 for (set = pcmk__xe_first_child(xml_obj); set != NULL;
2756 set = pcmk__xe_next(set)) {
2761 if (!unpack_colocation_set(set, score_i,
id, influence_s,
2765 if ((last != NULL) && !colocate_rsc_sets(
id, last, set, score_i,
2766 influence_s, data_set)) {
2779 unpack_simple_colocation(xml_obj,
id, influence_s, data_set);
2785 const char *state_lh,
const char *loss_policy,
pe_working_set_t * data_set)
2789 if (rsc_lh == NULL) {
2791 "does not exist",
id);
2796 if (new_rsc_ticket == NULL) {
2804 new_rsc_ticket->
id =
id;
2805 new_rsc_ticket->
ticket = ticket;
2806 new_rsc_ticket->
rsc_lh = rsc_lh;
2814 "' for ticket '%s' to 'stop' "
2815 "because fencing is not configured", ticket->
id);
2816 loss_policy =
"stop";
2821 crm_debug(
"On loss of ticket '%s': Fence the nodes running %s (%s)",
2826 crm_debug(
"On loss of ticket '%s': Freeze %s (%s)",
2832 crm_debug(
"On loss of ticket '%s': Demote %s (%s)",
2838 crm_debug(
"On loss of ticket '%s': Stop %s (%s)",
2845 crm_debug(
"On loss of ticket '%s': Default to demote %s (%s)",
2851 crm_debug(
"On loss of ticket '%s': Default to stop %s (%s)",
2873 unpack_rsc_ticket_set(xmlNode * set,
pe_ticket_t * ticket,
const char *loss_policy,
2876 xmlNode *xml_rsc = NULL;
2878 const char *set_id = NULL;
2879 const char *role = NULL;
2882 CRM_CHECK(ticket != NULL,
return FALSE);
2885 if (set_id == NULL) {
2897 pe_rsc_trace(resource,
"Resource '%s' depends on ticket '%s'",
2898 resource->
id, ticket->
id);
2899 rsc_ticket_new(set_id, resource, ticket, role, loss_policy, data_set);
2908 const char *
id = NULL;
2922 CRM_CHECK(xml_obj != NULL,
return FALSE);
2927 crm_element_name(xml_obj));
2931 if (ticket_str == NULL) {
2936 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
2939 if (ticket == NULL) {
2941 "does not exist",
id, ticket_str);
2945 if (id_lh == NULL) {
2949 rsc_lh = pe_find_constraint_resource(data_set->
resources, id_lh);
2952 if (rsc_lh == NULL) {
2954 "does not exist",
id, id_lh);
2957 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2959 "is not a clone but instance '%s' was requested",
2960 id, id_lh, instance_lh);
2966 if (rsc_lh == NULL) {
2968 "does not have an instance '%s'",
2969 "'%s'",
id, id_lh, instance_lh);
2974 rsc_ticket_new(
id, rsc_lh, ticket, state_lh, loss_policy, data_set);
2979 unpack_rsc_ticket_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2981 const char *
id = NULL;
2982 const char *id_lh = NULL;
2983 const char *state_lh = NULL;
2988 xmlNode *new_xml = NULL;
2989 xmlNode *rsc_set_lh = NULL;
2990 gboolean any_sets = FALSE;
2992 *expanded_xml = NULL;
2994 CRM_CHECK(xml_obj != NULL,
return FALSE);
2999 crm_element_name(xml_obj));
3004 expand_tags_in_sets(xml_obj, &new_xml, data_set);
3008 *expanded_xml = new_xml;
3013 if (id_lh == NULL) {
3017 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
3019 "valid resource or tag",
id, id_lh);
3022 }
else if (rsc_lh) {
3049 *expanded_xml = new_xml;
3060 xmlNode *set = NULL;
3061 gboolean any_sets = FALSE;
3063 const char *
id = NULL;
3069 xmlNode *orig_xml = NULL;
3070 xmlNode *expanded_xml = NULL;
3074 CRM_CHECK(xml_obj != NULL,
return FALSE);
3079 crm_element_name(xml_obj));
3083 if (data_set->
tickets == NULL) {
3087 if (ticket_str == NULL) {
3091 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
3094 if (ticket == NULL) {
3096 if (ticket == NULL) {
3101 rc = unpack_rsc_ticket_tags(xml_obj, &expanded_xml, data_set);
3104 xml_obj = expanded_xml;
3106 }
else if (rc == FALSE) {
3110 for (set = pcmk__xe_first_child(xml_obj); set != NULL;
3111 set = pcmk__xe_next(set)) {
3116 if (unpack_rsc_ticket_set(set, ticket, loss_policy, data_set) == FALSE) {
3127 if (any_sets == FALSE) {
3128 return unpack_simple_rsc_ticket(xml_obj, data_set);
GList * pcmk__copy_node_list(const GList *list, bool reset)
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
#define CRM_CHECK(expr, failure_action)
pe_node_t * pe_find_node(GList *node_list, const char *uname)
enum rsc_role_e role_filter
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
const char * pe_node_attribute_calculated(const pe_node_t *node, const char *name, const pe_resource_t *rsc)
#define XML_ORDER_ATTR_THEN_ACTION
gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc)
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
int pcmk__scan_min_int(const char *text, int *result, int minimum)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
#define XML_ORDER_ATTR_THEN
#define XML_COLOC_ATTR_TARGET_INSTANCE
struct crm_time_s crm_time_t
void pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
#define CRM_OP_RELAXED_SET
#define pcmk__config_warn(fmt...)
#define RSC_ROLE_STARTED_S
gboolean unpack_rsc_order(xmlNode *xml_obj, pe_working_set_t *data_set)
gboolean pe_test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, crm_time_t *next_change, pe_match_data_t *match_data)
#define XML_RULE_ATTR_SCORE
gboolean unpack_rsc_ticket(xmlNode *xml_obj, pe_working_set_t *data_set)
#define XML_BOOLEAN_FALSE
void pcmk__new_colocation(const char *id, const char *node_attr, int score, pe_resource_t *rsc_lh, pe_resource_t *rsc_rh, const char *state_lh, const char *state_rh, bool influence, pe_working_set_t *data_set)
void rsc_ticket_constraint(pe_resource_t *lh_rsc, rsc_ticket_t *rsc_ticket, pe_working_set_t *data_set)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
#define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name)
int char2score(const char *score)
#define pcmk__config_err(fmt...)
#define XML_LOCATION_ATTR_DISCOVERY
resource_object_functions_t * fns
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
pe_node_t * pe__copy_node(const pe_node_t *this_node)
#define CRMD_ACTION_PROMOTE
gboolean unpack_constraints(xmlNode *xml_constraints, pe_working_set_t *data_set)
#define XML_CONS_TAG_RSC_DEPEND
int order_id
Deprecated (will be removed in a future release)
#define XML_CONS_TAG_RSC_TICKET
enum crm_ais_msg_types type
pe_node_t * partial_migration_target
#define XML_COLOC_ATTR_TARGET_ROLE
#define XML_ORDER_ATTR_FIRST_INSTANCE
#define XML_LOC_ATTR_SOURCE
#define XML_CONS_TAG_RSC_SET
xmlDoc * getDocPtr(xmlNode *node)
#define CRMD_ACTION_START
#define XML_RSC_ATTR_INCARNATION_MIN
xmlNode * copy_xml(xmlNode *src_node)
const char * role2text(enum rsc_role_e role)
pe__location_t * rsc2node_new(const char *id, pe_resource_t *rsc, int weight, const char *discovery_mode, pe_node_t *node, pe_working_set_t *data_set)
#define XML_ORDER_ATTR_FIRST
GList * ticket_constraints
#define crm_warn(fmt, args...)
#define CRMD_ACTION_DEMOTE
#define XML_COLOC_ATTR_TARGET
#define pe_rsc_allow_migrate
pe_action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
#define crm_debug(fmt, args...)
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.
#define XML_LOC_ATTR_SOURCE_PATTERN
#define XML_CONS_TAG_RSC_LOCATION
pe_resource_t *(* find_rsc)(pe_resource_t *parent, const char *search, const pe_node_t *node, int flags)
#define pe_warn_once(pe_wo_bit, fmt...)
pe_ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
int custom_action_order(pe_resource_t *lh_rsc, char *lh_task, pe_action_t *lh_action, pe_resource_t *rh_rsc, char *rh_task, pe_action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set)
#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.
struct pe_node_shared_s * details
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
pe_resource_t * find_clone_instance(pe_resource_t *rsc, const char *sub_id, pe_working_set_t *data_set)
enum loss_ticket_policy_e loss_policy
#define pe_rsc_promotable
GHashTable * pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters.
Wrappers for and extensions to libxml2.
xmlNode * create_xml_node(xmlNode *parent, const char *name)
long long int crm_time_get_seconds_since_epoch(crm_time_t *dt)
enum pe_restart restart_type
#define pe_flag_stonith_enabled
#define XML_COLOC_ATTR_SOURCE_INSTANCE
#define XML_TAG_RESOURCE_REF
gboolean update_action_flags(pe_action_t *action, enum pe_action_flags flags, const char *source, int line)
char * pe_expand_re_matches(const char *string, pe_re_match_data_t *match_data)
void free_xml(xmlNode *child)
enum rsc_role_e text2role(const char *role)
enum pe_obj_types variant
int new_rsc_order(pe_resource_t *lh_rsc, const char *lh_task, pe_resource_t *rh_rsc, const char *rh_task, enum pe_ordering type, pe_working_set_t *data_set)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
#define XML_COLOC_ATTR_SOURCE_ROLE
#define XML_RULE_ATTR_BOOLEAN_OP
const xmlChar * pcmkXmlStr
pe_node_t * pe_find_node_id(GList *node_list, const char *id)
match resource ID or LRM history ID
#define XML_ORDER_ATTR_THEN_INSTANCE
#define XML_COLOC_ATTR_NODE_ATTR
int crm_str_to_boolean(const char *s, int *ret)
Cluster status and scheduling.
#define XML_COLOC_ATTR_INFLUENCE
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
GList * ordering_constraints
#define XML_ORDER_ATTR_KIND
int pe__add_scores(int score1, int score2)
#define crm_err(fmt, args...)
GList * colocation_constraints
void xml_remove_prop(xmlNode *obj, const char *name)
#define CRM_OP_RELAXED_CLONE
gboolean pe_evaluate_rules(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now, crm_time_t *next_change)
Evaluate any rules contained by given XML element.
rsc_role_e
Possible roles that a resource can be in.
const char * node_attribute
#define XML_CONS_TAG_RSC_ORDER
void destroy_ticket(gpointer data)
#define RSC_ROLE_UNKNOWN_S
#define crm_log_xml_trace(xml, text)
#define XML_RULE_ATTR_SCORE_ATTRIBUTE
enum pe_ordering get_flags(const char *id, enum pe_order_kind kind, const char *action_first, const char *action_then, gboolean invert)
gboolean crm_is_true(const char *s)
enum pe_ordering get_asymmetrical_flags(enum pe_order_kind kind)
#define XML_TICKET_ATTR_TICKET
#define pe_rsc_trace(rsc, fmt, args...)
#define pe__set_order_flags(order_flags, flags_to_set)
#define XML_CONS_ATTR_SYMMETRICAL
#define crm_info(fmt, args...)
gboolean rsc_ticket_new(const char *id, pe_resource_t *rsc_lh, pe_ticket_t *ticket, const char *state_lh, const char *loss_policy, pe_working_set_t *data_set)
GHashTable * template_rsc_sets
#define XML_COLOC_ATTR_SOURCE
#define XML_ORDER_ATTR_FIRST_ACTION
int required_runnable_before
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
#define XML_RULE_ATTR_ROLE
#define XML_TICKET_ATTR_LOSS_POLICY
void crm_time_free(crm_time_t *dt)