32 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \ 33 __rsc = pcmk__find_constraint_resource(data_set->resources, __name); \ 34 if (__rsc == NULL) { \ 35 pcmk__config_err("%s: No resource found for %s", __set, __name); \ 36 return pcmk_rc_unpack_error; \ 41 invert_action(
const char *
action)
67 crm_warn(
"Unknown action '%s' specified in order constraint",
action);
72 get_ordering_type(
const xmlNode *xml_obj)
90 "Support for 'score' in rsc_order is deprecated " 91 "and will be removed in a future release " 92 "(use 'kind' instead)");
106 "%s to 'Mandatory' because '%s' is not valid",
107 pcmk__s(
ID(xml_obj),
"missing ID"), kind);
124 get_ordering_symmetry(
const xmlNode *xml_obj,
enum pe_order_kind parent_kind,
125 const char *parent_symmetrical_s)
128 bool symmetric =
false;
134 kind = get_ordering_type(xml_obj);
140 if (rc !=
pcmk_rc_ok && parent_symmetrical_s != NULL) {
149 " for '%s' because not valid with " 177 ordering_flags_for_kind(
enum pe_order_kind kind,
const char *first,
229 get_ordering_resource(
const xmlNode *xml,
const char *resource_attr,
230 const char *instance_attr,
238 if (rsc_id == NULL) {
240 ID(xml), resource_attr);
247 "does not exist",
ID(xml), rsc_id);
251 if (instance_id != NULL) {
255 "removed in a future release.");
257 if (!pe_rsc_is_clone(rsc)) {
259 "is not a clone but instance '%s' was requested",
260 ID(xml), rsc_id, instance_id);
266 "does not have an instance '%s'",
267 "'%s'",
ID(xml), rsc_id, instance_id);
284 get_minimum_first_instances(
const pe_resource_t *rsc,
const xmlNode *xml)
286 const char *clone_min = NULL;
287 bool require_all =
false;
289 if (!pe_rsc_is_clone(rsc)) {
293 clone_min = g_hash_table_lookup(rsc->
meta,
295 if (clone_min != NULL) {
296 int clone_min_int = 0;
299 return clone_min_int;
307 "Support for require-all in ordering constraints " 308 "is deprecated and will be removed in a future release" 309 " (use clone-min clone meta-attribute instead)");
332 clone_min_ordering(
const char *
id,
350 for (GList *rIter = rsc_first->
children; rIter != NULL;
351 rIter = rIter->next) {
356 NULL, NULL, NULL, clone_min_met,
380 #define handle_restart_type(rsc, kind, flag, flags) do { \ 381 if (((kind) == pe_order_kind_optional) \ 382 && ((rsc)->restart_type == pe_restart_restart)) { \ 383 pe__set_order_flags((flags), (flag)); \ 403 action_then = invert_action(action_then);
404 action_first = invert_action(action_first);
405 if ((action_then == NULL) || (action_first == NULL)) {
407 "(please specify inverse manually)",
id);
409 uint32_t
flags = ordering_flags_for_kind(kind, action_first,
414 action_first,
flags);
423 int min_required_before = 0;
428 const char *action_then = NULL;
429 const char *action_first = NULL;
430 const char *
id = NULL;
437 crm_element_name(xml_obj));
444 if (rsc_first == NULL) {
451 if (rsc_then == NULL) {
456 if (action_first == NULL) {
461 if (action_then == NULL) {
462 action_then = action_first;
465 kind = get_ordering_type(xml_obj);
467 symmetry = get_ordering_symmetry(xml_obj, kind, NULL);
468 cons_weight = ordering_flags_for_kind(kind, action_first, symmetry);
477 min_required_before = get_minimum_first_instances(rsc_first, xml_obj);
478 if (min_required_before > 0) {
479 clone_min_ordering(
id, rsc_first, action_first, rsc_then, action_then,
480 cons_weight, min_required_before,
data_set);
483 action_then, cons_weight);
487 inverse_ordering(
id, kind, rsc_first, action_first,
488 rsc_then, action_then);
529 CRM_CHECK(((first_action != NULL) || (first_rsc != NULL))
530 && ((then_action != NULL) || (then_rsc != NULL)),
531 free(first_action_task); free(then_action_task);
return);
533 if ((first_rsc == NULL) && (first_action != NULL)) {
534 first_rsc = first_action->
rsc;
536 if ((then_rsc == NULL) && (then_action != NULL)) {
537 then_rsc = then_action->
rsc;
545 order->
lh_rsc = first_rsc;
560 if ((order->
lh_rsc == NULL) && (first_action != NULL)) {
564 if ((order->
rh_rsc == NULL) && (then_action != NULL)) {
568 pe_rsc_trace(first_rsc,
"Created ordering %d for %s then %s",
589 unpack_order_set(
const xmlNode *
set,
enum pe_order_kind parent_kind,
592 GList *set_iter = NULL;
593 GList *resources = NULL;
598 int local_kind = parent_kind;
599 bool sequential =
false;
604 const char *
id =
ID(
set);
614 local_kind = get_ordering_type(
set);
616 if (sequential_s == NULL) {
622 symmetry = get_ordering_symmetry(
set, parent_kind, parent_symmetrical_s);
623 flags = ordering_flags_for_kind(local_kind,
action, symmetry);
629 resources = g_list_append(resources, resource);
632 if (pcmk__list_of_1(resources)) {
637 set_iter = resources;
638 while (set_iter != NULL) {
640 set_iter = set_iter->next;
647 for (GList *gIter = set_iter; gIter != NULL; gIter = gIter->next) {
655 }
else if (sequential) {
672 flags = ordering_flags_for_kind(local_kind,
action,
675 set_iter = resources;
676 while (set_iter != NULL) {
678 set_iter = set_iter->next;
690 g_list_free(resources);
707 order_rsc_sets(
const char *
id,
const xmlNode *set1,
const xmlNode *set2,
712 const xmlNode *xml_rsc = NULL;
713 const xmlNode *xml_rsc_2 = NULL;
723 bool require_all =
true;
727 if (action_1 == NULL) {
731 if (action_2 == NULL) {
736 action_1 = invert_action(action_1);
737 action_2 = invert_action(action_2);
750 flags = ordering_flags_for_kind(kind, action_1, symmetry);
772 NULL, NULL, NULL, unordered_action,
797 if (xml_rsc != NULL) {
803 const char *rid = NULL;
817 const char *rid = NULL;
829 if (xml_rsc != NULL) {
835 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
838 }
else if (rsc_1 != NULL) {
847 }
else if (rsc_2 != NULL) {
887 unpack_order_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
890 const char *id_first = NULL;
891 const char *id_then = NULL;
892 const char *action_first = NULL;
893 const char *action_then = NULL;
900 xmlNode *rsc_set_first = NULL;
901 xmlNode *rsc_set_then = NULL;
902 bool any_sets =
false;
906 if (*expanded_xml != NULL) {
913 if ((id_first == NULL) || (id_then == NULL)) {
920 "valid resource or tag",
ID(xml_obj), id_first);
926 "valid resource or tag",
ID(xml_obj), id_then);
930 if ((rsc_first != NULL) && (rsc_then != NULL)) {
944 *expanded_xml = NULL;
948 if (rsc_set_first != NULL) {
949 if (action_first != NULL) {
951 crm_xml_add(rsc_set_first,
"action", action_first);
961 *expanded_xml = NULL;
965 if (rsc_set_then != NULL) {
966 if (action_then != NULL) {
978 *expanded_xml = NULL;
995 xmlNode *last = NULL;
997 xmlNode *orig_xml = NULL;
998 xmlNode *expanded_xml = NULL;
1011 if (expanded_xml != NULL) {
1013 xml_obj = expanded_xml;
1024 if (expanded_xml != NULL) {
1032 if (order_rsc_sets(
id, last,
set, kind,
data_set,
1034 if (expanded_xml != NULL) {
1041 && (order_rsc_sets(
id,
set, last, kind,
data_set,
1043 if (expanded_xml != NULL) {
1060 return unpack_simple_rsc_order(xml_obj,
data_set);
1071 && (
input->action->rsc != NULL)
1074 crm_warn(
"Invalid ordering constraint between %s and %s",
1098 for (GList *iter =
data_set->
actions; iter != NULL; iter = iter->next) {
1102 for (GList *input_iter =
action->actions_before;
1103 input_iter != NULL; input_iter = input_iter->next) {
1124 iter != NULL; iter = iter->next) {
1139 "Not ordering %s before shutdown of %s because " 1140 "resource in maintenance mode",
1141 action->uuid, pe__node_name(node));
1146 "Not ordering %s before shutdown of %s because " 1147 "node in maintenance mode",
1148 action->uuid, pe__node_name(node));
1156 if (!pcmk_any_flags_set(
action->rsc->flags,
1159 "Not ordering %s before shutdown of %s because " 1160 "resource is unmanaged or blocked",
1161 action->uuid, pe__node_name(node));
1166 action->uuid, pe__node_name(node));
1186 find_actions_by_task(
const pe_resource_t *rsc,
const char *original_key)
1195 guint interval_ms = 0;
1197 if (
parse_op_key(original_key, NULL, &task, &interval_ms)) {
1203 crm_err(
"Invalid operation key (bug?): %s", original_key);
1218 order_resource_actions_after(
pe_action_t *first_action,
1221 GList *then_actions = NULL;
1224 CRM_CHECK((rsc != NULL) && (order != NULL),
return);
1227 pe_rsc_trace(rsc,
"Applying ordering %d for 'then' resource %s",
1228 order->
id, rsc->
id);
1231 then_actions = g_list_prepend(NULL, order->
rh_action);
1237 if (then_actions == NULL) {
1238 pe_rsc_trace(rsc,
"Ignoring ordering %d: no %s actions found for %s",
1243 if ((first_action != NULL) && (first_action->
rsc == rsc)
1247 "Detected dangling migration ordering (%s then %s %s)",
1254 "Ignoring ordering %d for %s: No first action found",
1255 order->
id, rsc->
id);
1256 g_list_free(then_actions);
1260 for (GList *iter = then_actions; iter != NULL; iter = iter->next) {
1263 if (first_action != NULL) {
1267 crm_warn(
"%s of %s is unrunnable because there is no %s of %s " 1268 "to order it after", then_action_iter->
task, rsc->
id,
1273 g_list_free(then_actions);
1280 GList *first_actions = NULL;
1285 pe_rsc_trace(first_rsc,
"Applying ordering constraint %d (first: %s)",
1286 order->
id, first_rsc->
id);
1288 if (first_action != NULL) {
1289 first_actions = g_list_prepend(NULL, first_action);
1292 first_actions = find_actions_by_task(first_rsc, order->
lh_action_task);
1295 if ((first_actions == NULL) && (first_rsc == then_rsc)) {
1297 "Ignoring constraint %d: first (%s for %s) not found",
1300 }
else if (first_actions == NULL) {
1302 char *op_type = NULL;
1303 guint interval_ms = 0;
1312 "Ignoring constraint %d: first (%s for %s) not found",
1319 "Ignoring constraint %d: first (%s for %s) not found",
1324 "Creating first (%s for %s) for constraint %d ",
1326 first_action =
custom_action(first_rsc, key, op_type, NULL, TRUE,
1328 first_actions = g_list_prepend(NULL, first_action);
1334 if (then_rsc == NULL) {
1336 pe_rsc_trace(first_rsc,
"Ignoring constraint %d: then not found",
1342 for (GList *gIter = first_actions; gIter != NULL; gIter = gIter->next) {
1345 if (then_rsc == NULL) {
1349 order_resource_actions_after(first_action, then_rsc, order);
1353 g_list_free(first_actions);
1359 crm_trace(
"Applying ordering constraints");
1376 gIter != NULL; gIter = gIter->next) {
1382 rsc_order_first(rsc, order,
data_set);
1388 order_resource_actions_after(order->
lh_action, rsc, order);
1391 crm_trace(
"Applying ordering constraint %d (non-resource actions)",
1420 const char *after_desc = (after->
task == NULL)? after->
uuid : after->
task;
1422 for (GList *iter = list; iter != NULL; iter = iter->next) {
1424 const char *before_desc = before->
task? before->
task : before->
uuid;
1426 crm_debug(
"Ordering %s on %s before %s on %s",
1427 before_desc, pe__node_name(before->
node),
1428 after_desc, pe__node_name(after->
node));
#define CRM_CHECK(expr, failure_action)
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
void pcmk__unpack_ordering(xmlNode *xml_obj, pe_working_set_t *data_set)
#define pe_rsc_debug(rsc, fmt, args...)
#define XML_ORDER_ATTR_THEN_ACTION
#define pe__set_action_flags(action, flags_to_set)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
void pcmk__order_after_each(pe_action_t *after, GList *list)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
#define XML_ORDER_ATTR_THEN
#define CRM_OP_RELAXED_SET
#define pcmk__config_warn(fmt...)
#define XML_RULE_ATTR_SCORE
GList * find_actions(GList *input, const char *key, const pe_node_t *on_node)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
int char2score(const char *score)
Get the integer value of a score string.
#define pcmk__config_err(fmt...)
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.
int order_id
Deprecated (will be removed in a future release)
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pe_working_set_t *data_set)
G_GNUC_INTERNAL void pcmk__order_probes(pe_working_set_t *data_set)
void pcmk__new_ordering(pe_resource_t *first_rsc, char *first_action_task, pe_action_t *first_action, pe_resource_t *then_rsc, char *then_action_task, pe_action_t *then_action, uint32_t flags, pe_working_set_t *data_set)
#define XML_ORDER_ATTR_FIRST_INSTANCE
#define XML_CONS_TAG_RSC_SET
pe_working_set_t * data_set
Cluster that this node is part of.
G_GNUC_INTERNAL bool pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr, bool convert_rsc, const pe_working_set_t *data_set)
#define XML_RSC_ATTR_INCARNATION_MIN
xmlNode * copy_xml(xmlNode *src_node)
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(const pe_working_set_t *data_set, const char *id, pe_resource_t **rsc, pe_tag_t **tag)
#define XML_ORDER_ATTR_FIRST
#define crm_warn(fmt, args...)
pe_action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
#define crm_debug(fmt, args...)
#define pe__clear_order_flags(order_flags, flags_to_clear)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
void pcmk__apply_orderings(pe_working_set_t *data_set)
#define pe_warn_once(pe_wo_bit, fmt...)
#define pe__clear_action_flags(action, flags_to_clear)
#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)
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
pe_working_set_t * data_set
void pcmk__order_stops_before_shutdown(pe_node_t *node, pe_action_t *shutdown_op)
#define XML_TAG_RESOURCE_REF
pe_resource_t * find_clone_instance(const pe_resource_t *rsc, const char *sub_id)
#define handle_restart_type(rsc, kind, flag, flags)
void free_xml(xmlNode *child)
G_GNUC_INTERNAL pe_resource_t * pcmk__find_constraint_resource(GList *rsc_list, const char *id)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
#define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name)
void pcmk__promotable_restart_ordering(pe_resource_t *rsc)
#define XML_ORDER_ATTR_THEN_INSTANCE
void pcmk__disable_invalid_orderings(pe_working_set_t *data_set)
enum rsc_role_e(* state)(const pe_resource_t *, gboolean)
G_GNUC_INTERNAL void pcmk__update_action_for_orderings(pe_action_t *action, pe_working_set_t *data_set)
G_GNUC_INTERNAL bool pcmk__graph_has_loop(const pe_action_t *init_action, const pe_action_t *action, pe_action_wrapper_t *input)
GList * ordering_constraints
#define XML_ORDER_ATTR_KIND
#define crm_err(fmt, args...)
void xml_remove_prop(xmlNode *obj, const char *name)
#define CRM_OP_RELAXED_CLONE
enum pe_action_flags flags
#define pe_rsc_maintenance
#define crm_log_xml_trace(xml, text)
gboolean crm_is_true(const char *s)
#define pe_rsc_trace(rsc, fmt, args...)
#define pe__set_order_flags(order_flags, flags_to_set)
G_GNUC_INTERNAL void pcmk__block_colocation_dependents(pe_action_t *action, pe_working_set_t *data_set)
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, const pe_node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Create or update an action object.
#define XML_CONS_ATTR_SYMMETRICAL
G_GNUC_INTERNAL bool pcmk__rsc_corresponds_to_guest(const pe_resource_t *rsc, const pe_node_t *node)
#define XML_ORDER_ATTR_FIRST_ACTION
void pcmk__order_migration_equivalents(pe__ordering_t *order)
int required_runnable_before
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.