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)
68 crm_warn(
"Unknown action '%s' specified in order constraint",
action);
73 get_ordering_type(
const xmlNode *xml_obj)
91 "Support for 'score' in rsc_order is deprecated " 92 "and will be removed in a future release " 93 "(use 'kind' instead)");
107 "%s to 'Mandatory' because '%s' is not valid",
108 pcmk__s(
ID(xml_obj),
"missing ID"), kind);
125 get_ordering_symmetry(
const xmlNode *xml_obj,
enum pe_order_kind parent_kind,
126 const char *parent_symmetrical_s)
129 bool symmetric =
false;
135 kind = get_ordering_type(xml_obj);
141 if (rc !=
pcmk_rc_ok && parent_symmetrical_s != NULL) {
150 " for '%s' because not valid with " 178 ordering_flags_for_kind(
enum pe_order_kind kind,
const char *first,
235 get_ordering_resource(
const xmlNode *xml,
const char *resource_attr,
236 const char *instance_attr,
244 if (rsc_id == NULL) {
246 ID(xml), resource_attr);
253 "does not exist",
ID(xml), rsc_id);
257 if (instance_id != NULL) {
261 "removed in a future release.");
263 if (!pe_rsc_is_clone(rsc)) {
265 "is not a clone but instance '%s' was requested",
266 ID(xml), rsc_id, instance_id);
272 "does not have an instance '%s'",
273 "'%s'",
ID(xml), rsc_id, instance_id);
290 get_minimum_first_instances(
const pcmk_resource_t *rsc,
const xmlNode *xml)
292 const char *clone_min = NULL;
293 bool require_all =
false;
295 if (!pe_rsc_is_clone(rsc)) {
300 if (clone_min != NULL) {
301 int clone_min_int = 0;
304 return clone_min_int;
312 "Support for require-all in ordering constraints " 313 "is deprecated and will be removed in a future release" 314 " (use clone-min clone meta-attribute instead)");
336 clone_min_ordering(
const char *
id,
339 uint32_t
flags,
int clone_min)
354 for (GList *iter = rsc_first->
children; iter != NULL; iter = iter->next) {
358 NULL, NULL, NULL, clone_min_met,
384 #define handle_restart_type(rsc, kind, flag, flags) do { \ 385 if (((kind) == pe_order_kind_optional) \ 386 && ((rsc)->restart_type == pe_restart_restart)) { \ 387 pe__set_order_flags((flags), (flag)); \ 407 action_then = invert_action(action_then);
408 action_first = invert_action(action_first);
409 if ((action_then == NULL) || (action_first == NULL)) {
411 "(please specify inverse manually)",
id);
413 uint32_t
flags = ordering_flags_for_kind(kind, action_first,
418 action_first,
flags);
427 int min_required_before = 0;
432 const char *action_then = NULL;
433 const char *action_first = NULL;
434 const char *
id = NULL;
448 if (rsc_first == NULL) {
455 if (rsc_then == NULL) {
460 if (action_first == NULL) {
465 if (action_then == NULL) {
466 action_then = action_first;
469 kind = get_ordering_type(xml_obj);
471 symmetry = get_ordering_symmetry(xml_obj, kind, NULL);
472 flags = ordering_flags_for_kind(kind, action_first, symmetry);
481 min_required_before = get_minimum_first_instances(rsc_first, xml_obj);
482 if (min_required_before > 0) {
483 clone_min_ordering(
id, rsc_first, action_first, rsc_then, action_then,
484 flags, min_required_before);
491 inverse_ordering(
id, kind, rsc_first, action_first,
492 rsc_then, action_then);
533 CRM_CHECK(((first_action != NULL) || (first_rsc != NULL))
534 && ((then_action != NULL) || (then_rsc != NULL)),
535 free(first_action_task); free(then_action_task);
return);
537 if ((first_rsc == NULL) && (first_action != NULL)) {
538 first_rsc = first_action->
rsc;
540 if ((then_rsc == NULL) && (then_action != NULL)) {
541 then_rsc = then_action->
rsc;
549 order->
lh_rsc = first_rsc;
564 if ((order->
lh_rsc == NULL) && (first_action != NULL)) {
568 if ((order->
rh_rsc == NULL) && (then_action != NULL)) {
572 pe_rsc_trace(first_rsc,
"Created ordering %d for %s then %s",
593 unpack_order_set(
const xmlNode *
set,
enum pe_order_kind parent_kind,
596 GList *set_iter = NULL;
597 GList *resources = NULL;
602 int local_kind = parent_kind;
603 bool sequential =
false;
608 const char *
id =
ID(
set);
618 local_kind = get_ordering_type(
set);
620 if (sequential_s == NULL) {
626 symmetry = get_ordering_symmetry(
set, parent_kind, parent_symmetrical_s);
627 flags = ordering_flags_for_kind(local_kind,
action, symmetry);
633 resources = g_list_append(resources, resource);
636 if (pcmk__list_of_1(resources)) {
641 set_iter = resources;
642 while (set_iter != NULL) {
644 set_iter = set_iter->next;
651 for (GList *iter = set_iter; iter != NULL; iter = iter->next) {
659 }
else if (sequential) {
676 flags = ordering_flags_for_kind(local_kind,
action,
679 set_iter = resources;
680 while (set_iter != NULL) {
682 set_iter = set_iter->next;
694 g_list_free(resources);
711 order_rsc_sets(
const char *
id,
const xmlNode *set1,
const xmlNode *set2,
716 const xmlNode *xml_rsc = NULL;
717 const xmlNode *xml_rsc_2 = NULL;
727 bool require_all =
true;
731 if (action_1 == NULL) {
735 if (action_2 == NULL) {
740 action_1 = invert_action(action_1);
741 action_2 = invert_action(action_2);
754 flags = ordering_flags_for_kind(kind, action_1, symmetry);
776 NULL, NULL, NULL, unordered_action,
803 if (xml_rsc != NULL) {
809 const char *rid = NULL;
823 const char *rid = NULL;
835 if (xml_rsc != NULL) {
841 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
844 }
else if (rsc_1 != NULL) {
853 }
else if (rsc_2 != NULL) {
894 unpack_order_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
897 const char *id_first = NULL;
898 const char *id_then = NULL;
899 const char *action_first = NULL;
900 const char *action_then = NULL;
907 xmlNode *rsc_set_first = NULL;
908 xmlNode *rsc_set_then = NULL;
909 bool any_sets =
false;
913 if (*expanded_xml != NULL) {
920 if ((id_first == NULL) || (id_then == NULL)) {
927 "valid resource or tag",
ID(xml_obj), id_first);
934 "valid resource or tag",
ID(xml_obj), id_then);
938 if ((rsc_first != NULL) && (rsc_then != NULL)) {
952 *expanded_xml = NULL;
956 if (rsc_set_first != NULL) {
957 if (action_first != NULL) {
959 crm_xml_add(rsc_set_first,
"action", action_first);
969 *expanded_xml = NULL;
973 if (rsc_set_then != NULL) {
974 if (action_then != NULL) {
986 *expanded_xml = NULL;
1002 xmlNode *
set = NULL;
1003 xmlNode *last = NULL;
1005 xmlNode *orig_xml = NULL;
1006 xmlNode *expanded_xml = NULL;
1019 if (expanded_xml != NULL) {
1021 xml_obj = expanded_xml;
1032 if (expanded_xml != NULL) {
1040 if (order_rsc_sets(
id, last,
set, kind,
scheduler,
1042 if (expanded_xml != NULL) {
1049 && (order_rsc_sets(
id,
set, last, kind,
scheduler,
1051 if (expanded_xml != NULL) {
1068 return unpack_simple_rsc_order(xml_obj,
scheduler);
1079 && (
input->action->rsc != NULL)
1082 crm_warn(
"Invalid ordering constraint between %s and %s",
1111 for (GList *input_iter =
action->actions_before;
1112 input_iter != NULL; input_iter = input_iter->next) {
1114 input = input_iter->data;
1133 iter != NULL; iter = iter->next) {
1138 if (!pe__same_node(
action->node, node)
1147 "Not ordering %s before shutdown of %s because " 1148 "resource in maintenance mode",
1149 action->uuid, pe__node_name(node));
1154 "Not ordering %s before shutdown of %s because " 1155 "node in maintenance mode",
1156 action->uuid, pe__node_name(node));
1164 if (!pcmk_any_flags_set(
action->rsc->flags,
1167 "Not ordering %s before shutdown of %s because " 1168 "resource is unmanaged or blocked",
1169 action->uuid, pe__node_name(node));
1174 action->uuid, pe__node_name(node));
1194 find_actions_by_task(
const pcmk_resource_t *rsc,
const char *original_key)
1203 guint interval_ms = 0;
1205 if (
parse_op_key(original_key, NULL, &task, &interval_ms)) {
1211 crm_err(
"Invalid operation key (bug?): %s", original_key);
1229 GList *then_actions = NULL;
1232 CRM_CHECK((rsc != NULL) && (order != NULL),
return);
1235 pe_rsc_trace(rsc,
"Applying ordering %d for 'then' resource %s",
1236 order->
id, rsc->
id);
1239 then_actions = g_list_prepend(NULL, order->
rh_action);
1245 if (then_actions == NULL) {
1246 pe_rsc_trace(rsc,
"Ignoring ordering %d: no %s actions found for %s",
1251 if ((first_action != NULL) && (first_action->
rsc == rsc)
1255 "Detected dangling migration ordering (%s then %s %s)",
1260 if ((first_action == NULL)
1264 "Ignoring ordering %d for %s: No first action found",
1265 order->
id, rsc->
id);
1266 g_list_free(then_actions);
1270 for (GList *iter = then_actions; iter != NULL; iter = iter->next) {
1273 if (first_action != NULL) {
1277 crm_warn(
"%s of %s is unrunnable because there is no %s of %s " 1278 "to order it after", then_action_iter->
task, rsc->
id,
1283 g_list_free(then_actions);
1289 GList *first_actions = NULL;
1294 pe_rsc_trace(first_rsc,
"Applying ordering constraint %d (first: %s)",
1295 order->
id, first_rsc->
id);
1297 if (first_action != NULL) {
1298 first_actions = g_list_prepend(NULL, first_action);
1301 first_actions = find_actions_by_task(first_rsc, order->
lh_action_task);
1304 if ((first_actions == NULL) && (first_rsc == then_rsc)) {
1306 "Ignoring constraint %d: first (%s for %s) not found",
1309 }
else if (first_actions == NULL) {
1311 char *op_type = NULL;
1312 guint interval_ms = 0;
1321 "Ignoring constraint %d: first (%s for %s) not found",
1324 }
else if ((first_rsc->
fns->
state(first_rsc,
1330 "Ignoring constraint %d: first (%s for %s) not found",
1335 "Creating first (%s for %s) for constraint %d ",
1337 first_action =
custom_action(first_rsc, key, op_type, NULL, TRUE,
1339 first_actions = g_list_prepend(NULL, first_action);
1345 if (then_rsc == NULL) {
1347 pe_rsc_trace(first_rsc,
"Ignoring constraint %d: then not found",
1353 for (GList *iter = first_actions; iter != NULL; iter = iter->next) {
1354 first_action = iter->data;
1356 if (then_rsc == NULL) {
1360 order_resource_actions_after(first_action, then_rsc, order);
1364 g_list_free(first_actions);
1369 block_colocation_dependents(gpointer
data, gpointer user_data)
1376 update_action_for_orderings(gpointer
data, gpointer user_data)
1391 crm_trace(
"Applying ordering constraints");
1408 iter != NULL; iter = iter->next) {
1414 rsc_order_first(rsc, order);
1420 order_resource_actions_after(order->
lh_action, rsc, order);
1423 crm_trace(
"Applying ordering constraint %d (non-resource actions)",
1429 g_list_foreach(sched->
actions, block_colocation_dependents, NULL);
1435 g_list_foreach(sched->
actions, update_action_for_orderings, sched);
1450 const char *after_desc = (after->
task == NULL)? after->
uuid : after->
task;
1452 for (GList *iter = list; iter != NULL; iter = iter->next) {
1454 const char *before_desc = before->
task? before->
task : before->
uuid;
1456 crm_debug(
"Ordering %s on %s before %s on %s",
1457 before_desc, pe__node_name(before->
node),
1458 after_desc, pe__node_name(after->
node));
#define CRM_CHECK(expr, failure_action)
pcmk_action_t * lh_action
'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
Cluster that resource is part of.
Actions are ordered if on same node (or migration target for migrate_to)
#define pe_rsc_debug(rsc, fmt, args...)
pcmk_action_t * get_pseudo_op(const char *name, pcmk_scheduler_t *scheduler)
Whether action should not be executed.
#define XML_ORDER_ATTR_THEN_ACTION
User-configured asymmetric ordering.
#define pe__set_action_flags(action, flags_to_set)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
pcmk_action_t * rh_action
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
#define XML_ORDER_ATTR_THEN
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...)
GList * children
Resource's child resources, if any.
#define XML_RULE_ATTR_SCORE
gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, uint32_t flags)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
#define PCMK_META_CLONE_MIN
enum rsc_role_e(* state)(const pcmk_resource_t *rsc, gboolean current)
Get resource's current or assigned role.
Implementation of pcmk_action_t.
int char2score(const char *score)
Get the integer value of a score string.
#define pcmk__config_err(fmt...)
GHashTable * meta
Resource's meta-attributes.
G_GNUC_INTERNAL void pcmk__block_colocation_dependents(pcmk_action_t *action)
Whether resource, its node, or entire cluster is in maintenance mode.
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
GList * actions
Scheduled actions.
int order_id
ID to use for next created ordering.
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)
#define XML_ORDER_ATTR_FIRST_INSTANCE
pcmk_scheduler_t * data_set
Cluster that node is part of.
void pcmk__promotable_restart_ordering(pcmk_resource_t *rsc)
Implementation of pcmk_scheduler_t.
#define XML_CONS_TAG_RSC_SET
Ordering applies even if 'first' runs on guest node created by 'then'.
GList * resources
Resources in cluster.
xmlNode * copy_xml(xmlNode *src_node)
#define XML_ORDER_ATTR_FIRST
#define PCMK_ACTION_DEMOTE
#define crm_warn(fmt, args...)
pcmk_node_t * node
Node to execute action on, if any.
Implementation of pcmk_resource_t.
#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 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.
#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
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
Basic node information.
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)
#define XML_TAG_RESOURCE_REF
#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)
Whether resource is blocked from further action.
Implementation of pcmk_node_t.
#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 XML_ORDER_ATTR_THEN_INSTANCE
GList * ordering_constraints
Ordering constraints.
Whether action is runnable.
pcmk_rsc_methods_t * fns
Resource object methods.
void pcmk__disable_invalid_orderings(pcmk_scheduler_t *scheduler)
#define XML_ORDER_ATTR_KIND
G_GNUC_INTERNAL bool pcmk__graph_has_loop(const pcmk_action_t *init_action, const pcmk_action_t *action, pcmk__related_action_t *input)
#define crm_err(fmt, args...)
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
void xml_remove_prop(xmlNode *obj, const char *name)
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Configuration tag object.
#define PCMK_ACTION_PROMOTE
void pcmk__unpack_ordering(xmlNode *xml_obj, pcmk_scheduler_t *scheduler)
enum pe_action_flags flags
Group of enum pe_action_flags.
gboolean maintenance
Whether in maintenance mode.
#define crm_log_xml_trace(xml, text)
#define PCMK_ACTION_PROMOTED
Whether action is a stop to abort a dangling migration.
gboolean crm_is_true(const char *s)
pcmk_resource_t * rsc
Resource to apply action to, if any.
#define pe_rsc_trace(rsc, fmt, args...)
#define pe__set_order_flags(order_flags, flags_to_set)
#define PCMK_ACTION_RUNNING
pcmk_resource_t * find_clone_instance(const pcmk_resource_t *rsc, const char *sub_id)
#define PCMK_ACTION_DEMOTED
Whether resource is managed.
'then' action is runnable if certain number of 'first' instances are
#define PCMK_ACTION_ONE_OR_MORE
#define XML_CONS_ATTR_SYMMETRICAL
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)
#define XML_ORDER_ATTR_FIRST_ACTION
void pcmk__order_migration_equivalents(pe__ordering_t *order)
int required_runnable_before
No relation (compare with equality rather than bit set)
char * id
Resource ID in configuration.
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.