10 #include <sys/param.h>
11 #include <sys/types.h>
25 #include <../lib/pengine/unpack.h>
33 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \
34 __rsc = pe_find_constraint_resource(data_set->resources, __name); \
36 crm_config_err("%s: No resource found for %s", __set, __name); \
42 const char *action_first,
const char *action_then, gboolean invert);
46 const char *discovery,
53 xmlNode *xml_obj = NULL;
54 xmlNode *lifetime = NULL;
56 for (xml_obj = __xml_first_child(xml_constraints); xml_obj != NULL;
57 xml_obj = __xml_next_element(xml_obj)) {
59 const char *tag = crm_element_name(xml_obj);
66 crm_trace(
"Processing constraint %s %s", tag,
id);
70 crm_config_warn(
"Support for the lifetime tag, used by %s, is deprecated."
71 " The rules it contains should instead be direct descendents of the constraint object",
76 crm_info(
"Constraint %s %s is not active", tag,
id);
91 pe_err(
"Unsupported constraint type: %s", tag);
99 invert_action(
const char *action)
130 get_ordering_type(xmlNode * xml_obj)
148 "Support for 'score' in rsc_order is deprecated "
149 "and will be removed in a future release (use 'kind' instead)");
170 pe_find_constraint_resource(
GListPtr rsc_list,
const char *
id)
174 for (rIter = rsc_list;
id && rIter; rIter = rIter->next) {
199 NULL, (gpointer*) tag);
202 rc = g_hash_table_lookup_extended(data_set->
tags,
id,
203 NULL, (gpointer*) tag);
209 }
else if (*tag == NULL) {
214 }
else if (*tag == NULL) {
230 *rsc = pe_find_constraint_resource(data_set->
resources,
id);
238 rc = pe_find_constraint_tag(data_set,
id, tag);
245 order_is_symmetrical(xmlNode * xml_obj,
246 enum pe_order_kind parent_kind,
const char * parent_symmetrical_s)
254 if (kind_s || score_s) {
255 kind = get_ordering_type(xml_obj);
258 if (symmetrical_s == NULL) {
259 symmetrical_s = parent_symmetrical_s;
267 " Ignoring symmetrical=\"%s\"",
290 gboolean invert_bool = TRUE;
291 int min_required_before = 0;
295 const char *id_first = NULL;
296 const char *id_then = NULL;
297 const char *action_then = NULL;
298 const char *action_first = NULL;
299 const char *instance_then = NULL;
300 const char *instance_first = NULL;
302 const char *
id = NULL;
304 if (xml_obj == NULL) {
311 crm_config_err(
"%s constraint must have an id", crm_element_name(xml_obj));
315 invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
326 if (action_first == NULL) {
329 if (action_then == NULL) {
330 action_then = action_first;
333 if (id_then == NULL || id_first == NULL) {
339 rsc_then = pe_find_constraint_resource(data_set->
resources, id_then);
340 rsc_first = pe_find_constraint_resource(data_set->
resources, id_first);
342 if (rsc_then == NULL) {
343 crm_config_err(
"Constraint %s: no resource found for name '%s'",
id, id_then);
346 }
else if (rsc_first == NULL) {
347 crm_config_err(
"Constraint %s: no resource found for name '%s'",
id, id_first);
350 }
else if (instance_then && pe_rsc_is_clone(rsc_then) == FALSE) {
352 " Resource '%s' is not a clone but instance %s was requested",
353 id, id_then, instance_then);
356 }
else if (instance_first && pe_rsc_is_clone(rsc_first) == FALSE) {
358 " Resource '%s' is not a clone but instance %s was requested",
359 id, id_first, instance_first);
365 if (rsc_then == NULL) {
366 crm_config_warn(
"Invalid constraint '%s': No instance '%s' of '%s'",
id, instance_then,
372 if (instance_first) {
374 if (rsc_first == NULL) {
375 crm_config_warn(
"Invalid constraint '%s': No instance '%s' of '%s'",
id, instance_first,
382 kind = get_ordering_type(xml_obj);
385 crm_trace(
"Upgrade : recovery - implies right");
389 if (invert_bool == FALSE) {
392 cons_weight |=
get_flags(
id, kind, action_first, action_then, FALSE);
395 if (pe_rsc_is_clone(rsc_first)) {
399 const char *min_clones_s = g_hash_table_lookup(rsc_first->
meta,
408 }
else if (require_all_s) {
410 "Support for require-all in ordering constraints "
411 "is deprecated and will be removed in a future release"
412 " (use clone-min clone meta-attribute instead)");
415 min_required_before = 1;
423 if (min_required_before) {
435 for (rIter = rsc_first->
children;
id && rIter; rIter = rIter->next) {
439 NULL, NULL, unordered_action,
449 order_id =
new_rsc_order(rsc_first, action_first, rsc_then, action_then, cons_weight, data_set);
452 pe_rsc_trace(rsc_first,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
453 order_id,
id, rsc_first->
id, action_first, rsc_then->
id, action_then, cons_weight);
455 if (invert_bool == FALSE) {
459 action_then = invert_action(action_then);
460 action_first = invert_action(action_first);
461 if (action_then == NULL || action_first == NULL) {
463 " Please specify the inverse manually.",
id);
469 crm_trace(
"Upgrade : recovery - implies left");
473 cons_weight |=
get_flags(
id, kind, action_first, action_then, TRUE);
475 order_id =
new_rsc_order(rsc_then, action_then, rsc_first, action_first, cons_weight, data_set);
477 pe_rsc_trace(rsc_then,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
478 order_id,
id, rsc_then->
id, action_then, rsc_first->
id, action_first, cons_weight);
484 expand_tags_in_sets(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
486 xmlNode *new_xml = NULL;
488 gboolean any_refs = FALSE;
489 const char *cons_id = NULL;
491 *expanded_xml = NULL;
493 if (xml_obj == NULL) {
499 cons_id =
ID(new_xml);
501 for (set = __xml_first_child(new_xml); set != NULL; set = __xml_next_element(set)) {
502 xmlNode *xml_rsc = NULL;
510 for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
513 const char *
id =
ID(xml_rsc);
519 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
520 crm_config_err(
"Constraint '%s': Invalid reference to '%s'", cons_id,
id);
529 xmlNode *last_ref = xml_rsc;
553 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
554 const char *obj_ref = (
const char *) gIter->data;
555 xmlNode *new_rsc_ref = NULL;
557 new_rsc_ref = xmlNewDocRawNode(
getDocPtr(set), NULL,
560 xmlAddNextSibling(last_ref, new_rsc_ref);
562 last_ref = new_rsc_ref;
571 tag_refs = g_list_append(tag_refs, xml_rsc);
585 for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
586 xmlNode *tag_ref = gIter->data;
590 g_list_free(tag_refs);
594 *expanded_xml = new_xml;
603 tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set,
const char * attr,
606 const char *cons_id = NULL;
607 const char *
id = NULL;
614 if (xml_obj == NULL) {
625 if (cons_id == NULL) {
626 crm_config_err(
"%s constraint must have an id", crm_element_name(xml_obj));
635 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
636 crm_config_err(
"Constraint '%s': Invalid reference to '%s'", cons_id,
id);
648 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
649 const char *obj_ref = (
const char *) gIter->data;
650 xmlNode *rsc_ref = NULL;
659 }
else if (rsc && convert_rsc) {
662 xmlNode *rsc_ref = NULL;
682 static gboolean unpack_rsc_location(xmlNode * xml_obj,
resource_t * rsc_lh,
const char * role,
694 return unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
699 regex_t *r_patt = calloc(1,
sizeof(regex_t));
703 if(value[0] ==
'!') {
708 if (regcomp(r_patt, value, REG_EXTENDED)) {
715 for (rIter = data_set->
resources; rIter; rIter = rIter->next) {
718 regmatch_t *pmatch = NULL;
721 if(r_patt->re_nsub > 0) {
722 nregs = r_patt->re_nsub + 1;
726 pmatch = calloc(nregs,
sizeof(regmatch_t));
728 status = regexec(r_patt, r->
id, nregs, pmatch, 0);
730 if(invert == FALSE && status == 0) {
737 .
re = &re_match_data,
741 crm_debug(
"'%s' matched '%s' for %s", r->
id, value,
id);
742 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, &match_data);
744 }
if(invert && status != 0) {
745 crm_debug(
"'%s' is an inverted match of '%s' for %s", r->
id, value,
id);
746 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, NULL);
749 crm_trace(
"'%s' does not match '%s' for %s", r->
id, value,
id);
763 unpack_rsc_location(xmlNode * xml_obj,
resource_t * rsc_lh,
const char * role,
766 gboolean empty = TRUE;
773 if (rsc_lh == NULL) {
783 if (node != NULL && score != NULL) {
790 location =
rsc2node_new(
id, rsc_lh, score_i, discovery, match, data_set);
793 xmlNode *rule_xml = NULL;
795 for (rule_xml = __xml_first_child(xml_obj); rule_xml != NULL;
796 rule_xml = __xml_next_element(rule_xml)) {
800 generate_location_rule(rsc_lh, rule_xml, discovery, data_set, match_data);
806 " rsc_location must contain at least one rule",
ID(xml_obj));
814 if (location && role) {
816 pe_err(
"Invalid constraint %s: Bad role %s",
id, role);
839 unpack_location_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
841 const char *
id = NULL;
842 const char *id_lh = NULL;
843 const char *state_lh = NULL;
847 tag_t *tag_lh = NULL;
849 xmlNode *new_xml = NULL;
850 xmlNode *rsc_set_lh = NULL;
852 *expanded_xml = NULL;
854 if (xml_obj == NULL) {
861 crm_config_err(
"%s constraint must have an id", crm_element_name(xml_obj));
866 expand_tags_in_sets(xml_obj, &new_xml, data_set);
870 *expanded_xml = new_xml;
879 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
880 crm_config_err(
"Constraint '%s': Invalid reference to '%s'",
id, id_lh);
906 *expanded_xml = new_xml;
917 unpack_location_set(xmlNode * location, xmlNode * set,
pe_working_set_t * data_set)
919 xmlNode *xml_rsc = NULL;
923 const char *local_score;
931 if (set_id == NULL) {
939 for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
942 unpack_rsc_location(location, resource, role, local_score, data_set, NULL);
953 gboolean any_sets = FALSE;
955 xmlNode *orig_xml = NULL;
956 xmlNode *expanded_xml = NULL;
958 if (unpack_location_tags(xml_obj, &expanded_xml, data_set) == FALSE) {
964 xml_obj = expanded_xml;
967 for (set = __xml_first_child(xml_obj); set != NULL; set = __xml_next_element(set)) {
971 if (unpack_location_set(xml_obj, set, data_set) == FALSE) {
985 if (any_sets == FALSE) {
986 return unpack_simple_location(xml_obj, data_set);
993 get_node_score(
const char *rule,
const char *score, gboolean raw,
node_t * node,
resource_t *rsc)
998 pe_err(
"Rule %s: no score specified. Assuming 0.", rule);
1006 if (attr_score == NULL) {
1007 crm_debug(
"Rule %s: node %s did not have a value for %s",
1012 crm_debug(
"Rule %s: node %s had value %s for %s",
1021 generate_location_rule(
pe_resource_t *rsc, xmlNode *rule_xml,
1025 const char *rule_id = NULL;
1026 const char *score = NULL;
1027 const char *
boolean = NULL;
1028 const char *role = NULL;
1033 gboolean do_and = TRUE;
1034 gboolean accept = TRUE;
1035 gboolean raw_score = TRUE;
1036 gboolean score_allocated = FALSE;
1045 crm_trace(
"Processing rule: %s", rule_id);
1048 pe_err(
"Bad role specified for %s: %s", rule_id, role);
1053 if (score == NULL) {
1055 if (score != NULL) {
1063 location_rule =
rsc2node_new(rule_id, rsc, 0, discovery, NULL, data_set);
1065 if (location_rule == NULL) {
1069 if (match_data && match_data->
re && match_data->
re->
nregs > 0 && match_data->
re->
pmatch[0].rm_so != -1) {
1070 if (raw_score == FALSE) {
1074 score = (
const char *) result;
1075 score_allocated = TRUE;
1081 crm_trace(
"Setting role filter: %s", role);
1094 for (gIter = match_L; gIter != NULL; gIter = gIter->next) {
1097 node->
weight = get_node_score(rule_id, score, raw_score, node, rsc);
1101 for (gIter = data_set->
nodes; gIter != NULL; gIter = gIter->next) {
1107 crm_trace(
"Rule %s %s on %s",
ID(rule_xml), accept ?
"passed" :
"failed",
1110 score_f = get_node_score(rule_id, score, raw_score, node, rsc);
1118 if (local == NULL && do_and) {
1121 }
else if (local == NULL) {
1123 match_L = g_list_append(match_L, local);
1126 if (do_and == FALSE) {
1131 }
else if (do_and && !accept) {
1135 if (
delete != NULL) {
1136 match_L = g_list_remove(match_L,
delete);
1143 if (score_allocated == TRUE) {
1144 free((
char *)score);
1149 crm_trace(
"No matching nodes for rule %s", rule_id);
1154 return location_rule;
1158 sort_cons_priority_lh(gconstpointer a, gconstpointer b)
1206 sort_cons_priority_rh(gconstpointer a, gconstpointer b)
1254 anti_colocation_order(
resource_t * first_rsc,
int first_role,
1258 const char *first_tasks[] = { NULL, NULL };
1259 const char *then_tasks[] = { NULL, NULL };
1287 for (first_lpc = 0; first_lpc <= 1 && first_tasks[first_lpc] != NULL; first_lpc++) {
1288 for (then_lpc = 0; then_lpc <= 1 && then_tasks[then_lpc] != NULL; then_lpc++) {
1289 new_rsc_order(first_rsc, first_tasks[first_lpc], then_rsc, then_tasks[then_lpc],
1302 if (rsc_lh == NULL) {
1306 }
else if (rsc_rh == NULL) {
1312 if (new_con == NULL) {
1325 new_con->
rsc_lh = rsc_lh;
1326 new_con->
rsc_rh = rsc_rh;
1327 new_con->
score = score;
1332 if (node_attr == NULL) {
1336 pe_rsc_trace(rsc_lh,
"%s ==> %s (%s %d)", rsc_lh->
id, rsc_rh->
id, node_attr, score);
1338 rsc_lh->
rsc_cons = g_list_insert_sorted(rsc_lh->
rsc_cons, new_con, sort_cons_priority_rh);
1341 g_list_insert_sorted(rsc_rh->
rsc_cons_lhs, new_con, sort_cons_priority_lh);
1346 anti_colocation_order(rsc_lh, new_con->
role_lh, rsc_rh, new_con->
role_rh, data_set);
1347 anti_colocation_order(rsc_rh, new_con->
role_rh, rsc_lh, new_con->
role_lh, data_set);
1359 char *lh_key = NULL;
1360 char *rh_key = NULL;
1371 if (validate_order_resources(lh_rsc, lh_task, rh_rsc, rh_task)) {
1383 task_from_action_or_key(
action_t *action,
const char *key)
1388 res = strdup(action->
task);
1402 char *lh_task = NULL;
1403 char *rh_task = NULL;
1404 gboolean rh_migratable;
1405 gboolean lh_migratable;
1424 if (lh_migratable == FALSE && rh_migratable == FALSE) {
1434 if (lh_task == NULL || rh_task == NULL) {
1441 if (lh_migratable && rh_migratable) {
1449 if (rh_migratable) {
1450 if (lh_migratable) {
1464 if (lh_migratable) {
1486 if (rh_migratable) {
1497 if (rh_migratable) {
1527 if (lh_rsc == NULL && lh_action) {
1528 lh_rsc = lh_action->
rsc;
1530 if (rh_rsc == NULL && rh_action) {
1531 rh_rsc = rh_action->
rsc;
1534 if ((lh_action == NULL && lh_rsc == NULL)
1535 || (rh_action == NULL && rh_rsc == NULL)) {
1536 crm_config_err(
"Invalid inputs %p.%p %p.%p", lh_rsc, lh_action, rh_rsc, rh_action);
1537 free(lh_action_task);
1538 free(rh_action_task);
1545 lh_rsc?lh_rsc->
id:
"NA", lh_action_task, lh_action?lh_action->
uuid:
"NA",
1546 rh_rsc?rh_rsc->
id:
"NA", rh_action_task, rh_action?rh_action->
uuid:
"NA");
1567 if (order->
lh_rsc == NULL && lh_action) {
1571 if (order->
rh_rsc == NULL && rh_action) {
1576 handle_migration_ordering(order, data_set);
1596 const char *action_first,
const char *action_then, gboolean invert)
1601 crm_trace(
"Upgrade %s: implies left",
id);
1605 crm_trace(
"Upgrade %s: implies right",
id);
1625 xmlNode *xml_rsc = NULL;
1632 int local_kind = parent_kind;
1633 gboolean sequential = FALSE;
1635 gboolean symmetrical = TRUE;
1638 const char *
id =
ID(set);
1649 if (action == NULL) {
1654 local_kind = get_ordering_type(set);
1656 if (sequential_s == NULL) {
1662 symmetrical = order_is_symmetrical(set, parent_kind, parent_symmetrical_s);
1664 flags =
get_flags(
id, local_kind, action, action, FALSE);
1669 for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1672 resources = g_list_append(resources, resource);
1676 if (g_list_length(resources) == 1) {
1702 set_iter = resources;
1703 while (set_iter != NULL) {
1705 set_iter = set_iter->next;
1722 for (gIter = set_iter; gIter != NULL; gIter = gIter->next) {
1730 }
else if (sequential) {
1732 new_rsc_order(last, action, resource, action, flags, data_set);
1739 if (symmetrical == FALSE) {
1744 action = invert_action(action);
1759 flags =
get_flags(
id, local_kind, action, action, TRUE);
1761 set_iter = resources;
1762 while (set_iter != NULL) {
1764 set_iter = set_iter->next;
1778 new_rsc_order(resource, action, last, action, flags, data_set);
1785 g_list_free(resources);
1790 order_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
enum pe_order_kind kind,
1794 xmlNode *xml_rsc = NULL;
1795 xmlNode *xml_rsc_2 = NULL;
1807 gboolean require_all = require_all_s ?
crm_is_true(require_all_s) : TRUE;
1811 if (action_1 == NULL) {
1815 if (action_2 == NULL) {
1820 action_1 = invert_action(action_1);
1821 action_2 = invert_action(action_2);
1832 if (symmetrical == FALSE) {
1835 flags =
get_flags(
id, kind, action_2, action_1, invert);
1846 for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1856 NULL, NULL, unordered_action,
1859 for (xml_rsc_2 = __xml_first_child(set2); xml_rsc_2 != NULL; xml_rsc_2 = __xml_next_element(xml_rsc_2)) {
1877 if (invert == FALSE) {
1879 const char *rid = NULL;
1881 for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1890 for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1900 if (invert == FALSE) {
1902 for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1911 const char *rid = NULL;
1913 for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1922 if (rsc_1 != NULL && rsc_2 != NULL) {
1923 new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set);
1925 }
else if (rsc_1 != NULL) {
1926 for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1929 new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set);
1933 }
else if (rsc_2 != NULL) {
1934 xmlNode *xml_rsc = NULL;
1936 for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1939 new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set);
1944 for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
1946 xmlNode *xml_rsc_2 = NULL;
1950 for (xml_rsc_2 = __xml_first_child(set2); xml_rsc_2 != NULL;
1951 xml_rsc_2 = __xml_next_element(xml_rsc_2)) {
1954 new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set);
1965 unpack_order_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
1967 const char *
id = NULL;
1968 const char *id_first = NULL;
1969 const char *id_then = NULL;
1970 const char *action_first = NULL;
1971 const char *action_then = NULL;
1975 tag_t *tag_first = NULL;
1976 tag_t *tag_then = NULL;
1978 xmlNode *new_xml = NULL;
1979 xmlNode *rsc_set_first = NULL;
1980 xmlNode *rsc_set_then = NULL;
1981 gboolean any_sets = FALSE;
1983 *expanded_xml = NULL;
1985 if (xml_obj == NULL) {
1992 crm_config_err(
"%s constraint must have an id", crm_element_name(xml_obj));
1997 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2001 *expanded_xml = new_xml;
2007 if (id_first == NULL || id_then == NULL) {
2011 if (valid_resource_or_tag(data_set, id_first, &rsc_first, &tag_first) == FALSE) {
2012 crm_config_err(
"Constraint '%s': Invalid reference to '%s'",
id, id_first);
2016 if (valid_resource_or_tag(data_set, id_then, &rsc_then, &tag_then) == FALSE) {
2017 crm_config_err(
"Constraint '%s': Invalid reference to '%s'",
id, id_then);
2021 if (rsc_first && rsc_then) {
2037 if (rsc_set_first) {
2041 crm_xml_add(rsc_set_first,
"action", action_first);
2065 *expanded_xml = new_xml;
2076 gboolean any_sets = FALSE;
2090 xmlNode *set = NULL;
2091 xmlNode *last = NULL;
2093 xmlNode *orig_xml = NULL;
2094 xmlNode *expanded_xml = NULL;
2107 gboolean invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
2110 rc = unpack_order_tags(xml_obj, &expanded_xml, data_set);
2113 xml_obj = expanded_xml;
2115 }
else if (rc == FALSE) {
2119 for (set = __xml_first_child(xml_obj); set != NULL; set = __xml_next_element(set)) {
2123 if (unpack_order_set(set, kind, &rsc, &set_begin, &set_end,
2124 &set_inv_begin, &set_inv_end, invert, data_set) == FALSE) {
2165 if (order_rsc_sets(
id, last, set, kind, data_set, FALSE, invert_bool) == FALSE) {
2170 && order_rsc_sets(
id, set, last, kind, data_set, TRUE, invert_bool) == FALSE) {
2191 if (any_sets == FALSE) {
2192 return unpack_simple_rsc_order(xml_obj, data_set);
2199 unpack_colocation_set(xmlNode * set,
int score,
pe_working_set_t * data_set)
2201 xmlNode *xml_rsc = NULL;
2204 const char *set_id =
ID(set);
2208 int local_score = score;
2216 if(ordering == NULL) {
2220 if (sequential != NULL &&
crm_is_true(sequential) == FALSE) {
2223 }
else if (local_score >= 0 &&
safe_str_eq(ordering,
"group")) {
2224 for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
2236 }
else if (local_score >= 0) {
2238 for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
2257 for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
2259 xmlNode *xml_rsc_with = NULL;
2263 for (xml_rsc_with = __xml_first_child(set); xml_rsc_with != NULL;
2264 xml_rsc_with = __xml_next_element(xml_rsc_with)) {
2270 pe_rsc_trace(resource,
"Anti-Colocating %s with %s", resource->
id,
2284 colocate_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
int score,
2287 xmlNode *xml_rsc = NULL;
2297 if (sequential_1 == NULL ||
crm_is_true(sequential_1)) {
2299 for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
2307 if (sequential_2 == NULL ||
crm_is_true(sequential_2)) {
2309 const char *rid = NULL;
2311 for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
2319 if (rsc_1 != NULL && rsc_2 != NULL) {
2322 }
else if (rsc_1 != NULL) {
2323 for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
2330 }
else if (rsc_2 != NULL) {
2331 for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
2339 for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
2341 xmlNode *xml_rsc_2 = NULL;
2345 for (xml_rsc_2 = __xml_first_child(set2); xml_rsc_2 != NULL;
2346 xml_rsc_2 = __xml_next_element(xml_rsc_2)) {
2381 if (rsc_lh == NULL) {
2382 crm_config_err(
"Invalid constraint '%s': No resource named '%s'",
id, id_lh);
2385 }
else if (rsc_rh == NULL) {
2386 crm_config_err(
"Invalid constraint '%s': No resource named '%s'",
id, id_rh);
2389 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2391 (
"Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested",
2392 id, id_lh, instance_lh);
2395 }
else if (instance_rh && pe_rsc_is_clone(rsc_rh) == FALSE) {
2397 (
"Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested",
2398 id, id_rh, instance_rh);
2404 if (rsc_lh == NULL) {
2405 crm_config_warn(
"Invalid constraint '%s': No instance '%s' of '%s'",
id, instance_lh,
2413 if (rsc_rh == NULL) {
2414 crm_config_warn(
"Invalid constraint '%s': No instance '%s' of '%s'",
id, instance_rh,
2421 crm_config_warn(
"The %s colocation constraint attribute has been removed."
2434 unpack_colocation_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2436 const char *
id = NULL;
2437 const char *id_lh = NULL;
2438 const char *id_rh = NULL;
2439 const char *state_lh = NULL;
2440 const char *state_rh = NULL;
2445 tag_t *tag_lh = NULL;
2446 tag_t *tag_rh = NULL;
2448 xmlNode *new_xml = NULL;
2449 xmlNode *rsc_set_lh = NULL;
2450 xmlNode *rsc_set_rh = NULL;
2451 gboolean any_sets = FALSE;
2453 *expanded_xml = NULL;
2455 if (xml_obj == NULL) {
2462 crm_config_err(
"%s constraint must have an id", crm_element_name(xml_obj));
2467 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2471 *expanded_xml = new_xml;
2477 if (id_lh == NULL || id_rh == NULL) {
2481 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
2482 crm_config_err(
"Constraint '%s': Invalid reference to '%s'",
id, id_lh);
2486 if (valid_resource_or_tag(data_set, id_rh, &rsc_rh, &tag_rh) == FALSE) {
2487 crm_config_err(
"Constraint '%s': Invalid reference to '%s'",
id, id_rh);
2491 if (rsc_lh && rsc_rh) {
2496 if (tag_lh && tag_rh) {
2498 crm_config_err(
"Either LHS or RHS of %s should be a normal resource instead of a template/tag",
2542 *expanded_xml = new_xml;
2554 xmlNode *set = NULL;
2555 xmlNode *last = NULL;
2556 gboolean any_sets = FALSE;
2558 xmlNode *orig_xml = NULL;
2559 xmlNode *expanded_xml = NULL;
2570 rc = unpack_colocation_tags(xml_obj, &expanded_xml, data_set);
2573 xml_obj = expanded_xml;
2575 }
else if (rc == FALSE) {
2579 for (set = __xml_first_child(xml_obj); set != NULL; set = __xml_next_element(set)) {
2583 if (unpack_colocation_set(set, score_i, data_set) == FALSE) {
2586 }
else if (last && colocate_rsc_sets(
id, last, set, score_i, data_set) == FALSE) {
2598 if (any_sets == FALSE) {
2599 return unpack_simple_colocation(xml_obj, data_set);
2607 const char *state_lh,
const char *loss_policy,
pe_working_set_t * data_set)
2611 if (rsc_lh == NULL) {
2617 if (new_rsc_ticket == NULL) {
2625 new_rsc_ticket->
id =
id;
2626 new_rsc_ticket->
ticket = ticket;
2627 new_rsc_ticket->
rsc_lh = rsc_lh;
2634 crm_config_err(
"Resetting %s loss-policy to 'stop': fencing is not configured",
2636 loss_policy =
"stop";
2641 crm_debug(
"On loss of ticket '%s': Fence the nodes running %s (%s)",
2646 crm_debug(
"On loss of ticket '%s': Freeze %s (%s)",
2652 crm_debug(
"On loss of ticket '%s': Demote %s (%s)",
2658 crm_debug(
"On loss of ticket '%s': Stop %s (%s)",
2665 crm_debug(
"On loss of ticket '%s': Default to demote %s (%s)",
2671 crm_debug(
"On loss of ticket '%s': Default to stop %s (%s)",
2693 unpack_rsc_ticket_set(xmlNode * set,
ticket_t * ticket,
const char *loss_policy,
2696 xmlNode *xml_rsc = NULL;
2698 const char *set_id = NULL;
2699 const char *role = NULL;
2702 CRM_CHECK(ticket != NULL,
return FALSE);
2705 if (set_id == NULL) {
2716 pe_rsc_trace(resource,
"Resource '%s' depends on ticket '%s'",
2717 resource->
id, ticket->
id);
2718 rsc_ticket_new(set_id, resource, ticket, role, loss_policy, data_set);
2741 if (xml_obj == NULL) {
2747 crm_config_err(
"%s constraint must have an id", crm_element_name(xml_obj));
2751 if (ticket_str == NULL) {
2752 crm_config_err(
"Invalid constraint '%s': No ticket specified",
id);
2755 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
2758 if (ticket == NULL) {
2759 crm_config_err(
"Invalid constraint '%s': No ticket named '%s'",
id, ticket_str);
2763 if (id_lh == NULL) {
2764 crm_config_err(
"Invalid constraint '%s': No resource specified",
id);
2767 rsc_lh = pe_find_constraint_resource(data_set->
resources, id_lh);
2770 if (rsc_lh == NULL) {
2771 crm_config_err(
"Invalid constraint '%s': No resource named '%s'",
id, id_lh);
2774 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2776 (
"Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested",
2777 id, id_lh, instance_lh);
2783 if (rsc_lh == NULL) {
2784 crm_config_warn(
"Invalid constraint '%s': No instance '%s' of '%s'",
id, instance_lh,
2790 rsc_ticket_new(
id, rsc_lh, ticket, state_lh, loss_policy, data_set);
2795 unpack_rsc_ticket_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2797 const char *
id = NULL;
2798 const char *id_lh = NULL;
2799 const char *state_lh = NULL;
2802 tag_t *tag_lh = NULL;
2804 xmlNode *new_xml = NULL;
2805 xmlNode *rsc_set_lh = NULL;
2806 gboolean any_sets = FALSE;
2808 *expanded_xml = NULL;
2810 if (xml_obj == NULL) {
2817 crm_config_err(
"%s constraint must have an id", crm_element_name(xml_obj));
2822 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2826 *expanded_xml = new_xml;
2831 if (id_lh == NULL) {
2835 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
2836 crm_config_err(
"Constraint '%s': Invalid reference to '%s'",
id, id_lh);
2839 }
else if (rsc_lh) {
2866 *expanded_xml = new_xml;
2877 xmlNode *set = NULL;
2878 gboolean any_sets = FALSE;
2886 xmlNode *orig_xml = NULL;
2887 xmlNode *expanded_xml = NULL;
2891 if (xml_obj == NULL) {
2897 crm_config_err(
"%s constraint must have an id", crm_element_name(xml_obj));
2901 if (data_set->
tickets == NULL) {
2906 if (ticket_str == NULL) {
2907 crm_config_err(
"Invalid constraint '%s': No ticket specified",
id);
2910 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
2913 if (ticket == NULL) {
2915 if (ticket == NULL) {
2920 rc = unpack_rsc_ticket_tags(xml_obj, &expanded_xml, data_set);
2923 xml_obj = expanded_xml;
2925 }
else if (rc == FALSE) {
2929 for (set = __xml_first_child(xml_obj); set != NULL; set = __xml_next_element(set)) {
2933 if (unpack_rsc_ticket_set(set, ticket, loss_policy, data_set) == FALSE) {
2944 if (any_sets == FALSE) {
2945 return unpack_simple_rsc_ticket(xml_obj, data_set);
#define CRM_CHECK(expr, failure_action)
enum rsc_role_e role_filter
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
gboolean safe_str_neq(const char *a, const char *b)
#define XML_ORDER_ATTR_THEN_ACTION
gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc)
gboolean is_active(pe__location_t *cons)
node_t * node_copy(const node_t *this_node)
GListPtr node_list_dup(GListPtr list, gboolean reset, gboolean filter)
#define XML_ORDER_ATTR_THEN
#define XML_COLOC_ATTR_TARGET_INSTANCE
#define CRM_OP_RELAXED_SET
#define RSC_ROLE_STARTED_S
gboolean unpack_rsc_order(xmlNode *xml_obj, pe_working_set_t *data_set)
#define XML_RULE_ATTR_SCORE
gboolean unpack_rsc_ticket(xmlNode *xml_obj, pe_working_set_t *data_set)
#define XML_BOOLEAN_FALSE
#define crm_config_err(fmt...)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
#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.
#define CRMD_ACTION_PROMOTE
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
gboolean unpack_constraints(xmlNode *xml_constraints, pe_working_set_t *data_set)
#define XML_CONS_TAG_RSC_DEPEND
pe_node_t * pe_find_node(GListPtr node_list, const char *uname)
#define XML_CONS_TAG_RSC_TICKET
void rsc_ticket_constraint(resource_t *lh_rsc, rsc_ticket_t *rsc_ticket, pe_working_set_t *data_set)
pe_node_t * partial_migration_target
action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
#define XML_COLOC_ATTR_TARGET_ROLE
#define XML_ORDER_ATTR_FIRST_INSTANCE
gboolean unpack_rsc_colocation(xmlNode *xml_obj, pe_working_set_t *data_set)
#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)
gboolean rsc_colocation_new(const char *id, const char *node_attr, int score, resource_t *rsc_lh, resource_t *rsc_rh, const char *state_lh, const char *state_rh, pe_working_set_t *data_set)
#define XML_ORDER_ATTR_FIRST
#define CRMD_ACTION_DEMOTE
#define XML_COLOC_ATTR_TARGET
#define pe_rsc_allow_migrate
#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
const char * node_attribute
#define XML_CONS_TAG_RSC_LOCATION
gboolean pe_test_rule_full(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_match_data_t *match_data)
pe_resource_t *(* find_rsc)(pe_resource_t *parent, const char *search, const pe_node_t *node, int flags)
#define crm_trace(fmt, args...)
struct pe_node_shared_s * details
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
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)
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
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
#define XML_COLOC_ATTR_SOURCE_ROLE
#define XML_RULE_ATTR_BOOLEAN_OP
GListPtr ordering_constraints
const xmlChar * pcmkXmlStr
GListPtr colocation_constraints
#define crm_config_warn(fmt...)
match resource ID or LRM history ID
#define XML_ORDER_ATTR_THEN_INSTANCE
gboolean rsc_ticket_new(const char *id, resource_t *rsc_lh, ticket_t *ticket, const char *state_lh, const char *loss_policy, pe_working_set_t *data_set)
#define XML_COLOC_ATTR_NODE_ATTR
Cluster status and scheduling.
gboolean test_ruleset(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now)
gboolean update_action_flags(action_t *action, enum pe_action_flags flags, const char *source, int line)
#define XML_ORDER_ATTR_KIND
GListPtr ticket_constraints
ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
void xml_remove_prop(xmlNode *obj, const char *name)
#define CRM_OP_RELAXED_CLONE
int merge_weights(int w1, int w2)
#define XML_CONS_TAG_RSC_ORDER
void destroy_ticket(gpointer data)
#define RSC_ROLE_UNKNOWN_S
int custom_action_order(resource_t *lh_rsc, char *lh_task, action_t *lh_action, resource_t *rh_rsc, char *rh_task, action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set)
#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 safe_str_eq(a, b)
resource_t * find_clone_instance(resource_t *rsc, const char *sub_id, pe_working_set_t *data_set)
#define XML_CONS_ATTR_SYMMETRICAL
#define crm_info(fmt, args...)
gboolean unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set)
char * generate_op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key.
GHashTable * template_rsc_sets
#define XML_COLOC_ATTR_SOURCE
#define XML_ORDER_ATTR_FIRST_ACTION
int required_runnable_before
enum crm_ais_msg_types type
#define pe_warn_once(pe_wo_bit, fmt...)
int new_rsc_order(resource_t *lh_rsc, const char *lh_task, resource_t *rh_rsc, const char *rh_task, enum pe_ordering type, pe_working_set_t *data_set)
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
const char * pe_node_attribute_calculated(const pe_node_t *node, const char *name, const resource_t *rsc)