12 #include <sys/param.h>
13 #include <sys/types.h>
33 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \
34 __rsc = pe_find_constraint_resource(data_set->resources, __name); \
36 pcmk__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,
70 xmlNode *xml_obj = NULL;
71 xmlNode *lifetime = NULL;
73 for (xml_obj = __xml_first_child_element(xml_constraints); xml_obj != NULL;
74 xml_obj = __xml_next_element(xml_obj)) {
76 const char *tag = crm_element_name(xml_obj);
84 crm_trace(
"Processing constraint %s %s", tag,
id);
89 "deprecated (the rules it contains should "
90 "instead be direct descendents of the "
91 "constraint object)",
id);
94 if (lifetime && !evaluate_lifetime(lifetime, data_set)) {
95 crm_info(
"Constraint %s %s is not active", tag,
id);
110 pe_err(
"Unsupported constraint type: %s", tag);
118 invert_action(
const char *
action)
144 crm_warn(
"Unknown action '%s' specified in order constraint",
action);
149 get_ordering_type(xmlNode * xml_obj)
167 "Support for 'score' in rsc_order is deprecated "
168 "and will be removed in a future release (use 'kind' instead)");
182 "'%s' to Mandatory because '%s' is not valid",
189 pe_find_constraint_resource(
GListPtr rsc_list,
const char *
id)
193 for (rIter = rsc_list;
id && rIter; rIter = rIter->next) {
218 NULL, (gpointer*) tag);
221 rc = g_hash_table_lookup_extended(data_set->
tags,
id,
222 NULL, (gpointer*) tag);
225 crm_warn(
"No template or tag named '%s'",
id);
228 }
else if (*tag == NULL) {
229 crm_warn(
"No resource is tagged with '%s'",
id);
233 }
else if (*tag == NULL) {
234 crm_warn(
"No resource is derived from template '%s'",
id);
249 *rsc = pe_find_constraint_resource(data_set->
resources,
id);
257 rc = pe_find_constraint_tag(data_set,
id, tag);
264 order_is_symmetrical(xmlNode * xml_obj,
265 enum pe_order_kind parent_kind,
const char * parent_symmetrical_s)
273 if (kind_s || score_s) {
274 kind = get_ordering_type(xml_obj);
277 if (symmetrical_s == NULL) {
278 symmetrical_s = parent_symmetrical_s;
286 " for '%s' because not valid with "
309 gboolean invert_bool = TRUE;
310 int min_required_before = 0;
314 const char *id_first = NULL;
315 const char *id_then = NULL;
316 const char *action_then = NULL;
317 const char *action_first = NULL;
318 const char *instance_then = NULL;
319 const char *instance_first = NULL;
321 const char *
id = NULL;
323 CRM_CHECK(xml_obj != NULL,
return FALSE);
328 crm_element_name(xml_obj));
332 invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
343 if (action_first == NULL) {
346 if (action_then == NULL) {
347 action_then = action_first;
350 if (id_first == NULL) {
355 if (id_then == NULL) {
361 rsc_then = pe_find_constraint_resource(data_set->
resources, id_then);
362 rsc_first = pe_find_constraint_resource(data_set->
resources, id_first);
364 if (rsc_then == NULL) {
366 "does not exist",
id, id_then);
369 }
else if (rsc_first == NULL) {
371 "does not exist",
id, id_first);
374 }
else if (instance_then && pe_rsc_is_clone(rsc_then) == FALSE) {
376 "is not a clone but instance '%s' was requested",
377 id, id_then, instance_then);
380 }
else if (instance_first && pe_rsc_is_clone(rsc_first) == FALSE) {
382 "is not a clone but instance '%s' was requested",
383 id, id_first, instance_first);
389 if (rsc_then == NULL) {
391 "does not have an instance '%s'",
392 id, id_then, instance_then);
397 if (instance_first) {
399 if (rsc_first == NULL) {
401 "does not have an instance '%s'",
402 "'%s'",
id, id_first, instance_first);
408 kind = get_ordering_type(xml_obj);
411 crm_trace(
"Upgrade : recovery - implies right");
415 if (invert_bool == FALSE) {
418 cons_weight |=
get_flags(
id, kind, action_first, action_then, FALSE);
421 if (pe_rsc_is_clone(rsc_first)) {
425 const char *min_clones_s = g_hash_table_lookup(rsc_first->
meta,
434 }
else if (require_all_s) {
436 "Support for require-all in ordering constraints "
437 "is deprecated and will be removed in a future release"
438 " (use clone-min clone meta-attribute instead)");
441 min_required_before = 1;
449 if (min_required_before) {
461 for (rIter = rsc_first->
children;
id && rIter; rIter = rIter->next) {
465 NULL, NULL, NULL, unordered_action,
477 order_id =
new_rsc_order(rsc_first, action_first, rsc_then, action_then, cons_weight, data_set);
480 pe_rsc_trace(rsc_first,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
481 order_id,
id, rsc_first->
id, action_first, rsc_then->
id, action_then, cons_weight);
483 if (invert_bool == FALSE) {
487 action_then = invert_action(action_then);
488 action_first = invert_action(action_first);
489 if (action_then == NULL || action_first == NULL) {
491 "(please specify inverse manually)",
id);
497 crm_trace(
"Upgrade : recovery - implies left");
501 cons_weight |=
get_flags(
id, kind, action_first, action_then, TRUE);
503 order_id =
new_rsc_order(rsc_then, action_then, rsc_first, action_first, cons_weight, data_set);
505 pe_rsc_trace(rsc_then,
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
506 order_id,
id, rsc_then->
id, action_then, rsc_first->
id, action_first, cons_weight);
512 expand_tags_in_sets(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
514 xmlNode *new_xml = NULL;
516 gboolean any_refs = FALSE;
517 const char *cons_id = NULL;
519 *expanded_xml = NULL;
521 CRM_CHECK(xml_obj != NULL,
return FALSE);
524 cons_id =
ID(new_xml);
526 for (set = __xml_first_child_element(new_xml); set != NULL;
527 set = __xml_next_element(set)) {
529 xmlNode *xml_rsc = NULL;
537 for (xml_rsc = __xml_first_child_element(set); xml_rsc != NULL;
538 xml_rsc = __xml_next_element(xml_rsc)) {
542 const char *
id =
ID(xml_rsc);
548 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
550 "because '%s' is not a valid resource or tag",
560 xmlNode *last_ref = xml_rsc;
584 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
585 const char *obj_ref = (
const char *) gIter->data;
586 xmlNode *new_rsc_ref = NULL;
588 new_rsc_ref = xmlNewDocRawNode(
getDocPtr(set), NULL,
591 xmlAddNextSibling(last_ref, new_rsc_ref);
593 last_ref = new_rsc_ref;
602 tag_refs = g_list_append(tag_refs, xml_rsc);
616 for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
617 xmlNode *tag_ref = gIter->data;
621 g_list_free(tag_refs);
625 *expanded_xml = new_xml;
634 tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set,
const char * attr,
637 const char *cons_id = NULL;
638 const char *
id = NULL;
645 CRM_CHECK((xml_obj != NULL) && (attr != NULL),
return FALSE);
647 cons_id =
ID(xml_obj);
648 if (cons_id == NULL) {
650 crm_element_name(xml_obj));
659 if (valid_resource_or_tag(data_set,
id, &rsc, &tag) == FALSE) {
661 "valid resource or tag", cons_id,
id);
673 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
674 const char *obj_ref = (
const char *) gIter->data;
675 xmlNode *rsc_ref = NULL;
684 }
else if (rsc && convert_rsc) {
687 xmlNode *rsc_ref = NULL;
707 static gboolean unpack_rsc_location(xmlNode * xml_obj,
pe_resource_t * rsc_lh,
const char * role,
719 return unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
724 regex_t *r_patt = calloc(1,
sizeof(regex_t));
728 if(value[0] ==
'!') {
733 if (regcomp(r_patt, value, REG_EXTENDED)) {
736 " has invalid value '%s'",
id, value);
742 for (rIter = data_set->
resources; rIter; rIter = rIter->next) {
745 regmatch_t *pmatch = NULL;
748 if(r_patt->re_nsub > 0) {
749 nregs = r_patt->re_nsub + 1;
753 pmatch = calloc(nregs,
sizeof(regmatch_t));
755 status = regexec(r_patt, r->
id, nregs, pmatch, 0);
757 if(invert == FALSE && status == 0) {
764 .
re = &re_match_data,
768 crm_debug(
"'%s' matched '%s' for %s", r->
id, value,
id);
769 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, &match_data);
771 }
else if (invert && (status != 0)) {
772 crm_debug(
"'%s' is an inverted match of '%s' for %s", r->
id, value,
id);
773 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, NULL);
776 crm_trace(
"'%s' does not match '%s' for %s", r->
id, value,
id);
790 unpack_rsc_location(xmlNode * xml_obj,
pe_resource_t * rsc_lh,
const char * role,
799 if (rsc_lh == NULL) {
801 "does not exist",
id, id_lh);
809 if (node != NULL && score != NULL) {
816 location =
rsc2node_new(
id, rsc_lh, score_i, discovery, match, data_set);
830 generate_location_rule(rsc_lh, rule_xml, discovery, next_change,
831 data_set, match_data);
855 if (location && role) {
857 pe_err(
"Invalid constraint %s: Bad role %s",
id, role);
880 unpack_location_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
882 const char *
id = NULL;
883 const char *id_lh = NULL;
884 const char *state_lh = NULL;
890 xmlNode *new_xml = NULL;
891 xmlNode *rsc_set_lh = NULL;
893 *expanded_xml = NULL;
895 CRM_CHECK(xml_obj != NULL,
return FALSE);
900 crm_element_name(xml_obj));
905 expand_tags_in_sets(xml_obj, &new_xml, data_set);
909 *expanded_xml = new_xml;
918 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
920 "valid resource or tag",
id, id_lh);
946 *expanded_xml = new_xml;
957 unpack_location_set(xmlNode * location, xmlNode * set,
pe_working_set_t * data_set)
959 xmlNode *xml_rsc = NULL;
963 const char *local_score;
968 if (set_id == NULL) {
978 for (xml_rsc = __xml_first_child_element(set); xml_rsc != NULL;
979 xml_rsc = __xml_next_element(xml_rsc)) {
983 unpack_rsc_location(location, resource, role, local_score, data_set, NULL);
994 gboolean any_sets = FALSE;
996 xmlNode *orig_xml = NULL;
997 xmlNode *expanded_xml = NULL;
999 if (unpack_location_tags(xml_obj, &expanded_xml, data_set) == FALSE) {
1005 xml_obj = expanded_xml;
1008 for (set = __xml_first_child_element(xml_obj); set != NULL;
1009 set = __xml_next_element(set)) {
1014 if (unpack_location_set(xml_obj, set, data_set) == FALSE) {
1028 if (any_sets == FALSE) {
1029 return 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,
1068 const char *rule_id = NULL;
1069 const char *score = NULL;
1070 const char *
boolean = NULL;
1071 const char *role = NULL;
1076 gboolean do_and = TRUE;
1077 gboolean accept = TRUE;
1078 gboolean raw_score = TRUE;
1079 gboolean score_allocated = FALSE;
1088 crm_trace(
"Processing rule: %s", rule_id);
1091 pe_err(
"Bad role specified for %s: %s", rule_id, role);
1096 if (score == NULL) {
1098 if (score != NULL) {
1106 location_rule =
rsc2node_new(rule_id, rsc, 0, discovery, NULL, data_set);
1108 if (location_rule == NULL) {
1112 if (match_data && match_data->
re && match_data->
re->
nregs > 0 && match_data->
re->
pmatch[0].rm_so != -1) {
1113 if (raw_score == FALSE) {
1117 score = (
const char *) result;
1118 score_allocated = TRUE;
1124 crm_trace(
"Setting role filter: %s", role);
1137 for (gIter = match_L; gIter != NULL; gIter = gIter->next) {
1140 node->
weight = get_node_score(rule_id, score, raw_score, node, rsc);
1144 for (gIter = data_set->
nodes; gIter != NULL; gIter = gIter->next) {
1149 data_set->
now, next_change, match_data);
1151 crm_trace(
"Rule %s %s on %s",
ID(rule_xml), accept ?
"passed" :
"failed",
1154 score_f = get_node_score(rule_id, score, raw_score, node, rsc);
1162 if (
local == NULL && do_and) {
1165 }
else if (
local == NULL) {
1167 match_L = g_list_append(match_L,
local);
1170 if (do_and == FALSE) {
1175 }
else if (do_and && !accept) {
1179 if (
delete != NULL) {
1180 match_L = g_list_remove(match_L,
delete);
1187 if (score_allocated == TRUE) {
1188 free((
char *)score);
1193 crm_trace(
"No matching nodes for rule %s", rule_id);
1198 return location_rule;
1202 sort_cons_priority_lh(gconstpointer a, gconstpointer b)
1250 sort_cons_priority_rh(gconstpointer a, gconstpointer b)
1298 anti_colocation_order(
pe_resource_t * first_rsc,
int first_role,
1302 const char *first_tasks[] = { NULL, NULL };
1303 const char *then_tasks[] = { NULL, NULL };
1331 for (first_lpc = 0; first_lpc <= 1 && first_tasks[first_lpc] != NULL; first_lpc++) {
1332 for (then_lpc = 0; then_lpc <= 1 && then_tasks[then_lpc] != NULL; then_lpc++) {
1333 new_rsc_order(first_rsc, first_tasks[first_lpc], then_rsc, then_tasks[then_lpc],
1346 if ((rsc_lh == NULL) || (rsc_rh == NULL)) {
1348 "does not exist",
id);
1353 if (new_con == NULL) {
1366 new_con->
rsc_lh = rsc_lh;
1367 new_con->
rsc_rh = rsc_rh;
1368 new_con->
score = score;
1373 if (node_attr == NULL) {
1377 pe_rsc_trace(rsc_lh,
"%s ==> %s (%s %d)", rsc_lh->
id, rsc_rh->
id, node_attr, score);
1379 rsc_lh->
rsc_cons = g_list_insert_sorted(rsc_lh->
rsc_cons, new_con, sort_cons_priority_rh);
1382 g_list_insert_sorted(rsc_rh->
rsc_cons_lhs, new_con, sort_cons_priority_lh);
1387 anti_colocation_order(rsc_lh, new_con->
role_lh, rsc_rh, new_con->
role_rh, data_set);
1388 anti_colocation_order(rsc_rh, new_con->
role_rh, rsc_lh, new_con->
role_lh, data_set);
1400 char *lh_key = NULL;
1401 char *rh_key = NULL;
1412 if (validate_order_resources(lh_rsc, lh_task, rh_rsc, rh_task)) {
1429 res = strdup(
action->task);
1443 char *lh_task = NULL;
1444 char *rh_task = NULL;
1445 gboolean rh_migratable;
1446 gboolean lh_migratable;
1465 if (lh_migratable == FALSE && rh_migratable == FALSE) {
1475 if (lh_task == NULL || rh_task == NULL) {
1482 if (lh_migratable && rh_migratable) {
1489 NULL,
flags, data_set);
1492 if (rh_migratable) {
1493 if (lh_migratable) {
1503 NULL,
flags, data_set);
1509 if (lh_migratable) {
1520 NULL,
flags, data_set);
1529 NULL,
flags, data_set);
1535 if (rh_migratable) {
1542 NULL,
flags, data_set);
1548 if (rh_migratable) {
1562 NULL,
flags, data_set);
1580 if (lh_rsc == NULL && lh_action) {
1581 lh_rsc = lh_action->
rsc;
1583 if (rh_rsc == NULL && rh_action) {
1584 rh_rsc = rh_action->
rsc;
1587 if ((lh_action == NULL && lh_rsc == NULL)
1588 || (rh_action == NULL && rh_rsc == NULL)) {
1589 crm_err(
"Invalid ordering (bug?)");
1590 free(lh_action_task);
1591 free(rh_action_task);
1598 lh_rsc?lh_rsc->
id:
"NA", lh_action_task?lh_action_task:
"NA", lh_action?lh_action->
uuid:
"NA",
1599 rh_rsc?rh_rsc->
id:
"NA", rh_action_task?rh_action_task:
"NA", rh_action?rh_action->
uuid:
"NA");
1620 if (order->
lh_rsc == NULL && lh_action) {
1624 if (order->
rh_rsc == NULL && rh_action) {
1629 handle_migration_ordering(order, data_set);
1649 const char *action_first,
const char *action_then, gboolean invert)
1654 crm_trace(
"Upgrade %s: implies left",
id);
1658 crm_trace(
"Upgrade %s: implies right",
id);
1676 pe_action_t ** inv_end,
const char *parent_symmetrical_s,
1679 xmlNode *xml_rsc = NULL;
1686 int local_kind = parent_kind;
1687 gboolean sequential = FALSE;
1689 gboolean symmetrical = TRUE;
1692 const char *
id =
ID(set);
1708 local_kind = get_ordering_type(set);
1710 if (sequential_s == NULL) {
1716 symmetrical = order_is_symmetrical(set, parent_kind, parent_symmetrical_s);
1723 for (xml_rsc = __xml_first_child_element(set); xml_rsc != NULL;
1724 xml_rsc = __xml_next_element(xml_rsc)) {
1728 resources = g_list_append(resources, resource);
1732 if (pcmk__list_of_1(resources)) {
1758 set_iter = resources;
1759 while (set_iter != NULL) {
1761 set_iter = set_iter->next;
1778 for (gIter = set_iter; gIter != NULL; gIter = gIter->next) {
1786 }
else if (sequential) {
1795 if (symmetrical == FALSE) {
1817 set_iter = resources;
1818 while (set_iter != NULL) {
1820 set_iter = set_iter->next;
1841 g_list_free(resources);
1846 order_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
enum pe_order_kind kind,
1850 xmlNode *xml_rsc = NULL;
1851 xmlNode *xml_rsc_2 = NULL;
1863 gboolean require_all = require_all_s ?
crm_is_true(require_all_s) : TRUE;
1867 if (action_1 == NULL) {
1871 if (action_2 == NULL) {
1876 action_1 = invert_action(action_1);
1877 action_2 = invert_action(action_2);
1888 if (symmetrical == FALSE) {
1902 for (xml_rsc = __xml_first_child_element(set1); xml_rsc != NULL;
1903 xml_rsc = __xml_next_element(xml_rsc)) {
1914 NULL, NULL, NULL, unordered_action,
1918 for (xml_rsc_2 = __xml_first_child_element(set2); xml_rsc_2 != NULL;
1919 xml_rsc_2 = __xml_next_element(xml_rsc_2)) {
1938 if (invert == FALSE) {
1940 const char *rid = NULL;
1942 for (xml_rsc = __xml_first_child_element(set1); xml_rsc != NULL;
1943 xml_rsc = __xml_next_element(xml_rsc)) {
1953 for (xml_rsc = __xml_first_child_element(set1); xml_rsc != NULL;
1954 xml_rsc = __xml_next_element(xml_rsc)) {
1965 if (invert == FALSE) {
1967 for (xml_rsc = __xml_first_child_element(set2); xml_rsc != NULL;
1968 xml_rsc = __xml_next_element(xml_rsc)) {
1978 const char *rid = NULL;
1980 for (xml_rsc = __xml_first_child_element(set2); xml_rsc != NULL;
1981 xml_rsc = __xml_next_element(xml_rsc)) {
1991 if (rsc_1 != NULL && rsc_2 != NULL) {
1994 }
else if (rsc_1 != NULL) {
1995 for (xml_rsc = __xml_first_child_element(set2); xml_rsc != NULL;
1996 xml_rsc = __xml_next_element(xml_rsc)) {
2004 }
else if (rsc_2 != NULL) {
2005 xmlNode *xml_rsc = NULL;
2007 for (xml_rsc = __xml_first_child_element(set1); xml_rsc != NULL;
2008 xml_rsc = __xml_next_element(xml_rsc)) {
2017 for (xml_rsc = __xml_first_child_element(set1); xml_rsc != NULL;
2018 xml_rsc = __xml_next_element(xml_rsc)) {
2021 xmlNode *xml_rsc_2 = NULL;
2025 for (xml_rsc_2 = __xml_first_child_element(set2);
2027 xml_rsc_2 = __xml_next_element(xml_rsc_2)) {
2042 unpack_order_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2044 const char *
id = NULL;
2045 const char *id_first = NULL;
2046 const char *id_then = NULL;
2047 const char *action_first = NULL;
2048 const char *action_then = NULL;
2055 xmlNode *new_xml = NULL;
2056 xmlNode *rsc_set_first = NULL;
2057 xmlNode *rsc_set_then = NULL;
2058 gboolean any_sets = FALSE;
2060 *expanded_xml = NULL;
2062 CRM_CHECK(xml_obj != NULL,
return FALSE);
2067 crm_element_name(xml_obj));
2072 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2076 *expanded_xml = new_xml;
2082 if (id_first == NULL || id_then == NULL) {
2086 if (valid_resource_or_tag(data_set, id_first, &rsc_first, &tag_first) == FALSE) {
2088 "valid resource or tag",
id, id_first);
2092 if (valid_resource_or_tag(data_set, id_then, &rsc_then, &tag_then) == FALSE) {
2094 "valid resource or tag",
id, id_then);
2098 if (rsc_first && rsc_then) {
2114 if (rsc_set_first) {
2118 crm_xml_add(rsc_set_first,
"action", action_first);
2142 *expanded_xml = new_xml;
2153 gboolean any_sets = FALSE;
2167 xmlNode *set = NULL;
2168 xmlNode *last = NULL;
2170 xmlNode *orig_xml = NULL;
2171 xmlNode *expanded_xml = NULL;
2184 gboolean invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
2187 rc = unpack_order_tags(xml_obj, &expanded_xml, data_set);
2190 xml_obj = expanded_xml;
2192 }
else if (
rc == FALSE) {
2196 for (set = __xml_first_child_element(xml_obj); set != NULL;
2197 set = __xml_next_element(set)) {
2202 if (unpack_order_set(set, kind, &rsc, &set_begin, &set_end,
2203 &set_inv_begin, &set_inv_end, invert, data_set) == FALSE) {
2244 if (order_rsc_sets(
id, last, set, kind, data_set, FALSE, invert_bool) == FALSE) {
2249 && order_rsc_sets(
id, set, last, kind, data_set, TRUE, invert_bool) == FALSE) {
2270 if (any_sets == FALSE) {
2271 return unpack_simple_rsc_order(xml_obj, data_set);
2278 unpack_colocation_set(xmlNode * set,
int score,
pe_working_set_t * data_set)
2280 xmlNode *xml_rsc = NULL;
2283 const char *set_id =
ID(set);
2287 int local_score = score;
2295 if(ordering == NULL) {
2299 if (sequential != NULL &&
crm_is_true(sequential) == FALSE) {
2302 }
else if (local_score >= 0 &&
safe_str_eq(ordering,
"group")) {
2303 for (xml_rsc = __xml_first_child_element(set); xml_rsc != NULL;
2304 xml_rsc = __xml_next_element(xml_rsc)) {
2317 }
else if (local_score >= 0) {
2319 for (xml_rsc = __xml_first_child_element(set); xml_rsc != NULL;
2320 xml_rsc = __xml_next_element(xml_rsc)) {
2340 for (xml_rsc = __xml_first_child_element(set); xml_rsc != NULL;
2341 xml_rsc = __xml_next_element(xml_rsc)) {
2344 xmlNode *xml_rsc_with = NULL;
2348 for (xml_rsc_with = __xml_first_child_element(set);
2349 xml_rsc_with != NULL;
2350 xml_rsc_with = __xml_next_element(xml_rsc_with)) {
2357 pe_rsc_trace(resource,
"Anti-Colocating %s with %s", resource->
id,
2371 colocate_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2,
int score,
2374 xmlNode *xml_rsc = NULL;
2384 if (sequential_1 == NULL ||
crm_is_true(sequential_1)) {
2386 for (xml_rsc = __xml_first_child_element(set1); xml_rsc != NULL;
2387 xml_rsc = __xml_next_element(xml_rsc)) {
2396 if (sequential_2 == NULL ||
crm_is_true(sequential_2)) {
2398 const char *rid = NULL;
2400 for (xml_rsc = __xml_first_child_element(set2); xml_rsc != NULL;
2401 xml_rsc = __xml_next_element(xml_rsc)) {
2410 if (rsc_1 != NULL && rsc_2 != NULL) {
2413 }
else if (rsc_1 != NULL) {
2414 for (xml_rsc = __xml_first_child_element(set2); xml_rsc != NULL;
2415 xml_rsc = __xml_next_element(xml_rsc)) {
2423 }
else if (rsc_2 != NULL) {
2424 for (xml_rsc = __xml_first_child_element(set1); xml_rsc != NULL;
2425 xml_rsc = __xml_next_element(xml_rsc)) {
2434 for (xml_rsc = __xml_first_child_element(set1); xml_rsc != NULL;
2435 xml_rsc = __xml_next_element(xml_rsc)) {
2438 xmlNode *xml_rsc_2 = NULL;
2442 for (xml_rsc_2 = __xml_first_child_element(set2);
2444 xml_rsc_2 = __xml_next_element(xml_rsc_2)) {
2480 if (rsc_lh == NULL) {
2482 "does not exist",
id, id_lh);
2485 }
else if (rsc_rh == NULL) {
2487 "does not exist",
id, id_rh);
2490 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2492 "is not a clone but instance '%s' was requested",
2493 id, id_lh, instance_lh);
2496 }
else if (instance_rh && pe_rsc_is_clone(rsc_rh) == FALSE) {
2498 "is not a clone but instance '%s' was requested",
2499 id, id_rh, instance_rh);
2505 if (rsc_lh == NULL) {
2507 "does not have an instance '%s'",
2508 id, id_lh, instance_lh);
2515 if (rsc_rh == NULL) {
2517 "does not have an instance '%s'",
2518 "'%s'",
id, id_rh, instance_rh);
2526 "' attribute has been removed");
2538 unpack_colocation_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2540 const char *
id = NULL;
2541 const char *id_lh = NULL;
2542 const char *id_rh = NULL;
2543 const char *state_lh = NULL;
2544 const char *state_rh = NULL;
2552 xmlNode *new_xml = NULL;
2553 xmlNode *rsc_set_lh = NULL;
2554 xmlNode *rsc_set_rh = NULL;
2555 gboolean any_sets = FALSE;
2557 *expanded_xml = NULL;
2559 CRM_CHECK(xml_obj != NULL,
return FALSE);
2564 crm_element_name(xml_obj));
2569 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2573 *expanded_xml = new_xml;
2579 if (id_lh == NULL || id_rh == NULL) {
2583 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
2585 "valid resource or tag",
id, id_lh);
2589 if (valid_resource_or_tag(data_set, id_rh, &rsc_rh, &tag_rh) == FALSE) {
2591 "valid resource or tag",
id, id_rh);
2595 if (rsc_lh && rsc_rh) {
2600 if (tag_lh && tag_rh) {
2603 "tags cannot be colocated",
id);
2646 *expanded_xml = new_xml;
2658 xmlNode *set = NULL;
2659 xmlNode *last = NULL;
2660 gboolean any_sets = FALSE;
2662 xmlNode *orig_xml = NULL;
2663 xmlNode *expanded_xml = NULL;
2674 rc = unpack_colocation_tags(xml_obj, &expanded_xml, data_set);
2677 xml_obj = expanded_xml;
2679 }
else if (
rc == FALSE) {
2683 for (set = __xml_first_child_element(xml_obj); set != NULL;
2684 set = __xml_next_element(set)) {
2689 if (unpack_colocation_set(set, score_i, data_set) == FALSE) {
2692 }
else if (last && colocate_rsc_sets(
id, last, set, score_i, data_set) == FALSE) {
2704 if (any_sets == FALSE) {
2705 return unpack_simple_colocation(xml_obj, data_set);
2713 const char *state_lh,
const char *loss_policy,
pe_working_set_t * data_set)
2717 if (rsc_lh == NULL) {
2719 "does not exist",
id);
2724 if (new_rsc_ticket == NULL) {
2732 new_rsc_ticket->
id =
id;
2733 new_rsc_ticket->
ticket = ticket;
2734 new_rsc_ticket->
rsc_lh = rsc_lh;
2742 "' for ticket '%s' to 'stop' "
2743 "because fencing is not configured", ticket->
id);
2744 loss_policy =
"stop";
2749 crm_debug(
"On loss of ticket '%s': Fence the nodes running %s (%s)",
2754 crm_debug(
"On loss of ticket '%s': Freeze %s (%s)",
2760 crm_debug(
"On loss of ticket '%s': Demote %s (%s)",
2766 crm_debug(
"On loss of ticket '%s': Stop %s (%s)",
2773 crm_debug(
"On loss of ticket '%s': Default to demote %s (%s)",
2779 crm_debug(
"On loss of ticket '%s': Default to stop %s (%s)",
2801 unpack_rsc_ticket_set(xmlNode * set,
pe_ticket_t * ticket,
const char *loss_policy,
2804 xmlNode *xml_rsc = NULL;
2806 const char *set_id = NULL;
2807 const char *role = NULL;
2810 CRM_CHECK(ticket != NULL,
return FALSE);
2813 if (set_id == NULL) {
2825 pe_rsc_trace(resource,
"Resource '%s' depends on ticket '%s'",
2826 resource->
id, ticket->
id);
2827 rsc_ticket_new(set_id, resource, ticket, role, loss_policy, data_set);
2836 const char *
id = NULL;
2850 CRM_CHECK(xml_obj != NULL,
return FALSE);
2855 crm_element_name(xml_obj));
2859 if (ticket_str == NULL) {
2864 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
2867 if (ticket == NULL) {
2869 "does not exist",
id, ticket_str);
2873 if (id_lh == NULL) {
2877 rsc_lh = pe_find_constraint_resource(data_set->
resources, id_lh);
2880 if (rsc_lh == NULL) {
2882 "does not exist",
id, id_lh);
2885 }
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
2887 "is not a clone but instance '%s' was requested",
2888 id, id_lh, instance_lh);
2894 if (rsc_lh == NULL) {
2896 "does not have an instance '%s'",
2897 "'%s'",
id, id_lh, instance_lh);
2902 rsc_ticket_new(
id, rsc_lh, ticket, state_lh, loss_policy, data_set);
2907 unpack_rsc_ticket_tags(xmlNode * xml_obj, xmlNode ** expanded_xml,
pe_working_set_t * data_set)
2909 const char *
id = NULL;
2910 const char *id_lh = NULL;
2911 const char *state_lh = NULL;
2916 xmlNode *new_xml = NULL;
2917 xmlNode *rsc_set_lh = NULL;
2918 gboolean any_sets = FALSE;
2920 *expanded_xml = NULL;
2922 CRM_CHECK(xml_obj != NULL,
return FALSE);
2927 crm_element_name(xml_obj));
2932 expand_tags_in_sets(xml_obj, &new_xml, data_set);
2936 *expanded_xml = new_xml;
2941 if (id_lh == NULL) {
2945 if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
2947 "valid resource or tag",
id, id_lh);
2950 }
else if (rsc_lh) {
2977 *expanded_xml = new_xml;
2988 xmlNode *set = NULL;
2989 gboolean any_sets = FALSE;
2991 const char *
id = NULL;
2997 xmlNode *orig_xml = NULL;
2998 xmlNode *expanded_xml = NULL;
3002 CRM_CHECK(xml_obj != NULL,
return FALSE);
3007 crm_element_name(xml_obj));
3011 if (data_set->
tickets == NULL) {
3016 if (ticket_str == NULL) {
3020 ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
3023 if (ticket == NULL) {
3025 if (ticket == NULL) {
3030 rc = unpack_rsc_ticket_tags(xml_obj, &expanded_xml, data_set);
3033 xml_obj = expanded_xml;
3035 }
else if (
rc == FALSE) {
3039 for (set = __xml_first_child_element(xml_obj); set != NULL;
3040 set = __xml_next_element(set)) {
3045 if (unpack_rsc_ticket_set(set, ticket, loss_policy, data_set) == FALSE) {
3056 if (any_sets == FALSE) {
3057 return unpack_simple_rsc_ticket(xml_obj, data_set);
enum crm_ais_msg_types type
#define pcmk__config_warn(fmt...)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
#define pcmk__config_err(fmt...)
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
gboolean safe_str_neq(const char *a, const char *b)
int char2score(const char *score)
gboolean crm_is_true(const char *s)
#define safe_str_eq(a, b)
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
#define RSC_ROLE_STARTED_S
const char * role2text(enum rsc_role_e role)
enum rsc_role_e text2role(const char *role)
#define RSC_ROLE_UNKNOWN_S
gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc)
pe_resource_t * uber_parent(pe_resource_t *rsc)
#define CRM_OP_RELAXED_SET
#define CRM_OP_RELAXED_CLONE
#define CRMD_ACTION_DEMOTE
#define CRMD_ACTION_START
#define CRMD_ACTION_PROMOTE
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
long long int crm_time_get_seconds_since_epoch(crm_time_t *dt)
void crm_time_free(crm_time_t *dt)
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
struct crm_time_s crm_time_t
#define crm_info(fmt, args...)
#define crm_warn(fmt, args...)
#define CRM_CHECK(expr, failure_action)
#define crm_debug(fmt, args...)
#define crm_err(fmt, args...)
#define crm_log_xml_trace(xml, text)
#define crm_trace(fmt, args...)
#define XML_LOCATION_ATTR_DISCOVERY
#define XML_COLOC_ATTR_SOURCE_ROLE
#define XML_TAG_RESOURCE_REF
#define XML_RULE_ATTR_BOOLEAN_OP
#define XML_LOC_ATTR_SOURCE_PATTERN
#define XML_CONS_TAG_RSC_LOCATION
#define XML_COLOC_ATTR_NODE_ATTR
#define XML_CONS_TAG_RSC_TICKET
#define XML_ORDER_ATTR_THEN_INSTANCE
#define XML_RULE_ATTR_SCORE
#define XML_RULE_ATTR_ROLE
#define XML_RSC_ATTR_INCARNATION_MIN
#define XML_CONS_TAG_RSC_DEPEND
#define XML_CONS_TAG_RSC_SET
#define XML_COLOC_ATTR_TARGET_ROLE
#define XML_CONS_TAG_RSC_ORDER
#define XML_COLOC_ATTR_TARGET_INSTANCE
#define XML_ORDER_ATTR_THEN_ACTION
#define XML_BOOLEAN_FALSE
#define XML_TICKET_ATTR_LOSS_POLICY
#define XML_ORDER_ATTR_FIRST_INSTANCE
#define XML_COLOC_ATTR_SOURCE_INSTANCE
#define XML_ORDER_ATTR_FIRST
#define XML_ORDER_ATTR_FIRST_ACTION
#define XML_ORDER_ATTR_KIND
#define XML_TICKET_ATTR_TICKET
#define XML_CONS_ATTR_SYMMETRICAL
#define XML_RULE_ATTR_SCORE_ATTRIBUTE
#define XML_COLOC_ATTR_TARGET
#define XML_ORDER_ATTR_THEN
#define XML_LOC_ATTR_SOURCE
#define XML_COLOC_ATTR_SOURCE
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
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)
gboolean unpack_rsc_order(xmlNode *xml_obj, pe_working_set_t *data_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)
enum pe_ordering get_flags(const char *id, enum pe_order_kind kind, const char *action_first, const char *action_then, gboolean invert)
gboolean unpack_rsc_ticket(xmlNode *xml_obj, pe_working_set_t *data_set)
#define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name)
enum pe_ordering get_asymmetrical_flags(enum pe_order_kind kind)
gboolean unpack_rsc_colocation(xmlNode *xml_obj, pe_working_set_t *data_set)
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)
@ pe_order_kind_mandatory
@ pe_order_kind_serialize
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)
gboolean unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set)
gboolean unpack_constraints(xmlNode *xml_constraints, pe_working_set_t *data_set)
gboolean update_action_flags(pe_action_t *action, enum pe_action_flags flags, const char *source, int line)
void rsc_ticket_constraint(pe_resource_t *lh_rsc, rsc_ticket_t *rsc_ticket, pe_working_set_t *data_set)
GList * pcmk__copy_node_list(const GList *list, bool reset)
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)
@ pe_order_anti_colocation
@ pe_order_serialize_only
@ pe_order_implies_then_printed
@ pe_order_apply_first_non_migratable
#define pe_rsc_allow_migrate
@ pe_find_renamed
match resource ID or LRM history ID
#define pe_flag_stonith_enabled
#define pe_rsc_promotable
pe_resource_t * find_clone_instance(pe_resource_t *rsc, const char *sub_id, pe_working_set_t *data_set)
#define pe_warn_once(pe_wo_bit, fmt...)
void destroy_ticket(gpointer data)
pe_action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
#define pe_rsc_trace(rsc, fmt, args...)
int pe__add_scores(int score1, int score2)
const char * pe_node_attribute_calculated(const pe_node_t *node, const char *name, const pe_resource_t *rsc)
pe_ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
void pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
pe_node_t * pe__copy_node(const pe_node_t *this_node)
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)
char * pe_expand_re_matches(const char *string, pe_re_match_data_t *match_data)
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.
Cluster status and scheduling.
pe_node_t * pe_find_node(GListPtr node_list, const char *uname)
pe_node_t * pe_find_node_id(GListPtr node_list, const char *id)
enum rsc_role_e role_filter
int required_runnable_before
struct pe_node_shared_s * details
enum pe_obj_types variant
enum pe_restart restart_type
pe_node_t * partial_migration_target
resource_object_functions_t * fns
GHashTable * template_rsc_sets
GListPtr ticket_constraints
GListPtr colocation_constraints
GListPtr ordering_constraints
int order_id
Deprecated (will be removed in a future release)
pe_resource_t *(* find_rsc)(pe_resource_t *parent, const char *search, const pe_node_t *node, int flags)
const char * node_attribute
enum loss_ticket_policy_e loss_policy
Wrappers for and extensions to libxml2.
xmlNode * copy_xml(xmlNode *src_node)
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
const xmlChar * pcmkXmlStr
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
void free_xml(xmlNode *child)
xmlDoc * getDocPtr(xmlNode *node)
xmlNode * create_xml_node(xmlNode *parent, const char *name)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
void xml_remove_prop(xmlNode *obj, const char *name)