71 if (matches == NULL) {
92find_exact_action_config(
const pcmk_resource_t *rsc,
const char *action_name,
93 guint interval_ms,
bool include_disabled)
100 const char *config_name = NULL;
101 const char *interval_spec = NULL;
105 if (!include_disabled
113 if (tmp_ms != interval_ms) {
138 guint interval_ms,
bool include_disabled)
140 xmlNode *action_config = NULL;
143 action_config = find_exact_action_config(rsc, action_name, interval_ms,
148 if ((action_config == NULL)
151 action_config = find_exact_action_config(rsc,
"migrate", 0,
155 return action_config;
203 guint interval_ms = 0;
212 if ((
action->op_entry == NULL) && (strstr(key,
"_notify_") != NULL)) {
217 unpack_operation(
action,
action->op_entry, interval_ms);
221 (optional?
"optional" :
"required"),
223 ((rsc == NULL)?
"no resource" : rsc->
id),
224 pcmk__node_name(node));
248 GHashTable *node_attrs,
255 .node_attrs = node_attrs,
279 "%s on %s is optional (%s is unmanaged)",
286 }
else if (!optional) {
336 if (
action->node == NULL) {
341 && !(
action->node->details->online)
342 && (!pcmk__is_guest_or_bundle_node(
action->node)
346 do_crm_log(LOG_WARNING,
"%s on %s is unrunnable (node is offline)",
350 && !(
action->node->details->unclean)) {
355 &&
action->node->details->pending) {
358 "Action %s on %s is unrunnable (node is pending)",
363 if (pcmk__is_guest_or_bundle_node(
action->node)
371 "%s on %s is unrunnable "
372 "(node's host cannot be fenced)",
377 "%s on %s does not require fencing or quorum",
383 switch (effective_quorum_policy(rsc,
scheduler)) {
396 pcmk__node_name(
action->node));
411valid_stop_on_fail(
const char *value)
429 const xmlNode *action_config, GHashTable *meta)
431 const char *
name = NULL;
432 const char *role = NULL;
433 const char *interval_spec = NULL;
435 guint interval_ms = 0U;
439 && !valid_stop_on_fail(value)) {
442 "action to default value because '%s' is not "
443 "allowed for stop", rsc->
id, value);
452 && (value == NULL)) {
463 bool enabled =
false;
464 const char *promote_on_fail = NULL;
470 if (promote_on_fail == NULL) {
484 if (interval_ms == 0U) {
523 && ((interval_ms == 0U)
529 "action to default value because 'demote' is not "
530 "allowed for it", rsc->
id,
name);
538unpack_timeout(
const char *value)
542 if (timeout_ms <= 0) {
545 return (
int) QB_MIN(timeout_ms, INT_MAX);
550unpack_interval_origin(
const char *value,
const xmlNode *xml_obj,
552 long long *start_delay)
559 if ((value == NULL) || (interval_ms == 0) || (now == NULL)) {
565 if (origin == NULL) {
567 "operation '%s' because '%s' is not valid",
568 pcmk__s(pcmk__xe_id(xml_obj),
"(missing ID)"), value);
581 crm_info(
"Calculated a start delay of %llds for operation '%s'",
582 result, pcmk__s(pcmk__xe_id(xml_obj),
"(unspecified)"));
584 if (start_delay != NULL) {
585 *start_delay =
result * 1000;
591unpack_start_delay(
const char *value, GHashTable *meta)
593 long long start_delay_ms = 0;
600 start_delay_ms = QB_MIN(start_delay_ms, INT_MAX);
601 if (start_delay_ms < 0) {
607 pcmk__itoa(start_delay_ms));
610 return (
int) start_delay_ms;
625 guint min_interval_ms = G_MAXUINT;
632 bool enabled =
false;
633 guint interval_ms = 0U;
644 if (interval_ms == 0U) {
654 if (interval_ms < min_interval_ms) {
655 min_interval_ms = interval_ms;
680 const char *action_name, guint interval_ms,
681 const xmlNode *action_config)
683 GHashTable *meta = NULL;
684 const char *timeout_spec = NULL;
685 const char *str = NULL;
695 .op_name = action_name,
696 .op_interval_ms = interval_ms,
701 if (action_config != NULL) {
704 &rule_input, meta, NULL,
711 for (xmlAttrPtr attr = action_config->properties;
712 attr != NULL; attr = attr->next) {
714 pcmk__xml_attr_value(attr));
722 xmlNode *min_interval_mon = most_frequent_monitor(rsc);
724 if (min_interval_mon != NULL) {
731 if (timeout_spec != NULL) {
733 "Setting default timeout for %s probe to "
734 "most frequent monitor's timeout '%s'",
735 rsc->
id, timeout_spec);
749 if (interval_ms > 0) {
774 timeout_spec = g_hash_table_lookup(params,
"pcmk_monitor_timeout");
775 if (timeout_spec != NULL) {
777 "Setting timeout for %s %s to "
778 "pcmk_monitor_timeout (%s)",
779 rsc->
id, action_name, timeout_spec);
787 pcmk__itoa(unpack_timeout(timeout_spec)));
790 validate_on_fail(rsc, action_name, action_config, meta);
795 unpack_start_delay(str, meta);
797 long long start_delay = 0;
800 if (unpack_interval_origin(str, action_config, interval_ms,
822 const char *value = NULL;
825 CRM_CHECK((rsc != NULL) && (action_name != NULL),
return requires);
829 value =
"nothing (not start or promote)";
859 guint interval_ms,
const char *value)
861 const char *desc = NULL;
862 bool needs_remote_reset =
false;
880 desc =
"node fencing";
883 "%s of %s to 'stop' because 'fence' is not "
884 "valid when fencing is disabled",
885 action_name, rsc->
id);
891 desc =
"stop resource";
896 desc =
"node standby";
905 desc =
"force migration";
909 desc =
"stop resource";
913 desc =
"restart (and possibly migrate)";
920 "of %s because it does not have a launcher",
921 action_name, rsc->
id);
924 desc =
"restart container (and possibly migrate)";
929 desc =
"demote instance";
933 "%s of %s because '%s' is not valid",
934 action_name, rsc->
id, value);
946 needs_remote_reset =
true;
957 desc =
"restart container (and possibly migrate) (default)";
959 }
else if (needs_remote_reset) {
962 desc =
"fence remote node (default)";
964 desc =
"recover remote node connection (default)";
969 desc =
"stop unmanaged remote node (enforcing default)";
975 desc =
"resource fence (default)";
978 desc =
"resource block (default)";
983 desc =
"restart (and possibly migrate) (default)";
1054 const char *value = NULL;
1057 action->task, interval_ms, xml_obj);
1062 interval_ms, value);
1100 update_action_optional(
action, optional);
1108 if ((
action->node != NULL) && (
action->op_entry != NULL)
1111 GHashTable *attrs =
action->node->priv->attrs;
1113 if (
action->extra != NULL) {
1114 g_hash_table_destroy(
action->extra);
1124 if (
action->extra == NULL) {
1144find_unfencing_devices(GList *candidates, GList *matches)
1146 for (GList *gIter = candidates; gIter != NULL; gIter = gIter->next) {
1150 matches = find_unfencing_devices(candidate->
priv->
children,
1157 matches = g_list_prepend(matches, candidate);
1159 }
else if (pcmk__str_eq(g_hash_table_lookup(candidate->
priv->
meta,
1162 matches = g_list_prepend(matches, candidate);
1169node_priority_fencing_delay(
const pcmk_node_t *node,
1172 int member_count = 0;
1173 int online_count = 0;
1174 int top_priority = 0;
1175 int lowest_priority = 0;
1176 GList *gIter = NULL;
1194 for (gIter =
scheduler->
nodes; gIter != NULL; gIter = gIter->next) {
1207 if (member_count == 1
1212 if (member_count == 1
1219 if (online_count > member_count / 2) {
1225 if (lowest_priority == top_priority) {
1238 const char *reason,
bool priority_delay,
1241 char *op_key = NULL;
1251 stonith_op = lookup_singleton(
scheduler, op_key);
1252 if(stonith_op == NULL) {
1264 GString *digests_all = g_string_sized_new(1024);
1265 GString *digests_secure = g_string_sized_new(1024);
1270 for (GList *gIter = matches; gIter != NULL; gIter = gIter->next) {
1272 const char *agent = g_hash_table_lookup(match->
priv->
meta,
1280 crm_notice(
"Unfencing node %s because the definition of "
1281 "%s changed", pcmk__node_name(node), match->
id);
1286 "notice: Unfencing node %s because the "
1287 "definition of %s changed",
1288 pcmk__node_name(node), match->
id);
1293 match->
id,
":", agent,
":",
1294 data->digest_all_calc,
",", NULL);
1296 match->
id,
":", agent,
":",
1297 data->digest_secure_calc,
",", NULL);
1301 g_string_free(digests_all, TRUE);
1304 digests_secure->str);
1305 g_string_free(digests_secure, TRUE);
1307 g_list_free(matches);
1326 || g_hash_table_lookup(stonith_op->
meta,
1333 char *delay_s = pcmk__itoa(node_priority_fencing_delay(node,
1336 g_hash_table_insert(stonith_op->
meta,
1345 }
else if(reason && stonith_op->
reason == NULL) {
1346 stonith_op->
reason = strdup(reason);
1357 if (pcmk__is_primitive(rsc)) {
1363 crm_trace(
"Folding %s back into its atomic counterpart for %s",
1391 for (
const GList *gIter =
input; gIter != NULL; gIter = gIter->next) {
1400 }
else if (on_node == NULL) {
1403 }
else if (
action->node == NULL) {
1406 }
else if (pcmk__same_node(on_node,
action->node)) {
1417 GList *gIter =
input;
1422 for (; gIter != NULL; gIter = gIter->next) {
1428 }
else if (on_node == NULL) {
1429 crm_trace(
"Action %s matches (ignoring node)", key);
1432 }
else if (
action->node == NULL) {
1433 crm_trace(
"Action %s matches (unallocated, assigning to %s)",
1434 key, pcmk__node_name(on_node));
1439 }
else if (pcmk__same_node(on_node,
action->node)) {
1440 crm_trace(
"Action %s on %s matches", key, pcmk__node_name(on_node));
1455 if (on_node == NULL) {
1459 for (GList *gIter =
input; gIter != NULL; gIter = gIter->next) {
1462 if ((
action->node != NULL)
1464 && pcmk__same_node(on_node,
action->node)) {
1466 crm_trace(
"Action %s on %s matches", key, pcmk__node_name(on_node));
1488 const char *task,
bool require_node)
1515 const char *change = NULL;
1519 change =
"unrunnable";
1522 change =
"unmigrateable";
1525 change =
"required";
1533 (
action->rsc == NULL)?
"" :
" ",
1541 if (
action->reason != NULL && overwrite) {
1544 pcmk__s(reason,
"(none)"));
1545 }
else if (
action->reason == NULL) {
1547 action->uuid, pcmk__s(reason,
"(none)"));
1572#define sort_return(an_int, why) do { \
1575 crm_trace("%s (%d) %c %s (%d) : %s", \
1576 a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \
1577 b_xml_id, b_call_id, why); \
1587 char *a_uuid = NULL;
1588 char *b_uuid = NULL;
1597 if (same_node && pcmk__str_eq(a_xml_id, b_xml_id,
pcmk__str_none)) {
1611 if (a_call_id == -1 && b_call_id == -1) {
1617 }
else if (same_node && a_call_id >= 0 && a_call_id < b_call_id) {
1620 }
else if (same_node && b_call_id >= 0 && a_call_id > b_call_id) {
1623 }
else if (a_call_id >= 0 && b_call_id >= 0
1624 && (!same_node || a_call_id == b_call_id)) {
1635 (
long long) last_a, (
long long) last_b);
1636 if (last_a >= 0 && last_a < last_b) {
1639 }
else if (last_b >= 0 && last_a > last_b) {
1683 if (b_call_id == -1) {
1686 }
else if (a_call_id == -1) {
1690 }
else if ((a_id >= 0 && a_id < b_id) || b_id == -1) {
1693 }
else if ((b_id >= 0 && a_id > b_id) || a_id == -1) {
1751 pcmk__itoa(expected_result));
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
#define PCMK_ACTION_PROMOTE
#define PCMK_ACTION_LRM_DELETE
#define PCMK_ACTION_START
#define PCMK_ACTION_MIGRATE_FROM
#define PCMK_ACTION_MIGRATE_TO
#define PCMK_DEFAULT_ACTION_TIMEOUT_MS
Default timeout (in milliseconds) for non-metadata actions.
#define PCMK_ACTION_MONITOR
#define PCMK_ACTION_STONITH
#define PCMK_ACTION_DEMOTE
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_ACTION_NOTIFY
@ pcmk__action_migratable
@ pcmk__action_attrs_evaluated
#define pcmk__set_action_flags(action, 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)
@ pcmk__on_fail_reset_remote
@ pcmk__on_fail_restart_container
@ pcmk__on_fail_fence_node
@ pcmk__on_fail_standby_node
#define pcmk__clear_action_flags(action, flags_to_clear)
enum pcmk__action_type pcmk__parse_action(const char *action_name)
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
@ pcmk_ra_cap_fence_params
#define PCMK_STONITH_PROVIDES
guint pcmk__timeout_ms2s(guint timeout_ms)
#define pcmk__assert_alloc(nmemb, size)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
GHashTable * pe_rsc_params(pcmk_resource_t *rsc, const pcmk_node_t *node, pcmk_scheduler_t *scheduler)
Get a table of resource parameters.
void crm_time_free(crm_time_t *dt)
long long crm_time_get_seconds(const crm_time_t *dt)
crm_time_t * crm_time_new(const char *string)
struct crm_time_s crm_time_t
const char * pcmk__readable_interval(guint interval_ms)
#define crm_info(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
#define CRM_LOG_ASSERT(expr)
#define crm_notice(fmt, args...)
#define CRM_CHECK(expr, failure_action)
#define crm_trace(fmt, args...)
#define pcmk__config_err(fmt...)
pcmk_scheduler_t * scheduler
@ pcmk__node_remote_reset
@ pcmk__node_variant_cluster
#define pcmk__insert_meta(obj, name, value)
#define PCMK_VALUE_RESTART
#define PCMK_META_INTERVAL
#define PCMK_META_ON_FAIL
#define PCMK_OPT_NO_QUORUM_POLICY
#define PCMK_META_ENABLED
#define PCMK_OPT_PRIORITY_FENCING_DELAY
#define PCMK_VALUE_STANDBY
#define PCMK_VALUE_DEMOTE
#define PCMK_META_START_DELAY
#define PCMK_META_INTERVAL_ORIGIN
#define PCMK_VALUE_IGNORE
#define PCMK_META_TIMEOUT
#define PCMK_VALUE_RESTART_CONTAINER
#define PCMK_VALUE_UNFENCING
#define PCMK_VALUE_NOTHING
#define PCMK__META_ON_NODE_UUID
#define PCMK__META_ON_NODE
#define PCMK__META_OP_TARGET_RC
#define PCMK__META_DIGESTS_SECURE
#define PCMK__META_DIGESTS_ALL
#define PCMK__META_STONITH_ACTION
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)
pcmk_action_t * get_pseudo_op(const char *name, pcmk_scheduler_t *scheduler)
enum rsc_role_e pcmk__role_after_failure(const pcmk_resource_t *rsc, const char *action_name, enum pcmk__on_fail on_fail, GHashTable *meta)
char * pe__action2reason(const pcmk_action_t *action, enum pcmk__action_flags flag)
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.
enum pcmk__requires pcmk__action_requires(const pcmk_resource_t *rsc, const char *action_name)
GList * find_actions(GList *input, const char *key, const pcmk_node_t *on_node)
pcmk_action_t * pe__new_rsc_pseudo_action(pcmk_resource_t *rsc, const char *task, bool optional, bool runnable)
pcmk_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pcmk_node_t *on_node)
void pe_action_set_reason(pcmk_action_t *action, const char *reason, bool overwrite)
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)
void pe__add_action_expected_result(pcmk_action_t *action, int expected_result)
enum pcmk__on_fail pcmk__parse_on_fail(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, const char *value)
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
#define sort_return(an_int, why)
enum pcmk__action_type get_complex_task(const pcmk_resource_t *rsc, const char *name)
GHashTable * pcmk__unpack_action_rsc_params(const xmlNode *action_xml, GHashTable *node_attrs, pcmk_scheduler_t *scheduler)
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.
int pe__is_newer_op(const xmlNode *xml_a, const xmlNode *xml_b)
void pe__clear_resource_history(pcmk_resource_t *rsc, const pcmk_node_t *node)
xmlNode * pcmk__find_action_config(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, bool include_disabled)
GList * find_actions_exact(GList *input, const char *key, const pcmk_node_t *on_node)
pcmk__op_digest_t * pe__compare_fencing_digest(pcmk_resource_t *rsc, const char *agent, pcmk_node_t *node, pcmk_scheduler_t *scheduler)
bool pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
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.
void pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, const pcmk_rule_input_t *rule_input, GHashTable *hash, const char *always_first, pcmk_scheduler_t *scheduler)
void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why)
bool pcmk_is_probe(const char *task, guint interval)
Check whether an action name and interval represent a probe.
@ pcmk__rsc_needs_unfencing
@ pcmk__rsc_needs_fencing
@ pcmk__rsc_is_remote_connection
#define pcmk__assert(expr)
#define PCMK_ROLE_PROMOTED
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
@ pcmk_role_started
Started.
@ pcmk_role_unknown
Resource role is unknown.
@ pcmk_role_unpromoted
Unpromoted.
@ pcmk_role_promoted
Promoted.
@ pcmk_role_stopped
Stopped.
#define PCMK__ROLE_PROMOTED_LEGACY
pe_quorum_policy
Possible responses to loss of quorum.
@ pcmk_no_quorum_freeze
Do not recover resources from outside partition.
@ pcmk_no_quorum_stop
Stop all resources in partition.
@ pcmk_no_quorum_ignore
Act as if partition still holds quorum.
@ pcmk_no_quorum_demote
Demote promotable resources and stop all others.
pcmk_node_t * pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name)
Find a node by name in scheduler data.
#define pcmk__rsc_trace(rsc, fmt, args...)
#define pcmk__rsc_debug(rsc, fmt, args...)
@ pcmk__sched_enable_unfencing
@ pcmk__sched_fencing_enabled
int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
long long crm_get_msec(const char *input)
Parse a time+units string and return milliseconds equivalent.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
void pcmk__str_update(char **str, const char *value)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
#define pcmk__str_copy(str)
enum pcmk__node_variant variant
This structure contains everything that makes up a single output formatter.
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
pcmk_scheduler_t * scheduler
enum rsc_role_e orig_role
pcmk_resource_t * launcher
enum rsc_role_e next_role
const pcmk__rsc_methods_t * fns
guint remote_reconnect_ms
pcmk__resource_private_t * priv
bool(* active)(const pcmk_resource_t *rsc, bool all)
guint priority_fencing_ms
const char * fence_action
pcmk__scheduler_private_t * priv
enum pe_quorum_policy no_quorum_policy
pcmk__node_private_t * priv
struct pcmk__node_details * details
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
#define PCMK_XE_INSTANCE_ATTRIBUTES
#define PCMK_XA_LAST_RC_CHANGE
#define PCMK_XE_META_ATTRIBUTES
#define PCMK__XE_LRM_RSC_OP
#define PCMK__XA_TRANSITION_MAGIC