32 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \ 33 __rsc = pcmk__find_constraint_resource(scheduler->resources, \ 35 if (__rsc == NULL) { \ 36 pcmk__config_err("%s: No resource found for %s", __set, __name);\ 37 return pcmk_rc_unpack_error; \ 42 invert_action(
const char *
action)
74 get_ordering_type(
const xmlNode *xml_obj)
94 "removed in a future release " 110 pcmk__s(pcmk__xe_id(xml_obj),
"missing ID"), kind);
128 get_ordering_symmetry(
const xmlNode *xml_obj,
enum pe_order_kind parent_kind,
129 const char *parent_symmetrical_s)
132 bool symmetric =
false;
138 kind = get_ordering_type(xml_obj);
144 if (rc !=
pcmk_rc_ok && parent_symmetrical_s != NULL) {
153 " for '%s' because not valid with " 155 pcmk__xe_id(xml_obj));
181 ordering_flags_for_kind(
enum pe_order_kind kind,
const char *first,
240 get_ordering_resource(
const xmlNode *xml,
const char *resource_attr,
241 const char *instance_attr,
249 if (rsc_id == NULL) {
251 pcmk__xe_id(xml), resource_attr);
258 "does not exist", pcmk__xe_id(xml), rsc_id);
262 if (instance_id != NULL) {
266 "removed in a future release.");
268 if (!pcmk__is_clone(rsc)) {
270 "is not a clone but instance '%s' was requested",
271 pcmk__xe_id(xml), rsc_id, instance_id);
277 "does not have an instance '%s'",
278 pcmk__xe_id(xml), rsc_id, instance_id);
295 get_minimum_first_instances(
const pcmk_resource_t *rsc,
const xmlNode *xml)
297 const char *clone_min = NULL;
298 bool require_all =
false;
300 if (!pcmk__is_clone(rsc)) {
305 if (clone_min != NULL) {
306 int clone_min_int = 0;
309 return clone_min_int;
320 "constraints is deprecated and will be removed in a " 322 "meta-attribute instead)");
344 clone_min_ordering(
const char *
id,
347 uint32_t
flags,
int clone_min)
362 for (GList *iter = rsc_first->
children; iter != NULL; iter = iter->next) {
366 NULL, NULL, NULL, clone_min_met,
392 #define handle_restart_type(rsc, kind, flag, flags) do { \ 393 if (((kind) == pe_order_kind_optional) \ 394 && ((rsc)->restart_type == pe_restart_restart)) { \ 395 pcmk__set_relation_flags((flags), (flag)); \ 415 action_then = invert_action(action_then);
416 action_first = invert_action(action_first);
417 if ((action_then == NULL) || (action_first == NULL)) {
419 "(please specify inverse manually)",
id);
421 uint32_t
flags = ordering_flags_for_kind(kind, action_first,
426 action_first,
flags);
435 int min_required_before = 0;
440 const char *action_then = NULL;
441 const char *action_first = NULL;
442 const char *
id = NULL;
455 if (rsc_first == NULL) {
461 if (rsc_then == NULL) {
466 if (action_first == NULL) {
471 if (action_then == NULL) {
472 action_then = action_first;
475 kind = get_ordering_type(xml_obj);
477 symmetry = get_ordering_symmetry(xml_obj, kind, NULL);
478 flags = ordering_flags_for_kind(kind, action_first, symmetry);
487 min_required_before = get_minimum_first_instances(rsc_first, xml_obj);
488 if (min_required_before > 0) {
489 clone_min_ordering(
id, rsc_first, action_first, rsc_then, action_then,
490 flags, min_required_before);
497 inverse_ordering(
id, kind, rsc_first, action_first,
498 rsc_then, action_then);
539 CRM_CHECK(((first_action != NULL) || (first_rsc != NULL))
540 && ((then_action != NULL) || (then_rsc != NULL)),
541 free(first_action_task); free(then_action_task);
return);
543 if ((first_rsc == NULL) && (first_action != NULL)) {
544 first_rsc = first_action->
rsc;
546 if ((then_rsc == NULL) && (then_action != NULL)) {
547 then_rsc = then_action->
rsc;
554 order->
rsc1 = first_rsc;
555 order->
rsc2 = then_rsc;
558 order->
task1 = first_action_task;
559 order->
task2 = then_action_task;
561 if ((order->
task1 == NULL) && (first_action != NULL)) {
562 order->
task1 = strdup(first_action->
uuid);
565 if ((order->
task2 == NULL) && (then_action != NULL)) {
566 order->
task2 = strdup(then_action->
uuid);
569 if ((order->
rsc1 == NULL) && (first_action != NULL)) {
570 order->
rsc1 = first_action->
rsc;
573 if ((order->
rsc2 == NULL) && (then_action != NULL)) {
574 order->
rsc2 = then_action->
rsc;
579 pcmk__s(order->
task1,
"an underspecified action"),
580 pcmk__s(order->
task2,
"an underspecified action"));
600 unpack_order_set(
const xmlNode *
set,
enum pe_order_kind parent_kind,
603 GList *set_iter = NULL;
604 GList *resources = NULL;
609 int local_kind = parent_kind;
610 bool sequential =
false;
615 const char *
id = pcmk__xe_id(
set);
625 local_kind = get_ordering_type(
set);
627 if (sequential_s == NULL) {
633 symmetry = get_ordering_symmetry(
set, parent_kind, parent_symmetrical_s);
634 flags = ordering_flags_for_kind(local_kind,
action, symmetry);
642 resources = g_list_append(resources, resource);
645 if (pcmk__list_of_1(resources)) {
650 set_iter = resources;
651 while (set_iter != NULL) {
653 set_iter = set_iter->next;
660 for (GList *iter = set_iter; iter != NULL; iter = iter->next) {
668 }
else if (sequential) {
685 flags = ordering_flags_for_kind(local_kind,
action,
688 set_iter = resources;
689 while (set_iter != NULL) {
691 set_iter = set_iter->next;
703 g_list_free(resources);
720 order_rsc_sets(
const char *
id,
const xmlNode *set1,
const xmlNode *set2,
725 const xmlNode *xml_rsc = NULL;
726 const xmlNode *xml_rsc_2 = NULL;
736 bool require_all =
true;
740 if (action_1 == NULL) {
744 if (action_2 == NULL) {
749 action_1 = invert_action(action_1);
750 action_2 = invert_action(action_2);
763 flags = ordering_flags_for_kind(kind, action_1, symmetry);
787 NULL, NULL, NULL, unordered_action,
816 if (xml_rsc != NULL) {
822 const char *rid = NULL;
828 rid = pcmk__xe_id(xml_rsc);
837 const char *rid = NULL;
843 rid = pcmk__xe_id(xml_rsc);
851 if (xml_rsc != NULL) {
857 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
860 }
else if (rsc_1 != NULL) {
870 }
else if (rsc_2 != NULL) {
914 unpack_order_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
917 const char *id_first = NULL;
918 const char *id_then = NULL;
919 const char *action_first = NULL;
920 const char *action_then = NULL;
927 xmlNode *rsc_set_first = NULL;
928 xmlNode *rsc_set_then = NULL;
929 bool any_sets =
false;
933 if (*expanded_xml != NULL) {
940 if ((id_first == NULL) || (id_then == NULL)) {
947 "valid resource or tag",
948 pcmk__xe_id(xml_obj), id_first);
955 "valid resource or tag",
956 pcmk__xe_id(xml_obj), id_then);
960 if ((rsc_first != NULL) && (rsc_then != NULL)) {
976 *expanded_xml = NULL;
980 if (rsc_set_first != NULL) {
981 if (action_first != NULL) {
997 *expanded_xml = NULL;
1001 if (rsc_set_then != NULL) {
1002 if (action_then != NULL) {
1016 *expanded_xml = NULL;
1032 xmlNode *
set = NULL;
1033 xmlNode *last = NULL;
1035 xmlNode *orig_xml = NULL;
1036 xmlNode *expanded_xml = NULL;
1049 if (expanded_xml != NULL) {
1051 xml_obj = expanded_xml;
1062 if (expanded_xml != NULL) {
1070 if (order_rsc_sets(
id, last,
set, kind,
scheduler,
1072 if (expanded_xml != NULL) {
1079 && (order_rsc_sets(
id,
set, last, kind,
scheduler,
1081 if (expanded_xml != NULL) {
1098 return unpack_simple_rsc_order(xml_obj,
scheduler);
1109 && (
input->action->rsc != NULL)
1141 for (GList *input_iter =
action->actions_before;
1142 input_iter != NULL; input_iter = input_iter->next) {
1144 input = input_iter->data;
1163 iter != NULL; iter = iter->next) {
1168 if (!pcmk__same_node(
action->node, node)
1177 "Not ordering %s before shutdown of %s because " 1178 "resource in maintenance mode",
1179 action->uuid, pcmk__node_name(node));
1184 "Not ordering %s before shutdown of %s because " 1185 "node in maintenance mode",
1186 action->uuid, pcmk__node_name(node));
1194 if (!pcmk_any_flags_set(
action->rsc->flags,
1197 "Not ordering %s before shutdown of %s because " 1198 "resource is unmanaged or blocked",
1199 action->uuid, pcmk__node_name(node));
1204 action->uuid, pcmk__node_name(node));
1224 find_actions_by_task(
const pcmk_resource_t *rsc,
const char *original_key)
1233 guint interval_ms = 0;
1258 GList *then_actions = NULL;
1261 CRM_CHECK((rsc != NULL) && (order != NULL),
return);
1265 order->
id, rsc->
id);
1268 then_actions = g_list_prepend(NULL, order->
action2);
1271 then_actions = find_actions_by_task(rsc, order->
task2);
1274 if (then_actions == NULL) {
1275 pcmk__rsc_trace(rsc,
"Ignoring ordering %d: no %s actions found for %s",
1280 if ((first_action != NULL) && (first_action->
rsc == rsc)
1284 "Detected dangling migration ordering (%s then %s %s)",
1289 if ((first_action == NULL)
1293 "Ignoring ordering %d for %s: No first action found",
1294 order->
id, rsc->
id);
1295 g_list_free(then_actions);
1299 for (GList *iter = then_actions; iter != NULL; iter = iter->next) {
1302 if (first_action != NULL) {
1306 crm_warn(
"%s of %s is unrunnable because there is no %s of %s " 1307 "to order it after", then_action_iter->
task, rsc->
id,
1312 g_list_free(then_actions);
1318 GList *first_actions = NULL;
1323 pcmk__rsc_trace(first_rsc,
"Applying ordering constraint %d (first: %s)",
1324 order->
id, first_rsc->
id);
1326 if (first_action != NULL) {
1327 first_actions = g_list_prepend(NULL, first_action);
1330 first_actions = find_actions_by_task(first_rsc, order->
task1);
1333 if ((first_actions == NULL) && (first_rsc == then_rsc)) {
1335 "Ignoring constraint %d: first (%s for %s) not found",
1336 order->
id, order->
task1, first_rsc->
id);
1338 }
else if (first_actions == NULL) {
1340 char *op_type = NULL;
1341 guint interval_ms = 0;
1350 "Ignoring constraint %d: first (%s for %s) " 1352 order->
id, order->
task1, first_rsc->
id);
1354 }
else if ((first_rsc->
fns->
state(first_rsc,
1360 "Ignoring constraint %d: first (%s for %s) " 1362 order->
id, order->
task1, first_rsc->
id);
1366 "Creating first (%s for %s) for constraint %d ",
1367 order->
task1, first_rsc->
id, order->
id);
1368 first_action =
custom_action(first_rsc, key, op_type, NULL, TRUE,
1370 first_actions = g_list_prepend(NULL, first_action);
1376 if (then_rsc == NULL) {
1384 for (GList *iter = first_actions; iter != NULL; iter = iter->next) {
1385 first_action = iter->data;
1387 if (then_rsc == NULL) {
1391 order_resource_actions_after(first_action, then_rsc, order);
1395 g_list_free(first_actions);
1400 block_colocation_dependents(gpointer
data, gpointer user_data)
1407 update_action_for_orderings(gpointer
data, gpointer user_data)
1422 crm_trace(
"Applying ordering constraints");
1439 iter != NULL; iter = iter->next) {
1445 rsc_order_first(rsc, order);
1451 order_resource_actions_after(order->
action1, rsc, order);
1454 crm_trace(
"Applying ordering constraint %d (non-resource actions)",
1460 g_list_foreach(sched->
actions, block_colocation_dependents, NULL);
1466 g_list_foreach(sched->
actions, update_action_for_orderings, sched);
1481 const char *after_desc = (after->
task == NULL)? after->
uuid : after->
task;
1483 for (GList *iter = list; iter != NULL; iter = iter->next) {
1485 const char *before_desc = before->
task? before->
task : before->
uuid;
1487 crm_debug(
"Ordering %s on %s before %s on %s",
1488 before_desc, pcmk__node_name(before->
node),
1489 after_desc, pcmk__node_name(after->
node));
#define CRM_CHECK(expr, failure_action)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
#define PCMK__XA_FIRST_INSTANCE
'then' is runnable (and migratable) only if 'first' is runnable
void pcmk__order_after_each(pcmk_action_t *after, GList *list)
pcmk_scheduler_t * cluster
Actions are ordered if on same node (or migration target for migrate_to)
pcmk_action_t * get_pseudo_op(const char *name, pcmk_scheduler_t *scheduler)
#define PCMK_XE_RSC_ORDER
User-configured asymmetric ordering.
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 PCMK__XA_THEN_INSTANCE
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)
#define pcmk__config_warn(fmt...)
#define pcmk__rsc_trace(rsc, fmt, args...)
gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, uint32_t flags)
#define PCMK_XE_RESOURCE_REF
enum rsc_role_e(* state)(const pcmk_resource_t *rsc, gboolean current)
#define pcmk__config_err(fmt...)
G_GNUC_INTERNAL void pcmk__block_colocation_dependents(pcmk_action_t *action)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
#define PCMK_ACTION_MIGRATE_TO
#define PCMK_ACTION_DO_SHUTDOWN
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
G_GNUC_INTERNAL void pcmk__update_action_for_orderings(pcmk_action_t *action, pcmk_scheduler_t *scheduler)
pcmk_scheduler_t * data_set
void pcmk__promotable_restart_ordering(pcmk_resource_t *rsc)
Ordering applies even if 'first' runs on guest node created by 'then'.
#define pcmk__set_relation_flags(ar_flags, flags_to_set)
#define pcmk__rsc_debug(rsc, fmt, args...)
#define PCMK_ACTION_DEMOTE
#define crm_warn(fmt, args...)
#define PCMK_ACTION_CLONE_ONE_OR_MORE
#define crm_debug(fmt, args...)
Actions are ordered (optionally, if no other flags are set)
G_GNUC_INTERNAL pcmk_resource_t * pcmk__find_constraint_resource(GList *rsc_list, const char *id)
#define pcmk__clear_action_flags(action, flags_to_clear)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
#define PCMK_XA_THEN_ACTION
int char2score(const char *score)
Get the integer value of a score string.
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void pcmk__apply_orderings(pcmk_scheduler_t *sched)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
struct pe_node_shared_s * details
G_GNUC_INTERNAL bool pcmk__rsc_corresponds_to_guest(const pcmk_resource_t *rsc, const pcmk_node_t *node)
G_GNUC_INTERNAL void pcmk__order_probes(pcmk_scheduler_t *scheduler)
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
#define PCMK_ACTION_START
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
#define PCMK_META_CLONE_MIN
#define handle_restart_type(rsc, kind, flag, flags)
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(const pcmk_scheduler_t *scheduler, const char *id, pcmk_resource_t **rsc, pcmk_tag_t **tag)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
void free_xml(xmlNode *child)
#define pcmk__warn_once(wo_flag, fmt...)
#define PCMK_XA_REQUIRE_ALL
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
#define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name)
void pcmk__new_ordering(pcmk_resource_t *first_rsc, char *first_action_task, pcmk_action_t *first_action, pcmk_resource_t *then_rsc, char *then_action_task, pcmk_action_t *then_action, uint32_t flags, pcmk_scheduler_t *sched)
pcmk_action_t * custom_action(pcmk_resource_t *rsc, char *key, const char *task, const pcmk_node_t *on_node, gboolean optional, pcmk_scheduler_t *scheduler)
Create or update an action object.
#define pcmk__clear_relation_flags(ar_flags, flags_to_clear)
#define PCMK_VALUE_SERIALIZE
GList * ordering_constraints
void pcmk__disable_invalid_orderings(pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL bool pcmk__graph_has_loop(const pcmk_action_t *init_action, const pcmk_action_t *action, pcmk__related_action_t *input)
pcmk_scheduler_t * scheduler
GList * find_actions(GList *input, const char *key, const pcmk_node_t *on_node)
If 'first' is required and runnable, 'then' must be in graph.
#define PCMK_ACTION_STOPPED
#define PCMK_XE_RESOURCE_SET
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
#define PCMK_ACTION_PROMOTE
void pcmk__unpack_ordering(xmlNode *xml_obj, pcmk_scheduler_t *scheduler)
#define PCMK_XA_FIRST_ACTION
enum pe_action_flags flags
#define pcmk__set_action_flags(action, flags_to_set)
void pcmk__order_migration_equivalents(pcmk__action_relation_t *order)
#define PCMK_XA_SYMMETRICAL
#define crm_log_xml_trace(xml, text)
#define PCMK_ACTION_PROMOTED
gboolean crm_is_true(const char *s)
#define PCMK_ACTION_RUNNING
pcmk_resource_t * find_clone_instance(const pcmk_resource_t *rsc, const char *sub_id)
#define PCMK_ACTION_DEMOTED
#define pcmk__assert_alloc(nmemb, size)
xmlNode * pcmk__xe_next_same(const xmlNode *node)
'then' action is runnable if certain number of 'first' instances are
#define PCMK_ACTION_ONE_OR_MORE
#define PCMK_XA_SEQUENTIAL
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pcmk_scheduler_t *scheduler)
void pcmk__order_stops_before_shutdown(pcmk_node_t *node, pcmk_action_t *shutdown_op)
int required_runnable_before
#define PCMK_VALUE_MANDATORY
No relation (compare with equality rather than bit set)
#define PCMK_VALUE_OPTIONAL