31 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \ 32 __rsc = pcmk__find_constraint_resource(data_set->resources, __name); \ 33 if (__rsc == NULL) { \ 34 pcmk__config_err("%s: No resource found for %s", __set, __name); \ 35 return pcmk_rc_schema_validation; \ 40 invert_action(
const char *
action)
66 crm_warn(
"Unknown action '%s' specified in order constraint",
action);
71 get_ordering_type(xmlNode *xml_obj)
89 "Support for 'score' in rsc_order is deprecated " 90 "and will be removed in a future release " 91 "(use 'kind' instead)");
105 "'%s' to Mandatory because '%s' is not valid",
123 get_ordering_symmetry(xmlNode *xml_obj,
enum pe_order_kind parent_kind,
124 const char *parent_symmetrical_s)
127 bool symmetric =
false;
133 kind = get_ordering_type(xml_obj);
139 if (rc !=
pcmk_rc_ok && parent_symmetrical_s != NULL) {
148 " for '%s' because not valid with " 176 ordering_flags_for_kind(
enum pe_order_kind kind,
const char *first,
226 get_ordering_resource(xmlNode *xml,
const char *resource_attr,
233 if (rsc_id == NULL) {
235 ID(xml), resource_attr);
242 "does not exist",
ID(xml), rsc_id);
246 if (instance_id != NULL) {
247 if (!pe_rsc_is_clone(rsc)) {
249 "is not a clone but instance '%s' was requested",
250 ID(xml), rsc_id, instance_id);
256 "does not have an instance '%s'",
257 "'%s'",
ID(xml), rsc_id, instance_id);
274 get_minimum_first_instances(
pe_resource_t *rsc, xmlNode *xml)
276 const char *clone_min = NULL;
277 bool require_all =
false;
279 if (!pe_rsc_is_clone(rsc)) {
283 clone_min = g_hash_table_lookup(rsc->
meta,
285 if (clone_min != NULL) {
286 int clone_min_int = 0;
289 return clone_min_int;
297 "Support for require-all in ordering constraints " 298 "is deprecated and will be removed in a future release" 299 " (use clone-min clone meta-attribute instead)");
322 clone_min_ordering(
const char *
id,
341 for (GList *rIter = rsc_first->
children; rIter != NULL;
342 rIter = rIter->next) {
347 NULL, NULL, NULL, clone_min_met,
371 #define handle_restart_type(rsc, kind, flag, flags) do { \ 372 if (((kind) == pe_order_kind_optional) \ 373 && ((rsc)->restart_type == pe_restart_restart)) { \ 374 pe__set_order_flags((flags), (flag)); \ 396 action_then = invert_action(action_then);
397 action_first = invert_action(action_first);
398 if ((action_then == NULL) || (action_first == NULL)) {
400 "(please specify inverse manually)",
id);
416 int min_required_before = 0;
421 const char *action_then = NULL;
422 const char *action_first = NULL;
423 const char *
id = NULL;
430 crm_element_name(xml_obj));
437 if (rsc_first == NULL) {
444 if (rsc_then == NULL) {
449 if (action_first == NULL) {
454 if (action_then == NULL) {
455 action_then = action_first;
458 kind = get_ordering_type(xml_obj);
460 symmetry = get_ordering_symmetry(xml_obj, kind, NULL);
461 cons_weight = ordering_flags_for_kind(kind, action_first, symmetry);
470 min_required_before = get_minimum_first_instances(rsc_first, xml_obj);
471 if (min_required_before > 0) {
472 clone_min_ordering(
id, rsc_first, action_first, rsc_then, action_then,
473 cons_weight, min_required_before,
data_set);
476 action_then, cons_weight,
data_set);
480 inverse_ordering(
id, kind, rsc_first, action_first,
491 res = strdup(
action->task);
492 }
else if (key != NULL) {
512 char *lh_task = NULL;
513 char *rh_task = NULL;
532 if (!lh_migratable && !rh_migratable) {
539 if ((lh_task == NULL) || (rh_task == NULL)) {
548 if (lh_migratable && rh_migratable) {
681 CRM_CHECK(((lh_action != NULL) || (lh_rsc != NULL))
682 && ((rh_action != NULL) || (rh_rsc != NULL)),
683 free(lh_action_task); free(rh_action_task);
return);
685 if ((lh_rsc == NULL) && (lh_action != NULL)) {
686 lh_rsc = lh_action->
rsc;
688 if ((rh_rsc == NULL) && (rh_action != NULL)) {
689 rh_rsc = rh_action->
rsc;
712 if ((order->
lh_rsc == NULL) && (lh_action != NULL)) {
716 if ((order->
rh_rsc == NULL) && (rh_action != NULL)) {
720 pe_rsc_trace(lh_rsc,
"Created ordering %d for %s then %s",
722 ((lh_action_task == NULL)?
"?" : lh_action_task),
723 ((rh_action_task == NULL)?
"?" : rh_action_task));
727 handle_migration_ordering(order,
data_set);
741 unpack_order_set(xmlNode *
set,
enum pe_order_kind parent_kind,
744 xmlNode *xml_rsc = NULL;
745 GList *set_iter = NULL;
746 GList *resources = NULL;
751 int local_kind = parent_kind;
752 bool sequential =
false;
757 const char *
id =
ID(
set);
767 local_kind = get_ordering_type(
set);
769 if (sequential_s == NULL) {
775 symmetry = get_ordering_symmetry(
set, parent_kind, parent_symmetrical_s);
776 flags = ordering_flags_for_kind(local_kind,
action, symmetry);
782 resources = g_list_append(resources, resource);
785 if (pcmk__list_of_1(resources)) {
790 set_iter = resources;
791 while (set_iter != NULL) {
793 set_iter = set_iter->next;
800 for (GList *gIter = set_iter; gIter != NULL; gIter = gIter->next) {
808 }
else if (sequential) {
825 flags = ordering_flags_for_kind(local_kind,
action,
828 set_iter = resources;
829 while (set_iter != NULL) {
831 set_iter = set_iter->next;
843 g_list_free(resources);
860 order_rsc_sets(
const char *
id, xmlNode *set1, xmlNode *set2,
865 xmlNode *xml_rsc = NULL;
866 xmlNode *xml_rsc_2 = NULL;
876 bool require_all =
true;
880 if (action_1 == NULL) {
884 if (action_2 == NULL) {
889 action_1 = invert_action(action_1);
890 action_2 = invert_action(action_2);
904 flags = ordering_flags_for_kind(kind, action_2, symmetry);
926 NULL, NULL, NULL, unordered_action,
951 if (xml_rsc != NULL) {
957 const char *rid = NULL;
971 const char *rid = NULL;
983 if (xml_rsc != NULL) {
989 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
993 }
else if (rsc_1 != NULL) {
1002 }
else if (rsc_2 != NULL) {
1042 unpack_order_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
1045 const char *id_first = NULL;
1046 const char *id_then = NULL;
1047 const char *action_first = NULL;
1048 const char *action_then = NULL;
1055 xmlNode *rsc_set_first = NULL;
1056 xmlNode *rsc_set_then = NULL;
1057 bool any_sets =
false;
1061 if (*expanded_xml != NULL) {
1068 if ((id_first == NULL) || (id_then == NULL)) {
1075 "valid resource or tag",
ID(xml_obj), id_first);
1081 "valid resource or tag",
ID(xml_obj), id_then);
1085 if ((rsc_first != NULL) && (rsc_then != NULL)) {
1099 *expanded_xml = NULL;
1103 if (rsc_set_first != NULL) {
1104 if (action_first != NULL) {
1106 crm_xml_add(rsc_set_first,
"action", action_first);
1116 *expanded_xml = NULL;
1120 if (rsc_set_then != NULL) {
1121 if (action_then != NULL) {
1133 *expanded_xml = NULL;
1149 xmlNode *
set = NULL;
1150 xmlNode *last = NULL;
1152 xmlNode *orig_xml = NULL;
1153 xmlNode *expanded_xml = NULL;
1166 if (expanded_xml != NULL) {
1168 xml_obj = expanded_xml;
1179 if (expanded_xml != NULL) {
1187 if (order_rsc_sets(
id, last,
set, kind,
data_set,
1189 if (expanded_xml != NULL) {
1196 && (order_rsc_sets(
id,
set, last, kind,
data_set,
1198 if (expanded_xml != NULL) {
1215 return unpack_simple_rsc_order(xml_obj,
data_set);
1226 && (
input->action->rsc != NULL)
1229 crm_warn(
"Invalid ordering constraint between %s and %s",
1253 for (GList *iter =
data_set->
actions; iter != NULL; iter = iter->next) {
1257 for (GList *input_iter =
action->actions_before;
1258 input_iter != NULL; input_iter = input_iter->next) {
1280 for (GList *iter =
data_set->
actions; iter != NULL; iter = iter->next) {
1294 "Not ordering %s before %s shutdown because " 1295 "resource in maintenance mode",
1301 "Not ordering %s before %s shutdown because " 1302 "node in maintenance mode",
1311 if (!pcmk_any_flags_set(
action->rsc->flags,
1314 "Not ordering %s before %s shutdown because " 1315 "resource is unmanaged or blocked",
1340 find_actions_by_task(
pe_resource_t *rsc,
const char *original_key)
1349 guint interval_ms = 0;
1351 if (
parse_op_key(original_key, NULL, &task, &interval_ms)) {
1357 crm_err(
"Invalid operation key (bug?): %s", original_key);
1367 GList *rh_actions = NULL;
1376 crm_trace(
"Applying ordering constraint %d (then: %s)", order->
id, rsc->
id);
1378 if (rh_action != NULL) {
1379 rh_actions = g_list_prepend(NULL, rh_action);
1381 }
else if (rsc != NULL) {
1385 if (rh_actions == NULL) {
1387 "Ignoring constraint %d: then (%s for %s) not found",
1392 if ((lh_action != NULL) && (lh_action->
rsc == rsc)
1395 pe_rsc_trace(rsc,
"Detected dangling operation %s -> %s",
1400 for (GList *gIter = rh_actions; gIter != NULL; gIter = gIter->next) {
1414 g_list_free(rh_actions);
1421 GList *lh_actions = NULL;
1426 pe_rsc_trace(lh_rsc,
"Applying ordering constraint %d (first: %s)",
1427 order->
id, lh_rsc->
id);
1429 if (lh_action != NULL) {
1430 lh_actions = g_list_prepend(NULL, lh_action);
1433 lh_actions = find_actions_by_task(lh_rsc, order->
lh_action_task);
1436 if ((lh_actions == NULL) && (lh_rsc == rh_rsc)) {
1438 "Ignoring constraint %d: first (%s for %s) not found",
1441 }
else if (lh_actions == NULL) {
1443 char *op_type = NULL;
1444 guint interval_ms = 0;
1453 "Ignoring constraint %d: first (%s for %s) not found",
1460 "Ignoring constraint %d: first (%s for %s) not found",
1465 "Creating first (%s for %s) for constraint %d ",
1468 lh_actions = g_list_prepend(NULL, lh_action);
1474 if (rh_rsc == NULL) {
1476 pe_rsc_trace(lh_rsc,
"Ignoring constraint %d: then not found",
1482 for (GList *gIter = lh_actions; gIter != NULL; gIter = gIter->next) {
1485 if (rh_rsc == NULL) {
1489 rsc_order_then(lh_action, rh_rsc, order);
1493 g_list_free(lh_actions);
1499 crm_trace(
"Applying ordering constraints");
1510 gIter != NULL; gIter = gIter->next) {
1516 rsc_order_first(rsc, order,
data_set);
1522 rsc_order_then(order->
lh_action, rsc, order);
1525 crm_trace(
"Applying ordering constraint %d (non-resource actions)",
1554 const char *after_desc = (after->
task == NULL)? after->
uuid : after->
task;
1556 for (GList *iter = list; iter != NULL; iter = iter->next) {
1558 const char *before_desc = before->
task? before->
task : before->
uuid;
1560 crm_debug(
"Ordering %s on %s before %s on %s",
#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 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 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)
enum crm_ais_msg_types type
G_GNUC_INTERNAL void pcmk__order_probes(pe_working_set_t *data_set)
pe_node_t * partial_migration_target
#define XML_ORDER_ATTR_FIRST_INSTANCE
#define XML_CONS_TAG_RSC_SET
#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...)
int pcmk__xe_get_bool_attr(xmlNodePtr node, const char *name, bool *value)
#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...)
#define pe__clear_order_flags(order_flags, flags_to_clear)
G_GNUC_INTERNAL void pcmk__block_colocated_starts(pe_action_t *action, pe_working_set_t *data_set)
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)
void pcmk__new_ordering(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)
#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)
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
pe_working_set_t * data_set
#define pcmk__order_resource_actions(lh_rsc, lh_task, rh_rsc, rh_task, flags, data_set)
#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 EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name)
#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)
bool pcmk__xe_attr_is_true(xmlNodePtr node, const char *name)
#define pe_rsc_trace(rsc, fmt, args...)
#define pe__set_order_flags(order_flags, flags_to_set)
#define XML_CONS_ATTR_SYMMETRICAL
void pcmk__order_stops_before_shutdown(pe_node_t *node, pe_action_t *shutdown_op, pe_working_set_t *data_set)
#define XML_ORDER_ATTR_FIRST_ACTION
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)
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, pe_node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Create or update an action object.
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.