12 #include <sys/param.h> 13 #include <sys/types.h> 34 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \ 35 __rsc = pe_find_constraint_resource(data_set->resources, __name); \ 37 pcmk__config_err("%s: No resource found for %s", __set, __name); \ 43 const char *action_first,
const char *action_then, gboolean invert);
47 const char *discovery,
71 xmlNode *xml_obj = NULL;
72 xmlNode *lifetime = NULL;
74 for (xml_obj = pcmk__xe_first_child(xml_constraints); xml_obj != NULL;
75 xml_obj = pcmk__xe_next(xml_obj)) {
77 const char *tag = crm_element_name(xml_obj);
85 crm_trace(
"Processing constraint %s %s", tag,
id);
90 "deprecated (the rules it contains should " 91 "instead be direct descendents of the " 92 "constraint object)",
id);
95 if (lifetime && !evaluate_lifetime(lifetime, data_set)) {
96 crm_info(
"Constraint %s %s is not active", tag,
id);
111 pe_err(
"Unsupported constraint type: %s", tag);
119 invert_action(
const char *
action)
145 crm_warn(
"Unknown action '%s' specified in order constraint",
action);
150 get_ordering_type(xmlNode * xml_obj)
168 "Support for 'score' in rsc_order is deprecated " 169 "and will be removed in a future release (use 'kind' instead)");
183 "'%s' to Mandatory because '%s' is not valid",
190 pe_find_constraint_resource(
GListPtr rsc_list,
const char *
id)
194 for (rIter = rsc_list;
id && rIter; rIter = rIter->next) {
219 NULL, (gpointer*) tag);
222 rc = g_hash_table_lookup_extended(data_set->
tags,
id,
223 NULL, (gpointer*) tag);
226 crm_warn(
"No template or tag named '%s'",
id);
229 }
else if (*tag == NULL) {
230 crm_warn(
"No resource is tagged with '%s'",
id);
234 }
else if (*tag == NULL) {
235 crm_warn(
"No resource is derived from template '%s'",
id);
250 *rsc = pe_find_constraint_resource(data_set->
resources,
id);
258 rc = pe_find_constraint_tag(data_set,
id, tag);
265 order_is_symmetrical(xmlNode * xml_obj,
266 enum pe_order_kind parent_kind,
const char * parent_symmetrical_s)
274 if (kind_s || score_s) {
275 kind = get_ordering_type(xml_obj);
278 if (symmetrical_s == NULL) {
279 symmetrical_s = parent_symmetrical_s;
287 " for '%s' because not valid with " 310 gboolean invert_bool = TRUE;
311 int min_required_before = 0;
315 const char *id_first = NULL;
316 const char *id_then = NULL;
317 const char *action_then = NULL;
318 const char *action_first = NULL;
319 const char *instance_then = NULL;
320 const char *instance_first = NULL;
322 const char *
id = NULL;
324 CRM_CHECK(xml_obj != NULL,
return FALSE);
329 crm_element_name(xml_obj));
333 invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
344 if (action_first == NULL) {
347 if (action_then == NULL) {
348 action_then = action_first;
351 if (id_first == NULL) {
356 if (id_then == NULL) {
362 rsc_then = pe_find_constraint_resource(data_set->
resources, id_then);
363 rsc_first = pe_find_constraint_resource(data_set->
resources, id_first);
365 if (rsc_then == NULL) {
367 "does not exist",
id, id_then);
370 }
else if (rsc_first == NULL) {
372 "does not exist",
id, id_first);
375 }
else if (instance_then && pe_rsc_is_clone(rsc_then) == FALSE) {
377 "is not a clone but instance '%s' was requested",
378 id, id_then, instance_then);
381 }
else if (instance_first && pe_rsc_is_clone(rsc_first) == FALSE) {
383 "is not a clone but instance '%s' was requested",
384 id, id_first, instance_first);
390 if (rsc_then == NULL) {
392 "does not have an instance '%s'",
393 id, id_then, instance_then);
398 if (instance_first) {
400 if (rsc_first == NULL) {
402 "does not have an instance '%s'",
403 "'%s'",
id, id_first, instance_first);
409 kind = get_ordering_type(xml_obj);
412 crm_trace(
"Upgrade : recovery - implies right");
416 if (invert_bool == FALSE) {
420 get_flags(
id, kind, action_first, action_then, FALSE));
423 if (pe_rsc_is_clone(rsc_first)) {
427 const char *min_clones_s = g_hash_table_lookup(rsc_first->
meta,
436 }
else if (require_all_s) {
438 "Support for require-all in ordering constraints " 439 "is deprecated and will be removed in a future release" 440 " (use clone-min clone meta-attribute instead)");
443 min_required_before = 1;
451 if (min_required_before) {
464 for (rIter = rsc_first->
children;
id && rIter; rIter = rIter->next) {
468 NULL, NULL, NULL, unordered_action,
480 order_id =
new_rsc_order(rsc_first, action_first, rsc_then, action_then, cons_weight, data_set);
483 pe_rsc_trace(rsc_first,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
484 order_id,
id, rsc_first->
id, action_first, rsc_then->
id, action_then, cons_weight);
486 if (invert_bool == FALSE) {
490 action_then = invert_action(action_then);
491 action_first = invert_action(action_first);
492 if (action_then == NULL || action_first == NULL) {
494 "(please specify inverse manually)",
id);
500 crm_trace(
"Upgrade : recovery - implies left");
505 get_flags(
id, kind, action_first, action_then, TRUE));
507 order_id =
new_rsc_order(rsc_then, action_then, rsc_first, action_first, cons_weight, data_set);
509 pe_rsc_trace(rsc_then,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
510 order_id,
id, rsc_then->
id, action_then, rsc_first->
id, action_first, cons_weight);
516 expand_tags_in_sets(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
518 xmlNode *new_xml = NULL;
520 gboolean any_refs = FALSE;
521 const char *cons_id = NULL;
523 *expanded_xml = NULL;
525 CRM_CHECK(xml_obj != NULL,
return FALSE);
528 cons_id =
ID(new_xml);
530 for (set = pcmk__xe_first_child(new_xml); set != NULL;
531 set = pcmk__xe_next(set)) {
533 xmlNode *xml_rsc = NULL;
541 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
542 xml_rsc = pcmk__xe_next(xml_rsc)) {
546 const char *
id =
ID(xml_rsc);
552 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
554 "because '%s' is not a valid resource or tag",
564 xmlNode *last_ref = xml_rsc;
588 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
589 const char *obj_ref = (
const char *) gIter->data;
590 xmlNode *new_rsc_ref = NULL;
592 new_rsc_ref = xmlNewDocRawNode(
getDocPtr(set), NULL,
595 xmlAddNextSibling(last_ref, new_rsc_ref);
597 last_ref = new_rsc_ref;
607 tag_refs = g_list_append(tag_refs, xml_rsc);
621 for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
622 xmlNode *tag_ref = gIter->data;
626 g_list_free(tag_refs);
630 *expanded_xml = new_xml;
639 tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set,
const char * attr,
642 const char *cons_id = NULL;
643 const char *
id = NULL;
650 CRM_CHECK((xml_obj != NULL) && (attr != NULL),
return FALSE);
652 cons_id =
ID(xml_obj);
653 if (cons_id == NULL) {
655 crm_element_name(xml_obj));
664 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
666 "valid resource or tag", cons_id,
id);
678 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
679 const char *obj_ref = (
const char *) gIter->data;
680 xmlNode *rsc_ref = NULL;
689 }
else if (rsc && convert_rsc) {
692 xmlNode *rsc_ref = NULL;
712 static gboolean unpack_rsc_location(xmlNode * xml_obj,
pe_resource_t * rsc_lh,
const char * role,
724 return unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
729 regex_t *r_patt = calloc(1,
sizeof(regex_t));
733 if(value[0] ==
'!') {
738 if (regcomp(r_patt, value, REG_EXTENDED)) {
741 " has invalid value '%s'",
id, value);
747 for (rIter = data_set->
resources; rIter; rIter = rIter->next) {
750 regmatch_t *pmatch = NULL;
753 if(r_patt->re_nsub > 0) {
754 nregs = r_patt->re_nsub + 1;
758 pmatch = calloc(nregs,
sizeof(regmatch_t));
760 status = regexec(r_patt, r->
id, nregs, pmatch, 0);
762 if(invert == FALSE && status == 0) {
769 .
re = &re_match_data,
773 crm_debug(
"'%s' matched '%s' for %s", r->
id, value,
id);
774 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, &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);
795 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, match_data);
860 if (location && role) {
862 pe_err(
"Invalid constraint %s: Bad role %s",
id, role);
885 unpack_location_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
887 const char *
id = NULL;
888 const char *id_lh = NULL;
889 const char *state_lh = NULL;
895 xmlNode *new_xml = NULL;
896 xmlNode *rsc_set_lh = NULL;
898 *expanded_xml = NULL;
900 CRM_CHECK(xml_obj != NULL,
return FALSE);
905 crm_element_name(xml_obj));
910 expand_tags_in_sets(xml_obj, &new_xml, data_set);
914 *expanded_xml = new_xml;
923 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
925 "valid resource or tag",
id, id_lh);
951 *expanded_xml = new_xml;
962 unpack_location_set(xmlNode * location, xmlNode * set,
pe_working_set_t * data_set)
964 xmlNode *xml_rsc = NULL;
968 const char *local_score;
973 if (set_id == NULL) {
983 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
984 xml_rsc = pcmk__xe_next(xml_rsc)) {
988 unpack_rsc_location(location, resource, role, local_score, data_set, NULL);
999 gboolean any_sets = FALSE;
1001 xmlNode *orig_xml = NULL;
1002 xmlNode *expanded_xml = NULL;
1004 if (unpack_location_tags(xml_obj, &expanded_xml, data_set) == FALSE) {
1010 xml_obj = expanded_xml;
1013 for (set = pcmk__xe_first_child(xml_obj); set != NULL;
1014 set = pcmk__xe_next(set)) {
1019 if (unpack_location_set(xml_obj, set, data_set) == FALSE) {
1033 if (any_sets == FALSE) {
1034 return unpack_simple_location(xml_obj, data_set);
1045 if (score == NULL) {
1046 pe_err(
"Rule %s: no score specified. Assuming 0.", rule);
1054 if (attr_score == NULL) {
1055 crm_debug(
"Rule %s: node %s did not have a value for %s",
1060 crm_debug(
"Rule %s: node %s had value %s for %s",
1069 generate_location_rule(
pe_resource_t *rsc, xmlNode *rule_xml,
1070 const char *discovery,
crm_time_t *next_change,
1073 const char *rule_id = NULL;
1074 const char *score = NULL;
1075 const char *
boolean = NULL;
1076 const char *role = NULL;
1081 gboolean do_and = TRUE;
1082 gboolean accept = TRUE;
1083 gboolean raw_score = TRUE;
1084 gboolean score_allocated = FALSE;
1093 crm_trace(
"Processing rule: %s", rule_id);
1096 pe_err(
"Bad role specified for %s: %s", rule_id, role);
1101 if (score == NULL) {
1103 if (score != NULL) {
1111 location_rule =
rsc2node_new(rule_id, rsc, 0, discovery, NULL, data_set);
1113 if (location_rule == NULL) {
1117 if (match_data && match_data->
re && match_data->
re->
nregs > 0 && match_data->
re->
pmatch[0].rm_so != -1) {
1118 if (raw_score == FALSE) {
1122 score = (
const char *) result;
1123 score_allocated = TRUE;
1129 crm_trace(
"Setting role filter: %s", role);
1142 for (gIter = match_L; gIter != NULL; gIter = gIter->next) {
1145 node->
weight = get_node_score(rule_id, score, raw_score, node, rsc);
1149 for (gIter = data_set->
nodes; gIter != NULL; gIter = gIter->next) {
1154 data_set->
now, next_change, match_data);
1156 crm_trace(
"Rule %s %s on %s",
ID(rule_xml), accept ?
"passed" :
"failed",
1159 score_f = get_node_score(rule_id, score, raw_score, node, rsc);
1167 if (
local == NULL && do_and) {
1170 }
else if (
local == NULL) {
1172 match_L = g_list_append(match_L,
local);
1175 if (do_and == FALSE) {
1180 }
else if (do_and && !accept) {
1184 if (
delete != NULL) {
1185 match_L = g_list_remove(match_L,
delete);
1192 if (score_allocated == TRUE) {
1193 free((
char *)score);
1198 crm_trace(
"No matching nodes for rule %s", rule_id);
1203 return location_rule;
1207 sort_cons_priority_lh(gconstpointer a, gconstpointer b)
1255 sort_cons_priority_rh(gconstpointer a, gconstpointer b)
1303 anti_colocation_order(
pe_resource_t * first_rsc,
int first_role,
1307 const char *first_tasks[] = { NULL, NULL };
1308 const char *then_tasks[] = { NULL, NULL };
1336 for (first_lpc = 0; first_lpc <= 1 && first_tasks[first_lpc] != NULL; first_lpc++) {
1337 for (then_lpc = 0; then_lpc <= 1 && then_tasks[then_lpc] != NULL; then_lpc++) {
1338 new_rsc_order(first_rsc, first_tasks[first_lpc], then_rsc, then_tasks[then_lpc],
1351 if ((rsc_lh == NULL) || (rsc_rh == NULL)) {
1353 "does not exist",
id);
1358 if (new_con == NULL) {
1371 new_con->
rsc_lh = rsc_lh;
1372 new_con->
rsc_rh = rsc_rh;
1373 new_con->
score = score;
1378 if (node_attr == NULL) {
1382 pe_rsc_trace(rsc_lh,
"%s ==> %s (%s %d)", rsc_lh->
id, rsc_rh->
id, node_attr, score);
1384 rsc_lh->
rsc_cons = g_list_insert_sorted(rsc_lh->
rsc_cons, new_con, sort_cons_priority_rh);
1387 g_list_insert_sorted(rsc_rh->
rsc_cons_lhs, new_con, sort_cons_priority_lh);
1392 anti_colocation_order(rsc_lh, new_con->
role_lh, rsc_rh, new_con->
role_rh, data_set);
1393 anti_colocation_order(rsc_rh, new_con->
role_rh, rsc_lh, new_con->
role_lh, data_set);
1405 char *lh_key = NULL;
1406 char *rh_key = NULL;
1417 if (validate_order_resources(lh_rsc, lh_task, rh_rsc, rh_task)) {
1434 res = strdup(
action->task);
1448 char *lh_task = NULL;
1449 char *rh_task = NULL;
1450 gboolean rh_migratable;
1451 gboolean lh_migratable;
1470 if (lh_migratable == FALSE && rh_migratable == FALSE) {
1480 if (lh_task == NULL || rh_task == NULL) {
1487 if (lh_migratable && rh_migratable) {
1494 NULL,
flags, data_set);
1497 if (rh_migratable) {
1498 if (lh_migratable) {
1508 NULL,
flags, data_set);
1514 if (lh_migratable) {
1525 NULL,
flags, data_set);
1534 NULL,
flags, data_set);
1540 if (rh_migratable) {
1547 NULL,
flags, data_set);
1553 if (rh_migratable) {
1567 NULL,
flags, data_set);
1585 if (lh_rsc == NULL && lh_action) {
1586 lh_rsc = lh_action->
rsc;
1588 if (rh_rsc == NULL && rh_action) {
1589 rh_rsc = rh_action->
rsc;
1592 if ((lh_action == NULL && lh_rsc == NULL)
1593 || (rh_action == NULL && rh_rsc == NULL)) {
1594 crm_err(
"Invalid ordering (bug?)");
1595 free(lh_action_task);
1596 free(rh_action_task);
1603 lh_rsc?lh_rsc->
id:
"NA", lh_action_task?lh_action_task:
"NA", lh_action?lh_action->
uuid:
"NA",
1604 rh_rsc?rh_rsc->
id:
"NA", rh_action_task?rh_action_task:
"NA", rh_action?rh_action->
uuid:
"NA");
1625 if (order->
lh_rsc == NULL && lh_action) {
1629 if (order->
rh_rsc == NULL && rh_action) {
1634 handle_migration_ordering(order, data_set);
1654 const char *action_first,
const char *action_then, gboolean invert)
1659 crm_trace(
"Upgrade %s: implies left",
id);
1663 crm_trace(
"Upgrade %s: implies right",
id);
1680 pe_action_t ** inv_end,
const char *parent_symmetrical_s,
1683 xmlNode *xml_rsc = NULL;
1690 int local_kind = parent_kind;
1691 gboolean sequential = FALSE;
1693 gboolean symmetrical = TRUE;
1696 const char *
id =
ID(set);
1712 local_kind = get_ordering_type(set);
1714 if (sequential_s == NULL) {
1720 symmetrical = order_is_symmetrical(set, parent_kind, parent_symmetrical_s);
1727 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
1728 xml_rsc = pcmk__xe_next(xml_rsc)) {
1732 resources = g_list_append(resources, resource);
1736 if (pcmk__list_of_1(resources)) {
1762 set_iter = resources;
1763 while (set_iter != NULL) {
1765 set_iter = set_iter->next;
1782 for (gIter = set_iter; gIter != NULL; gIter = gIter->next) {
1790 }
else if (sequential) {
1799 if (symmetrical == FALSE) {
1821 set_iter = resources;
1822 while (set_iter != NULL) {
1824 set_iter = set_iter->next;
1845 g_list_free(resources);
1850 order_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
enum pe_order_kind kind,
1854 xmlNode *xml_rsc = NULL;
1855 xmlNode *xml_rsc_2 = NULL;
1867 gboolean require_all = require_all_s ?
crm_is_true(require_all_s) : TRUE;
1871 if (action_1 == NULL) {
1875 if (action_2 == NULL) {
1880 action_1 = invert_action(action_1);
1881 action_2 = invert_action(action_2);
1892 if (symmetrical == FALSE) {
1905 __func__, __LINE__);
1907 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1908 xml_rsc = pcmk__xe_next(xml_rsc)) {
1919 NULL, NULL, NULL, unordered_action,
1923 for (xml_rsc_2 = pcmk__xe_first_child(set2); xml_rsc_2 != NULL;
1924 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
1943 if (invert == FALSE) {
1945 const char *rid = NULL;
1947 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1948 xml_rsc = pcmk__xe_next(xml_rsc)) {
1958 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
1959 xml_rsc = pcmk__xe_next(xml_rsc)) {
1970 if (invert == FALSE) {
1972 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
1973 xml_rsc = pcmk__xe_next(xml_rsc)) {
1983 const char *rid = NULL;
1985 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
1986 xml_rsc = pcmk__xe_next(xml_rsc)) {
1996 if (rsc_1 != NULL && rsc_2 != NULL) {
1999 }
else if (rsc_1 != NULL) {
2000 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2001 xml_rsc = pcmk__xe_next(xml_rsc)) {
2009 }
else if (rsc_2 != NULL) {
2010 xmlNode *xml_rsc = NULL;
2012 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2013 xml_rsc = pcmk__xe_next(xml_rsc)) {
2022 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2023 xml_rsc = pcmk__xe_next(xml_rsc)) {
2026 xmlNode *xml_rsc_2 = NULL;
2030 for (xml_rsc_2 = pcmk__xe_first_child(set2);
2032 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
2047 unpack_order_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2049 const char *
id = NULL;
2050 const char *id_first = NULL;
2051 const char *id_then = NULL;
2052 const char *action_first = NULL;
2053 const char *action_then = NULL;
2060 xmlNode *new_xml = NULL;
2061 xmlNode *rsc_set_first = NULL;
2062 xmlNode *rsc_set_then = NULL;
2063 gboolean any_sets = FALSE;
2065 *expanded_xml = NULL;
2067 CRM_CHECK(xml_obj != NULL,
return FALSE);
2072 crm_element_name(xml_obj));
2077 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2081 *expanded_xml = new_xml;
2087 if (id_first == NULL || id_then == NULL) {
2091 if (valid_resource_or_tag(data_set, id_first, &rsc_first, &tag_first) == FALSE) {
2093 "valid resource or tag",
id, id_first);
2097 if (valid_resource_or_tag(data_set, id_then, &rsc_then, &tag_then) == FALSE) {
2099 "valid resource or tag",
id, id_then);
2103 if (rsc_first && rsc_then) {
2119 if (rsc_set_first) {
2123 crm_xml_add(rsc_set_first,
"action", action_first);
2147 *expanded_xml = new_xml;
2158 gboolean any_sets = FALSE;
2172 xmlNode *set = NULL;
2173 xmlNode *last = NULL;
2175 xmlNode *orig_xml = NULL;
2176 xmlNode *expanded_xml = NULL;
2189 gboolean invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
2192 rc = unpack_order_tags(xml_obj, &expanded_xml, data_set);
2195 xml_obj = expanded_xml;
2197 }
else if (
rc == FALSE) {
2201 for (set = pcmk__xe_first_child(xml_obj); set != NULL;
2202 set = pcmk__xe_next(set)) {
2207 if (unpack_order_set(set, kind, &rsc, &set_begin, &set_end,
2208 &set_inv_begin, &set_inv_end, invert, data_set) == FALSE) {
2249 if (order_rsc_sets(
id, last, set, kind, data_set, FALSE, invert_bool) == FALSE) {
2254 && order_rsc_sets(
id, set, last, kind, data_set, TRUE, invert_bool) == FALSE) {
2275 if (any_sets == FALSE) {
2276 return unpack_simple_rsc_order(xml_obj, data_set);
2283 unpack_colocation_set(xmlNode * set,
int score,
pe_working_set_t * data_set)
2285 xmlNode *xml_rsc = NULL;
2288 const char *set_id =
ID(set);
2292 int local_score = score;
2300 if(ordering == NULL) {
2304 if (sequential != NULL &&
crm_is_true(sequential) == FALSE) {
2307 }
else if ((local_score >= 0)
2309 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
2310 xml_rsc = pcmk__xe_next(xml_rsc)) {
2323 }
else if (local_score >= 0) {
2325 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
2326 xml_rsc = pcmk__xe_next(xml_rsc)) {
2346 for (xml_rsc = pcmk__xe_first_child(set); xml_rsc != NULL;
2347 xml_rsc = pcmk__xe_next(xml_rsc)) {
2350 xmlNode *xml_rsc_with = NULL;
2354 for (xml_rsc_with = pcmk__xe_first_child(set);
2355 xml_rsc_with != NULL;
2356 xml_rsc_with = pcmk__xe_next(xml_rsc_with)) {
2363 pe_rsc_trace(resource,
"Anti-Colocating %s with %s", resource->
id,
2377 colocate_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
int score,
2380 xmlNode *xml_rsc = NULL;
2390 if (sequential_1 == NULL ||
crm_is_true(sequential_1)) {
2392 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2393 xml_rsc = pcmk__xe_next(xml_rsc)) {
2402 if (sequential_2 == NULL ||
crm_is_true(sequential_2)) {
2404 const char *rid = NULL;
2406 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2407 xml_rsc = pcmk__xe_next(xml_rsc)) {
2416 if (rsc_1 != NULL && rsc_2 != NULL) {
2419 }
else if (rsc_1 != NULL) {
2420 for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
2421 xml_rsc = pcmk__xe_next(xml_rsc)) {
2429 }
else if (rsc_2 != NULL) {
2430 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2431 xml_rsc = pcmk__xe_next(xml_rsc)) {
2440 for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
2441 xml_rsc = pcmk__xe_next(xml_rsc)) {
2444 xmlNode *xml_rsc_2 = NULL;
2448 for (xml_rsc_2 = pcmk__xe_first_child(set2);
2450 xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
2486 if (rsc_lh == NULL) {
2488 "does not exist",
id, id_lh);
2491 }
else if (rsc_rh == NULL) {
2493 "does not exist",
id, id_rh);
2496 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2498 "is not a clone but instance '%s' was requested",
2499 id, id_lh, instance_lh);
2502 }
else if (instance_rh && pe_rsc_is_clone(rsc_rh) == FALSE) {
2504 "is not a clone but instance '%s' was requested",
2505 id, id_rh, instance_rh);
2511 if (rsc_lh == NULL) {
2513 "does not have an instance '%s'",
2514 id, id_lh, instance_lh);
2521 if (rsc_rh == NULL) {
2523 "does not have an instance '%s'",
2524 "'%s'",
id, id_rh, instance_rh);
2532 "' attribute has been removed");
2544 unpack_colocation_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2546 const char *
id = NULL;
2547 const char *id_lh = NULL;
2548 const char *id_rh = NULL;
2549 const char *state_lh = NULL;
2550 const char *state_rh = NULL;
2558 xmlNode *new_xml = NULL;
2559 xmlNode *rsc_set_lh = NULL;
2560 xmlNode *rsc_set_rh = NULL;
2561 gboolean any_sets = FALSE;
2563 *expanded_xml = NULL;
2565 CRM_CHECK(xml_obj != NULL,
return FALSE);
2570 crm_element_name(xml_obj));
2575 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2579 *expanded_xml = new_xml;
2585 if (id_lh == NULL || id_rh == NULL) {
2589 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
2591 "valid resource or tag",
id, id_lh);
2595 if (valid_resource_or_tag(data_set, id_rh, &rsc_rh, &tag_rh) == FALSE) {
2597 "valid resource or tag",
id, id_rh);
2601 if (rsc_lh && rsc_rh) {
2606 if (tag_lh && tag_rh) {
2609 "tags cannot be colocated",
id);
2652 *expanded_xml = new_xml;
2664 xmlNode *set = NULL;
2665 xmlNode *last = NULL;
2666 gboolean any_sets = FALSE;
2668 xmlNode *orig_xml = NULL;
2669 xmlNode *expanded_xml = NULL;
2680 rc = unpack_colocation_tags(xml_obj, &expanded_xml, data_set);
2683 xml_obj = expanded_xml;
2685 }
else if (
rc == FALSE) {
2689 for (set = pcmk__xe_first_child(xml_obj); set != NULL;
2690 set = pcmk__xe_next(set)) {
2695 if (unpack_colocation_set(set, score_i, data_set) == FALSE) {
2698 }
else if (last && colocate_rsc_sets(
id, last, set, score_i, data_set) == FALSE) {
2710 if (any_sets == FALSE) {
2711 return unpack_simple_colocation(xml_obj, data_set);
2719 const char *state_lh,
const char *loss_policy,
pe_working_set_t * data_set)
2723 if (rsc_lh == NULL) {
2725 "does not exist",
id);
2730 if (new_rsc_ticket == NULL) {
2738 new_rsc_ticket->
id =
id;
2739 new_rsc_ticket->
ticket = ticket;
2740 new_rsc_ticket->
rsc_lh = rsc_lh;
2748 "' for ticket '%s' to 'stop' " 2749 "because fencing is not configured", ticket->
id);
2750 loss_policy =
"stop";
2755 crm_debug(
"On loss of ticket '%s': Fence the nodes running %s (%s)",
2760 crm_debug(
"On loss of ticket '%s': Freeze %s (%s)",
2766 crm_debug(
"On loss of ticket '%s': Demote %s (%s)",
2772 crm_debug(
"On loss of ticket '%s': Stop %s (%s)",
2779 crm_debug(
"On loss of ticket '%s': Default to demote %s (%s)",
2785 crm_debug(
"On loss of ticket '%s': Default to stop %s (%s)",
2807 unpack_rsc_ticket_set(xmlNode * set,
pe_ticket_t * ticket,
const char *loss_policy,
2810 xmlNode *xml_rsc = NULL;
2812 const char *set_id = NULL;
2813 const char *role = NULL;
2816 CRM_CHECK(ticket != NULL,
return FALSE);
2819 if (set_id == NULL) {
2831 pe_rsc_trace(resource,
"Resource '%s' depends on ticket '%s'",
2832 resource->
id, ticket->
id);
2833 rsc_ticket_new(set_id, resource, ticket, role, loss_policy, data_set);
2842 const char *
id = NULL;
2856 CRM_CHECK(xml_obj != NULL,
return FALSE);
2861 crm_element_name(xml_obj));
2865 if (ticket_str == NULL) {
2870 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
2873 if (ticket == NULL) {
2875 "does not exist",
id, ticket_str);
2879 if (id_lh == NULL) {
2883 rsc_lh = pe_find_constraint_resource(data_set->
resources, id_lh);
2886 if (rsc_lh == NULL) {
2888 "does not exist",
id, id_lh);
2891 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2893 "is not a clone but instance '%s' was requested",
2894 id, id_lh, instance_lh);
2900 if (rsc_lh == NULL) {
2902 "does not have an instance '%s'",
2903 "'%s'",
id, id_lh, instance_lh);
2908 rsc_ticket_new(
id, rsc_lh, ticket, state_lh, loss_policy, data_set);
2913 unpack_rsc_ticket_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2915 const char *
id = NULL;
2916 const char *id_lh = NULL;
2917 const char *state_lh = NULL;
2922 xmlNode *new_xml = NULL;
2923 xmlNode *rsc_set_lh = NULL;
2924 gboolean any_sets = FALSE;
2926 *expanded_xml = NULL;
2928 CRM_CHECK(xml_obj != NULL,
return FALSE);
2933 crm_element_name(xml_obj));
2938 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2942 *expanded_xml = new_xml;
2947 if (id_lh == NULL) {
2951 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
2953 "valid resource or tag",
id, id_lh);
2956 }
else if (rsc_lh) {
2983 *expanded_xml = new_xml;
2994 xmlNode *set = NULL;
2995 gboolean any_sets = FALSE;
2997 const char *
id = NULL;
3003 xmlNode *orig_xml = NULL;
3004 xmlNode *expanded_xml = NULL;
3008 CRM_CHECK(xml_obj != NULL,
return FALSE);
3013 crm_element_name(xml_obj));
3017 if (data_set->
tickets == NULL) {
3022 if (ticket_str == NULL) {
3026 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
3029 if (ticket == NULL) {
3031 if (ticket == NULL) {
3036 rc = unpack_rsc_ticket_tags(xml_obj, &expanded_xml, data_set);
3039 xml_obj = expanded_xml;
3041 }
else if (
rc == FALSE) {
3045 for (set = pcmk__xe_first_child(xml_obj); set != NULL;
3046 set = pcmk__xe_next(set)) {
3051 if (unpack_rsc_ticket_set(set, ticket, loss_policy, data_set) == FALSE) {
3062 if (any_sets == FALSE) {
3063 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)
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)
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.
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 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)
#define pcmk__config_err(fmt...)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
gboolean unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set)
#define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name)
int char2score(const char *score)
#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
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
#define XML_CONS_TAG_RSC_DEPEND
pe_node_t * pe_find_node(GListPtr node_list, const char *uname)
int order_id
Deprecated (will be removed in a future release)
#define XML_CONS_TAG_RSC_TICKET
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
pe_node_t * pe_find_node_id(GListPtr node_list, const char *id)
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
#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
const char * node_attribute
#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...)
#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
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
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
gboolean unpack_rsc_colocation(xmlNode *xml_obj, pe_working_set_t *data_set)
GListPtr ordering_constraints
gboolean rsc_colocation_new(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, pe_working_set_t *data_set)
const xmlChar * pcmkXmlStr
GListPtr colocation_constraints
match resource ID or LRM history ID
#define XML_ORDER_ATTR_THEN_INSTANCE
#define XML_COLOC_ATTR_NODE_ATTR
Cluster status and scheduling.
#define XML_ORDER_ATTR_KIND
int pe__add_scores(int score1, int score2)
#define crm_err(fmt, args...)
GListPtr ticket_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.
#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)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define XML_CONS_ATTR_SYMMETRICAL
#define crm_info(fmt, args...)
GHashTable * template_rsc_sets
#define XML_COLOC_ATTR_SOURCE
#define pcmk__config_warn(fmt...)
#define XML_ORDER_ATTR_FIRST_ACTION
int required_runnable_before
enum crm_ais_msg_types type
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)