54 find_existing_action(
const char *key,
const pe_resource_t *rsc,
57 GList *matches = NULL;
65 if (matches == NULL) {
76 find_rsc_op_entry_helper(
const pe_resource_t *rsc,
const char *key,
77 gboolean include_disabled)
79 guint interval_ms = 0;
80 gboolean do_retry = TRUE;
81 char *local_key = NULL;
82 const char *
name = NULL;
83 const char *interval_spec = NULL;
84 char *match_key = NULL;
86 xmlNode *operation = NULL;
89 for (operation = pcmk__xe_first_child(rsc->
ops_xml); operation != NULL;
90 operation = pcmk__xe_next(operation)) {
92 if (pcmk__str_eq((
const char *)operation->name,
"op",
pcmk__str_none)) {
125 if (do_retry == FALSE) {
135 }
else if (strstr(key,
"_notify_")) {
147 return find_rsc_op_entry_helper(rsc, key, FALSE);
168 const pe_node_t *node,
bool optional,
bool for_graph,
198 guint interval_ms = 0;
200 action->op_entry = find_rsc_op_entry_helper(rsc, key, TRUE);
207 pe_rsc_trace(rsc,
"Created %s action %d (%s): %s for %s on %s",
208 (optional?
"optional" :
"required"),
210 ((rsc == NULL)?
"no resource" : rsc->
id),
211 pe__node_name(node));
235 && (
action->op_entry != NULL)) {
248 &rule_data,
action->extra, NULL,
267 && (g_hash_table_lookup(
action->meta,
276 }
else if (!optional) {
295 "no-quorum-policy=demote");
325 if (
action->node == NULL) {
331 && !(
action->node->details->online)
333 ||
action->node->details->remote_requires_reset)) {
336 "%s on %s is unrunnable (node is offline)",
341 && !(
action->node->details->unclean)) {
346 &&
action->node->details->pending) {
349 "Action %s on %s is unrunnable (node is pending)",
362 "(node's host cannot be fenced)",
367 "%s on %s does not require fencing or quorum",
385 "%s on %s is unrunnable (no quorum)",
426 valid_stop_on_fail(
const char *value)
434 const char *
name = NULL;
435 const char *role = NULL;
436 const char *on_fail = NULL;
437 const char *interval_spec = NULL;
441 && !valid_stop_on_fail(value)) {
444 "action to default value because '%s' is not " 445 "allowed for stop",
action->rsc->id, value);
450 xmlNode *operation = NULL;
454 for (operation = pcmk__xe_first_child(
action->rsc->ops_xml);
455 (operation != NULL) && (value == NULL);
456 operation = pcmk__xe_next(operation)) {
457 bool enabled =
false;
459 if (!pcmk__str_eq((
const char *)operation->name,
"op",
pcmk__str_none)) {
498 "action to default value because 'demote' is not " 508 unpack_timeout(
const char *value)
512 if (timeout_ms < 0) {
520 unpack_interval_origin(
const char *value,
const xmlNode *xml_obj,
522 long long *start_delay)
525 guint interval_sec = interval_ms / 1000;
529 if ((value == NULL) || (interval_ms == 0) || (now == NULL)) {
535 if (origin == NULL) {
537 "'%s' because '%s' is not valid",
538 (
ID(xml_obj)?
ID(xml_obj) :
"(missing ID)"), value);
551 crm_info(
"Calculated a start delay of %llds for operation '%s'",
553 (
ID(xml_obj)?
ID(xml_obj) :
"(unspecified)"));
555 if (start_delay != NULL) {
556 *start_delay =
result * 1000;
562 unpack_start_delay(
const char *value, GHashTable *meta)
569 if (start_delay < 0) {
575 pcmk__itoa(start_delay));
583 find_min_interval_mon(
pe_resource_t * rsc, gboolean include_disabled)
585 guint interval_ms = 0;
586 guint min_interval_ms = G_MAXUINT;
587 const char *
name = NULL;
588 const char *interval_spec = NULL;
590 xmlNode *operation = NULL;
592 for (operation = pcmk__xe_first_child(rsc->
ops_xml);
594 operation = pcmk__xe_next(operation)) {
596 if (pcmk__str_eq((
const char *)operation->name,
"op",
pcmk__str_none)) {
597 bool enabled =
false;
612 if (interval_ms && (interval_ms < min_interval_ms)) {
613 min_interval_ms = interval_ms;
641 const char *value = NULL;
642 bool is_probe =
false;
652 .interval = interval_ms
660 .rsc_data = &rsc_rule_data,
661 .op_data = &op_rule_data
674 xmlNode *min_interval_mon = find_min_interval_mon(
action->rsc, FALSE);
676 if (min_interval_mon) {
679 crm_trace(
"\t%s: Setting default timeout to minimum-interval " 680 "monitor's timeout '%s'",
action->uuid, value);
688 xmlAttrPtr xIter = NULL;
697 for (xIter = xml_obj->properties; xIter; xIter = xIter->next) {
698 const char *prop_name = (
const char *)xIter->name;
701 g_hash_table_replace(
action->meta, strdup(prop_name), strdup(prop_value));
705 g_hash_table_remove(
action->meta,
"id");
708 if (interval_ms > 0) {
736 value = g_hash_table_lookup(params,
"pcmk_monitor_timeout");
739 crm_trace(
"\t%s: Setting timeout to pcmk_monitor_timeout '%s', " 740 "overriding default",
action->uuid, value);
748 timeout_ms = unpack_timeout(value);
750 pcmk__itoa(timeout_ms));
754 value =
"nothing (not start or promote)";
770 value = unpack_operation_on_fail(
action);
781 value =
"node fencing";
785 "operation '%s' to 'stop' because 'fence' is not " 786 "valid when fencing is disabled",
action->uuid);
789 value =
"stop resource";
794 value =
"node standby";
803 value =
"force migration";
808 value =
"stop resource";
812 value =
"restart (and possibly migrate)";
814 }
else if (pcmk__str_eq(value,
"restart-container",
pcmk__str_casei)) {
817 value =
"restart container (and possibly migrate)";
825 value =
"demote instance";
828 pe_err(
"Resource %s: Unknown failure type (%s)",
action->rsc->id, value);
833 if (value == NULL && container) {
835 value =
"restart container (and possibly migrate) (default)";
848 && (interval_ms == 0))
854 value =
"stop unmanaged remote node (enforcing default)";
858 value =
"fence remote node (default)";
860 value =
"recover remote node connection (default)";
863 if (
action->rsc->remote_reconnect_ms) {
872 value =
"resource fence (default)";
876 value =
"resource block (default)";
879 }
else if (value == NULL) {
881 value =
"restart (and possibly migrate) (default)";
888 if (xml_obj != NULL) {
889 value = g_hash_table_lookup(
action->meta,
"role_after_failure");
892 "Support for role_after_failure is deprecated and will be removed in a future release");
911 unpack_start_delay(value,
action->meta);
913 long long start_delay = 0;
916 if (unpack_interval_origin(value, xml_obj, interval_ms,
data_set->
now,
943 const pe_node_t *on_node, gboolean optional, gboolean save_action,
955 action = new_action(key, task, rsc, on_node, optional, save_action,
961 update_action_optional(
action, optional);
964 if (
action->node != NULL) {
971 update_resource_flags_for_action(rsc,
action);
991 find_unfencing_devices(GList *candidates, GList *matches)
993 for (GList *gIter = candidates; gIter != NULL; gIter = gIter->next) {
997 matches = find_unfencing_devices(candidate->
children, matches);
1003 matches = g_list_prepend(matches, candidate);
1005 }
else if (pcmk__str_eq(g_hash_table_lookup(candidate->
meta,
1009 matches = g_list_prepend(matches, candidate);
1016 node_priority_fencing_delay(
const pe_node_t *node,
1019 int member_count = 0;
1020 int online_count = 0;
1021 int top_priority = 0;
1022 int lowest_priority = 0;
1023 GList *gIter = NULL;
1041 for (gIter =
data_set->
nodes; gIter != NULL; gIter = gIter->next) {
1054 if (member_count == 1
1059 if (member_count == 1
1066 if (online_count > member_count / 2) {
1072 if (lowest_priority == top_priority) {
1087 char *op_key = NULL;
1096 stonith_op = lookup_singleton(
data_set, op_key);
1097 if(stonith_op == NULL) {
1107 GString *digests_all = g_string_sized_new(1024);
1108 GString *digests_secure = g_string_sized_new(1024);
1115 for (GList *gIter = matches; gIter != NULL; gIter = gIter->next) {
1117 const char *agent = g_hash_table_lookup(match->
meta,
1124 crm_notice(
"Unfencing node %s because the definition of " 1125 "%s changed", pe__node_name(node), match->
id);
1130 "notice: Unfencing node %s because the " 1131 "definition of %s changed",
1132 pe__node_name(node), match->
id);
1137 match->
id,
":", agent,
":",
1138 data->digest_all_calc,
",", NULL);
1140 match->
id,
":", agent,
":",
1141 data->digest_secure_calc,
",", NULL);
1144 value = strdup((
const char *) digests_all->str);
1145 CRM_ASSERT((key != NULL) && (value != NULL));
1146 g_hash_table_insert(stonith_op->
meta, key, value);
1147 g_string_free(digests_all, TRUE);
1150 value = strdup((
const char *) digests_secure->str);
1151 CRM_ASSERT((key != NULL) && (value != NULL));
1152 g_hash_table_insert(stonith_op->
meta, key, value);
1153 g_string_free(digests_secure, TRUE);
1170 || g_hash_table_lookup(stonith_op->
meta,
1177 char *delay_s = pcmk__itoa(node_priority_fencing_delay(node,
data_set));
1179 g_hash_table_insert(stonith_op->
meta,
1188 }
else if(reason && stonith_op->
reason == NULL) {
1189 stonith_op->
reason = strdup(reason);
1201 g_list_free_full(
action->actions_before, free);
1202 g_list_free_full(
action->actions_after, free);
1204 g_hash_table_destroy(
action->extra);
1207 g_hash_table_destroy(
action->meta);
1209 free(
action->cancel_task);
1220 xmlNode *child = NULL;
1221 GHashTable *action_meta = NULL;
1222 const char *timeout_spec = NULL;
1246 &rule_data, action_meta, NULL, FALSE,
data_set);
1254 if (timeout_ms < 0) {
1258 if (action_meta != NULL) {
1259 g_hash_table_destroy(action_meta);
1275 crm_trace(
"Folding %s back into its atomic counterpart for %s",
1303 for (
const GList *gIter =
input; gIter != NULL; gIter = gIter->next) {
1312 }
else if (on_node == NULL) {
1315 }
else if (
action->node == NULL) {
1329 GList *gIter =
input;
1334 for (; gIter != NULL; gIter = gIter->next) {
1340 }
else if (on_node == NULL) {
1341 crm_trace(
"Action %s matches (ignoring node)", key);
1344 }
else if (
action->node == NULL) {
1345 crm_trace(
"Action %s matches (unallocated, assigning to %s)",
1346 key, pe__node_name(on_node));
1352 crm_trace(
"Action %s on %s matches", key, pe__node_name(on_node));
1367 if (on_node == NULL) {
1371 for (GList *gIter =
input; gIter != NULL; gIter = gIter->next) {
1374 if ((
action->node != NULL)
1379 crm_trace(
"Action %s on %s matches", key, pe__node_name(on_node));
1401 const char *task,
bool require_node)
1428 const char *change = NULL;
1433 change =
"unrunnable";
1436 change =
"required";
1444 (
action->rsc == NULL)?
"" :
" ",
1451 if (
action->reason != NULL && overwrite) {
1453 action->uuid,
action->reason, pcmk__s(reason,
"(none)"));
1454 }
else if (
action->reason == NULL) {
1456 action->uuid, pcmk__s(reason,
"(none)"));
1487 #define sort_return(an_int, why) do { \ 1490 crm_trace("%s (%d) %c %s (%d) : %s", \ 1491 a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \ 1492 b_xml_id, b_call_id, why); \ 1498 bool same_node_default)
1503 char *a_uuid = NULL;
1504 char *b_uuid = NULL;
1511 bool same_node =
true;
1520 if (a_node == NULL || b_node == NULL) {
1521 same_node = same_node_default;
1527 if (same_node && pcmk__str_eq(a_xml_id, b_xml_id,
pcmk__str_none)) {
1533 pe_err(
"Duplicate lrm_rsc_op entries named %s", a_xml_id);
1540 if (a_call_id == -1 && b_call_id == -1) {
1546 }
else if (same_node && a_call_id >= 0 && a_call_id < b_call_id) {
1549 }
else if (same_node && b_call_id >= 0 && a_call_id > b_call_id) {
1552 }
else if (a_call_id >= 0 && b_call_id >= 0
1553 && (!same_node || a_call_id == b_call_id)) {
1565 (
long long) last_a, (
long long) last_b);
1566 if (last_a >= 0 && last_a < last_b) {
1569 }
else if (last_b >= 0 && last_a > last_b) {
1610 if (b_call_id == -1) {
1613 }
else if (a_call_id == -1) {
1617 }
else if ((a_id >= 0 && a_id < b_id) || b_id == -1) {
1620 }
else if ((b_id >= 0 && a_id > b_id) || a_id == -1) {
1632 const xmlNode *xml_a = a;
1633 const xmlNode *xml_b = b;
1658 optional, TRUE, rsc->
cluster);
1685 g_hash_table_insert(
action->meta,
name, pcmk__itoa(expected_result));
#define XML_OP_ATTR_ORIGIN
#define CRM_CHECK(expr, failure_action)
#define XML_RSC_OP_LAST_CHANGE
enum pe_quorum_policy no_quorum_policy
GList * find_actions(GList *input, const char *key, const pe_node_t *on_node)
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
#define crm_notice(fmt, args...)
#define CRMD_ACTION_MIGRATED
#define pe_rsc_debug(rsc, fmt, args...)
#define XML_OP_ATTR_DIGESTS_ALL
#define pe__set_action_flags(action, flags_to_set)
#define XML_EXPR_ATTR_TYPE
#define XML_ATTR_TRANSITION_MAGIC
#define PCMK_STONITH_PROVIDES
pe_resource_t * container
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
#define XML_CONFIG_ATTR_PRIORITY_FENCING_DELAY
struct crm_time_s crm_time_t
int priority_fencing_delay
xmlNode * first_named_child(const xmlNode *parent, const char *name)
enum rsc_role_e next_role
pe_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pe_node_t *on_node)
#define pcmk__config_err(fmt...)
long long crm_get_msec(const char *input)
Parse a time+units string and return milliseconds equivalent.
#define XML_LRM_ATTR_INTERVAL
pe_node_t * pe__copy_node(const pe_node_t *this_node)
bool pcmk_is_probe(const char *task, guint interval)
#define CRMD_ACTION_PROMOTE
#define PCMK__VALUE_UNFENCING
#define XML_NVPAIR_ATTR_NAME
#define XML_OP_ATTR_DIGESTS_SECURE
#define RSC_ROLE_PROMOTED_LEGACY_S
enum action_tasks text2task(const char *task)
#define CRM_LOG_ASSERT(expr)
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
int pe_get_configured_timeout(pe_resource_t *rsc, const char *action, pe_working_set_t *data_set)
xmlNode * find_rsc_op_entry(const pe_resource_t *rsc, const char *key)
#define XML_OP_ATTR_ON_FAIL
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
#define pe_flag_have_quorum
void pe__add_action_expected_result(pe_action_t *action, int expected_result)
#define pe__set_resource_flags(resource, flags_to_set)
#define CRMD_ACTION_START
pe_action_t * pe__new_rsc_pseudo_action(pe_resource_t *rsc, const char *task, bool optional, bool runnable)
#define XML_TAG_ATTR_SETS
const char * role2text(enum rsc_role_e role)
#define CRMD_ACTION_DEMOTE
GList * find_actions_exact(GList *input, const char *key, const pe_node_t *on_node)
bool pe_can_fence(const pe_working_set_t *data_set, const pe_node_t *node)
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, const pe_node_t *on_node, gboolean optional, gboolean save_action, pe_working_set_t *data_set)
Create or update an action object.
pe_action_t * pe_fence_op(pe_node_t *node, const char *op, bool optional, const char *reason, bool priority_delay, pe_working_set_t *data_set)
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
bool pe__is_guest_node(const pe_node_t *node)
pe_action_t * get_pseudo_op(const char *name, 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...)
#define do_crm_log(level, fmt, args...)
Log a message.
void pe_fence_node(pe_working_set_t *data_set, pe_node_t *node, const char *reason, bool priority_delay)
Schedule a fence action for a node.
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
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.
const char * stonith_action
struct pe_node_shared_s * details
#define XML_AGENT_ATTR_PROVIDER
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
#define pe_rsc_needs_fencing
pe_working_set_t * data_set
#define XML_TAG_META_SETS
void pcmk__str_update(char **str, const char *value)
Internal state tracking when creating graph.
#define pe_flag_stonith_enabled
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
#define CRM_DEFAULT_OP_TIMEOUT_S
char * pe__action2reason(const pe_action_t *action, enum pe_action_flags flag)
enum rsc_role_e text2role(const char *role)
op_digest_cache_t * pe__compare_fencing_digest(pe_resource_t *rsc, const char *agent, pe_node_t *node, pe_working_set_t *data_set)
enum pe_obj_types variant
long long crm_time_get_seconds(const crm_time_t *dt)
#define RSC_ROLE_PROMOTED_S
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
#define XML_LRM_ATTR_TARGET_UUID
#define pe_rsc_fence_device
void pe_action_set_reason(pe_action_t *action, const char *reason, bool overwrite)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
pcmk__action_result_t result
void add_hash_param(GHashTable *hash, const char *name, const char *value)
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
crm_time_t * crm_time_new(const char *string)
void pe__set_next_role(pe_resource_t *rsc, enum rsc_role_e role, const char *why)
This structure contains everything that makes up a single output formatter.
GHashTable * pe_rsc_params(pe_resource_t *rsc, const pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters.
#define XML_LRM_ATTR_INTERVAL_MS
#define XML_LRM_ATTR_CALLID
#define CRMD_ACTION_MIGRATE
#define pe_rsc_needs_unfencing
#define pe__clear_resource_flags(resource, flags_to_clear)
gboolean decode_transition_magic(const char *magic, char **uuid, int *transition_id, int *action_id, int *op_status, int *op_rc, int *target_rc)
Parse a transition magic string into its constituent parts.
#define PCMK__VALUE_NOTHING
#define XML_OP_ATTR_START_DELAY
pe_working_set_t * cluster
#define sort_return(an_int, why)
#define pe_rsc_needs_quorum
bool pe__resource_is_remote_conn(const pe_resource_t *rsc, const pe_working_set_t *data_set)
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
void pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, const pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, pe_working_set_t *data_set)
enum action_tasks get_complex_task(const pe_resource_t *rsc, const char *name)
int pe__is_newer_op(const xmlNode *xml_a, const xmlNode *xml_b, bool same_node_default)
#define pe_flag_enable_unfencing
#define XML_LRM_ATTR_TARGET
void pe_free_action(pe_action_t *action)
#define pe_rsc_trace(rsc, fmt, args...)
pe_action_t * pe__clear_resource_history(pe_resource_t *rsc, const pe_node_t *node, pe_working_set_t *data_set)
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
#define CRM_OP_LRM_DELETE
#define crm_info(fmt, args...)
#define XML_ATTR_TE_TARGET_RC
#define XML_AGENT_ATTR_CLASS
#define CRMD_ACTION_STATUS
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
void crm_time_free(crm_time_t *dt)