71 if (matches == NULL) {
92 find_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,
282 "%s on %s is optional (%s is unmanaged)",
289 }
else if (!optional) {
339 if (
action->node == NULL) {
344 && !(
action->node->details->online)
345 && (!pcmk__is_guest_or_bundle_node(
action->node)
349 do_crm_log(LOG_WARNING,
"%s on %s is unrunnable (node is offline)",
353 && !(
action->node->details->unclean)) {
358 &&
action->node->details->pending) {
361 "Action %s on %s is unrunnable (node is pending)",
366 if (pcmk__is_guest_or_bundle_node(
action->node)
374 "%s on %s is unrunnable " 375 "(node's host cannot be fenced)",
380 "%s on %s does not require fencing or quorum",
386 switch (effective_quorum_policy(rsc,
scheduler)) {
399 pcmk__node_name(
action->node));
414 valid_stop_on_fail(
const char *value)
432 const xmlNode *action_config, GHashTable *meta)
434 const char *
name = NULL;
435 const char *role = NULL;
436 const char *interval_spec = NULL;
438 guint interval_ms = 0U;
442 && !valid_stop_on_fail(value)) {
445 "action to default value because '%s' is not " 446 "allowed for stop", rsc->
id, value);
455 && (value == NULL)) {
466 bool enabled =
false;
467 const char *promote_on_fail = NULL;
473 if (promote_on_fail == NULL) {
487 if (interval_ms == 0U) {
526 && ((interval_ms == 0U)
532 "action to default value because 'demote' is not " 533 "allowed for it", rsc->
id,
name);
541 unpack_timeout(
const char *value)
545 if (timeout_ms <= 0) {
548 return (
int) QB_MIN(timeout_ms, INT_MAX);
553 unpack_interval_origin(
const char *value,
const xmlNode *xml_obj,
555 long long *start_delay)
562 if ((value == NULL) || (interval_ms == 0) || (now == NULL)) {
568 if (origin == NULL) {
570 "operation '%s' because '%s' is not valid",
571 pcmk__s(pcmk__xe_id(xml_obj),
"(missing ID)"), value);
584 crm_info(
"Calculated a start delay of %llds for operation '%s'",
585 result, pcmk__s(pcmk__xe_id(xml_obj),
"(unspecified)"));
587 if (start_delay != NULL) {
588 *start_delay =
result * 1000;
594 unpack_start_delay(
const char *value, GHashTable *meta)
596 long long start_delay_ms = 0;
603 start_delay_ms = QB_MIN(start_delay_ms, INT_MAX);
604 if (start_delay_ms < 0) {
610 pcmk__itoa(start_delay_ms));
613 return (
int) start_delay_ms;
628 guint min_interval_ms = G_MAXUINT;
635 bool enabled =
false;
636 guint interval_ms = 0U;
647 if (interval_ms == 0U) {
657 if (interval_ms < min_interval_ms) {
658 min_interval_ms = interval_ms;
683 const char *action_name, guint interval_ms,
684 const xmlNode *action_config)
686 GHashTable *meta = NULL;
687 const char *timeout_spec = NULL;
688 const char *str = NULL;
698 .interval = interval_ms,
707 .rsc_data = &rsc_rule_data,
708 .op_data = &op_rule_data,
713 if (action_config != NULL) {
716 &rule_data, meta, NULL,
723 for (xmlAttrPtr attr = action_config->properties;
724 attr != NULL; attr = attr->next) {
726 pcmk__xml_attr_value(attr));
734 xmlNode *min_interval_mon = most_frequent_monitor(rsc);
736 if (min_interval_mon != NULL) {
743 if (timeout_spec != NULL) {
745 "Setting default timeout for %s probe to " 746 "most frequent monitor's timeout '%s'",
747 rsc->
id, timeout_spec);
761 if (interval_ms > 0) {
786 timeout_spec = g_hash_table_lookup(params,
"pcmk_monitor_timeout");
787 if (timeout_spec != NULL) {
789 "Setting timeout for %s %s to " 790 "pcmk_monitor_timeout (%s)",
791 rsc->
id, action_name, timeout_spec);
799 pcmk__itoa(unpack_timeout(timeout_spec)));
802 validate_on_fail(rsc, action_name, action_config, meta);
807 unpack_start_delay(str, meta);
809 long long start_delay = 0;
812 if (unpack_interval_origin(str, action_config, interval_ms,
834 const char *value = NULL;
837 CRM_CHECK((rsc != NULL) && (action_name != NULL),
return requires);
841 value =
"nothing (not start or promote)";
871 guint interval_ms,
const char *value)
873 const char *desc = NULL;
874 bool needs_remote_reset =
false;
892 desc =
"node fencing";
895 "%s of %s to 'stop' because 'fence' is not " 896 "valid when fencing is disabled",
897 action_name, rsc->
id);
899 desc =
"stop resource";
904 desc =
"node standby";
913 desc =
"force migration";
917 desc =
"stop resource";
921 desc =
"restart (and possibly migrate)";
928 "of %s because it does not have a launcher",
929 action_name, rsc->
id);
932 desc =
"restart container (and possibly migrate)";
937 desc =
"demote instance";
941 "%s of %s because '%s' is not valid",
942 action_name, rsc->
id, value);
954 needs_remote_reset =
true;
965 desc =
"restart container (and possibly migrate) (default)";
967 }
else if (needs_remote_reset) {
970 desc =
"fence remote node (default)";
972 desc =
"recover remote node connection (default)";
977 desc =
"stop unmanaged remote node (enforcing default)";
983 desc =
"resource fence (default)";
986 desc =
"resource block (default)";
991 desc =
"restart (and possibly migrate) (default)";
1062 const char *value = NULL;
1065 action->task, interval_ms, xml_obj);
1070 interval_ms, value);
1108 update_action_optional(
action, optional);
1116 if ((
action->node != NULL) && (
action->op_entry != NULL)
1119 GHashTable *attrs =
action->node->priv->attrs;
1121 if (
action->extra != NULL) {
1122 g_hash_table_destroy(
action->extra);
1132 if (
action->extra == NULL) {
1152 find_unfencing_devices(GList *candidates, GList *matches)
1154 for (GList *gIter = candidates; gIter != NULL; gIter = gIter->next) {
1158 matches = find_unfencing_devices(candidate->
priv->
children,
1165 matches = g_list_prepend(matches, candidate);
1167 }
else if (pcmk__str_eq(g_hash_table_lookup(candidate->
priv->
meta,
1170 matches = g_list_prepend(matches, candidate);
1177 node_priority_fencing_delay(
const pcmk_node_t *node,
1180 int member_count = 0;
1181 int online_count = 0;
1182 int top_priority = 0;
1183 int lowest_priority = 0;
1184 GList *gIter = NULL;
1202 for (gIter =
scheduler->
nodes; gIter != NULL; gIter = gIter->next) {
1215 if (member_count == 1
1220 if (member_count == 1
1227 if (online_count > member_count / 2) {
1233 if (lowest_priority == top_priority) {
1246 const char *reason,
bool priority_delay,
1249 char *op_key = NULL;
1259 stonith_op = lookup_singleton(
scheduler, op_key);
1260 if(stonith_op == NULL) {
1272 GString *digests_all = g_string_sized_new(1024);
1273 GString *digests_secure = g_string_sized_new(1024);
1278 for (GList *gIter = matches; gIter != NULL; gIter = gIter->next) {
1280 const char *agent = g_hash_table_lookup(match->
priv->
meta,
1288 crm_notice(
"Unfencing node %s because the definition of " 1289 "%s changed", pcmk__node_name(node), match->
id);
1294 "notice: Unfencing node %s because the " 1295 "definition of %s changed",
1296 pcmk__node_name(node), match->
id);
1301 match->
id,
":", agent,
":",
1302 data->digest_all_calc,
",", NULL);
1304 match->
id,
":", agent,
":",
1305 data->digest_secure_calc,
",", NULL);
1309 g_string_free(digests_all, TRUE);
1312 digests_secure->str);
1313 g_string_free(digests_secure, TRUE);
1315 g_list_free(matches);
1334 || g_hash_table_lookup(stonith_op->
meta,
1341 char *delay_s = pcmk__itoa(node_priority_fencing_delay(node,
1344 g_hash_table_insert(stonith_op->
meta,
1353 }
else if(reason && stonith_op->
reason == NULL) {
1354 stonith_op->
reason = strdup(reason);
1366 g_list_free_full(
action->actions_before, free);
1367 g_list_free_full(
action->actions_after, free);
1369 g_hash_table_destroy(
action->extra);
1372 g_hash_table_destroy(
action->meta);
1375 free(
action->cancel_task);
1387 if (pcmk__is_primitive(rsc)) {
1393 crm_trace(
"Folding %s back into its atomic counterpart for %s",
1421 for (
const GList *gIter =
input; gIter != NULL; gIter = gIter->next) {
1430 }
else if (on_node == NULL) {
1433 }
else if (
action->node == NULL) {
1436 }
else if (pcmk__same_node(on_node,
action->node)) {
1447 GList *gIter =
input;
1452 for (; gIter != NULL; gIter = gIter->next) {
1458 }
else if (on_node == NULL) {
1459 crm_trace(
"Action %s matches (ignoring node)", key);
1462 }
else if (
action->node == NULL) {
1463 crm_trace(
"Action %s matches (unallocated, assigning to %s)",
1464 key, pcmk__node_name(on_node));
1469 }
else if (pcmk__same_node(on_node,
action->node)) {
1470 crm_trace(
"Action %s on %s matches", key, pcmk__node_name(on_node));
1485 if (on_node == NULL) {
1489 for (GList *gIter =
input; gIter != NULL; gIter = gIter->next) {
1492 if ((
action->node != NULL)
1494 && pcmk__same_node(on_node,
action->node)) {
1496 crm_trace(
"Action %s on %s matches", key, pcmk__node_name(on_node));
1518 const char *task,
bool require_node)
1545 const char *change = NULL;
1549 change =
"unrunnable";
1552 change =
"unmigrateable";
1555 change =
"required";
1563 (
action->rsc == NULL)?
"" :
" ",
1571 if (
action->reason != NULL && overwrite) {
1574 pcmk__s(reason,
"(none)"));
1575 }
else if (
action->reason == NULL) {
1577 action->uuid, pcmk__s(reason,
"(none)"));
1602 #define sort_return(an_int, why) do { \ 1605 crm_trace("%s (%d) %c %s (%d) : %s", \ 1606 a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \ 1607 b_xml_id, b_call_id, why); \ 1617 char *a_uuid = NULL;
1618 char *b_uuid = NULL;
1627 if (same_node && pcmk__str_eq(a_xml_id, b_xml_id,
pcmk__str_none)) {
1641 if (a_call_id == -1 && b_call_id == -1) {
1647 }
else if (same_node && a_call_id >= 0 && a_call_id < b_call_id) {
1650 }
else if (same_node && b_call_id >= 0 && a_call_id > b_call_id) {
1653 }
else if (a_call_id >= 0 && b_call_id >= 0
1654 && (!same_node || a_call_id == b_call_id)) {
1665 (
long long) last_a, (
long long) last_b);
1666 if (last_a >= 0 && last_a < last_b) {
1669 }
else if (last_b >= 0 && last_a > last_b) {
1713 if (b_call_id == -1) {
1716 }
else if (a_call_id == -1) {
1720 }
else if ((a_id >= 0 && a_id < b_id) || b_id == -1) {
1723 }
else if ((b_id >= 0 && a_id > b_id) || a_id == -1) {
1781 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.
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
#define crm_notice(fmt, args...)
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
Do not recover resources from outside partition.
#define PCMK__META_DIGESTS_SECURE
void pe__add_action_expected_result(pcmk_action_t *action, int expected_result)
#define PCMK_META_INTERVAL_ORIGIN
gboolean(* active)(pcmk_resource_t *rsc, gboolean all)
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
enum pcmk__action_type get_complex_task(const pcmk_resource_t *rsc, const char *name)
struct crm_time_s crm_time_t
#define pcmk__rsc_trace(rsc, fmt, args...)
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)
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 PCMK__META_OP_TARGET_RC
#define PCMK_VALUE_STANDBY
enum pcmk__requires pcmk__action_requires(const pcmk_resource_t *rsc, const char *action_name)
#define pcmk__insert_meta(obj, name, value)
#define pcmk__config_err(fmt...)
#define PCMK_ACTION_MONITOR
#define PCMK_VALUE_RESTART
pcmk__scheduler_private_t * priv
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
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
Stop all resources in partition.
#define CRM_LOG_ASSERT(expr)
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define PCMK__META_ON_NODE
const pcmk__rsc_methods_t * fns
void pcmk__free_node_copy(void *data)
pcmk_action_t * get_pseudo_op(const char *name, pcmk_scheduler_t *scheduler)
enum pe_quorum_policy no_quorum_policy
pe_quorum_policy
Possible responses to loss of quorum.
#define pcmk__rsc_debug(rsc, fmt, args...)
#define PCMK_VALUE_NOTHING
#define PCMK__ROLE_PROMOTED_LEGACY
pcmk__node_private_t * priv
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
#define PCMK_DEFAULT_ACTION_TIMEOUT_MS
Default timeout (in milliseconds) for non-metadata actions.
#define PCMK_ACTION_DEMOTE
void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why)
pcmk_scheduler_t * scheduler
void pe__clear_resource_history(pcmk_resource_t *rsc, const pcmk_node_t *node)
#define pcmk__clear_action_flags(action, flags_to_clear)
int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#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 * pe__action2reason(const pcmk_action_t *action, enum pcmk__action_flags flag)
Demote promotable resources and stop all others.
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
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
pcmk__resource_private_t * priv
#define PCMK__META_ON_NODE_UUID
#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.
enum rsc_role_e next_role
#define PCMK_META_ENABLED
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
Act as if partition still holds quorum.
const char * fence_action
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
bool pcmk_is_probe(const char *task, guint interval)
Check whether an action name and interval represent a probe.
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)
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)
long long crm_get_msec(const char *input)
Parse a time+units string and return milliseconds equivalent.
#define PCMK_XE_META_ATTRIBUTES
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
#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
guint remote_reconnect_ms
pcmk_scheduler_t * scheduler
#define PCMK__XE_LRM_RSC_OP
enum pcmk__node_variant variant
enum pcmk__action_type pcmk__parse_action(const char *action_name)
crm_time_t * crm_time_new(const char *string)
enum rsc_role_e orig_role
pcmk_resource_t * launcher
#define PCMK_ACTION_MIGRATE_FROM
#define PCMK_META_ON_FAIL
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
GList * find_actions_exact(GList *input, const char *key, const pcmk_node_t *on_node)
guint pcmk__timeout_ms2s(guint timeout_ms)
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
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, pcmk_scheduler_t *scheduler)
#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
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.
struct pcmk__node_details * details
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
#define pcmk__assert_alloc(nmemb, size)
#define PCMK_XE_INSTANCE_ATTRIBUTES
int pe__is_newer_op(const xmlNode *xml_a, const xmlNode *xml_b)
#define crm_info(fmt, args...)
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
#define PCMK_VALUE_DEMOTE
#define PCMK_VALUE_RESTART_CONTAINER
enum pcmk__on_fail pcmk__parse_on_fail(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, const char *value)
#define PCMK_ACTION_NOTIFY
guint priority_fencing_ms
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void crm_time_free(crm_time_t *dt)