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) {
466 for (rIter = rsc_first->
children;
id && rIter; rIter = rIter->next) {
470 NULL, NULL, NULL, unordered_action,
482 order_id =
new_rsc_order(rsc_first, action_first, rsc_then, action_then, cons_weight, data_set);
485 pe_rsc_trace(rsc_first,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
486 order_id,
id, rsc_first->
id, action_first, rsc_then->
id, action_then, cons_weight);
488 if (invert_bool == FALSE) {
492 action_then = invert_action(action_then);
493 action_first = invert_action(action_first);
494 if (action_then == NULL || action_first == NULL) {
496 "(please specify inverse manually)",
id);
502 crm_trace(
"Upgrade : recovery - implies left");
507 get_flags(
id, kind, action_first, action_then, TRUE));
509 order_id =
new_rsc_order(rsc_then, action_then, rsc_first, action_first, cons_weight, data_set);
511 pe_rsc_trace(rsc_then,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
512 order_id,
id, rsc_then->
id, action_then, rsc_first->
id, action_first, cons_weight);
518 expand_tags_in_sets(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
520 xmlNode *new_xml = NULL;
522 gboolean any_refs = FALSE;
523 const char *cons_id = NULL;
525 *expanded_xml = NULL;
527 CRM_CHECK(xml_obj != NULL,
return FALSE);
530 cons_id =
ID(new_xml);
532 for (
set = pcmk__xe_first_child(new_xml);
set != NULL;
533 set = pcmk__xe_next(
set)) {
535 xmlNode *xml_rsc = NULL;
536 GList *tag_refs = NULL;
543 for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
544 xml_rsc = pcmk__xe_next(xml_rsc)) {
548 const char *
id =
ID(xml_rsc);
554 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
556 "because '%s' is not a valid resource or tag",
566 xmlNode *last_ref = xml_rsc;
590 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
591 const char *obj_ref = (
const char *) gIter->data;
592 xmlNode *new_rsc_ref = NULL;
594 new_rsc_ref = xmlNewDocRawNode(
getDocPtr(
set), NULL,
597 xmlAddNextSibling(last_ref, new_rsc_ref);
599 last_ref = new_rsc_ref;
609 tag_refs = g_list_append(tag_refs, xml_rsc);
623 for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
624 xmlNode *tag_ref = gIter->data;
628 g_list_free(tag_refs);
632 *expanded_xml = new_xml;
641 tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set,
const char * attr,
644 const char *cons_id = NULL;
645 const char *
id = NULL;
652 CRM_CHECK((xml_obj != NULL) && (attr != NULL),
return FALSE);
654 cons_id =
ID(xml_obj);
655 if (cons_id == NULL) {
657 crm_element_name(xml_obj));
666 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
668 "valid resource or tag", cons_id,
id);
680 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
681 const char *obj_ref = (
const char *) gIter->data;
682 xmlNode *rsc_ref = NULL;
691 }
else if (rsc && convert_rsc) {
694 xmlNode *rsc_ref = NULL;
714 static void unpack_rsc_location(xmlNode *xml_obj,
pe_resource_t *rsc_lh,
715 const char *role,
const char *score,
728 unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
733 regex_t *r_patt = calloc(1,
sizeof(regex_t));
737 if(value[0] ==
'!') {
742 if (regcomp(r_patt, value, REG_EXTENDED)) {
745 " has invalid value '%s'",
id, value);
751 for (rIter = data_set->
resources; rIter; rIter = rIter->next) {
754 regmatch_t *pmatch = NULL;
757 if(r_patt->re_nsub > 0) {
758 nregs = r_patt->re_nsub + 1;
762 pmatch = calloc(nregs,
sizeof(regmatch_t));
764 status = regexec(r_patt, r->
id, nregs, pmatch, 0);
766 if(invert == FALSE && status == 0) {
773 crm_debug(
"'%s' matched '%s' for %s", r->
id, value,
id);
774 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, &re_match_data);
776 }
else if (invert && (status != 0)) {
777 crm_debug(
"'%s' is an inverted match of '%s' for %s", r->
id, value,
id);
778 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, NULL);
781 crm_trace(
"'%s' does not match '%s' for %s", r->
id, value,
id);
793 unpack_rsc_location(xmlNode *xml_obj,
pe_resource_t *rsc_lh,
const char *role,
803 if (rsc_lh == NULL) {
805 "does not exist",
id, id_lh);
813 if (node != NULL && score != NULL) {
820 location =
rsc2node_new(
id, rsc_lh, score_i, discovery, match, data_set);
834 generate_location_rule(rsc_lh, rule_xml, discovery, next_change,
835 data_set, re_match_data);
859 if (location && role) {
861 pe_err(
"Invalid constraint %s: Bad role %s",
id, role);
882 unpack_location_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
884 const char *
id = NULL;
885 const char *id_lh = NULL;
886 const char *state_lh = NULL;
892 xmlNode *new_xml = NULL;
893 xmlNode *rsc_set_lh = NULL;
895 *expanded_xml = NULL;
897 CRM_CHECK(xml_obj != NULL,
return FALSE);
902 crm_element_name(xml_obj));
907 expand_tags_in_sets(xml_obj, &new_xml, data_set);
911 *expanded_xml = new_xml;
920 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
922 "valid resource or tag",
id, id_lh);
948 *expanded_xml = new_xml;
959 unpack_location_set(xmlNode * location, xmlNode *
set,
pe_working_set_t * data_set)
961 xmlNode *xml_rsc = NULL;
965 const char *local_score;
970 if (set_id == NULL) {
980 for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
981 xml_rsc = pcmk__xe_next(xml_rsc)) {
985 unpack_rsc_location(location, resource, role, local_score, data_set, NULL);
996 gboolean any_sets = FALSE;
998 xmlNode *orig_xml = NULL;
999 xmlNode *expanded_xml = NULL;
1001 if (unpack_location_tags(xml_obj, &expanded_xml, data_set) == FALSE) {
1007 xml_obj = expanded_xml;
1010 for (
set = pcmk__xe_first_child(xml_obj);
set != NULL;
1011 set = pcmk__xe_next(
set)) {
1016 if (unpack_location_set(xml_obj,
set, data_set) == FALSE) {
1030 if (any_sets == FALSE) {
1031 unpack_simple_location(xml_obj, data_set);
1040 if (score == NULL) {
1041 pe_err(
"Rule %s: no score specified. Assuming 0.", rule);
1049 if (attr_score == NULL) {
1050 crm_debug(
"Rule %s: node %s did not have a value for %s",
1055 crm_debug(
"Rule %s: node %s had value %s for %s",
1064 generate_location_rule(
pe_resource_t *rsc, xmlNode *rule_xml,
1065 const char *discovery,
crm_time_t *next_change,
1069 const char *rule_id = NULL;
1070 const char *score = NULL;
1071 const char *
boolean = NULL;
1072 const char *role = NULL;
1074 GList *gIter = NULL;
1075 GList *match_L = NULL;
1077 gboolean do_and = TRUE;
1078 gboolean accept = TRUE;
1079 gboolean raw_score = TRUE;
1080 gboolean score_allocated = FALSE;
1089 crm_trace(
"Processing rule: %s", rule_id);
1092 pe_err(
"Bad role specified for %s: %s", rule_id, role);
1097 if (score == NULL) {
1099 if (score != NULL) {
1107 location_rule =
rsc2node_new(rule_id, rsc, 0, discovery, NULL, data_set);
1109 if (location_rule == NULL) {
1113 if ((re_match_data != NULL) && (re_match_data->
nregs > 0)
1114 && (re_match_data->
pmatch[0].rm_so != -1) && !raw_score) {
1118 if (result != NULL) {
1120 score_allocated = TRUE;
1125 crm_trace(
"Setting role filter: %s", role);
1136 GList *gIter = NULL;
1139 for (gIter = match_L; gIter != NULL; gIter = gIter->next) {
1142 node->
weight = get_node_score(rule_id, score, raw_score, node, rsc);
1146 for (gIter = data_set->
nodes; gIter != NULL; gIter = gIter->next) {
1150 .
re = re_match_data,
1156 data_set->
now, next_change, &match_data);
1158 crm_trace(
"Rule %s %s on %s",
ID(rule_xml), accept ?
"passed" :
"failed",
1161 score_f = get_node_score(rule_id, score, raw_score, node, rsc);
1169 if (
local == NULL && do_and) {
1172 }
else if (
local == NULL) {
1174 match_L = g_list_append(match_L,
local);
1177 if (do_and == FALSE) {
1182 }
else if (do_and && !accept) {
1186 if (
delete != NULL) {
1187 match_L = g_list_remove(match_L,
delete);
1194 if (score_allocated == TRUE) {
1195 free((
char *)score);
1200 crm_trace(
"No matching nodes for rule %s", rule_id);
1205 return location_rule;
1209 sort_cons_priority_lh(gconstpointer a, gconstpointer b)
1257 sort_cons_priority_rh(gconstpointer a, gconstpointer b)
1305 anti_colocation_order(
pe_resource_t * first_rsc,
int first_role,
1309 const char *first_tasks[] = { NULL, NULL };
1310 const char *then_tasks[] = { NULL, NULL };
1338 for (first_lpc = 0; first_lpc <= 1 && first_tasks[first_lpc] != NULL; first_lpc++) {
1339 for (then_lpc = 0; then_lpc <= 1 && then_tasks[then_lpc] != NULL; then_lpc++) {
1340 new_rsc_order(first_rsc, first_tasks[first_lpc], then_rsc, then_tasks[then_lpc],
1349 const char *state_lh,
const char *state_rh,
1355 crm_trace(
"Ignoring colocation '%s' because score is 0",
id);
1358 if ((rsc_lh == NULL) || (rsc_rh == NULL)) {
1360 "does not exist",
id);
1365 if (new_con == NULL) {
1378 new_con->
rsc_lh = rsc_lh;
1379 new_con->
rsc_rh = rsc_rh;
1380 new_con->
score = score;
1386 if (node_attr == NULL) {
1390 pe_rsc_trace(rsc_lh,
"%s ==> %s (%s %d)", rsc_lh->
id, rsc_rh->
id, node_attr, score);
1392 rsc_lh->
rsc_cons = g_list_insert_sorted(rsc_lh->
rsc_cons, new_con, sort_cons_priority_rh);
1395 g_list_insert_sorted(rsc_rh->
rsc_cons_lhs, new_con, sort_cons_priority_lh);
1400 anti_colocation_order(rsc_lh, new_con->
role_lh, rsc_rh, new_con->
role_rh, data_set);
1401 anti_colocation_order(rsc_rh, new_con->
role_rh, rsc_lh, new_con->
role_lh, data_set);
1411 char *lh_key = NULL;
1412 char *rh_key = NULL;
1423 if (validate_order_resources(lh_rsc, lh_task, rh_rsc, rh_task)) {
1440 res = strdup(
action->task);
1454 char *lh_task = NULL;
1455 char *rh_task = NULL;
1456 gboolean rh_migratable;
1457 gboolean lh_migratable;
1476 if (lh_migratable == FALSE && rh_migratable == FALSE) {
1486 if (lh_task == NULL || rh_task == NULL) {
1493 if (lh_migratable && rh_migratable) {
1500 NULL,
flags, data_set);
1503 if (rh_migratable) {
1504 if (lh_migratable) {
1514 NULL,
flags, data_set);
1520 if (lh_migratable) {
1531 NULL,
flags, data_set);
1540 NULL,
flags, data_set);
1546 if (rh_migratable) {
1553 NULL,
flags, data_set);
1559 if (rh_migratable) {
1573 NULL,
flags, data_set);
1591 if (lh_rsc == NULL && lh_action) {
1592 lh_rsc = lh_action->
rsc;
1594 if (rh_rsc == NULL && rh_action) {
1595 rh_rsc = rh_action->
rsc;
1598 if ((lh_action == NULL && lh_rsc == NULL)
1599 || (rh_action == NULL && rh_rsc == NULL)) {
1600 crm_err(
"Invalid ordering (bug?)");
1601 free(lh_action_task);
1602 free(rh_action_task);
1609 lh_rsc?lh_rsc->
id:
"NA", lh_action_task?lh_action_task:
"NA", lh_action?lh_action->
uuid:
"NA",
1610 rh_rsc?rh_rsc->
id:
"NA", rh_action_task?rh_action_task:
"NA", rh_action?rh_action->
uuid:
"NA");
1631 if (order->
lh_rsc == NULL && lh_action) {
1635 if (order->
rh_rsc == NULL && rh_action) {
1640 handle_migration_ordering(order, data_set);
1660 const char *action_first,
const char *action_then, gboolean invert)
1665 crm_trace(
"Upgrade %s: implies left",
id);
1669 crm_trace(
"Upgrade %s: implies right",
id);
1686 pe_action_t ** inv_end,
const char *parent_symmetrical_s,
1689 xmlNode *xml_rsc = NULL;
1690 GList *set_iter = NULL;
1691 GList *resources = NULL;
1696 int local_kind = parent_kind;
1697 gboolean sequential = FALSE;
1699 gboolean symmetrical = TRUE;
1702 const char *
id =
ID(
set);
1718 local_kind = get_ordering_type(
set);
1720 if (sequential_s == NULL) {
1726 symmetrical = order_is_symmetrical(
set, parent_kind, parent_symmetrical_s);
1733 for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
1734 xml_rsc = pcmk__xe_next(xml_rsc)) {
1738 resources = g_list_append(resources, resource);
1742 if (pcmk__list_of_1(resources)) {
1768 set_iter = resources;
1769 while (set_iter != NULL) {
1771 set_iter = set_iter->next;
1786 GList *gIter = NULL;
1788 for (gIter = set_iter; gIter != NULL; gIter = gIter->next) {
1796 }
else if (sequential) {
1805 if (symmetrical == FALSE) {
1827 set_iter = resources;
1828 while (set_iter != NULL) {
1830 set_iter = set_iter->next;
1851 g_list_free(resources);
1856 order_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
enum pe_order_kind kind,
1860 xmlNode *xml_rsc = NULL;
1861 xmlNode *xml_rsc_2 = NULL;
1873 gboolean require_all = require_all_s ?
crm_is_true(require_all_s) : TRUE;
1877 if (action_1 == NULL) {
1881 if (action_2 == NULL) {
1886 action_1 = invert_action(action_1);
1887 action_2 = invert_action(action_2);
1898 if (symmetrical == FALSE) {
1912 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1913 xml_rsc = pcmk__xe_next(xml_rsc)) {
1924 NULL, NULL, NULL, unordered_action,
1928 for (xml_rsc_2 = pcmk__xe_first_child(set2); xml_rsc_2 != NULL;
1929 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
1948 if (invert == FALSE) {
1950 const char *rid = NULL;
1952 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1953 xml_rsc = pcmk__xe_next(xml_rsc)) {
1963 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1964 xml_rsc = pcmk__xe_next(xml_rsc)) {
1975 if (invert == FALSE) {
1977 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
1978 xml_rsc = pcmk__xe_next(xml_rsc)) {
1988 const char *rid = NULL;
1990 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
1991 xml_rsc = pcmk__xe_next(xml_rsc)) {
2001 if (rsc_1 != NULL && rsc_2 != NULL) {
2004 }
else if (rsc_1 != NULL) {
2005 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2006 xml_rsc = pcmk__xe_next(xml_rsc)) {
2014 }
else if (rsc_2 != NULL) {
2015 xmlNode *xml_rsc = NULL;
2017 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2018 xml_rsc = pcmk__xe_next(xml_rsc)) {
2027 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2028 xml_rsc = pcmk__xe_next(xml_rsc)) {
2031 xmlNode *xml_rsc_2 = NULL;
2035 for (xml_rsc_2 = pcmk__xe_first_child(set2);
2037 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
2052 unpack_order_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2054 const char *
id = NULL;
2055 const char *id_first = NULL;
2056 const char *id_then = NULL;
2057 const char *action_first = NULL;
2058 const char *action_then = NULL;
2065 xmlNode *new_xml = NULL;
2066 xmlNode *rsc_set_first = NULL;
2067 xmlNode *rsc_set_then = NULL;
2068 gboolean any_sets = FALSE;
2070 *expanded_xml = NULL;
2072 CRM_CHECK(xml_obj != NULL,
return FALSE);
2077 crm_element_name(xml_obj));
2082 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2086 *expanded_xml = new_xml;
2092 if (id_first == NULL || id_then == NULL) {
2096 if (valid_resource_or_tag(data_set, id_first, &rsc_first, &tag_first) == FALSE) {
2098 "valid resource or tag",
id, id_first);
2102 if (valid_resource_or_tag(data_set, id_then, &rsc_then, &tag_then) == FALSE) {
2104 "valid resource or tag",
id, id_then);
2108 if (rsc_first && rsc_then) {
2124 if (rsc_set_first) {
2128 crm_xml_add(rsc_set_first,
"action", action_first);
2152 *expanded_xml = new_xml;
2163 gboolean any_sets = FALSE;
2177 xmlNode *
set = NULL;
2178 xmlNode *last = NULL;
2180 xmlNode *orig_xml = NULL;
2181 xmlNode *expanded_xml = NULL;
2194 gboolean invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
2197 rc = unpack_order_tags(xml_obj, &expanded_xml, data_set);
2200 xml_obj = expanded_xml;
2202 }
else if (
rc == FALSE) {
2206 for (
set = pcmk__xe_first_child(xml_obj);
set != NULL;
2207 set = pcmk__xe_next(
set)) {
2212 if (unpack_order_set(
set, kind, &rsc, &set_begin, &set_end,
2213 &set_inv_begin, &set_inv_end, invert, data_set) == FALSE) {
2254 if (order_rsc_sets(
id, last,
set, kind, data_set, FALSE, invert_bool) == FALSE) {
2259 && order_rsc_sets(
id,
set, last, kind, data_set, TRUE, invert_bool) == FALSE) {
2280 if (any_sets == FALSE) {
2281 return unpack_simple_rsc_order(xml_obj, data_set);
2299 unpack_influence(
const char *coloc_id,
const pe_resource_t *rsc,
2300 const char *influence_s)
2302 if (influence_s != NULL) {
2303 int influence_i = 0;
2310 return (influence_i == TRUE);
2317 unpack_colocation_set(xmlNode *
set,
int score,
const char *coloc_id,
2320 xmlNode *xml_rsc = NULL;
2323 const char *set_id =
ID(
set);
2327 int local_score = score;
2334 if (local_score == 0) {
2335 crm_trace(
"Ignoring colocation '%s' for set '%s' because score is 0",
2340 if(ordering == NULL) {
2344 if (sequential != NULL &&
crm_is_true(sequential) == FALSE) {
2347 }
else if ((local_score > 0)
2349 for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
2350 xml_rsc = pcmk__xe_next(xml_rsc)) {
2358 unpack_influence(coloc_id, resource,
2366 }
else if (local_score > 0) {
2368 for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
2369 xml_rsc = pcmk__xe_next(xml_rsc)) {
2376 resource, role, role,
2377 unpack_influence(coloc_id, last,
2392 for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
2393 xml_rsc = pcmk__xe_next(xml_rsc)) {
2396 xmlNode *xml_rsc_with = NULL;
2397 bool influence =
true;
2400 influence = unpack_influence(coloc_id, resource, influence_s);
2402 for (xml_rsc_with = pcmk__xe_first_child(
set);
2403 xml_rsc_with != NULL;
2404 xml_rsc_with = pcmk__xe_next(xml_rsc_with)) {
2411 pe_rsc_trace(resource,
"Anti-Colocating %s with %s", resource->
id,
2414 resource, with, role, role,
2415 influence, data_set);
2426 colocate_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
int score,
2429 xmlNode *xml_rsc = NULL;
2440 crm_trace(
"Ignoring colocation '%s' between sets because score is 0",
2444 if (sequential_1 == NULL ||
crm_is_true(sequential_1)) {
2446 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2447 xml_rsc = pcmk__xe_next(xml_rsc)) {
2456 if (sequential_2 == NULL ||
crm_is_true(sequential_2)) {
2458 const char *rid = NULL;
2460 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2461 xml_rsc = pcmk__xe_next(xml_rsc)) {
2470 if (rsc_1 != NULL && rsc_2 != NULL) {
2472 unpack_influence(
id, rsc_1, influence_s),
2475 }
else if (rsc_1 != NULL) {
2476 bool influence = unpack_influence(
id, rsc_1, influence_s);
2478 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2479 xml_rsc = pcmk__xe_next(xml_rsc)) {
2484 role_2, influence, data_set);
2488 }
else if (rsc_2 != NULL) {
2489 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2490 xml_rsc = pcmk__xe_next(xml_rsc)) {
2496 unpack_influence(
id, rsc_1, influence_s),
2502 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2503 xml_rsc = pcmk__xe_next(xml_rsc)) {
2506 xmlNode *xml_rsc_2 = NULL;
2507 bool influence =
true;
2510 influence = unpack_influence(
id, rsc_1, influence_s);
2512 for (xml_rsc_2 = pcmk__xe_first_child(set2);
2514 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
2519 role_1, role_2, influence,
2531 unpack_simple_colocation(xmlNode *xml_obj,
const char *
id,
2551 if (rsc_lh == NULL) {
2553 "does not exist",
id, id_lh);
2556 }
else if (rsc_rh == NULL) {
2558 "does not exist",
id, id_rh);
2561 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2563 "is not a clone but instance '%s' was requested",
2564 id, id_lh, instance_lh);
2567 }
else if (instance_rh && pe_rsc_is_clone(rsc_rh) == FALSE) {
2569 "is not a clone but instance '%s' was requested",
2570 id, id_rh, instance_rh);
2576 if (rsc_lh == NULL) {
2578 "does not have an instance '%s'",
2579 id, id_lh, instance_lh);
2586 if (rsc_rh == NULL) {
2588 "does not have an instance '%s'",
2589 "'%s'",
id, id_rh, instance_rh);
2597 "' attribute has been removed");
2605 unpack_influence(
id, rsc_lh, influence_s), data_set);
2609 unpack_colocation_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2611 const char *
id = NULL;
2612 const char *id_lh = NULL;
2613 const char *id_rh = NULL;
2614 const char *state_lh = NULL;
2615 const char *state_rh = NULL;
2623 xmlNode *new_xml = NULL;
2624 xmlNode *rsc_set_lh = NULL;
2625 xmlNode *rsc_set_rh = NULL;
2626 gboolean any_sets = FALSE;
2628 *expanded_xml = NULL;
2630 CRM_CHECK(xml_obj != NULL,
return FALSE);
2635 crm_element_name(xml_obj));
2640 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2644 *expanded_xml = new_xml;
2650 if (id_lh == NULL || id_rh == NULL) {
2654 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
2656 "valid resource or tag",
id, id_lh);
2660 if (valid_resource_or_tag(data_set, id_rh, &rsc_rh, &tag_rh) == FALSE) {
2662 "valid resource or tag",
id, id_rh);
2666 if (rsc_lh && rsc_rh) {
2671 if (tag_lh && tag_rh) {
2674 "tags cannot be colocated",
id);
2717 *expanded_xml = new_xml;
2729 xmlNode *
set = NULL;
2730 xmlNode *last = NULL;
2731 gboolean any_sets = FALSE;
2733 xmlNode *orig_xml = NULL;
2734 xmlNode *expanded_xml = NULL;
2745 if (!unpack_colocation_tags(xml_obj, &expanded_xml, data_set)) {
2750 xml_obj = expanded_xml;
2753 for (
set = pcmk__xe_first_child(xml_obj);
set != NULL;
2754 set = pcmk__xe_next(
set)) {
2759 if (!unpack_colocation_set(
set, score_i,
id, influence_s,
2763 if ((last != NULL) && !colocate_rsc_sets(
id, last,
set, score_i,
2764 influence_s, data_set)) {
2777 unpack_simple_colocation(xml_obj,
id, influence_s, data_set);
2783 const char *state_lh,
const char *loss_policy,
pe_working_set_t * data_set)
2787 if (rsc_lh == NULL) {
2789 "does not exist",
id);
2794 if (new_rsc_ticket == NULL) {
2802 new_rsc_ticket->
id =
id;
2803 new_rsc_ticket->
ticket = ticket;
2804 new_rsc_ticket->
rsc_lh = rsc_lh;
2812 "' for ticket '%s' to 'stop' " 2813 "because fencing is not configured", ticket->
id);
2814 loss_policy =
"stop";
2819 crm_debug(
"On loss of ticket '%s': Fence the nodes running %s (%s)",
2824 crm_debug(
"On loss of ticket '%s': Freeze %s (%s)",
2830 crm_debug(
"On loss of ticket '%s': Demote %s (%s)",
2836 crm_debug(
"On loss of ticket '%s': Stop %s (%s)",
2843 crm_debug(
"On loss of ticket '%s': Default to demote %s (%s)",
2849 crm_debug(
"On loss of ticket '%s': Default to stop %s (%s)",
2871 unpack_rsc_ticket_set(xmlNode *
set,
pe_ticket_t * ticket,
const char *loss_policy,
2874 xmlNode *xml_rsc = NULL;
2876 const char *set_id = NULL;
2877 const char *role = NULL;
2880 CRM_CHECK(ticket != NULL,
return FALSE);
2883 if (set_id == NULL) {
2895 pe_rsc_trace(resource,
"Resource '%s' depends on ticket '%s'",
2896 resource->
id, ticket->
id);
2897 rsc_ticket_new(set_id, resource, ticket, role, loss_policy, data_set);
2906 const char *
id = NULL;
2920 CRM_CHECK(xml_obj != NULL,
return FALSE);
2925 crm_element_name(xml_obj));
2929 if (ticket_str == NULL) {
2934 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
2937 if (ticket == NULL) {
2939 "does not exist",
id, ticket_str);
2943 if (id_lh == NULL) {
2947 rsc_lh = pe_find_constraint_resource(data_set->
resources, id_lh);
2950 if (rsc_lh == NULL) {
2952 "does not exist",
id, id_lh);
2955 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2957 "is not a clone but instance '%s' was requested",
2958 id, id_lh, instance_lh);
2964 if (rsc_lh == NULL) {
2966 "does not have an instance '%s'",
2967 "'%s'",
id, id_lh, instance_lh);
2972 rsc_ticket_new(
id, rsc_lh, ticket, state_lh, loss_policy, data_set);
2977 unpack_rsc_ticket_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2979 const char *
id = NULL;
2980 const char *id_lh = NULL;
2981 const char *state_lh = NULL;
2986 xmlNode *new_xml = NULL;
2987 xmlNode *rsc_set_lh = NULL;
2988 gboolean any_sets = FALSE;
2990 *expanded_xml = NULL;
2992 CRM_CHECK(xml_obj != NULL,
return FALSE);
2997 crm_element_name(xml_obj));
3002 expand_tags_in_sets(xml_obj, &new_xml, data_set);
3006 *expanded_xml = new_xml;
3011 if (id_lh == NULL) {
3015 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
3017 "valid resource or tag",
id, id_lh);
3020 }
else if (rsc_lh) {
3047 *expanded_xml = new_xml;
3058 xmlNode *
set = NULL;
3059 gboolean any_sets = FALSE;
3061 const char *
id = NULL;
3067 xmlNode *orig_xml = NULL;
3068 xmlNode *expanded_xml = NULL;
3072 CRM_CHECK(xml_obj != NULL,
return FALSE);
3077 crm_element_name(xml_obj));
3081 if (data_set->
tickets == NULL) {
3085 if (ticket_str == NULL) {
3089 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
3092 if (ticket == NULL) {
3094 if (ticket == NULL) {
3099 rc = unpack_rsc_ticket_tags(xml_obj, &expanded_xml, data_set);
3102 xml_obj = expanded_xml;
3104 }
else if (
rc == FALSE) {
3108 for (
set = pcmk__xe_first_child(xml_obj);
set != NULL;
3109 set = pcmk__xe_next(
set)) {
3114 if (unpack_rsc_ticket_set(
set, ticket, loss_policy, data_set) == FALSE) {
3125 if (any_sets == FALSE) {
3126 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)
gboolean unpack_constraints(xmlNode *xml_constraints, pe_working_set_t *data_set)
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
#define pe__set_action_flags(action, flags_to_set)
gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc)
int custom_action_order(pe_resource_t *lh_rsc, char *lh_action_task, pe_action_t *lh_action, pe_resource_t *rh_rsc, char *rh_action_task, pe_action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set)
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 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
#define XML_BOOLEAN_FALSE
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)
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
#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
gboolean unpack_rsc_order(xmlNode *xml_obj, pe_working_set_t *data_set)
#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)
gboolean unpack_rsc_ticket(xmlNode *xml_obj, pe_working_set_t *data_set)
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
#define pe_warn_once(pe_wo_bit, fmt...)
pe_ticket_t * ticket_new(const char *ticket_id, 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
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
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
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)
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)
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)
pe_resource_t *(* find_rsc)(pe_resource_t *parent, const char *search, const pe_node_t *node, int flags)
#define XML_CONS_ATTR_SYMMETRICAL
#define crm_info(fmt, args...)
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)