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)