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)
95 "removed in a future release " 111 pcmk__s(pcmk__xe_id(xml_obj),
"missing ID"), kind);
129 get_ordering_symmetry(
const xmlNode *xml_obj,
enum pe_order_kind parent_kind,
130 const char *parent_symmetrical_s)
133 bool symmetric =
false;
139 kind = get_ordering_type(xml_obj);
145 if (rc !=
pcmk_rc_ok && parent_symmetrical_s != NULL) {
154 " for '%s' because not valid with " 156 pcmk__xe_id(xml_obj));
182 ordering_flags_for_kind(
enum pe_order_kind kind,
const char *first,
241 get_ordering_resource(
const xmlNode *xml,
const char *resource_attr,
242 const char *instance_attr,
250 if (rsc_id == NULL) {
252 pcmk__xe_id(xml), resource_attr);
259 "does not exist", pcmk__xe_id(xml), rsc_id);
263 if (instance_id != NULL) {
267 "removed in a future release.");
269 if (!pcmk__is_clone(rsc)) {
271 "is not a clone but instance '%s' was requested",
272 pcmk__xe_id(xml), rsc_id, instance_id);
278 "does not have an instance '%s'",
279 pcmk__xe_id(xml), rsc_id, instance_id);
296 get_minimum_first_instances(
const pcmk_resource_t *rsc,
const xmlNode *xml)
298 const char *clone_min = NULL;
299 bool require_all =
false;
301 if (!pcmk__is_clone(rsc)) {
306 if (clone_min != NULL) {
307 int clone_min_int = 0;
310 return clone_min_int;
321 "constraints is deprecated and will be removed in a " 323 "meta-attribute instead)");
345 clone_min_ordering(
const char *
id,
348 uint32_t
flags,
int clone_min)
363 for (GList *iter = rsc_first->
children; iter != NULL; iter = iter->next) {
367 NULL, NULL, NULL, clone_min_met,
393 #define handle_restart_type(rsc, kind, flag, flags) do { \ 394 if (((kind) == pe_order_kind_optional) \ 395 && ((rsc)->restart_type == pe_restart_restart)) { \ 396 pcmk__set_relation_flags((flags), (flag)); \ 416 action_then = invert_action(action_then);
417 action_first = invert_action(action_first);
418 if ((action_then == NULL) || (action_first == NULL)) {
420 "(please specify inverse manually)",
id);
422 uint32_t
flags = ordering_flags_for_kind(kind, action_first,
427 action_first,
flags);
436 int min_required_before = 0;
441 const char *action_then = NULL;
442 const char *action_first = NULL;
443 const char *
id = NULL;
456 if (rsc_first == NULL) {
462 if (rsc_then == NULL) {
467 if (action_first == NULL) {
472 if (action_then == NULL) {
473 action_then = action_first;
476 kind = get_ordering_type(xml_obj);
478 symmetry = get_ordering_symmetry(xml_obj, kind, NULL);
479 flags = ordering_flags_for_kind(kind, action_first, symmetry);
488 min_required_before = get_minimum_first_instances(rsc_first, xml_obj);
489 if (min_required_before > 0) {
490 clone_min_ordering(
id, rsc_first, action_first, rsc_then, action_then,
491 flags, min_required_before);
498 inverse_ordering(
id, kind, rsc_first, action_first,
499 rsc_then, action_then);
540 CRM_CHECK(((first_action != NULL) || (first_rsc != NULL))
541 && ((then_action != NULL) || (then_rsc != NULL)),
542 free(first_action_task); free(then_action_task);
return);
544 if ((first_rsc == NULL) && (first_action != NULL)) {
545 first_rsc = first_action->
rsc;
547 if ((then_rsc == NULL) && (then_action != NULL)) {
548 then_rsc = then_action->
rsc;
555 order->
rsc1 = first_rsc;
556 order->
rsc2 = then_rsc;
559 order->
task1 = first_action_task;
560 order->
task2 = then_action_task;
562 if ((order->
task1 == NULL) && (first_action != NULL)) {
563 order->
task1 = strdup(first_action->
uuid);
566 if ((order->
task2 == NULL) && (then_action != NULL)) {
567 order->
task2 = strdup(then_action->
uuid);
570 if ((order->
rsc1 == NULL) && (first_action != NULL)) {
571 order->
rsc1 = first_action->
rsc;
574 if ((order->
rsc2 == NULL) && (then_action != NULL)) {
575 order->
rsc2 = then_action->
rsc;
580 pcmk__s(order->
task1,
"an underspecified action"),
581 pcmk__s(order->
task2,
"an underspecified action"));
601 unpack_order_set(
const xmlNode *
set,
enum pe_order_kind parent_kind,
604 GList *set_iter = NULL;
605 GList *resources = NULL;
610 int local_kind = parent_kind;
611 bool sequential =
false;
616 const char *
id = pcmk__xe_id(
set);
626 local_kind = get_ordering_type(
set);
628 if (sequential_s == NULL) {
634 symmetry = get_ordering_symmetry(
set, parent_kind, parent_symmetrical_s);
635 flags = ordering_flags_for_kind(local_kind,
action, symmetry);
643 resources = g_list_append(resources, resource);
646 if (pcmk__list_of_1(resources)) {
651 set_iter = resources;
652 while (set_iter != NULL) {
654 set_iter = set_iter->next;
661 for (GList *iter = set_iter; iter != NULL; iter = iter->next) {
669 }
else if (sequential) {
686 flags = ordering_flags_for_kind(local_kind,
action,
689 set_iter = resources;
690 while (set_iter != NULL) {
692 set_iter = set_iter->next;
704 g_list_free(resources);
721 order_rsc_sets(
const char *
id,
const xmlNode *set1,
const xmlNode *set2,
726 const xmlNode *xml_rsc = NULL;
727 const xmlNode *xml_rsc_2 = NULL;
737 bool require_all =
true;
741 if (action_1 == NULL) {
745 if (action_2 == NULL) {
750 action_1 = invert_action(action_1);
751 action_2 = invert_action(action_2);
764 flags = ordering_flags_for_kind(kind, action_1, symmetry);
788 NULL, NULL, NULL, unordered_action,
817 if (xml_rsc != NULL) {
823 const char *rid = NULL;
829 rid = pcmk__xe_id(xml_rsc);
838 const char *rid = NULL;
844 rid = pcmk__xe_id(xml_rsc);
852 if (xml_rsc != NULL) {
858 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
861 }
else if (rsc_1 != NULL) {
871 }
else if (rsc_2 != NULL) {
915 unpack_order_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
918 const char *id_first = NULL;
919 const char *id_then = NULL;
920 const char *action_first = NULL;
921 const char *action_then = NULL;
928 xmlNode *rsc_set_first = NULL;
929 xmlNode *rsc_set_then = NULL;
930 bool any_sets =
false;
934 if (*expanded_xml != NULL) {
941 if ((id_first == NULL) || (id_then == NULL)) {
948 "valid resource or tag",
949 pcmk__xe_id(xml_obj), id_first);
956 "valid resource or tag",
957 pcmk__xe_id(xml_obj), id_then);
961 if ((rsc_first != NULL) && (rsc_then != NULL)) {
977 *expanded_xml = NULL;
981 if (rsc_set_first != NULL) {
982 if (action_first != NULL) {
998 *expanded_xml = NULL;
1002 if (rsc_set_then != NULL) {
1003 if (action_then != NULL) {
1017 *expanded_xml = NULL;
1033 xmlNode *
set = NULL;
1034 xmlNode *last = NULL;
1036 xmlNode *orig_xml = NULL;
1037 xmlNode *expanded_xml = NULL;
1050 if (expanded_xml != NULL) {
1052 xml_obj = expanded_xml;
1063 if (expanded_xml != NULL) {
1071 if (order_rsc_sets(
id, last,
set, kind,
scheduler,
1073 if (expanded_xml != NULL) {
1080 && (order_rsc_sets(
id,
set, last, kind,
scheduler,
1082 if (expanded_xml != NULL) {
1099 return unpack_simple_rsc_order(xml_obj,
scheduler);
1110 && (
input->action->rsc != NULL)
1142 for (GList *input_iter =
action->actions_before;
1143 input_iter != NULL; input_iter = input_iter->next) {
1145 input = input_iter->data;
1164 iter != NULL; iter = iter->next) {
1169 if (!pcmk__same_node(
action->node, node)
1178 "Not ordering %s before shutdown of %s because " 1179 "resource in maintenance mode",
1180 action->uuid, pcmk__node_name(node));
1185 "Not ordering %s before shutdown of %s because " 1186 "node in maintenance mode",
1187 action->uuid, pcmk__node_name(node));
1195 if (!pcmk_any_flags_set(
action->rsc->flags,
1198 "Not ordering %s before shutdown of %s because " 1199 "resource is unmanaged or blocked",
1200 action->uuid, pcmk__node_name(node));
1205 action->uuid, pcmk__node_name(node));
1225 find_actions_by_task(
const pcmk_resource_t *rsc,
const char *original_key)
1234 guint interval_ms = 0;
1259 GList *then_actions = NULL;
1262 CRM_CHECK((rsc != NULL) && (order != NULL),
return);
1266 order->
id, rsc->
id);
1269 then_actions = g_list_prepend(NULL, order->
action2);
1272 then_actions = find_actions_by_task(rsc, order->
task2);
1275 if (then_actions == NULL) {
1276 pcmk__rsc_trace(rsc,
"Ignoring ordering %d: no %s actions found for %s",
1281 if ((first_action != NULL) && (first_action->
rsc == rsc)
1285 "Detected dangling migration ordering (%s then %s %s)",
1290 if ((first_action == NULL)
1294 "Ignoring ordering %d for %s: No first action found",
1295 order->
id, rsc->
id);
1296 g_list_free(then_actions);
1300 for (GList *iter = then_actions; iter != NULL; iter = iter->next) {
1303 if (first_action != NULL) {
1307 crm_warn(
"%s of %s is unrunnable because there is no %s of %s " 1308 "to order it after", then_action_iter->
task, rsc->
id,
1313 g_list_free(then_actions);
1319 GList *first_actions = NULL;
1324 pcmk__rsc_trace(first_rsc,
"Applying ordering constraint %d (first: %s)",
1325 order->
id, first_rsc->
id);
1327 if (first_action != NULL) {
1328 first_actions = g_list_prepend(NULL, first_action);
1331 first_actions = find_actions_by_task(first_rsc, order->
task1);
1334 if ((first_actions == NULL) && (first_rsc == then_rsc)) {
1336 "Ignoring constraint %d: first (%s for %s) not found",
1337 order->
id, order->
task1, first_rsc->
id);
1339 }
else if (first_actions == NULL) {
1341 char *op_type = NULL;
1342 guint interval_ms = 0;
1351 "Ignoring constraint %d: first (%s for %s) " 1353 order->
id, order->
task1, first_rsc->
id);
1355 }
else if ((first_rsc->
fns->
state(first_rsc,
1361 "Ignoring constraint %d: first (%s for %s) " 1363 order->
id, order->
task1, first_rsc->
id);
1367 "Creating first (%s for %s) for constraint %d ",
1368 order->
task1, first_rsc->
id, order->
id);
1369 first_action =
custom_action(first_rsc, key, op_type, NULL, TRUE,
1371 first_actions = g_list_prepend(NULL, first_action);
1377 if (then_rsc == NULL) {
1385 for (GList *iter = first_actions; iter != NULL; iter = iter->next) {
1386 first_action = iter->data;
1388 if (then_rsc == NULL) {
1392 order_resource_actions_after(first_action, then_rsc, order);
1396 g_list_free(first_actions);
1401 block_colocation_dependents(gpointer
data, gpointer user_data)
1408 update_action_for_orderings(gpointer
data, gpointer user_data)
1423 crm_trace(
"Applying ordering constraints");
1440 iter != NULL; iter = iter->next) {
1446 rsc_order_first(rsc, order);
1452 order_resource_actions_after(order->
action1, rsc, order);
1455 crm_trace(
"Applying ordering constraint %d (non-resource actions)",
1461 g_list_foreach(sched->
actions, block_colocation_dependents, NULL);
1467 g_list_foreach(sched->
actions, update_action_for_orderings, sched);
1482 const char *after_desc = (after->
task == NULL)? after->
uuid : after->
task;
1484 for (GList *iter = list; iter != NULL; iter = iter->next) {
1486 const char *before_desc = before->
task? before->
task : before->
uuid;
1488 crm_debug(
"Ordering %s on %s before %s on %s",
1489 before_desc, pcmk__node_name(before->
node),
1490 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...)
#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
#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...)
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
#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__assert(expr)
#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
int pcmk_parse_score(const char *score_s, int *score, int default_score)
Parse an integer score from a string.
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