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)
126 const char *symmetrical_s = NULL;
132 kind = get_ordering_type(xml_obj);
137 if (symmetrical_s == NULL) {
138 symmetrical_s = parent_symmetrical_s;
140 if (symmetrical_s != NULL) {
144 " for '%s' because not valid with " 172 ordering_flags_for_kind(
enum pe_order_kind kind,
const char *first,
222 get_ordering_resource(xmlNode *xml,
const char *resource_attr,
229 if (rsc_id == NULL) {
231 ID(xml), resource_attr);
238 "does not exist",
ID(xml), rsc_id);
242 if (instance_id != NULL) {
243 if (!pe_rsc_is_clone(rsc)) {
245 "is not a clone but instance '%s' was requested",
246 ID(xml), rsc_id, instance_id);
252 "does not have an instance '%s'",
253 "'%s'",
ID(xml), rsc_id, instance_id);
270 get_minimum_first_instances(
pe_resource_t *rsc, xmlNode *xml)
272 if (pe_rsc_is_clone(rsc)) {
273 const char *clone_min = NULL;
275 clone_min = g_hash_table_lookup(rsc->
meta,
277 if (clone_min != NULL) {
278 int clone_min_int = 0;
281 return clone_min_int;
288 if (clone_min != NULL) {
290 "Support for require-all in ordering constraints " 291 "is deprecated and will be removed in a future release" 292 " (use clone-min clone meta-attribute instead)");
315 clone_min_ordering(
const char *
id,
334 for (GList *rIter = rsc_first->
children; rIter != NULL;
335 rIter = rIter->next) {
340 NULL, NULL, NULL, clone_min_met,
364 #define handle_restart_type(rsc, kind, flag, flags) do { \ 365 if (((kind) == pe_order_kind_optional) \ 366 && ((rsc)->restart_type == pe_restart_restart)) { \ 367 pe__set_order_flags((flags), (flag)); \ 389 action_then = invert_action(action_then);
390 action_first = invert_action(action_first);
391 if ((action_then == NULL) || (action_first == NULL)) {
393 "(please specify inverse manually)",
id);
400 action_first,
flags, data_set);
409 int min_required_before = 0;
414 const char *action_then = NULL;
415 const char *action_first = NULL;
416 const char *
id = NULL;
423 crm_element_name(xml_obj));
430 if (rsc_first == NULL) {
437 if (rsc_then == NULL) {
442 if (action_first == NULL) {
447 if (action_then == NULL) {
448 action_then = action_first;
451 kind = get_ordering_type(xml_obj);
453 symmetry = get_ordering_symmetry(xml_obj, kind, NULL);
454 cons_weight = ordering_flags_for_kind(kind, action_first, symmetry);
463 min_required_before = get_minimum_first_instances(rsc_first, xml_obj);
464 if (min_required_before > 0) {
465 clone_min_ordering(
id, rsc_first, action_first, rsc_then, action_then,
466 cons_weight, min_required_before, data_set);
469 action_then, cons_weight, data_set);
473 inverse_ordering(
id, kind, rsc_first, action_first,
474 rsc_then, action_then, data_set);
484 res = strdup(
action->task);
485 }
else if (key != NULL) {
505 char *lh_task = NULL;
506 char *rh_task = NULL;
525 if (!lh_migratable && !rh_migratable) {
532 if ((lh_task == NULL) || (rh_task == NULL)) {
541 if (lh_migratable && rh_migratable) {
548 NULL,
flags, data_set);
564 NULL,
flags, data_set);
583 NULL,
flags, data_set);
591 NULL,
flags, data_set);
606 NULL,
flags, data_set);
621 NULL,
flags, data_set);
629 NULL,
flags, data_set);
674 CRM_CHECK(((lh_action != NULL) || (lh_rsc != NULL))
675 && ((rh_action != NULL) || (rh_rsc != NULL)),
676 free(lh_action_task); free(rh_action_task);
return);
678 if ((lh_rsc == NULL) && (lh_action != NULL)) {
679 lh_rsc = lh_action->
rsc;
681 if ((rh_rsc == NULL) && (rh_action != NULL)) {
682 rh_rsc = rh_action->
rsc;
704 if ((order->
lh_rsc == NULL) && (lh_action != NULL)) {
708 if ((order->
rh_rsc == NULL) && (rh_action != NULL)) {
712 pe_rsc_trace(lh_rsc,
"Created ordering %d for %s then %s",
714 ((lh_action_task == NULL)?
"?" : lh_action_task),
715 ((rh_action_task == NULL)?
"?" : rh_action_task));
719 handle_migration_ordering(order, data_set);
733 unpack_order_set(xmlNode *
set,
enum pe_order_kind parent_kind,
736 xmlNode *xml_rsc = NULL;
737 GList *set_iter = NULL;
738 GList *resources = NULL;
743 int local_kind = parent_kind;
744 bool sequential =
false;
749 const char *
id =
ID(
set);
759 local_kind = get_ordering_type(
set);
761 if (sequential_s == NULL) {
767 symmetry = get_ordering_symmetry(
set, parent_kind, parent_symmetrical_s);
768 flags = ordering_flags_for_kind(local_kind,
action, symmetry);
774 resources = g_list_append(resources, resource);
777 if (pcmk__list_of_1(resources)) {
782 set_iter = resources;
783 while (set_iter != NULL) {
785 set_iter = set_iter->next;
792 for (GList *gIter = set_iter; gIter != NULL; gIter = gIter->next) {
797 then_key, NULL,
flags, data_set);
800 }
else if (sequential) {
817 flags = ordering_flags_for_kind(local_kind,
action,
820 set_iter = resources;
821 while (set_iter != NULL) {
823 set_iter = set_iter->next;
835 g_list_free(resources);
852 order_rsc_sets(
const char *
id, xmlNode *set1, xmlNode *set2,
857 xmlNode *xml_rsc = NULL;
858 xmlNode *xml_rsc_2 = NULL;
870 bool require_all = require_all_s?
crm_is_true(require_all_s) : true;
874 if (action_1 == NULL) {
878 if (action_2 == NULL) {
883 action_1 = invert_action(action_1);
884 action_2 = invert_action(action_2);
898 flags = ordering_flags_for_kind(kind, action_2, symmetry);
920 NULL, NULL, NULL, unordered_action,
945 if (xml_rsc != NULL) {
951 const char *rid = NULL;
965 const char *rid = NULL;
977 if (xml_rsc != NULL) {
983 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
987 }
else if (rsc_1 != NULL) {
996 }
else if (rsc_2 != NULL) {
1016 action_2,
flags, data_set);
1036 unpack_order_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
1039 const char *id_first = NULL;
1040 const char *id_then = NULL;
1041 const char *action_first = NULL;
1042 const char *action_then = NULL;
1049 xmlNode *rsc_set_first = NULL;
1050 xmlNode *rsc_set_then = NULL;
1051 bool any_sets =
false;
1055 if (*expanded_xml != NULL) {
1062 if ((id_first == NULL) || (id_then == NULL)) {
1069 "valid resource or tag",
ID(xml_obj), id_first);
1075 "valid resource or tag",
ID(xml_obj), id_then);
1079 if ((rsc_first != NULL) && (rsc_then != NULL)) {
1093 *expanded_xml = NULL;
1097 if (rsc_set_first != NULL) {
1098 if (action_first != NULL) {
1100 crm_xml_add(rsc_set_first,
"action", action_first);
1110 *expanded_xml = NULL;
1114 if (rsc_set_then != NULL) {
1115 if (action_then != NULL) {
1127 *expanded_xml = NULL;
1143 xmlNode *
set = NULL;
1144 xmlNode *last = NULL;
1146 xmlNode *orig_xml = NULL;
1147 xmlNode *expanded_xml = NULL;
1157 if (unpack_order_tags(xml_obj, &expanded_xml, data_set) !=
pcmk_rc_ok) {
1160 if (expanded_xml != NULL) {
1162 xml_obj = expanded_xml;
1171 || (unpack_order_set(
set, kind, invert, data_set) !=
pcmk_rc_ok)) {
1173 if (expanded_xml != NULL) {
1181 if (order_rsc_sets(
id, last,
set, kind, data_set,
1183 if (expanded_xml != NULL) {
1190 && (order_rsc_sets(
id,
set, last, kind, data_set,
1192 if (expanded_xml != NULL) {
1209 return unpack_simple_rsc_order(xml_obj, data_set);
1223 crm_warn(
"Invalid ordering constraint between %s and %s",
1247 for (GList *iter = data_set->
actions; iter != NULL; iter = iter->next) {
1251 for (GList *input_iter =
action->actions_before;
1252 input_iter != NULL; input_iter = input_iter->next) {
1255 if (ordering_is_invalid(
action, input)) {
1274 for (GList *iter = data_set->
actions; iter != NULL; iter = iter->next) {
1288 "Not ordering %s before %s shutdown because " 1289 "resource in maintenance mode",
1295 "Not ordering %s before %s shutdown because " 1296 "node in maintenance mode",
1305 if (!pcmk_any_flags_set(
action->rsc->flags,
1308 "Not ordering %s before %s shutdown because " 1309 "resource is unmanaged or blocked",
1334 find_actions_by_task(
pe_resource_t *rsc,
const char *original_key)
1343 guint interval_ms = 0;
1345 if (
parse_op_key(original_key, NULL, &task, &interval_ms)) {
1351 crm_err(
"Invalid operation key (bug?): %s", original_key);
1361 GList *rh_actions = NULL;
1370 crm_trace(
"Applying ordering constraint %d (then: %s)", order->
id, rsc->
id);
1372 if (rh_action != NULL) {
1373 rh_actions = g_list_prepend(NULL, rh_action);
1375 }
else if (rsc != NULL) {
1379 if (rh_actions == NULL) {
1381 "Ignoring constraint %d: then (%s for %s) not found",
1386 if ((lh_action != NULL) && (lh_action->
rsc == rsc)
1389 pe_rsc_trace(rsc,
"Detected dangling operation %s -> %s",
1394 for (GList *gIter = rh_actions; gIter != NULL; gIter = gIter->next) {
1408 g_list_free(rh_actions);
1415 GList *lh_actions = NULL;
1420 pe_rsc_trace(lh_rsc,
"Applying ordering constraint %d (first: %s)",
1421 order->
id, lh_rsc->
id);
1423 if (lh_action != NULL) {
1424 lh_actions = g_list_prepend(NULL, lh_action);
1427 lh_actions = find_actions_by_task(lh_rsc, order->
lh_action_task);
1430 if ((lh_actions == NULL) && (lh_rsc == rh_rsc)) {
1432 "Ignoring constraint %d: first (%s for %s) not found",
1435 }
else if (lh_actions == NULL) {
1437 char *op_type = NULL;
1438 guint interval_ms = 0;
1447 "Ignoring constraint %d: first (%s for %s) not found",
1454 "Ignoring constraint %d: first (%s for %s) not found",
1459 "Creating first (%s for %s) for constraint %d ",
1461 lh_action =
custom_action(lh_rsc, key, op_type, NULL, TRUE, TRUE, data_set);
1462 lh_actions = g_list_prepend(NULL, lh_action);
1468 if (rh_rsc == NULL) {
1470 pe_rsc_trace(lh_rsc,
"Ignoring constraint %d: then not found",
1476 for (GList *gIter = lh_actions; gIter != NULL; gIter = gIter->next) {
1479 if (rh_rsc == NULL) {
1483 rsc_order_then(lh_action, rh_rsc, order);
1487 g_list_free(lh_actions);
1493 crm_trace(
"Applying ordering constraints");
1504 gIter != NULL; gIter = gIter->next) {
1510 rsc_order_first(rsc, order, data_set);
1516 rsc_order_then(order->
lh_action, rsc, order);
1519 crm_trace(
"Applying ordering constraint %d (non-resource actions)",
#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)
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)
#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...)
#define pe_rsc_allow_migrate
pe_action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
#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...)
gboolean update_action(pe_action_t *action, pe_working_set_t *data_set)
#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)
#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)
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)
#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.