58 GList *matches = NULL;
66 if (matches == NULL) {
87 find_exact_action_config(
const pcmk_resource_t *rsc,
const char *action_name,
88 guint interval_ms,
bool include_disabled)
95 const char *config_name = NULL;
96 const char *interval_spec = NULL;
100 if (!include_disabled
108 if (tmp_ms != interval_ms) {
133 guint interval_ms,
bool include_disabled)
135 xmlNode *action_config = NULL;
138 action_config = find_exact_action_config(rsc, action_name, interval_ms,
143 if ((action_config == NULL)
146 action_config = find_exact_action_config(rsc,
"migrate", 0,
150 return action_config;
197 guint interval_ms = 0;
206 if ((
action->op_entry == NULL) && (strstr(key,
"_notify_") != NULL)) {
211 unpack_operation(
action,
action->op_entry, interval_ms);
215 (optional?
"optional" :
"required"),
217 ((rsc == NULL)?
"no resource" : rsc->
id),
218 pcmk__node_name(node));
242 GHashTable *node_attrs,
256 &rule_data, params, NULL,
277 "%s on %s is optional (%s is unmanaged)",
284 }
else if (!optional) {
332 if (
action->node == NULL) {
338 && !(
action->node->details->online)
339 && (!pcmk__is_guest_or_bundle_node(
action->node)
340 ||
action->node->details->remote_requires_reset)) {
342 do_crm_log(LOG_WARNING,
"%s on %s is unrunnable (node is offline)",
346 && !(
action->node->details->unclean)) {
351 &&
action->node->details->pending) {
354 "Action %s on %s is unrunnable (node is pending)",
359 if (pcmk__is_guest_or_bundle_node(
action->node)
367 "%s on %s is unrunnable " 368 "(node's host cannot be fenced)",
373 "%s on %s does not require fencing or quorum",
382 "%s on %s is unrunnable (no quorum)",
392 "%s on %s is unrunnable (no quorum)",
394 pcmk__node_name(
action->node));
435 valid_stop_on_fail(
const char *value)
453 const xmlNode *action_config, GHashTable *meta)
455 const char *
name = NULL;
456 const char *role = NULL;
457 const char *interval_spec = NULL;
459 guint interval_ms = 0U;
463 && !valid_stop_on_fail(value)) {
466 "action to default value because '%s' is not " 467 "allowed for stop", rsc->
id, value);
476 && (value == NULL)) {
486 bool enabled =
false;
487 const char *promote_on_fail = NULL;
493 if (promote_on_fail == NULL) {
507 if (interval_ms == 0U) {
546 && ((interval_ms == 0U)
552 "action to default value because 'demote' is not " 553 "allowed for it", rsc->
id,
name);
561 unpack_timeout(
const char *value)
565 if (timeout_ms <= 0) {
568 return (
int) QB_MIN(timeout_ms, INT_MAX);
573 unpack_interval_origin(
const char *value,
const xmlNode *xml_obj,
575 long long *start_delay)
578 guint interval_sec = interval_ms / 1000;
582 if ((value == NULL) || (interval_ms == 0) || (now == NULL)) {
588 if (origin == NULL) {
590 "operation '%s' because '%s' is not valid",
591 pcmk__s(pcmk__xe_id(xml_obj),
"(missing ID)"), value);
604 crm_info(
"Calculated a start delay of %llds for operation '%s'",
605 result, pcmk__s(pcmk__xe_id(xml_obj),
"(unspecified)"));
607 if (start_delay != NULL) {
608 *start_delay =
result * 1000;
614 unpack_start_delay(
const char *value, GHashTable *meta)
616 long long start_delay_ms = 0;
623 start_delay_ms = QB_MIN(start_delay_ms, INT_MAX);
624 if (start_delay_ms < 0) {
630 pcmk__itoa(start_delay_ms));
633 return (
int) start_delay_ms;
648 guint min_interval_ms = G_MAXUINT;
655 bool enabled =
false;
656 guint interval_ms = 0U;
667 if (interval_ms == 0U) {
677 if (interval_ms < min_interval_ms) {
678 min_interval_ms = interval_ms;
703 const char *action_name, guint interval_ms,
704 const xmlNode *action_config)
706 GHashTable *meta = NULL;
707 const char *timeout_spec = NULL;
708 const char *str = NULL;
718 .interval = interval_ms,
731 .rsc_data = &rsc_rule_data,
732 .op_data = &op_rule_data,
744 xmlNode *min_interval_mon = most_frequent_monitor(rsc);
746 if (min_interval_mon != NULL) {
753 if (timeout_spec != NULL) {
755 "Setting default timeout for %s probe to " 756 "most frequent monitor's timeout '%s'",
757 rsc->
id, timeout_spec);
763 if (action_config != NULL) {
766 &rule_data, meta, NULL, TRUE, rsc->
cluster);
772 for (xmlAttrPtr attr = action_config->properties;
773 attr != NULL; attr = attr->next) {
775 pcmk__xml_attr_value(attr));
782 if (interval_ms > 0) {
807 timeout_spec = g_hash_table_lookup(params,
"pcmk_monitor_timeout");
808 if (timeout_spec != NULL) {
810 "Setting timeout for %s %s to " 811 "pcmk_monitor_timeout (%s)",
812 rsc->
id, action_name, timeout_spec);
820 pcmk__itoa(unpack_timeout(timeout_spec)));
823 validate_on_fail(rsc, action_name, action_config, meta);
828 unpack_start_delay(str, meta);
830 long long start_delay = 0;
833 if (unpack_interval_origin(str, action_config, interval_ms,
854 const char *value = NULL;
857 CRM_CHECK((rsc != NULL) && (action_name != NULL),
return requires);
861 value =
"nothing (not start or promote)";
891 guint interval_ms,
const char *value)
893 const char *desc = NULL;
894 bool needs_remote_reset =
false;
910 desc =
"node fencing";
913 "%s of %s to 'stop' because 'fence' is not " 914 "valid when fencing is disabled",
915 action_name, rsc->
id);
917 desc =
"stop resource";
922 desc =
"node standby";
931 desc =
"force migration";
935 desc =
"stop resource";
939 desc =
"restart (and possibly migrate)";
946 "of %s because it does not have a container",
947 action_name, rsc->
id);
950 desc =
"restart container (and possibly migrate)";
955 desc =
"demote instance";
959 "%s of %s because '%s' is not valid",
960 action_name, rsc->
id, value);
972 needs_remote_reset =
true;
983 desc =
"restart container (and possibly migrate) (default)";
985 }
else if (needs_remote_reset) {
989 desc =
"fence remote node (default)";
991 desc =
"recover remote node connection (default)";
996 desc =
"stop unmanaged remote node (enforcing default)";
1002 desc =
"resource fence (default)";
1005 desc =
"resource block (default)";
1010 desc =
"restart (and possibly migrate) (default)";
1034 const char *value = NULL;
1055 if (value != NULL) {
1058 "deprecated and will be removed in a future release");
1098 const char *value = NULL;
1101 action->task, interval_ms, xml_obj);
1106 interval_ms, value);
1144 update_action_optional(
action, optional);
1152 if ((
action->node != NULL) && (
action->op_entry != NULL)
1155 GHashTable *attrs =
action->node->details->attrs;
1157 if (
action->extra != NULL) {
1158 g_hash_table_destroy(
action->extra);
1166 update_resource_flags_for_action(rsc,
action);
1169 if (
action->extra == NULL) {
1189 find_unfencing_devices(GList *candidates, GList *matches)
1191 for (GList *gIter = candidates; gIter != NULL; gIter = gIter->next) {
1195 matches = find_unfencing_devices(candidate->
children, matches);
1201 matches = g_list_prepend(matches, candidate);
1203 }
else if (pcmk__str_eq(g_hash_table_lookup(candidate->
meta,
1206 matches = g_list_prepend(matches, candidate);
1213 node_priority_fencing_delay(
const pcmk_node_t *node,
1216 int member_count = 0;
1217 int online_count = 0;
1218 int top_priority = 0;
1219 int lowest_priority = 0;
1220 GList *gIter = NULL;
1238 for (gIter =
scheduler->
nodes; gIter != NULL; gIter = gIter->next) {
1251 if (member_count == 1
1256 if (member_count == 1
1263 if (online_count > member_count / 2) {
1269 if (lowest_priority == top_priority) {
1282 const char *reason,
bool priority_delay,
1285 char *op_key = NULL;
1295 stonith_op = lookup_singleton(
scheduler, op_key);
1296 if(stonith_op == NULL) {
1308 GString *digests_all = g_string_sized_new(1024);
1309 GString *digests_secure = g_string_sized_new(1024);
1313 for (GList *gIter = matches; gIter != NULL; gIter = gIter->next) {
1315 const char *agent = g_hash_table_lookup(match->
meta,
1323 crm_notice(
"Unfencing node %s because the definition of " 1324 "%s changed", pcmk__node_name(node), match->
id);
1329 "notice: Unfencing node %s because the " 1330 "definition of %s changed",
1331 pcmk__node_name(node), match->
id);
1336 match->
id,
":", agent,
":",
1337 data->digest_all_calc,
",", NULL);
1339 match->
id,
":", agent,
":",
1340 data->digest_secure_calc,
",", NULL);
1344 g_string_free(digests_all, TRUE);
1347 digests_secure->str);
1348 g_string_free(digests_secure, TRUE);
1350 g_list_free(matches);
1369 || g_hash_table_lookup(stonith_op->
meta,
1376 char *delay_s = pcmk__itoa(node_priority_fencing_delay(node,
1379 g_hash_table_insert(stonith_op->
meta,
1388 }
else if(reason && stonith_op->
reason == NULL) {
1389 stonith_op->
reason = strdup(reason);
1401 g_list_free_full(
action->actions_before, free);
1402 g_list_free_full(
action->actions_after, free);
1404 g_hash_table_destroy(
action->extra);
1407 g_hash_table_destroy(
action->meta);
1409 free(
action->cancel_task);
1422 if (pcmk__is_primitive(rsc)) {
1428 crm_trace(
"Folding %s back into its atomic counterpart for %s",
1456 for (
const GList *gIter =
input; gIter != NULL; gIter = gIter->next) {
1465 }
else if (on_node == NULL) {
1468 }
else if (
action->node == NULL) {
1471 }
else if (pcmk__same_node(on_node,
action->node)) {
1482 GList *gIter =
input;
1487 for (; gIter != NULL; gIter = gIter->next) {
1493 }
else if (on_node == NULL) {
1494 crm_trace(
"Action %s matches (ignoring node)", key);
1497 }
else if (
action->node == NULL) {
1498 crm_trace(
"Action %s matches (unallocated, assigning to %s)",
1499 key, pcmk__node_name(on_node));
1504 }
else if (pcmk__same_node(on_node,
action->node)) {
1505 crm_trace(
"Action %s on %s matches", key, pcmk__node_name(on_node));
1520 if (on_node == NULL) {
1524 for (GList *gIter =
input; gIter != NULL; gIter = gIter->next) {
1527 if ((
action->node != NULL)
1532 crm_trace(
"Action %s on %s matches", key, pcmk__node_name(on_node));
1554 const char *task,
bool require_node)
1581 const char *change = NULL;
1585 change =
"unrunnable";
1588 change =
"unmigrateable";
1591 change =
"required";
1599 (
action->rsc == NULL)?
"" :
" ",
1607 if (
action->reason != NULL && overwrite) {
1610 pcmk__s(reason,
"(none)"));
1611 }
else if (
action->reason == NULL) {
1613 action->uuid, pcmk__s(reason,
"(none)"));
1638 #define sort_return(an_int, why) do { \ 1641 crm_trace("%s (%d) %c %s (%d) : %s", \ 1642 a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \ 1643 b_xml_id, b_call_id, why); \ 1649 bool same_node_default)
1654 char *a_uuid = NULL;
1655 char *b_uuid = NULL;
1662 bool same_node =
true;
1671 if (a_node == NULL || b_node == NULL) {
1672 same_node = same_node_default;
1678 if (same_node && pcmk__str_eq(a_xml_id, b_xml_id,
pcmk__str_none)) {
1692 if (a_call_id == -1 && b_call_id == -1) {
1698 }
else if (same_node && a_call_id >= 0 && a_call_id < b_call_id) {
1701 }
else if (same_node && b_call_id >= 0 && a_call_id > b_call_id) {
1704 }
else if (a_call_id >= 0 && b_call_id >= 0
1705 && (!same_node || a_call_id == b_call_id)) {
1716 (
long long) last_a, (
long long) last_b);
1717 if (last_a >= 0 && last_a < last_b) {
1720 }
else if (last_b >= 0 && last_a > last_b) {
1764 if (b_call_id == -1) {
1767 }
else if (a_call_id == -1) {
1771 }
else if ((a_id >= 0 && a_id < b_id) || b_id == -1) {
1774 }
else if ((b_id >= 0 && a_id > b_id) || a_id == -1) {
1786 const xmlNode *xml_a = a;
1787 const xmlNode *xml_b = b;
1835 pcmk__itoa(expected_result));
#define CRM_CHECK(expr, failure_action)
bool pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
pcmk_node_t * pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name)
Find a node by name in scheduler data.
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.
enum pe_quorum_policy no_quorum_policy
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
#define crm_notice(fmt, args...)
pcmk_scheduler_t * cluster
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
#define PCMK__META_DIGESTS_SECURE
void pe__add_action_expected_result(pcmk_action_t *action, int expected_result)
enum action_tasks pcmk_parse_action(const char *action_name)
Parse an action type from an action name.
enum rsc_start_requirement pcmk__action_requires(const pcmk_resource_t *rsc, const char *action_name)
#define PCMK_META_INTERVAL_ORIGIN
GList * find_actions(GList *input, const char *key, const pcmk_node_t *on_node)
#define PCMK_STONITH_PROVIDES
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
#define PCMK__XA_TRANSITION_MAGIC
struct crm_time_s crm_time_t
#define pcmk__rsc_trace(rsc, fmt, args...)
int priority_fencing_delay
enum rsc_role_e next_role
#define PCMK__META_OP_TARGET_RC
bool pcmk_is_probe(const char *task, guint interval)
Check whether an action name and interval represent a probe.
#define PCMK__META_ROLE_AFTER_FAILURE
#define PCMK_VALUE_STANDBY
#define pcmk__insert_meta(obj, name, value)
#define pcmk__config_err(fmt...)
#define PCMK_ACTION_MONITOR
long long crm_get_msec(const char *input)
Parse a time+units string and return milliseconds equivalent.
#define PCMK_VALUE_RESTART
pcmk_action_t * pe_fence_op(pcmk_node_t *node, const char *op, bool optional, const char *reason, bool priority_delay, pcmk_scheduler_t *scheduler)
#define PCMK_ACTION_MIGRATE_TO
enum action_fail_response pcmk__parse_on_fail(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, const char *value)
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.
void pe_fence_node(pcmk_scheduler_t *scheduler, pcmk_node_t *node, const char *reason, bool priority_delay)
Schedule a fence action for a node.
#define PCMK__META_STONITH_ACTION
#define CRM_LOG_ASSERT(expr)
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define PCMK__META_ON_NODE
char * pe__action2reason(const pcmk_action_t *action, enum pe_action_flags flag)
pcmk_resource_t * container
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
pcmk_action_t * get_pseudo_op(const char *name, pcmk_scheduler_t *scheduler)
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
pe_quorum_policy
Possible responses to loss of quorum.
#define pcmk__rsc_debug(rsc, fmt, args...)
enum action_tasks get_complex_task(const pcmk_resource_t *rsc, const char *name)
#define PCMK_VALUE_NOTHING
char int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
#define PCMK__ROLE_PROMOTED_LEGACY
#define PCMK_DEFAULT_ACTION_TIMEOUT_MS
Default timeout (in milliseconds) for non-metadata actions.
#define PCMK_ACTION_DEMOTE
guint remote_reconnect_ms
void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why)
void pe__clear_resource_history(pcmk_resource_t *rsc, const pcmk_node_t *node)
#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)
enum rsc_role_e pcmk__role_after_failure(const pcmk_resource_t *rsc, const char *action_name, enum action_fail_response on_fail, GHashTable *meta)
#define PCMK_META_START_DELAY
#define crm_trace(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
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
pcmk_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pcmk_node_t *on_node)
#define PCMK_ACTION_START
#define PCMK__META_ON_NODE_UUID
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
#define PCMK_VALUE_IGNORE
#define PCMK_OPT_PRIORITY_FENCING_DELAY
void pcmk__str_update(char **str, const char *value)
Wrappers for and extensions to libxml2.
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, pcmk_scheduler_t *scheduler)
#define PCMK_META_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.
pcmk_action_t * pe__new_rsc_pseudo_action(pcmk_resource_t *rsc, const char *task, bool optional, bool runnable)
#define PCMK_ACTION_STONITH
#define PCMK__META_DIGESTS_ALL
#define pcmk__set_rsc_flags(resource, flags_to_set)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
long long crm_time_get_seconds(const crm_time_t *dt)
#define pcmk__str_copy(str)
#define pcmk__warn_once(wo_flag, fmt...)
void pe_action_set_reason(pcmk_action_t *action, const char *reason, bool overwrite)
#define PCMK_META_TIMEOUT
xmlNode * pcmk__find_action_config(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, bool include_disabled)
#define PCMK_XE_META_ATTRIBUTES
#define pcmk__assert(expr)
GList * pe__resource_actions(const pcmk_resource_t *rsc, const pcmk_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
pcmk__op_digest_t * pe__compare_fencing_digest(pcmk_resource_t *rsc, const char *agent, pcmk_node_t *node, pcmk_scheduler_t *scheduler)
#define PCMK_ACTION_LRM_DELETE
#define PCMK_META_INTERVAL
#define PCMK_XA_LAST_RC_CHANGE
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
pcmk__action_result_t result
GHashTable * pcmk__unpack_action_meta(pcmk_resource_t *rsc, const pcmk_node_t *node, const char *action_name, guint interval_ms, const xmlNode *action_config)
#define PCMK_ROLE_PROMOTED
pcmk_scheduler_t * scheduler
#define PCMK__XE_LRM_RSC_OP
crm_time_t * crm_time_new(const char *string)
#define PCMK_ACTION_MIGRATE_FROM
#define PCMK_META_ON_FAIL
GList * find_actions_exact(GList *input, const char *key, const pcmk_node_t *on_node)
This structure contains everything that makes up a single output formatter.
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
#define PCMK_ACTION_PROMOTE
#define PCMK_OPT_NO_QUORUM_POLICY
#define pcmk__set_action_flags(action, flags_to_set)
GHashTable * pcmk__unpack_action_rsc_params(const xmlNode *action_xml, GHashTable *node_attrs, pcmk_scheduler_t *scheduler)
#define sort_return(an_int, why)
const char * pcmk__readable_interval(guint interval_ms)
void pe_free_action(pcmk_action_t *action)
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
#define PCMK_VALUE_UNFENCING
int pe__is_newer_op(const xmlNode *xml_a, const xmlNode *xml_b, bool same_node_default)
Resource role is unknown.
GHashTable * pe_rsc_params(pcmk_resource_t *rsc, const pcmk_node_t *node, pcmk_scheduler_t *scheduler)
Get a table of resource parameters.
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
#define pcmk__assert_alloc(nmemb, size)
#define PCMK_XE_INSTANCE_ATTRIBUTES
xmlNode * pcmk__xe_next_same(const xmlNode *node)
#define crm_info(fmt, args...)
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
#define PCMK_VALUE_DEMOTE
#define PCMK_VALUE_RESTART_CONTAINER
#define PCMK_ACTION_NOTIFY
void crm_time_free(crm_time_t *dt)