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(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(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(xmlNode *xml,
const char *resource_attr,
237 if (rsc_id == NULL) {
239 ID(xml), resource_attr);
246 "does not exist",
ID(xml), rsc_id);
250 if (instance_id != NULL) {
254 "removed in a future release.");
256 if (!pe_rsc_is_clone(rsc)) {
258 "is not a clone but instance '%s' was requested",
259 ID(xml), rsc_id, instance_id);
265 "does not have an instance '%s'",
266 "'%s'",
ID(xml), rsc_id, instance_id);
283 get_minimum_first_instances(
pe_resource_t *rsc, xmlNode *xml)
285 const char *clone_min = NULL;
286 bool require_all =
false;
288 if (!pe_rsc_is_clone(rsc)) {
292 clone_min = g_hash_table_lookup(rsc->
meta,
294 if (clone_min != NULL) {
295 int clone_min_int = 0;
298 return clone_min_int;
306 "Support for require-all in ordering constraints " 307 "is deprecated and will be removed in a future release" 308 " (use clone-min clone meta-attribute instead)");
331 clone_min_ordering(
const char *
id,
349 for (GList *rIter = rsc_first->
children; rIter != NULL;
350 rIter = rIter->next) {
355 NULL, NULL, NULL, clone_min_met,
379 #define handle_restart_type(rsc, kind, flag, flags) do { \ 380 if (((kind) == pe_order_kind_optional) \ 381 && ((rsc)->restart_type == pe_restart_restart)) { \ 382 pe__set_order_flags((flags), (flag)); \ 404 action_then = invert_action(action_then);
405 action_first = invert_action(action_first);
406 if ((action_then == NULL) || (action_first == NULL)) {
408 "(please specify inverse manually)",
id);
410 uint32_t
flags = ordering_flags_for_kind(kind, action_first,
415 action_first,
flags);
424 int min_required_before = 0;
429 const char *action_then = NULL;
430 const char *action_first = NULL;
431 const char *
id = NULL;
438 crm_element_name(xml_obj));
445 if (rsc_first == NULL) {
452 if (rsc_then == NULL) {
457 if (action_first == NULL) {
462 if (action_then == NULL) {
463 action_then = action_first;
466 kind = get_ordering_type(xml_obj);
468 symmetry = get_ordering_symmetry(xml_obj, kind, NULL);
469 cons_weight = ordering_flags_for_kind(kind, action_first, symmetry);
478 min_required_before = get_minimum_first_instances(rsc_first, xml_obj);
479 if (min_required_before > 0) {
480 clone_min_ordering(
id, rsc_first, action_first, rsc_then, action_then,
481 cons_weight, min_required_before,
data_set);
484 action_then, cons_weight);
488 inverse_ordering(
id, kind, rsc_first, action_first,
530 CRM_CHECK(((first_action != NULL) || (first_rsc != NULL))
531 && ((then_action != NULL) || (then_rsc != NULL)),
532 free(first_action_task); free(then_action_task);
return);
534 if ((first_rsc == NULL) && (first_action != NULL)) {
535 first_rsc = first_action->
rsc;
537 if ((then_rsc == NULL) && (then_action != NULL)) {
538 then_rsc = then_action->
rsc;
546 order->
lh_rsc = first_rsc;
561 if ((order->
lh_rsc == NULL) && (first_action != NULL)) {
565 if ((order->
rh_rsc == NULL) && (then_action != NULL)) {
569 pe_rsc_trace(first_rsc,
"Created ordering %d for %s then %s",
571 ((first_action_task == NULL)?
"?" : first_action_task),
572 ((then_action_task == NULL)?
"?" : then_action_task));
590 unpack_order_set(xmlNode *
set,
enum pe_order_kind parent_kind,
593 xmlNode *xml_rsc = NULL;
594 GList *set_iter = NULL;
595 GList *resources = NULL;
600 int local_kind = parent_kind;
601 bool sequential =
false;
606 const char *
id =
ID(
set);
616 local_kind = get_ordering_type(
set);
618 if (sequential_s == NULL) {
624 symmetry = get_ordering_symmetry(
set, parent_kind, parent_symmetrical_s);
625 flags = ordering_flags_for_kind(local_kind,
action, symmetry);
631 resources = g_list_append(resources, resource);
634 if (pcmk__list_of_1(resources)) {
639 set_iter = resources;
640 while (set_iter != NULL) {
642 set_iter = set_iter->next;
649 for (GList *gIter = set_iter; gIter != NULL; gIter = gIter->next) {
657 }
else if (sequential) {
674 flags = ordering_flags_for_kind(local_kind,
action,
677 set_iter = resources;
678 while (set_iter != NULL) {
680 set_iter = set_iter->next;
692 g_list_free(resources);
709 order_rsc_sets(
const char *
id, xmlNode *set1, xmlNode *set2,
714 xmlNode *xml_rsc = NULL;
715 xmlNode *xml_rsc_2 = NULL;
725 bool require_all =
true;
729 if (action_1 == NULL) {
733 if (action_2 == NULL) {
738 action_1 = invert_action(action_1);
739 action_2 = invert_action(action_2);
753 flags = ordering_flags_for_kind(kind, action_2, symmetry);
775 NULL, NULL, NULL, unordered_action,
800 if (xml_rsc != NULL) {
806 const char *rid = NULL;
820 const char *rid = NULL;
832 if (xml_rsc != NULL) {
838 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
841 }
else if (rsc_1 != NULL) {
850 }
else if (rsc_2 != NULL) {
890 unpack_order_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
893 const char *id_first = NULL;
894 const char *id_then = NULL;
895 const char *action_first = NULL;
896 const char *action_then = NULL;
903 xmlNode *rsc_set_first = NULL;
904 xmlNode *rsc_set_then = NULL;
905 bool any_sets =
false;
909 if (*expanded_xml != NULL) {
916 if ((id_first == NULL) || (id_then == NULL)) {
923 "valid resource or tag",
ID(xml_obj), id_first);
929 "valid resource or tag",
ID(xml_obj), id_then);
933 if ((rsc_first != NULL) && (rsc_then != NULL)) {
947 *expanded_xml = NULL;
951 if (rsc_set_first != NULL) {
952 if (action_first != NULL) {
954 crm_xml_add(rsc_set_first,
"action", action_first);
964 *expanded_xml = NULL;
968 if (rsc_set_then != NULL) {
969 if (action_then != NULL) {
981 *expanded_xml = NULL;
998 xmlNode *last = NULL;
1000 xmlNode *orig_xml = NULL;
1001 xmlNode *expanded_xml = NULL;
1014 if (expanded_xml != NULL) {
1016 xml_obj = expanded_xml;
1027 if (expanded_xml != NULL) {
1035 if (order_rsc_sets(
id, last,
set, kind,
data_set,
1037 if (expanded_xml != NULL) {
1044 && (order_rsc_sets(
id,
set, last, kind,
data_set,
1046 if (expanded_xml != NULL) {
1063 return unpack_simple_rsc_order(xml_obj,
data_set);
1074 && (
input->action->rsc != NULL)
1077 crm_warn(
"Invalid ordering constraint between %s and %s",
1101 for (GList *iter =
data_set->
actions; iter != NULL; iter = iter->next) {
1105 for (GList *input_iter =
action->actions_before;
1106 input_iter != NULL; input_iter = input_iter->next) {
1127 iter != NULL; iter = iter->next) {
1142 "Not ordering %s before shutdown of %s because " 1143 "resource in maintenance mode",
1144 action->uuid, pe__node_name(node));
1149 "Not ordering %s before shutdown of %s because " 1150 "node in maintenance mode",
1151 action->uuid, pe__node_name(node));
1159 if (!pcmk_any_flags_set(
action->rsc->flags,
1162 "Not ordering %s before shutdown of %s because " 1163 "resource is unmanaged or blocked",
1164 action->uuid, pe__node_name(node));
1169 action->uuid, pe__node_name(node));
1189 find_actions_by_task(
const pe_resource_t *rsc,
const char *original_key)
1198 guint interval_ms = 0;
1200 if (
parse_op_key(original_key, NULL, &task, &interval_ms)) {
1206 crm_err(
"Invalid operation key (bug?): %s", original_key);
1221 order_resource_actions_after(
pe_action_t *first_action,
1224 GList *then_actions = NULL;
1227 CRM_CHECK((rsc != NULL) && (order != NULL),
return);
1230 pe_rsc_trace(rsc,
"Applying ordering %d for 'then' resource %s",
1231 order->
id, rsc->
id);
1234 then_actions = g_list_prepend(NULL, order->
rh_action);
1240 if (then_actions == NULL) {
1241 pe_rsc_trace(rsc,
"Ignoring ordering %d: no %s actions found for %s",
1246 if ((first_action != NULL) && (first_action->
rsc == rsc)
1250 "Detected dangling migration ordering (%s then %s %s)",
1257 "Ignoring ordering %d for %s: No first action found",
1258 order->
id, rsc->
id);
1259 g_list_free(then_actions);
1263 for (GList *iter = then_actions; iter != NULL; iter = iter->next) {
1266 if (first_action != NULL) {
1270 crm_warn(
"%s of %s is unrunnable because there is no %s of %s " 1271 "to order it after", then_action_iter->
task, rsc->
id,
1276 g_list_free(then_actions);
1283 GList *first_actions = NULL;
1288 pe_rsc_trace(first_rsc,
"Applying ordering constraint %d (first: %s)",
1289 order->
id, first_rsc->
id);
1291 if (first_action != NULL) {
1292 first_actions = g_list_prepend(NULL, first_action);
1295 first_actions = find_actions_by_task(first_rsc, order->
lh_action_task);
1298 if ((first_actions == NULL) && (first_rsc == then_rsc)) {
1300 "Ignoring constraint %d: first (%s for %s) not found",
1303 }
else if (first_actions == NULL) {
1305 char *op_type = NULL;
1306 guint interval_ms = 0;
1315 "Ignoring constraint %d: first (%s for %s) not found",
1322 "Ignoring constraint %d: first (%s for %s) not found",
1327 "Creating first (%s for %s) for constraint %d ",
1329 first_action =
custom_action(first_rsc, key, op_type, NULL, TRUE,
1331 first_actions = g_list_prepend(NULL, first_action);
1337 if (then_rsc == NULL) {
1339 pe_rsc_trace(first_rsc,
"Ignoring constraint %d: then not found",
1345 for (GList *gIter = first_actions; gIter != NULL; gIter = gIter->next) {
1348 if (then_rsc == NULL) {
1352 order_resource_actions_after(first_action, then_rsc, order);
1356 g_list_free(first_actions);
1362 crm_trace(
"Applying ordering constraints");
1379 gIter != NULL; gIter = gIter->next) {
1385 rsc_order_first(rsc, order,
data_set);
1391 order_resource_actions_after(order->
lh_action, rsc, order);
1394 crm_trace(
"Applying ordering constraint %d (non-resource actions)",
1423 const char *after_desc = (after->
task == NULL)? after->
uuid : after->
task;
1425 for (GList *iter = list; iter != NULL; iter = iter->next) {
1427 const char *before_desc = before->
task? before->
task : before->
uuid;
1429 crm_debug(
"Ordering %s on %s before %s on %s",
1430 before_desc, pe__node_name(before->
node),
1431 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...)
G_GNUC_INTERNAL bool pcmk__rsc_corresponds_to_guest(pe_resource_t *rsc, pe_node_t *node)
#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 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.
#define XML_RSC_ATTR_INCARNATION_MIN
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, pe_working_set_t *data_set)
xmlNode * copy_xml(xmlNode *src_node)
#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)
pe_resource_t * find_clone_instance(pe_resource_t *rsc, const char *sub_id, pe_working_set_t *data_set)
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
#define handle_restart_type(rsc, kind, flag, flags)
void free_xml(xmlNode *child)
G_GNUC_INTERNAL bool pcmk__graph_has_loop(pe_action_t *init_action, pe_action_t *action, pe_action_wrapper_t *input)
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)
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
#define XML_ORDER_ATTR_FIRST_ACTION
void pcmk__order_migration_equivalents(pe__ordering_t *order)
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(pe_working_set_t *data_set, const char *id, pe_resource_t **rsc, pe_tag_t **tag)
int required_runnable_before
G_GNUC_INTERNAL bool pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr, bool convert_rsc, pe_working_set_t *data_set)
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.