27#define INFINITY_HACK (PCMK_SCORE_INFINITY * -100)
50 if (pcmk__is_bundle_node(node) && pcmk__is_bundled(rsc)
54 }
else if (rsc != NULL) {
92 if (colocation1 == NULL) {
95 if (colocation2 == NULL) {
129 if (pcmk__is_clone(rsc1)) {
140 return strcmp(rsc1->
id, rsc2->
id);
164cmp_dependent_priority(gconstpointer a, gconstpointer b)
166 return cmp_colocation_priority(a, b,
true);
190cmp_primary_priority(gconstpointer a, gconstpointer b)
192 return cmp_colocation_priority(a, b,
false);
210 pcmk__assert((list != NULL) && (colocation != NULL) && (rsc != NULL));
213 "Adding colocation %s (%s with %s using %s @%s) to "
214 "'this with' list for %s",
218 *list = g_list_insert_sorted(*list, (gpointer) colocation,
219 cmp_primary_priority);
244 *list = g_list_copy(addition);
250 for (
const GList *iter = addition; iter != NULL; iter = iter->next) {
270 pcmk__assert((list != NULL) && (colocation != NULL) && (rsc != NULL));
273 "Adding colocation %s (%s with %s using %s @%s) to "
274 "'with this' list for %s",
278 *list = g_list_insert_sorted(*list, (gpointer) colocation,
279 cmp_dependent_priority);
304 *list = g_list_copy(addition);
310 for (
const GList *iter = addition; iter != NULL; iter = iter->next) {
328 const char *first_tasks[] = { NULL, NULL };
329 const char *then_tasks[] = { NULL, NULL };
355 for (
int first_lpc = 0;
356 (first_lpc <= 1) && (first_tasks[first_lpc] != NULL); first_lpc++) {
358 for (
int then_lpc = 0;
359 (then_lpc <= 1) && (then_tasks[then_lpc] != NULL); then_lpc++) {
362 then_rsc, then_tasks[then_lpc],
386 const char *dependent_role_spec,
387 const char *primary_role_spec, uint32_t
flags)
395 if ((dependent == NULL) || (primary == NULL)) {
397 "does not exist",
id);
410 "Ignoring colocation '%s' (%s with %s) because score is 0",
411 id, dependent->
id, primary->
id);
419 new_con->
score = score;
436 anti_colocation_order(dependent, new_con->
dependent_role, primary,
438 anti_colocation_order(primary, new_con->
primary_role, dependent,
457 const char *influence_s)
459 if (influence_s != NULL) {
477unpack_colocation_set(xmlNode *set,
int score,
const char *coloc_id,
480 xmlNode *xml_rsc = NULL;
483 const char *set_id = pcmk__xe_id(set);
485 bool with_previous =
false;
486 int local_score = score;
487 bool sequential =
false;
489 const char *xml_rsc_id = NULL;
492 if (score_s != NULL) {
497 "because '%s' is not a valid score",
498 coloc_id, set_id, score_s);
502 if (local_score == 0) {
503 crm_trace(
"Ignoring colocation '%s' for set '%s' because score is 0",
515 with_previous =
true;
520 " (such as %s) is deprecated and will be removed in a"
531 if (local_score > 0) {
537 xml_rsc_id = pcmk__xe_id(xml_rsc);
541 if (resource == NULL) {
544 "No such resource", xml_rsc_id, set_id);
549 | unpack_influence(coloc_id, resource, influence_s);
552 resource->
id, other->
id, set_id);
554 other, role, role,
flags);
557 other->
id, resource->
id, set_id);
559 resource, role, role,
flags);
576 xmlNode *xml_rsc_with = NULL;
578 xml_rsc_id = pcmk__xe_id(xml_rsc);
582 if (resource == NULL) {
585 "No such resource", xml_rsc_id, set_id);
589 | unpack_influence(coloc_id, resource, influence_s);
592 xml_rsc_with != NULL;
596 xml_rsc_id = pcmk__xe_id(xml_rsc_with);
605 resource, other, role, role,
flags);
624colocate_rsc_sets(
const char *
id,
const xmlNode *set1,
const xmlNode *set2,
625 int score,
const char *influence_s,
628 xmlNode *xml_rsc = NULL;
632 const char *xml_rsc_id = NULL;
637 bool sequential =
false;
641 crm_trace(
"Ignoring colocation '%s' between sets %s and %s "
642 "because score is 0",
643 id, pcmk__xe_id(set1), pcmk__xe_id(set2));
651 if (xml_rsc != NULL) {
652 xml_rsc_id = pcmk__xe_id(xml_rsc);
658 "because first resource %s not found",
659 pcmk__xe_id(set1), pcmk__xe_id(set2),
674 xml_rsc_id = pcmk__xe_id(xml_rsc);
681 "because last resource %s not found",
682 pcmk__xe_id(set1), pcmk__xe_id(set2), xml_rsc_id);
687 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
692 }
else if (rsc_1 != NULL) {
699 xml_rsc_id = pcmk__xe_id(xml_rsc);
705 "in set %s: No such resource",
706 pcmk__xe_id(set1), xml_rsc_id,
714 }
else if (rsc_2 != NULL) {
720 xml_rsc_id = pcmk__xe_id(xml_rsc);
726 "with set %s: No such resource",
727 pcmk__xe_id(set1), xml_rsc_id,
732 | unpack_influence(
id, rsc_1, influence_s);
743 xmlNode *xml_rsc_2 = NULL;
745 xml_rsc_id = pcmk__xe_id(xml_rsc);
751 "with set %s: No such resource",
752 pcmk__xe_id(set1), xml_rsc_id,
758 | unpack_influence(
id, rsc_1, influence_s);
764 xml_rsc_id = pcmk__xe_id(xml_rsc_2);
771 "%s with set %s resource %s: No such "
773 pcmk__xe_id(set1), pcmk__xe_id(xml_rsc),
774 pcmk__xe_id(set2), xml_rsc_id);
778 role_1, role_2,
flags);
795unpack_simple_colocation(
const xmlNode *xml_obj,
const char *
id,
int score,
815 if (dependent == NULL) {
817 "does not exist",
id, dependent_id);
820 }
else if (primary == NULL) {
822 "does not exist",
id, primary_id);
834 dependent_role, primary_role,
flags);
839unpack_colocation_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
842 const char *
id = NULL;
843 const char *dependent_id = NULL;
844 const char *primary_id = NULL;
845 const char *dependent_role = NULL;
846 const char *primary_role = NULL;
854 xmlNode *dependent_set = NULL;
855 xmlNode *primary_set = NULL;
856 bool any_sets =
false;
858 *expanded_xml = NULL;
860 CRM_CHECK(xml_obj != NULL,
return EINVAL);
862 id = pcmk__xe_id(xml_obj);
871 if (*expanded_xml != NULL) {
878 if ((dependent_id == NULL) || (primary_id == NULL)) {
885 "valid resource or tag",
id, dependent_id);
892 "valid resource or tag",
id, primary_id);
896 if ((dependent != NULL) && (primary != NULL)) {
901 if ((dependent_tag != NULL) && (primary_tag != NULL)) {
904 "tags cannot be colocated",
id);
919 *expanded_xml = NULL;
923 if (dependent_set != NULL) {
924 if (dependent_role != NULL) {
940 *expanded_xml = NULL;
944 if (primary_set != NULL) {
945 if (primary_role != NULL) {
959 *expanded_xml = NULL;
977 xmlNode *last = NULL;
979 xmlNode *orig_xml = NULL;
980 xmlNode *expanded_xml = NULL;
983 const char *score = NULL;
984 const char *influence_s = NULL;
986 if (pcmk__str_empty(
id)) {
992 if (unpack_colocation_tags(xml_obj, &expanded_xml,
996 if (expanded_xml != NULL) {
998 xml_obj = expanded_xml;
1002 if (score != NULL) {
1007 "is not a valid score",
id, score);
1018 if (expanded_xml != NULL) {
1024 if (pcmk__str_empty(pcmk__xe_id(set))) {
1029 unpack_colocation_set(set, score_i,
id, influence_s,
scheduler);
1032 colocate_rsc_sets(
id, last, set, score_i, influence_s,
scheduler);
1043 unpack_simple_colocation(xml_obj,
id, score_i, influence_s,
scheduler);
1108 for (iter = rsc->
priv->
actions; iter != NULL; iter = iter->next) {
1122 for (iter = rsc->
priv->
children; iter != NULL; iter = iter->next) {
1142 GList *colocations = NULL;
1144 bool is_start =
false;
1168 for (iter = rsc->
priv->
children; iter != NULL; iter = iter->next) {
1174 if ((child_action == NULL)
1176 crm_trace(
"Not blocking %s colocation dependents because "
1177 "at least %s has runnable %s",
1183 crm_trace(
"Blocking %s colocation dependents due to unrunnable %s %s",
1188 for (iter = colocations; iter != NULL; iter = iter->next) {
1214 g_list_free(colocations);
1241 if (child != NULL) {
1275 && (colocation != NULL));
1282 dependent_role_rsc = get_resource_for_role(dependent);
1284 primary_role_rsc = get_resource_for_role(primary);
1287 && (dependent_role_rsc->
priv->
parent != NULL)
1308 crm_trace(
"Skipping %scolocation '%s': dependent limited to %s role "
1310 "but %s next role is %s",
1311 ((colocation->
score < 0)?
"anti-" :
""),
1313 dependent_role_rsc->
id,
1320 crm_trace(
"Skipping %scolocation '%s': primary limited to %s role "
1321 "but %s next role is %s",
1322 ((colocation->
score < 0)?
"anti-" :
""),
1324 primary_role_rsc->
id,
1349 const char *value = NULL;
1350 GHashTable *work = NULL;
1351 GHashTableIter iter;
1358 }
else if (colocation->
score < 0) {
1365 g_hash_table_iter_init(&iter, work);
1366 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1371 "Applied %s to %s score on %s (now %s after "
1372 "subtracting %s because primary %s inactive)",
1373 colocation->
id, dependent->
id,
1374 pcmk__node_name(node),
1393 "Applied %s to %s score on %s (now %s after "
1395 colocation->
id, dependent->
id,
1396 pcmk__node_name(node),
1411 "Banned %s from %s because colocation %s attribute %s "
1413 dependent->
id, pcmk__node_name(node),
1414 colocation->
id, attr);
1428 "%s: Rolling back scores from %s (no available nodes)",
1429 dependent->
id, primary->
id);
1433 g_hash_table_destroy(work);
1455 const char *dependent_value = NULL;
1456 const char *primary_value = NULL;
1458 int score_multiplier = 1;
1459 int priority_delta = 0;
1464 && (colocation != NULL));
1469 if (dependent_node == NULL) {
1473 if ((primary_node != NULL)
1501 score_multiplier = -1;
1512 score_multiplier = -1;
1515 priority_delta = score_multiplier * colocation->
score;
1519 "Applied %s to %s promotion priority (now %s after %s %d)",
1520 colocation->
id, dependent->
id,
1522 ((score_multiplier == 1)?
"adding" :
"subtracting"),
1525 return priority_delta;
1542 GHashTable *allowed_nodes_orig = NULL;
1543 GHashTableIter iter;
1546 const char *best_node = NULL;
1548 if ((colocation != NULL) && (rsc == colocation->
dependent)
1566 loc_iter != NULL; loc_iter = loc_iter->next) {
1578 while (g_hash_table_iter_next(&iter, NULL, (
void **) &node)) {
1580 if ((node->assign->score > best_score)
1585 best_score = node->assign->score;
1586 best_node = node->priv->name;
1591 if (best_node == NULL) {
1592 crm_info(
"No allowed node for %s matches node attribute %s=%s",
1593 rsc->
id, attr, value);
1595 crm_info(
"Allowed node %s for %s had best score (%d) "
1596 "of those matching node attribute %s=%s",
1597 best_node, rsc->
id, best_score, attr, value);
1601 if (allowed_nodes_orig != NULL) {
1619 GHashTableIter iter;
1621 int allowed_nodes = 0;
1624 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &allowed_node)) {
1625 if ((allowed_node->assign->score >= 0) && (++allowed_nodes > 1)) {
1631 ((allowed_nodes == 1)?
"on a single node" :
"nowhere"));
1632 return (allowed_nodes == 1);
1654add_node_scores_matching_attr(GHashTable *nodes,
1658 float factor,
bool only_positive)
1660 GHashTableIter iter;
1665 g_hash_table_iter_init(&iter, nodes);
1666 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1673 score = best_node_score_matching_attr(colocation, source_rsc, attr, value);
1675 if ((factor < 0) && (score < 0)) {
1711 || !allowed_on_one(colocation->
dependent)) {
1713 "(double negative disallowed)",
1714 pcmk__node_name(node), node->assign->score, factor,
1721 crm_trace(
"%s: Filtering %d + %f * %d (node was marked unusable)",
1722 pcmk__node_name(node), node->assign->score, factor,
1727 delta_f = factor * score;
1730 delta = (int) ((delta_f < 0)? (delta_f - 0.5) : (delta_f + 0.5));
1736 if ((delta == 0) && (score != 0)) {
1739 }
else if (factor < 0.0) {
1746 if (only_positive && (new_score < 0) && (node->assign->score > 0)) {
1747 crm_trace(
"%s: Filtering %d + %f * %d = %d "
1748 "(negative disallowed, marking node unusable)",
1749 pcmk__node_name(node), node->assign->score, factor, score,
1755 if (only_positive && (new_score < 0) && (node->assign->score == 0)) {
1756 crm_trace(
"%s: Filtering %d + %f * %d = %d (negative disallowed)",
1757 pcmk__node_name(node), node->assign->score, factor, score,
1762 crm_trace(
"%s: %d + %f * %d = %d", pcmk__node_name(node),
1763 node->assign->score, factor, score, new_score);
1764 node->assign->score = new_score;
1804 float factor, uint32_t
flags)
1806 GHashTable *work = NULL;
1809 && ((colocation != NULL)
1810 || ((target_rsc == NULL) && (*nodes == NULL))));
1812 if (log_id == NULL) {
1813 log_id = source_rsc->
id;
1819 log_id, source_rsc->
id);
1824 if (*nodes == NULL) {
1826 target_rsc = source_rsc;
1830 pcmk__rsc_trace(source_rsc,
"%s: Merging %s scores from %s (at %.6f)",
1831 log_id, (pos?
"positive" :
"all"), source_rsc->
id, factor);
1833 add_node_scores_matching_attr(work, source_rsc, target_rsc, colocation,
1843 GList *colocations = NULL;
1848 "Checking additional %d optional '%s with' "
1850 g_list_length(colocations), source_rsc->
id);
1854 "Checking additional %d optional 'with %s' "
1856 g_list_length(colocations), source_rsc->
id);
1860 for (GList *iter = colocations; iter != NULL; iter = iter->next) {
1864 float other_factor = factor * constraint->
score
1876 "Optionally merging score of '%s' constraint "
1883 other_factor,
flags);
1887 g_list_free(colocations);
1890 pcmk__rsc_info(source_rsc,
"%s: Rolling back optional scores from %s",
1891 log_id, source_rsc->
id);
1892 g_hash_table_destroy(work);
1900 GHashTableIter iter;
1902 g_hash_table_iter_init(&iter, work);
1903 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
1910 if (*nodes != NULL) {
1911 g_hash_table_destroy(*nodes);
1938 if (pcmk__is_clone(primary)) {
1942 "%s: Incorporating attenuated %s assignment scores due "
1944 primary->
id, dependent->
id, colocation->
id);
1948 colocation, factor,
flags);
1972 const GList *primary_nodes,
bool merge_scores)
1974 GHashTableIter iter;
1978 && (colocation != NULL));
1981 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &dependent_node)) {
1985 dependent_node->
priv->
id);
1986 if (primary_node == NULL) {
1989 "Banning %s from %s (no primary instance) for %s",
1990 dependent->
id, pcmk__node_name(dependent_node),
1993 }
else if (merge_scores) {
1998 "Added %s's score %s to %s's score for %s (now %d) "
1999 "for colocation %s",
2002 dependent->
id, pcmk__node_name(dependent_node),
@ pcmk__ar_if_required_on_same_node
Ordering applies only if 'first' is required and on same node as 'then'.
#define PCMK_ACTION_PROMOTE
#define PCMK_ACTION_START
#define PCMK_ACTION_DEMOTE
#define pcmk__clear_action_flags(action, flags_to_clear)
const char * pcmk__node_attr(const pcmk_node_t *node, const char *name, const char *target, enum pcmk__rsc_node node_type)
#define pcmk__assert_alloc(nmemb, size)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
@ pcmk__coloc_select_active
@ pcmk__coloc_select_this_with
@ pcmk__coloc_select_nonnegative
G_GNUC_INTERNAL bool pcmk__any_node_available(GHashTable *nodes)
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
G_GNUC_INTERNAL pcmk_resource_t * pcmk__find_constraint_resource(GList *rsc_list, const char *id)
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL int pcmk__parse_constraint_role(const char *id, const char *role_spec, enum rsc_role_e *role)
G_GNUC_INTERNAL void pcmk__update_action_for_orderings(pcmk_action_t *action, pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL bool pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr, bool convert_rsc, const pcmk_scheduler_t *scheduler)
@ pcmk__coloc_affects_nothing
@ pcmk__coloc_affects_location
@ pcmk__coloc_affects_role
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(const pcmk_scheduler_t *scheduler, const char *id, pcmk_resource_t **rsc, pcmk__idref_t **tag)
G_GNUC_INTERNAL bool pcmk__node_available(const pcmk_node_t *node, bool consider_score, bool consider_guest)
G_GNUC_INTERNAL GHashTable * pcmk__copy_node_table(GHashTable *nodes)
#define crm_info(fmt, args...)
#define CRM_CHECK(expr, failure_action)
#define crm_log_xml_trace(xml, text)
#define crm_trace(fmt, args...)
#define pcmk__config_warn(fmt...)
#define pcmk__config_err(fmt...)
#define pcmk__if_tracing(if_action, else_action)
#define pcmk__warn_once(wo_flag, fmt...)
pcmk_scheduler_t * scheduler
#define PCMK_META_CONTAINER_ATTRIBUTE_TARGET
#define PCMK__VALUE_GROUP
void pcmk__add_this_with_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
void pcmk__new_colocation(const char *id, const char *node_attr, int score, pcmk_resource_t *dependent, pcmk_resource_t *primary, const char *dependent_role_spec, const char *primary_role_spec, uint32_t flags)
void pcmk__add_with_this_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
bool pcmk__colocation_has_influence(const pcmk__colocation_t *colocation, const pcmk_resource_t *rsc)
GList * pcmk__with_this_colocations(const pcmk_resource_t *rsc)
void pcmk__unpack_colocation(xmlNode *xml_obj, pcmk_scheduler_t *scheduler)
GList * pcmk__this_with_colocations(const pcmk_resource_t *rsc)
void pcmk__colocation_intersect_nodes(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, const GList *primary_nodes, bool merge_scores)
void pcmk__add_dependent_scores(gpointer data, gpointer user_data)
void pcmk__apply_coloc_to_scores(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation)
int pcmk__apply_coloc_to_priority(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation)
enum pcmk__coloc_affects pcmk__colocation_affects(const pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool preview)
void pcmk__add_this_with(GList **list, const pcmk__colocation_t *colocation, const pcmk_resource_t *rsc)
const char * pcmk__colocation_node_attr(const pcmk_node_t *node, const char *attr, const pcmk_resource_t *rsc)
void pcmk__block_colocation_dependents(pcmk_action_t *action)
void pcmk__add_with_this(GList **list, const pcmk__colocation_t *colocation, const pcmk_resource_t *rsc)
void pcmk__add_colocated_node_scores(pcmk_resource_t *source_rsc, const pcmk_resource_t *target_rsc, const char *log_id, GHashTable **nodes, const pcmk__colocation_t *colocation, float factor, uint32_t flags)
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
#define pe__show_node_scores(level, rsc, text, nodes, scheduler)
const pcmk_resource_t * pe__get_rsc_in_container(const pcmk_resource_t *instance)
pcmk_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pcmk_node_t *on_node)
void pe_action_set_reason(pcmk_action_t *action, const char *reason, bool overwrite)
pcmk_resource_t * pe__bundled_resource(const pcmk_resource_t *rsc)
@ pcmk__rsc_replica_container
@ pcmk__rsc_updating_nodes
@ pcmk__rsc_remote_nesting_allowed
#define pcmk__set_rsc_flags(resource, flags_to_set)
@ pcmk__rsc_node_assigned
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
#define pcmk__assert(expr)
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
@ pcmk_role_unknown
Resource role is unknown.
@ pcmk_role_unpromoted
Unpromoted.
@ pcmk_role_promoted
Promoted.
#define pcmk__rsc_info(rsc, fmt, args...)
#define pcmk__rsc_trace(rsc, fmt, args...)
int pcmk_parse_score(const char *score_s, int *score, int default_score)
Parse an integer score from a string.
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
int pcmk__add_scores(int score1, int score2)
Cluster status and scheduling.
pcmk_node_t * pe_find_node_id(const GList *node_list, const char *id)
Find a node by ID in a list of nodes.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int crm_str_to_boolean(const char *s, int *ret)
void(* this_with_colocations)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void(* add_colocated_node_scores)(pcmk_resource_t *source_rsc, const pcmk_resource_t *target_rsc, const char *log_id, GHashTable **nodes, const pcmk__colocation_t *colocation, float factor, uint32_t flags)
void(* with_this_colocations)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void(* apply_location)(pcmk_resource_t *rsc, pcmk__location_t *location)
const char * node_attribute
pcmk_resource_t * primary
pcmk_resource_t * dependent
Location constraint object.
pcmk_node_t * assigned_node
GList * this_with_colocations
GList * with_this_colocations
pcmk_scheduler_t * scheduler
enum pcmk__rsc_variant variant
enum rsc_role_e next_role
const pcmk__assignment_methods_t * cmds
GHashTable * allowed_nodes
pcmk__resource_private_t * priv
GList * colocation_constraints
GList * location_constraints
pcmk__scheduler_private_t * priv
pcmk__node_private_t * priv
struct pcmk__node_assignment * assign
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
xmlNode * pcmk__xe_resolve_idref(xmlNode *xml, xmlNode *search)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
void pcmk__xml_free(xmlNode *xml)
#define PCMK_XA_SYMMETRICAL
#define PCMK_XA_WITH_RSC_ROLE
#define PCMK_XE_RESOURCE_REF
#define PCMK_XA_NODE_ATTRIBUTE
#define PCMK_XE_RSC_COLOCATION
#define PCMK_XA_INFLUENCE
#define PCMK_XE_RESOURCE_SET
#define PCMK_XA_SEQUENTIAL
#define PCMK__XA_ORDERING