12 #include <sys/param.h>    13 #include <sys/types.h>    35 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do {              \    36     __rsc = pe_find_constraint_resource(data_set->resources, __name);       \    38         pcmk__config_err("%s: No resource found for %s", __set, __name);    \    44                            const char *action_first, 
const char *action_then, gboolean invert);
    48                                               const char *discovery,
    53 static void unpack_rsc_colocation(xmlNode *xml_obj, 
pe_working_set_t *data_set);
    74     xmlNode *xml_obj = NULL;
    75     xmlNode *lifetime = NULL;
    77     for (xml_obj = pcmk__xe_first_child(xml_constraints); xml_obj != NULL;
    78          xml_obj = pcmk__xe_next(xml_obj)) {
    80         const char *tag = crm_element_name(xml_obj);
    88         crm_trace(
"Processing constraint %s %s", tag, 
id);
    93                               "deprecated (the rules it contains should "    94                               "instead be direct descendents of the "    95                               "constraint object)", 
id);
    98         if (lifetime && !evaluate_lifetime(lifetime, data_set)) {
    99             crm_info(
"Constraint %s %s is not active", tag, 
id);
   105             unpack_rsc_colocation(xml_obj, data_set);
   108             unpack_location(xml_obj, data_set);
   114             pe_err(
"Unsupported constraint type: %s", tag);
   122 invert_action(
const char *
action)
   148     crm_warn(
"Unknown action '%s' specified in order constraint", 
action);
   153 get_ordering_type(xmlNode * xml_obj)
   171                          "Support for 'score' in rsc_order is deprecated "   172                          "and will be removed in a future release (use 'kind' instead)");
   186                          "'%s' to Mandatory because '%s' is not valid",
   193 pe_find_constraint_resource(GList *rsc_list, 
const char *
id)
   197     for (rIter = rsc_list; 
id && rIter; rIter = rIter->next) {
   222                                        NULL, (gpointer*) tag);
   225         rc = g_hash_table_lookup_extended(data_set->
tags, 
id,
   226                                           NULL, (gpointer*) tag);
   229             crm_warn(
"No template or tag named '%s'", 
id);
   232         } 
else if (*tag == NULL) {
   233             crm_warn(
"No resource is tagged with '%s'", 
id);
   237     } 
else if (*tag == NULL) {
   238         crm_warn(
"No resource is derived from template '%s'", 
id);
   253         *rsc = pe_find_constraint_resource(data_set->
resources, 
id);
   261         rc = pe_find_constraint_tag(data_set, 
id, tag);
   268 order_is_symmetrical(xmlNode * xml_obj,
   269                      enum pe_order_kind parent_kind, 
const char * parent_symmetrical_s)
   277     if (kind_s || score_s) {
   278         kind = get_ordering_type(xml_obj);
   281     if (symmetrical_s == NULL) {
   282         symmetrical_s = parent_symmetrical_s;
   290                               " for '%s' because not valid with "   313     gboolean invert_bool = TRUE;
   314     int min_required_before = 0;
   318     const char *id_first = NULL;
   319     const char *id_then = NULL;
   320     const char *action_then = NULL;
   321     const char *action_first = NULL;
   322     const char *instance_then = NULL;
   323     const char *instance_first = NULL;
   325     const char *
id = NULL;
   327     CRM_CHECK(xml_obj != NULL, 
return FALSE);
   332                          crm_element_name(xml_obj));
   336     invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
   347     if (action_first == NULL) {
   350     if (action_then == NULL) {
   351         action_then = action_first;
   354     if (id_first == NULL) {
   359     if (id_then == NULL) {
   365     rsc_then = pe_find_constraint_resource(data_set->
resources, id_then);
   366     rsc_first = pe_find_constraint_resource(data_set->
resources, id_first);
   368     if (rsc_then == NULL) {
   370                          "does not exist", 
id, id_then);
   373     } 
else if (rsc_first == NULL) {
   375                          "does not exist", 
id, id_first);
   378     } 
else if (instance_then && pe_rsc_is_clone(rsc_then) == FALSE) {
   380                          "is not a clone but instance '%s' was requested",
   381                          id, id_then, instance_then);
   384     } 
else if (instance_first && pe_rsc_is_clone(rsc_first) == FALSE) {
   386                          "is not a clone but instance '%s' was requested",
   387                          id, id_first, instance_first);
   393         if (rsc_then == NULL) {
   395                               "does not have an instance '%s'",
   396                               id, id_then, instance_then);
   401     if (instance_first) {
   403         if (rsc_first == NULL) {
   405                               "does not have an instance '%s'",
   406                               "'%s'", 
id, id_first, instance_first);
   412     kind = get_ordering_type(xml_obj);
   415         crm_trace(
"Upgrade : recovery - implies right");
   419     if (invert_bool == FALSE) {
   423                               get_flags(
id, kind, action_first, action_then, FALSE));
   426     if (pe_rsc_is_clone(rsc_first)) {
   430         const char *min_clones_s = g_hash_table_lookup(rsc_first->
meta,
   439         } 
else if (require_all_s) {
   441                         "Support for require-all in ordering constraints "   442                         "is deprecated and will be removed in a future release"   443                         " (use clone-min clone meta-attribute instead)");
   446                 min_required_before = 1;
   454     if (min_required_before) {
   466         for (rIter = rsc_first->
children; 
id && rIter; rIter = rIter->next) {
   470                                 NULL, NULL, NULL, unordered_action,
   482         order_id = 
new_rsc_order(rsc_first, action_first, rsc_then, action_then, cons_weight, data_set);
   485     pe_rsc_trace(rsc_first, 
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
   486                  order_id, 
id, rsc_first->
id, action_first, rsc_then->
id, action_then, cons_weight);
   488     if (invert_bool == FALSE) {
   492     action_then = invert_action(action_then);
   493     action_first = invert_action(action_first);
   494     if (action_then == NULL || action_first == NULL) {
   496                          "(please specify inverse manually)", 
id);
   502         crm_trace(
"Upgrade : recovery - implies left");
   507                           get_flags(
id, kind, action_first, action_then, TRUE));
   509     order_id = 
new_rsc_order(rsc_then, action_then, rsc_first, action_first, cons_weight, data_set);
   511     pe_rsc_trace(rsc_then, 
"order-%d (%s): %s_%s before %s_%s flags=0x%.6x",
   512                  order_id, 
id, rsc_then->
id, action_then, rsc_first->
id, action_first, cons_weight);
   518 expand_tags_in_sets(xmlNode * xml_obj, xmlNode ** expanded_xml, 
pe_working_set_t * data_set)
   520     xmlNode *new_xml = NULL;
   522     gboolean any_refs = FALSE;
   523     const char *cons_id = NULL;
   525     *expanded_xml = NULL;
   527     CRM_CHECK(xml_obj != NULL, 
return FALSE);
   530     cons_id = 
ID(new_xml);
   532     for (
set = pcmk__xe_first_child(new_xml); 
set != NULL;
   533          set = pcmk__xe_next(
set)) {
   535         xmlNode *xml_rsc = NULL;
   536         GList *tag_refs = NULL;
   543         for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
   544              xml_rsc = pcmk__xe_next(xml_rsc)) {
   548             const char *
id = 
ID(xml_rsc);
   554             if (valid_resource_or_tag(data_set, 
id, &rsc, &tag) == FALSE) {
   556                                  "because '%s' is not a valid resource or tag",
   566                 xmlNode *last_ref = xml_rsc;
   590                 for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
   591                     const char *obj_ref = (
const char *) gIter->data;
   592                     xmlNode *new_rsc_ref = NULL;
   594                     new_rsc_ref = xmlNewDocRawNode(
getDocPtr(
set), NULL,
   597                     xmlAddNextSibling(last_ref, new_rsc_ref);
   599                     last_ref = new_rsc_ref;
   609                 tag_refs = g_list_append(tag_refs, xml_rsc);
   623         for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
   624             xmlNode *tag_ref = gIter->data;
   628         g_list_free(tag_refs);
   632         *expanded_xml = new_xml;
   641 tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set, 
const char * attr,
   644     const char *cons_id = NULL;
   645     const char *
id = NULL;
   652     CRM_CHECK((xml_obj != NULL) && (attr != NULL), 
return FALSE);
   654     cons_id = 
ID(xml_obj);
   655     if (cons_id == NULL) {
   657                          crm_element_name(xml_obj));
   666     if (valid_resource_or_tag(data_set, 
id, &rsc, &tag) == FALSE) {
   668                          "valid resource or tag", cons_id, 
id);
   680         for (gIter = tag->
refs; gIter != NULL; gIter = gIter->next) {
   681             const char *obj_ref = (
const char *) gIter->data;
   682             xmlNode *rsc_ref = NULL;
   691     } 
else if (rsc && convert_rsc) {
   694         xmlNode *rsc_ref = NULL;
   714 static void unpack_rsc_location(xmlNode *xml_obj, 
pe_resource_t *rsc_lh,
   715                                 const char *role, 
const char *score,
   728         unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
   733         regex_t *r_patt = calloc(1, 
sizeof(regex_t));
   737         if(value[0] == 
'!') {
   742         if (regcomp(r_patt, value, REG_EXTENDED)) {
   745                              " has invalid value '%s'", 
id, value);
   751         for (rIter = data_set->
resources; rIter; rIter = rIter->next) {
   754             regmatch_t *pmatch = NULL;
   757             if(r_patt->re_nsub > 0) {
   758                 nregs = r_patt->re_nsub + 1;
   762             pmatch = calloc(nregs, 
sizeof(regmatch_t));
   764             status = regexec(r_patt, r->
id, nregs, pmatch, 0);
   766             if(invert == FALSE && status == 0) {
   773                 crm_debug(
"'%s' matched '%s' for %s", r->
id, value, 
id);
   774                 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, &re_match_data);
   776             } 
else if (invert && (status != 0)) {
   777                 crm_debug(
"'%s' is an inverted match of '%s' for %s", r->
id, value, 
id);
   778                 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, NULL);
   781                 crm_trace(
"'%s' does not match '%s' for %s", r->
id, value, 
id);
   793 unpack_rsc_location(xmlNode *xml_obj, 
pe_resource_t *rsc_lh, 
const char *role,
   803     if (rsc_lh == NULL) {
   805                           "does not exist", 
id, id_lh);
   813     if (node != NULL && score != NULL) {
   820         location = 
rsc2node_new(
id, rsc_lh, score_i, discovery, match, data_set);
   834             generate_location_rule(rsc_lh, rule_xml, discovery, next_change,
   835                                    data_set, re_match_data);
   859     if (location && role) {
   861             pe_err(
"Invalid constraint %s: Bad role %s", 
id, role);
   882 unpack_location_tags(xmlNode * xml_obj, xmlNode ** expanded_xml, 
pe_working_set_t * data_set)
   884     const char *
id = NULL;
   885     const char *id_lh = NULL;
   886     const char *state_lh = NULL;
   892     xmlNode *new_xml = NULL;
   893     xmlNode *rsc_set_lh = NULL;
   895     *expanded_xml = NULL;
   897     CRM_CHECK(xml_obj != NULL, 
return FALSE);
   902                          crm_element_name(xml_obj));
   907     expand_tags_in_sets(xml_obj, &new_xml, data_set);
   911         *expanded_xml = new_xml;
   920     if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
   922                          "valid resource or tag", 
id, id_lh);
   948         *expanded_xml = new_xml;
   959 unpack_location_set(xmlNode * location, xmlNode * 
set, 
pe_working_set_t * data_set)
   961     xmlNode *xml_rsc = NULL;
   965     const char *local_score;
   970     if (set_id == NULL) {
   980     for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
   981          xml_rsc = pcmk__xe_next(xml_rsc)) {
   985             unpack_rsc_location(location, resource, role, local_score, data_set, NULL);
   996     gboolean any_sets = FALSE;
   998     xmlNode *orig_xml = NULL;
   999     xmlNode *expanded_xml = NULL;
  1001     if (unpack_location_tags(xml_obj, &expanded_xml, data_set) == FALSE) {
  1007         xml_obj = expanded_xml;
  1010     for (
set = pcmk__xe_first_child(xml_obj); 
set != NULL;
  1011          set = pcmk__xe_next(
set)) {
  1016             if (unpack_location_set(xml_obj, 
set, data_set) == FALSE) {
  1030     if (any_sets == FALSE) {
  1031         unpack_simple_location(xml_obj, data_set);
  1040     if (score == NULL) {
  1041         pe_err(
"Rule %s: no score specified.  Assuming 0.", rule);
  1049         if (attr_score == NULL) {
  1050             crm_debug(
"Rule %s: node %s did not have a value for %s",
  1055             crm_debug(
"Rule %s: node %s had value %s for %s",
  1064 generate_location_rule(
pe_resource_t *rsc, xmlNode *rule_xml,
  1065                        const char *discovery, 
crm_time_t *next_change,
  1069     const char *rule_id = NULL;
  1070     const char *score = NULL;
  1071     const char *
boolean = NULL;
  1072     const char *role = NULL;
  1074     GList *gIter = NULL;
  1075     GList *match_L = NULL;
  1077     gboolean do_and = TRUE;
  1078     gboolean accept = TRUE;
  1079     gboolean raw_score = TRUE;
  1080     gboolean score_allocated = FALSE;
  1089     crm_trace(
"Processing rule: %s", rule_id);
  1092         pe_err(
"Bad role specified for %s: %s", rule_id, role);
  1097     if (score == NULL) {
  1099         if (score != NULL) {
  1107     location_rule = 
rsc2node_new(rule_id, rsc, 0, discovery, NULL, data_set);
  1109     if (location_rule == NULL) {
  1113     if ((re_match_data != NULL) && (re_match_data->
nregs > 0)
  1114         && (re_match_data->
pmatch[0].rm_so != -1) && !raw_score) {
  1118         if (result != NULL) {
  1120             score_allocated = TRUE;
  1125         crm_trace(
"Setting role filter: %s", role);
  1136         GList *gIter = NULL;
  1139         for (gIter = match_L; gIter != NULL; gIter = gIter->next) {
  1142             node->
weight = get_node_score(rule_id, score, raw_score, node, rsc);
  1146     for (gIter = data_set->
nodes; gIter != NULL; gIter = gIter->next) {
  1150             .
re = re_match_data,
  1156                               data_set->
now, next_change, &match_data);
  1158         crm_trace(
"Rule %s %s on %s", 
ID(rule_xml), accept ? 
"passed" : 
"failed",
  1161         score_f = get_node_score(rule_id, score, raw_score, node, rsc);
  1169             if (
local == NULL && do_and) {
  1172             } 
else if (
local == NULL) {
  1174                 match_L = g_list_append(match_L, 
local);
  1177             if (do_and == FALSE) {
  1182         } 
else if (do_and && !accept) {
  1186             if (
delete != NULL) {
  1187                 match_L = g_list_remove(match_L, 
delete);
  1194     if (score_allocated == TRUE) {
  1195         free((
char *)score);
  1200         crm_trace(
"No matching nodes for rule %s", rule_id);
  1205     return location_rule;
  1209 sort_cons_priority_lh(gconstpointer a, gconstpointer b)
  1257 sort_cons_priority_rh(gconstpointer a, gconstpointer b)
  1305 anti_colocation_order(
pe_resource_t * first_rsc, 
int first_role,
  1309     const char *first_tasks[] = { NULL, NULL };
  1310     const char *then_tasks[] = { NULL, NULL };
  1338     for (first_lpc = 0; first_lpc <= 1 && first_tasks[first_lpc] != NULL; first_lpc++) {
  1339         for (then_lpc = 0; then_lpc <= 1 && then_tasks[then_lpc] != NULL; then_lpc++) {
  1340             new_rsc_order(first_rsc, first_tasks[first_lpc], then_rsc, then_tasks[then_lpc],
  1349                      const char *state_lh, 
const char *state_rh,
  1355         crm_trace(
"Ignoring colocation '%s' because score is 0", 
id);
  1358     if ((rsc_lh == NULL) || (rsc_rh == NULL)) {
  1360                          "does not exist", 
id);
  1365     if (new_con == NULL) {
  1378     new_con->
rsc_lh = rsc_lh;
  1379     new_con->
rsc_rh = rsc_rh;
  1380     new_con->
score = score;
  1386     if (node_attr == NULL) {
  1390     pe_rsc_trace(rsc_lh, 
"%s ==> %s (%s %d)", rsc_lh->
id, rsc_rh->
id, node_attr, score);
  1392     rsc_lh->
rsc_cons = g_list_insert_sorted(rsc_lh->
rsc_cons, new_con, sort_cons_priority_rh);
  1395         g_list_insert_sorted(rsc_rh->
rsc_cons_lhs, new_con, sort_cons_priority_lh);
  1400         anti_colocation_order(rsc_lh, new_con->
role_lh, rsc_rh, new_con->
role_rh, data_set);
  1401         anti_colocation_order(rsc_rh, new_con->
role_rh, rsc_lh, new_con->
role_lh, data_set);
  1411     char *lh_key = NULL;
  1412     char *rh_key = NULL;
  1423     if (validate_order_resources(lh_rsc, lh_task, rh_rsc, rh_task)) {
  1440         res = strdup(
action->task);
  1454     char *lh_task = NULL;
  1455     char *rh_task = NULL;
  1456     gboolean rh_migratable;
  1457     gboolean lh_migratable;
  1476     if (lh_migratable == FALSE && rh_migratable == FALSE) {
  1486     if (lh_task == NULL || rh_task == NULL) {
  1493         if (lh_migratable && rh_migratable) {
  1500                                 NULL, 
flags, data_set);
  1503         if (rh_migratable) {
  1504             if (lh_migratable) {
  1514                                 NULL, 
flags, data_set);
  1520         if (lh_migratable) {
  1531                             NULL, 
flags, data_set);
  1540                                 NULL, 
flags, data_set);
  1546         if (rh_migratable) {
  1553                                 NULL, 
flags, data_set);
  1559         if (rh_migratable) {
  1573                                     NULL, 
flags, data_set);
  1591     if (lh_rsc == NULL && lh_action) {
  1592         lh_rsc = lh_action->
rsc;
  1594     if (rh_rsc == NULL && rh_action) {
  1595         rh_rsc = rh_action->
rsc;
  1598     if ((lh_action == NULL && lh_rsc == NULL)
  1599         || (rh_action == NULL && rh_rsc == NULL)) {
  1600         crm_err(
"Invalid ordering (bug?)");
  1601         free(lh_action_task);
  1602         free(rh_action_task);
  1609               lh_rsc?lh_rsc->
id:
"NA", lh_action_task?lh_action_task:
"NA", lh_action?lh_action->
uuid:
"NA",
  1610               rh_rsc?rh_rsc->
id:
"NA", rh_action_task?rh_action_task:
"NA", rh_action?rh_action->
uuid:
"NA");
  1631     if (order->
lh_rsc == NULL && lh_action) {
  1635     if (order->
rh_rsc == NULL && rh_action) {
  1640     handle_migration_ordering(order, data_set);
  1660           const char *action_first, 
const char *action_then, gboolean invert)
  1665         crm_trace(
"Upgrade %s: implies left", 
id);
  1669         crm_trace(
"Upgrade %s: implies right", 
id);
  1686                  pe_action_t ** inv_end, 
const char *parent_symmetrical_s,
  1689     xmlNode *xml_rsc = NULL;
  1690     GList *set_iter = NULL;
  1691     GList *resources = NULL;
  1696     int local_kind = parent_kind;
  1697     gboolean sequential = FALSE;
  1699     gboolean symmetrical = TRUE;
  1702     const char *
id = 
ID(
set);
  1718         local_kind = get_ordering_type(
set);
  1720     if (sequential_s == NULL) {
  1726     symmetrical = order_is_symmetrical(
set, parent_kind, parent_symmetrical_s);
  1733     for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
  1734          xml_rsc = pcmk__xe_next(xml_rsc)) {
  1738             resources = g_list_append(resources, resource);
  1742     if (pcmk__list_of_1(resources)) {
  1768     set_iter = resources;
  1769     while (set_iter != NULL) {
  1771         set_iter = set_iter->next;
  1786             GList *gIter = NULL;
  1788             for (gIter = set_iter; gIter != NULL; gIter = gIter->next) {
  1796         } 
else if (sequential) {
  1805     if (symmetrical == FALSE) {
  1827     set_iter = resources;
  1828     while (set_iter != NULL) {
  1830         set_iter = set_iter->next;
  1851     g_list_free(resources);
  1856 order_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2, 
enum pe_order_kind kind,
  1860     xmlNode *xml_rsc = NULL;
  1861     xmlNode *xml_rsc_2 = NULL;
  1873     gboolean require_all = require_all_s ? 
crm_is_true(require_all_s) : TRUE;
  1877     if (action_1 == NULL) {
  1881     if (action_2 == NULL) {
  1886         action_1 = invert_action(action_1);
  1887         action_2 = invert_action(action_2);
  1898     if (symmetrical == FALSE) {
  1912         for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
  1913              xml_rsc = pcmk__xe_next(xml_rsc)) {
  1924                                 NULL, NULL, NULL, unordered_action,
  1928         for (xml_rsc_2 = pcmk__xe_first_child(set2); xml_rsc_2 != NULL;
  1929              xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
  1948         if (invert == FALSE) {
  1950             const char *rid = NULL;
  1952             for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
  1953                  xml_rsc = pcmk__xe_next(xml_rsc)) {
  1963             for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
  1964                  xml_rsc = pcmk__xe_next(xml_rsc)) {
  1975         if (invert == FALSE) {
  1977             for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
  1978                  xml_rsc = pcmk__xe_next(xml_rsc)) {
  1988             const char *rid = NULL;
  1990             for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
  1991                  xml_rsc = pcmk__xe_next(xml_rsc)) {
  2001     if (rsc_1 != NULL && rsc_2 != NULL) {
  2004     } 
else if (rsc_1 != NULL) {
  2005         for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
  2006              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2014     } 
else if (rsc_2 != NULL) {
  2015         xmlNode *xml_rsc = NULL;
  2017         for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
  2018              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2027         for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
  2028              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2031                 xmlNode *xml_rsc_2 = NULL;
  2035                 for (xml_rsc_2 = pcmk__xe_first_child(set2);
  2037                      xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
  2052 unpack_order_tags(xmlNode * xml_obj, xmlNode ** expanded_xml, 
pe_working_set_t * data_set)
  2054     const char *
id = NULL;
  2055     const char *id_first = NULL;
  2056     const char *id_then = NULL;
  2057     const char *action_first = NULL;
  2058     const char *action_then = NULL;
  2065     xmlNode *new_xml = NULL;
  2066     xmlNode *rsc_set_first = NULL;
  2067     xmlNode *rsc_set_then = NULL;
  2068     gboolean any_sets = FALSE;
  2070     *expanded_xml = NULL;
  2072     CRM_CHECK(xml_obj != NULL, 
return FALSE);
  2077                          crm_element_name(xml_obj));
  2082     expand_tags_in_sets(xml_obj, &new_xml, data_set);
  2086         *expanded_xml = new_xml;
  2092     if (id_first == NULL || id_then == NULL) {
  2096     if (valid_resource_or_tag(data_set, id_first, &rsc_first, &tag_first) == FALSE) {
  2098                          "valid resource or tag", 
id, id_first);
  2102     if (valid_resource_or_tag(data_set, id_then, &rsc_then, &tag_then) == FALSE) {
  2104                          "valid resource or tag", 
id, id_then);
  2108     if (rsc_first && rsc_then) {
  2124     if (rsc_set_first) {
  2128             crm_xml_add(rsc_set_first, 
"action", action_first);
  2152         *expanded_xml = new_xml;
  2163     gboolean any_sets = FALSE;
  2177     xmlNode *
set = NULL;
  2178     xmlNode *last = NULL;
  2180     xmlNode *orig_xml = NULL;
  2181     xmlNode *expanded_xml = NULL;
  2194     gboolean invert_bool = order_is_symmetrical(xml_obj, kind, NULL);
  2197     rc = unpack_order_tags(xml_obj, &expanded_xml, data_set);
  2200         xml_obj = expanded_xml;
  2202     } 
else if (
rc == FALSE) {
  2206     for (
set = pcmk__xe_first_child(xml_obj); 
set != NULL;
  2207          set = pcmk__xe_next(
set)) {
  2212             if (unpack_order_set(
set, kind, &rsc, &set_begin, &set_end,
  2213                                  &set_inv_begin, &set_inv_end, invert, data_set) == FALSE) {
  2254                 if (order_rsc_sets(
id, last, 
set, kind, data_set, FALSE, invert_bool) == FALSE) {
  2259                     && order_rsc_sets(
id, 
set, last, kind, data_set, TRUE, invert_bool) == FALSE) {
  2280     if (any_sets == FALSE) {
  2281         return unpack_simple_rsc_order(xml_obj, data_set);
  2299 unpack_influence(
const char *coloc_id, 
const pe_resource_t *rsc,
  2300                  const char *influence_s)
  2302     if (influence_s != NULL) {
  2303         int influence_i = 0;
  2310             return (influence_i == TRUE);
  2317 unpack_colocation_set(xmlNode *
set, 
int score, 
const char *coloc_id,
  2320     xmlNode *xml_rsc = NULL;
  2323     const char *set_id = 
ID(
set);
  2327     int local_score = score;
  2334     if (local_score == 0) {
  2335         crm_trace(
"Ignoring colocation '%s' for set '%s' because score is 0",
  2340     if(ordering == NULL) {
  2344     if (sequential != NULL && 
crm_is_true(sequential) == FALSE) {
  2347     } 
else if ((local_score > 0)
  2349         for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
  2350              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2358                                          unpack_influence(coloc_id, resource,
  2366     } 
else if (local_score > 0) {
  2368         for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
  2369              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2376                                          resource, role, role,
  2377                                          unpack_influence(coloc_id, last,
  2392         for (xml_rsc = pcmk__xe_first_child(
set); xml_rsc != NULL;
  2393              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2396                 xmlNode *xml_rsc_with = NULL;
  2397                 bool influence = 
true;
  2400                 influence = unpack_influence(coloc_id, resource, influence_s);
  2402                 for (xml_rsc_with = pcmk__xe_first_child(
set);
  2403                      xml_rsc_with != NULL;
  2404                      xml_rsc_with = pcmk__xe_next(xml_rsc_with)) {
  2411                         pe_rsc_trace(resource, 
"Anti-Colocating %s with %s", resource->
id,
  2414                                              resource, with, role, role,
  2415                                              influence, data_set);
  2426 colocate_rsc_sets(
const char *
id, xmlNode * set1, xmlNode * set2, 
int score,
  2429     xmlNode *xml_rsc = NULL;
  2440         crm_trace(
"Ignoring colocation '%s' between sets because score is 0",
  2444     if (sequential_1 == NULL || 
crm_is_true(sequential_1)) {
  2446         for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
  2447              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2456     if (sequential_2 == NULL || 
crm_is_true(sequential_2)) {
  2458         const char *rid = NULL;
  2460         for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
  2461              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2470     if (rsc_1 != NULL && rsc_2 != NULL) {
  2472                              unpack_influence(
id, rsc_1, influence_s),
  2475     } 
else if (rsc_1 != NULL) {
  2476         bool influence = unpack_influence(
id, rsc_1, influence_s);
  2478         for (xml_rsc = pcmk__xe_first_child(set2); xml_rsc != NULL;
  2479              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2484                                      role_2, influence, data_set);
  2488     } 
else if (rsc_2 != NULL) {
  2489         for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
  2490              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2496                                      unpack_influence(
id, rsc_1, influence_s),
  2502         for (xml_rsc = pcmk__xe_first_child(set1); xml_rsc != NULL;
  2503              xml_rsc = pcmk__xe_next(xml_rsc)) {
  2506                 xmlNode *xml_rsc_2 = NULL;
  2507                 bool influence = 
true;
  2510                 influence = unpack_influence(
id, rsc_1, influence_s);
  2512                 for (xml_rsc_2 = pcmk__xe_first_child(set2);
  2514                      xml_rsc_2 = pcmk__xe_next(xml_rsc_2)) {
  2519                                              role_1, role_2, influence,
  2531 unpack_simple_colocation(xmlNode *xml_obj, 
const char *
id,
  2551     if (rsc_lh == NULL) {
  2553                          "does not exist", 
id, id_lh);
  2556     } 
else if (rsc_rh == NULL) {
  2558                          "does not exist", 
id, id_rh);
  2561     } 
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
  2563                          "is not a clone but instance '%s' was requested",
  2564                          id, id_lh, instance_lh);
  2567     } 
else if (instance_rh && pe_rsc_is_clone(rsc_rh) == FALSE) {
  2569                          "is not a clone but instance '%s' was requested",
  2570                          id, id_rh, instance_rh);
  2576         if (rsc_lh == NULL) {
  2578                               "does not have an instance '%s'",
  2579                               id, id_lh, instance_lh);
  2586         if (rsc_rh == NULL) {
  2588                               "does not have an instance '%s'",
  2589                               "'%s'", 
id, id_rh, instance_rh);
  2597                           "' attribute has been removed");
  2605                          unpack_influence(
id, rsc_lh, influence_s), data_set);
  2609 unpack_colocation_tags(xmlNode * xml_obj, xmlNode ** expanded_xml, 
pe_working_set_t * data_set)
  2611     const char *
id = NULL;
  2612     const char *id_lh = NULL;
  2613     const char *id_rh = NULL;
  2614     const char *state_lh = NULL;
  2615     const char *state_rh = NULL;
  2623     xmlNode *new_xml = NULL;
  2624     xmlNode *rsc_set_lh = NULL;
  2625     xmlNode *rsc_set_rh = NULL;
  2626     gboolean any_sets = FALSE;
  2628     *expanded_xml = NULL;
  2630     CRM_CHECK(xml_obj != NULL, 
return FALSE);
  2635                          crm_element_name(xml_obj));
  2640     expand_tags_in_sets(xml_obj, &new_xml, data_set);
  2644         *expanded_xml = new_xml;
  2650     if (id_lh == NULL || id_rh == NULL) {
  2654     if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
  2656                          "valid resource or tag", 
id, id_lh);
  2660     if (valid_resource_or_tag(data_set, id_rh, &rsc_rh, &tag_rh) == FALSE) {
  2662                          "valid resource or tag", 
id, id_rh);
  2666     if (rsc_lh && rsc_rh) {
  2671     if (tag_lh && tag_rh) {
  2674                          "tags cannot be colocated", 
id);
  2717         *expanded_xml = new_xml;
  2729     xmlNode *
set = NULL;
  2730     xmlNode *last = NULL;
  2731     gboolean any_sets = FALSE;
  2733     xmlNode *orig_xml = NULL;
  2734     xmlNode *expanded_xml = NULL;
  2745     if (!unpack_colocation_tags(xml_obj, &expanded_xml, data_set)) {
  2750         xml_obj = expanded_xml;
  2753     for (
set = pcmk__xe_first_child(xml_obj); 
set != NULL;
  2754          set = pcmk__xe_next(
set)) {
  2759             if (!unpack_colocation_set(
set, score_i, 
id, influence_s,
  2763             if ((last != NULL) && !colocate_rsc_sets(
id, last, 
set, score_i,
  2764                                                      influence_s, data_set)) {
  2777         unpack_simple_colocation(xml_obj, 
id, influence_s, data_set);
  2783                const char *state_lh, 
const char *loss_policy, 
pe_working_set_t * data_set)
  2787     if (rsc_lh == NULL) {
  2789                          "does not exist", 
id);
  2794     if (new_rsc_ticket == NULL) {
  2802     new_rsc_ticket->
id = 
id;
  2803     new_rsc_ticket->
ticket = ticket;
  2804     new_rsc_ticket->
rsc_lh = rsc_lh;
  2812                              "' for ticket '%s' to 'stop' "  2813                              "because fencing is not configured", ticket->
id);
  2814             loss_policy = 
"stop";
  2819         crm_debug(
"On loss of ticket '%s': Fence the nodes running %s (%s)",
  2824         crm_debug(
"On loss of ticket '%s': Freeze %s (%s)",
  2830         crm_debug(
"On loss of ticket '%s': Demote %s (%s)",
  2836         crm_debug(
"On loss of ticket '%s': Stop %s (%s)",
  2843             crm_debug(
"On loss of ticket '%s': Default to demote %s (%s)",
  2849             crm_debug(
"On loss of ticket '%s': Default to stop %s (%s)",
  2871 unpack_rsc_ticket_set(xmlNode * 
set, 
pe_ticket_t * ticket, 
const char *loss_policy,
  2874     xmlNode *xml_rsc = NULL;
  2876     const char *set_id = NULL;
  2877     const char *role = NULL;
  2880     CRM_CHECK(ticket != NULL, 
return FALSE);
  2883     if (set_id == NULL) {
  2895         pe_rsc_trace(resource, 
"Resource '%s' depends on ticket '%s'",
  2896                      resource->
id, ticket->
id);
  2897         rsc_ticket_new(set_id, resource, ticket, role, loss_policy, data_set);
  2906     const char *
id = NULL;
  2920     CRM_CHECK(xml_obj != NULL, 
return FALSE);
  2925                          crm_element_name(xml_obj));
  2929     if (ticket_str == NULL) {
  2934         ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
  2937     if (ticket == NULL) {
  2939                          "does not exist", 
id, ticket_str);
  2943     if (id_lh == NULL) {
  2947         rsc_lh = pe_find_constraint_resource(data_set->
resources, id_lh);
  2950     if (rsc_lh == NULL) {
  2952                          "does not exist", 
id, id_lh);
  2955     } 
else if (instance_lh && pe_rsc_is_clone(rsc_lh) == FALSE) {
  2957                          "is not a clone but instance '%s' was requested",
  2958                          id, id_lh, instance_lh);
  2964         if (rsc_lh == NULL) {
  2966                               "does not have an instance '%s'",
  2967                               "'%s'", 
id, id_lh, instance_lh);
  2972     rsc_ticket_new(
id, rsc_lh, ticket, state_lh, loss_policy, data_set);
  2977 unpack_rsc_ticket_tags(xmlNode * xml_obj, xmlNode ** expanded_xml, 
pe_working_set_t * data_set)
  2979     const char *
id = NULL;
  2980     const char *id_lh = NULL;
  2981     const char *state_lh = NULL;
  2986     xmlNode *new_xml = NULL;
  2987     xmlNode *rsc_set_lh = NULL;
  2988     gboolean any_sets = FALSE;
  2990     *expanded_xml = NULL;
  2992     CRM_CHECK(xml_obj != NULL, 
return FALSE);
  2997                          crm_element_name(xml_obj));
  3002     expand_tags_in_sets(xml_obj, &new_xml, data_set);
  3006         *expanded_xml = new_xml;
  3011     if (id_lh == NULL) {
  3015     if (valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh) == FALSE) {
  3017                          "valid resource or tag", 
id, id_lh);
  3020     } 
else if (rsc_lh) {
  3047         *expanded_xml = new_xml;
  3058     xmlNode *
set = NULL;
  3059     gboolean any_sets = FALSE;
  3061     const char *
id = NULL;
  3067     xmlNode *orig_xml = NULL;
  3068     xmlNode *expanded_xml = NULL;
  3072     CRM_CHECK(xml_obj != NULL, 
return FALSE);
  3077                          crm_element_name(xml_obj));
  3081     if (data_set->
tickets == NULL) {
  3085     if (ticket_str == NULL) {
  3089         ticket = g_hash_table_lookup(data_set->
tickets, ticket_str);
  3092     if (ticket == NULL) {
  3094         if (ticket == NULL) {
  3099     rc = unpack_rsc_ticket_tags(xml_obj, &expanded_xml, data_set);
  3102         xml_obj = expanded_xml;
  3104     } 
else if (
rc == FALSE) {
  3108     for (
set = pcmk__xe_first_child(xml_obj); 
set != NULL;
  3109          set = pcmk__xe_next(
set)) {
  3114             if (unpack_rsc_ticket_set(
set, ticket, loss_policy, data_set) == FALSE) {
  3125     if (any_sets == FALSE) {
  3126         return unpack_simple_rsc_ticket(xml_obj, data_set);
 GList * pcmk__copy_node_list(const GList *list, bool reset)
 
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object. 
 
#define CRM_CHECK(expr, failure_action)
 
gboolean unpack_constraints(xmlNode *xml_constraints, pe_working_set_t *data_set)
 
pe_node_t * pe_find_node(GList *node_list, const char *uname)
 
enum rsc_role_e role_filter
 
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
 
const char * pe_node_attribute_calculated(const pe_node_t *node, const char *name, const pe_resource_t *rsc)
 
#define XML_ORDER_ATTR_THEN_ACTION
 
#define pe__set_action_flags(action, flags_to_set)
 
gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc)
 
int custom_action_order(pe_resource_t *lh_rsc, char *lh_action_task, pe_action_t *lh_action, pe_resource_t *rh_rsc, char *rh_action_task, pe_action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set)
 
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet. 
 
int pcmk__scan_min_int(const char *text, int *result, int minimum)
 
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
 
#define XML_ORDER_ATTR_THEN
 
#define XML_COLOC_ATTR_TARGET_INSTANCE
 
struct crm_time_s crm_time_t
 
void pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
 
#define CRM_OP_RELAXED_SET
 
#define pcmk__config_warn(fmt...)
 
#define RSC_ROLE_STARTED_S
 
gboolean pe_test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, crm_time_t *next_change, pe_match_data_t *match_data)
 
#define XML_RULE_ATTR_SCORE
 
#define XML_BOOLEAN_FALSE
 
int new_rsc_order(pe_resource_t *lh_rsc, const char *lh_task, pe_resource_t *rh_rsc, const char *rh_task, enum pe_ordering type, pe_working_set_t *data_set)
 
void rsc_ticket_constraint(pe_resource_t *lh_rsc, rsc_ticket_t *rsc_ticket, pe_working_set_t *data_set)
 
xmlNode * first_named_child(const xmlNode *parent, const char *name)
 
#define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name)
 
int char2score(const char *score)
 
#define pcmk__config_err(fmt...)
 
#define XML_LOCATION_ATTR_DISCOVERY
 
resource_object_functions_t * fns
 
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value. 
 
pe_node_t * pe__copy_node(const pe_node_t *this_node)
 
#define CRMD_ACTION_PROMOTE
 
#define XML_CONS_TAG_RSC_DEPEND
 
int order_id
Deprecated (will be removed in a future release) 
 
#define XML_CONS_TAG_RSC_TICKET
 
enum crm_ais_msg_types type
 
pe_node_t * partial_migration_target
 
#define XML_COLOC_ATTR_TARGET_ROLE
 
#define XML_ORDER_ATTR_FIRST_INSTANCE
 
#define XML_LOC_ATTR_SOURCE
 
#define XML_CONS_TAG_RSC_SET
 
xmlDoc * getDocPtr(xmlNode *node)
 
#define CRMD_ACTION_START
 
#define XML_RSC_ATTR_INCARNATION_MIN
 
xmlNode * copy_xml(xmlNode *src_node)
 
const char * role2text(enum rsc_role_e role)
 
pe__location_t * rsc2node_new(const char *id, pe_resource_t *rsc, int weight, const char *discovery_mode, pe_node_t *node, pe_working_set_t *data_set)
 
#define XML_ORDER_ATTR_FIRST
 
GList * ticket_constraints
 
#define crm_warn(fmt, args...)
 
#define CRMD_ACTION_DEMOTE
 
#define XML_COLOC_ATTR_TARGET
 
gboolean unpack_rsc_order(xmlNode *xml_obj, pe_working_set_t *data_set)
 
#define pe_rsc_allow_migrate
 
pe_action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
 
#define crm_debug(fmt, args...)
 
pe_resource_t * uber_parent(pe_resource_t *rsc)
 
gboolean unpack_rsc_ticket(xmlNode *xml_obj, pe_working_set_t *data_set)
 
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute. 
 
#define XML_LOC_ATTR_SOURCE_PATTERN
 
#define XML_CONS_TAG_RSC_LOCATION
 
#define pe_warn_once(pe_wo_bit, fmt...)
 
pe_ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
 
#define crm_trace(fmt, args...)
 
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
 
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag. 
 
struct pe_node_shared_s * details
 
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
 
pe_resource_t * find_clone_instance(pe_resource_t *rsc, const char *sub_id, pe_working_set_t *data_set)
 
enum loss_ticket_policy_e loss_policy
 
#define pe_rsc_promotable
 
GHashTable * pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters. 
 
Wrappers for and extensions to libxml2. 
 
xmlNode * create_xml_node(xmlNode *parent, const char *name)
 
long long int crm_time_get_seconds_since_epoch(crm_time_t *dt)
 
enum pe_restart restart_type
 
#define pe_flag_stonith_enabled
 
#define XML_COLOC_ATTR_SOURCE_INSTANCE
 
#define XML_TAG_RESOURCE_REF
 
char * pe_expand_re_matches(const char *string, pe_re_match_data_t *match_data)
 
void free_xml(xmlNode *child)
 
enum rsc_role_e text2role(const char *role)
 
enum pe_obj_types variant
 
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL) 
 
#define XML_COLOC_ATTR_SOURCE_ROLE
 
#define XML_RULE_ATTR_BOOLEAN_OP
 
void pcmk__new_colocation(const char *id, const char *node_attr, int score, pe_resource_t *rsc_lh, pe_resource_t *rsc_rh, const char *state_lh, const char *state_rh, bool influence, pe_working_set_t *data_set)
 
const xmlChar * pcmkXmlStr
 
pe_node_t * pe_find_node_id(GList *node_list, const char *id)
 
match resource ID or LRM history ID 
 
#define XML_ORDER_ATTR_THEN_INSTANCE
 
#define XML_COLOC_ATTR_NODE_ATTR
 
int crm_str_to_boolean(const char *s, int *ret)
 
Cluster status and scheduling. 
 
#define XML_COLOC_ATTR_INFLUENCE
 
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
 
GList * ordering_constraints
 
#define XML_ORDER_ATTR_KIND
 
int pe__add_scores(int score1, int score2)
 
#define crm_err(fmt, args...)
 
GList * colocation_constraints
 
void xml_remove_prop(xmlNode *obj, const char *name)
 
#define CRM_OP_RELAXED_CLONE
 
gboolean pe_evaluate_rules(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now, crm_time_t *next_change)
Evaluate any rules contained by given XML element. 
 
rsc_role_e
Possible roles that a resource can be in. 
 
const char * node_attribute
 
#define XML_CONS_TAG_RSC_ORDER
 
void destroy_ticket(gpointer data)
 
#define RSC_ROLE_UNKNOWN_S
 
#define crm_log_xml_trace(xml, text)
 
#define XML_RULE_ATTR_SCORE_ATTRIBUTE
 
enum pe_ordering get_flags(const char *id, enum pe_order_kind kind, const char *action_first, const char *action_then, gboolean invert)
 
gboolean crm_is_true(const char *s)
 
enum pe_ordering get_asymmetrical_flags(enum pe_order_kind kind)
 
#define XML_TICKET_ATTR_TICKET
 
#define pe_rsc_trace(rsc, fmt, args...)
 
#define pe__set_order_flags(order_flags, flags_to_set)
 
gboolean rsc_ticket_new(const char *id, pe_resource_t *rsc_lh, pe_ticket_t *ticket, const char *state_lh, const char *loss_policy, pe_working_set_t *data_set)
 
pe_resource_t *(* find_rsc)(pe_resource_t *parent, const char *search, const pe_node_t *node, int flags)
 
#define XML_CONS_ATTR_SYMMETRICAL
 
#define crm_info(fmt, args...)
 
GHashTable * template_rsc_sets
 
#define XML_COLOC_ATTR_SOURCE
 
#define XML_ORDER_ATTR_FIRST_ACTION
 
int required_runnable_before
 
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag. 
 
#define XML_RULE_ATTR_ROLE
 
#define XML_TICKET_ATTR_LOSS_POLICY
 
void crm_time_free(crm_time_t *dt)