17#include <libxml/tree.h>
18#include <libxml/xpath.h>
32struct action_history {
41 const char *exit_reason;
44 int expected_exit_status;
53#define set_config_flag(scheduler, option, flag) do { \
54 GHashTable *config_hash = (scheduler)->priv->options; \
55 const char *scf_value = pcmk__cluster_option(config_hash, (option)); \
57 if (scf_value != NULL) { \
58 if (crm_is_true(scf_value)) { \
59 (scheduler)->flags = pcmk__set_flags_as(__func__, __LINE__, \
60 LOG_TRACE, "Scheduler", \
61 crm_system_name, (scheduler)->flags, \
64 (scheduler)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
65 LOG_TRACE, "Scheduler", \
66 crm_system_name, (scheduler)->flags, \
73 xmlNode *xml_op, xmlNode **last_failure,
77static void add_node_attrs(
const xmlNode *xml_obj,
pcmk_node_t *node,
79static void determine_online_status(
const xmlNode *node_state,
83static void unpack_node_lrm(
pcmk_node_t *node,
const xmlNode *xml,
99 return pcmk__is_pacemaker_remote_node(node)
117 const char *reason,
bool priority_delay)
121 if (pcmk__is_guest_or_bundle_node(node)) {
128 "(otherwise would because %s): "
129 "its guest resource %s is unmanaged",
130 pcmk__node_name(node), reason, rsc->
id);
133 "Guest node %s will be fenced "
134 "(by recovering its guest resource %s): %s",
135 pcmk__node_name(node), rsc->
id, reason);
147 }
else if (is_dangling_guest_node(node)) {
148 crm_info(
"Cleaning up dangling connection for guest node %s: "
149 "fencing was already done because %s, "
150 "and guest resource no longer exists",
151 pcmk__node_name(node), reason);
155 }
else if (pcmk__is_remote_node(node)) {
160 "(otherwise would because %s): connection is unmanaged",
161 pcmk__node_name(node), reason);
165 pcmk__node_name(node),
174 crm_trace(
"Cluster node %s %s because %s",
175 pcmk__node_name(node),
181 pcmk__node_name(node),
192#define XPATH_UNFENCING_NVPAIR PCMK_XE_NVPAIR \
193 "[(@" PCMK_XA_NAME "='" PCMK_STONITH_PROVIDES "'" \
194 "or @" PCMK_XA_NAME "='" PCMK_META_REQUIRES "') " \
195 "and @" PCMK_XA_VALUE "='" PCMK_VALUE_UNFENCING "']"
198#define XPATH_ENABLE_UNFENCING \
199 "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RESOURCES \
200 "//" PCMK_XE_META_ATTRIBUTES "/" XPATH_UNFENCING_NVPAIR \
201 "|/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RSC_DEFAULTS \
202 "/" PCMK_XE_META_ATTRIBUTES "/" XPATH_UNFENCING_NVPAIR
207 xmlXPathObject *
result = NULL;
211 if (pcmk__xpath_num_results(
result) > 0) {
214 xmlXPathFreeObject(
result);
221 const char *value = NULL;
231 &rule_input, config_hash,
239 crm_info(
"Startup probes: disabled (dangerous)");
244 crm_info(
"Watchdog-based self-fencing will be performed via SBD if "
259 crm_debug(
"Default fencing action timeout: %s",
265 crm_debug(
"STONITH of failed nodes is enabled");
267 crm_debug(
"STONITH of failed nodes is disabled");
277 crm_debug(
"Concurrent fencing is enabled");
279 crm_debug(
"Concurrent fencing is disabled");
286 crm_trace(
"Priority fencing delay is %s",
292 crm_debug(
"Stop all active resources: %s",
298 crm_debug(
"Cluster is symmetric" " - resources can run anywhere by default");
324 " to 'stop': cluster has never had quorum");
329 " to 'stop' because fencing is disabled");
340 "Freeze resources that require quorum");
344 "Stop resources that require quorum");
348 "Demote promotable resources and stop other resources");
351 crm_notice(
"On loss of quorum: Fence all remaining nodes");
361 crm_trace(
"Orphan resources are stopped");
363 crm_trace(
"Orphan resources are ignored");
369 crm_trace(
"Orphan resource actions are stopped");
371 crm_trace(
"Orphan resource actions are ignored");
382 crm_trace(
"Start failures are always fatal");
384 crm_trace(
"Start failures are handled by failcount");
392 crm_trace(
"Unseen nodes will be fenced");
395 "Blind faith: not fencing unseen nodes");
409 crm_trace(
"Resources will be locked to nodes that were cleanly "
410 "shut down (locks expire after %s)",
413 crm_trace(
"Resources will not be locked to nodes that were cleanly "
422 crm_trace(
"Fence pending nodes after %s",
429 crm_trace(
"Pacemaker Remote nodes may be fenced without quorum");
431 crm_trace(
"Pacemaker Remote nodes require quorum to be fenced");
476 if (new_node == NULL) {
485 if ((new_node->
assign == NULL) || (new_node->
details == NULL)
486 || (new_node->
priv == NULL)) {
489 free(new_node->
priv);
510 if (pcmk__is_pacemaker_remote_node(new_node)) {
525 xmlNode *attr_set = NULL;
526 xmlNode *attr = NULL;
528 const char *container_id = pcmk__xe_id(xml_obj);
529 const char *remote_name = NULL;
530 const char *remote_server = NULL;
531 const char *remote_port = NULL;
532 const char *connect_timeout =
"60s";
533 const char *remote_allow_migrate=NULL;
534 const char *is_managed = NULL;
556 remote_server = value;
562 connect_timeout = value;
565 remote_allow_migrate = value;
573 if (remote_name == NULL) {
582 remote_allow_migrate, is_managed,
583 connect_timeout, remote_server, remote_port);
612 xmlNode *xml_obj = NULL;
614 const char *
id = NULL;
615 const char *
uname = NULL;
616 const char *
type = NULL;
633 "> entry in configuration without id");
639 "because '%s' is not a valid score: %s",
640 pcmk__s(
uname,
"without name"),
646 if (new_node == NULL) {
650 handle_startup_fencing(
scheduler, new_node);
652 add_node_attrs(xml_obj, new_node, FALSE,
scheduler);
664 const char *launcher_id = NULL;
667 g_list_foreach(rsc->
priv->
children, (GFunc) unpack_launcher,
673 if ((launcher_id != NULL)
678 if (launcher != NULL) {
683 rsc->
id, launcher_id);
686 rsc->
id, launcher_id);
694 xmlNode *xml_obj = NULL;
702 const char *new_node_id = NULL;
708 new_node_id = pcmk__xe_id(xml_obj);
714 crm_trace(
"Found remote node %s defined by resource %s",
715 new_node_id, pcmk__xe_id(xml_obj));
730 new_node_id = expand_remote_rsc_meta(xml_obj, xml_resources,
734 crm_trace(
"Found guest node %s in resource %s",
735 new_node_id, pcmk__xe_id(xml_obj));
746 xmlNode *xml_obj2 = NULL;
748 xml_obj2 != NULL; xml_obj2 =
pcmk__xe_next(xml_obj2, NULL)) {
750 new_node_id = expand_remote_rsc_meta(xml_obj2, xml_resources,
755 crm_trace(
"Found guest node %s in resource %s inside group %s",
756 new_node_id, pcmk__xe_id(xml_obj2),
757 pcmk__xe_id(xml_obj));
792 pcmk__rsc_trace(new_rsc,
"Linking remote connection resource %s to %s",
793 new_rsc->
id, pcmk__node_name(remote_node));
800 handle_startup_fencing(
scheduler, remote_node);
826 xmlNode *xml_obj = NULL;
835 const char *
id = pcmk__xe_id(xml_obj);
837 if (pcmk__str_empty(
id)) {
845 NULL, NULL) == FALSE) {
861 "because configuration is invalid",
867 gIter != NULL; gIter = gIter->next) {
883 pcmk__config_err(
"Resource start-up disabled since no STONITH resources have been defined");
886 pcmk__config_err(
"NOTE: Clusters with shared data need STONITH to ensure data integrity");
911 const char *
id = pcmk__xe_id(level);
914 if (pcmk__str_empty(
id)) {
936 xmlNode *xml_tag = NULL;
943 xmlNode *xml_obj_ref = NULL;
944 const char *tag_id = pcmk__xe_id(xml_tag);
946 if (tag_id == NULL) {
948 (
const char *) xml_tag->name);
957 const char *obj_ref = pcmk__xe_id(xml_obj_ref);
959 if (obj_ref == NULL) {
961 xml_obj_ref->name, tag_id);
982unpack_ticket_state(xmlNode *xml_ticket,
void *userdata)
986 const char *ticket_id = NULL;
987 const char *granted = NULL;
988 const char *last_granted = NULL;
989 const char *standby = NULL;
990 xmlAttrPtr xIter = NULL;
994 ticket_id = pcmk__xe_id(xml_ticket);
995 if (pcmk__str_empty(ticket_id)) {
999 crm_trace(
"Processing ticket state for %s", ticket_id);
1003 if (ticket == NULL) {
1005 if (ticket == NULL) {
1010 for (xIter = xml_ticket->properties; xIter; xIter = xIter->next) {
1011 const char *prop_name = (
const char *)xIter->name;
1012 const char *prop_value = pcmk__xml_attr_value(xIter);
1026 crm_info(
"We do not have ticket '%s'", ticket->
id);
1031 long long last_granted_ll = 0LL;
1032 int rc =
pcmk__scan_ll(last_granted, &last_granted_ll, 0LL);
1036 " value '%s' in state for ticket %s: %s",
1037 last_granted_ll, last_granted, ticket->
id,
1047 crm_info(
"Granted ticket '%s' is in standby-mode", ticket->
id);
1053 crm_trace(
"Done with ticket state for %s", ticket_id);
1059unpack_handle_remote_attrs(
pcmk_node_t *this_node,
const xmlNode *state,
1062 const char *discovery = NULL;
1063 const xmlNode *attrs = NULL;
1071 if ((this_node == NULL) || !pcmk__is_pacemaker_remote_node(this_node)) {
1074 crm_trace(
"Processing Pacemaker Remote node %s",
1075 pcmk__node_name(this_node));
1092 add_node_attrs(attrs, this_node, TRUE,
scheduler);
1095 crm_info(
"%s is shutting down", pcmk__node_name(this_node));
1101 crm_info(
"%s is in standby mode", pcmk__node_name(this_node));
1108 crm_info(
"%s is in maintenance mode", pcmk__node_name(this_node));
1115 if ((discovery != NULL) && !
crm_is_true(discovery)) {
1119 " node attribute is deprecated and will be removed"
1120 " (and behave as 'true') in a future release.");
1122 if (pcmk__is_remote_node(this_node)
1126 " attribute on Pacemaker Remote node %s"
1127 " because fencing is disabled",
1128 pcmk__node_name(this_node));
1135 crm_info(
"%s has resource discovery disabled",
1136 pcmk__node_name(this_node));
1151unpack_transient_attributes(
const xmlNode *state,
pcmk_node_t *node,
1154 const char *discovery = NULL;
1159 add_node_attrs(attrs, node, TRUE,
scheduler);
1163 crm_info(
"%s is in standby mode", pcmk__node_name(node));
1169 crm_info(
"%s is in maintenance mode", pcmk__node_name(node));
1176 if ((discovery != NULL) && !
crm_is_true(discovery)) {
1179 " attribute for %s because disabling resource"
1180 " discovery is not allowed for cluster nodes",
1181 pcmk__node_name(node));
1200 const char *
id = NULL;
1201 const char *
uname = NULL;
1213 if (
uname == NULL) {
1226 if (this_node == NULL) {
1227 crm_notice(
"Ignoring recorded state for removed node with name %s and "
1232 if (pcmk__is_pacemaker_remote_node(this_node)) {
1233 int remote_fenced = 0;
1242 if (remote_fenced) {
1250 unpack_transient_attributes(state, this_node,
scheduler);
1258 crm_trace(
"Determining online status of cluster node %s (id %s)",
1259 pcmk__node_name(this_node),
id);
1260 determine_online_status(state, this_node,
scheduler);
1292unpack_node_history(
const xmlNode *status,
bool fence,
1303 const char *
id = pcmk__xe_id(state);
1307 if ((
id == NULL) || (
uname == NULL)) {
1309 crm_trace(
"Not unpacking resource history from malformed "
1315 if (this_node == NULL) {
1317 crm_trace(
"Not unpacking resource history for node %s because "
1318 "no longer in configuration",
id);
1323 crm_trace(
"Not unpacking resource history for node %s because "
1324 "already unpacked",
id);
1331 }
else if (pcmk__is_guest_or_bundle_node(this_node)) {
1341 crm_trace(
"Not unpacking resource history for guest node %s "
1342 "because launcher and connection are not known to "
1347 }
else if (pcmk__is_remote_node(this_node)) {
1358 crm_trace(
"Not unpacking resource history for remote node %s "
1359 "because connection is not known to be up",
id);
1372 crm_trace(
"Not unpacking resource history for offline "
1373 "cluster node %s",
id);
1377 if (pcmk__is_pacemaker_remote_node(this_node)) {
1378 determine_remote_online_status(
scheduler, this_node);
1379 unpack_handle_remote_attrs(this_node, state,
scheduler);
1382 crm_trace(
"Unpacking resource history for %snode %s",
1383 (fence?
"unseen " :
""),
id);
1386 unpack_node_lrm(this_node, state,
scheduler);
1399 xmlNode *state = NULL;
1420 while (unpack_node_history(status, FALSE,
scheduler) == EAGAIN) {
1421 crm_trace(
"Another pass through node resource histories is needed");
1425 unpack_node_history(status,
1435 item != NULL; item = item->next) {
1438 pcmk_node_t *node = pcmk__current_node(container);
1452 for (GList *gIter =
scheduler->
nodes; gIter != NULL; gIter = gIter->next) {
1455 if (!pcmk__is_pacemaker_remote_node(this_node)) {
1464 determine_remote_online_status(
scheduler, this_node);
1488 if (member_time == NULL) {
1504 long long when_member = 0LL;
1507 0LL) !=
pcmk_rc_ok) || (when_member < 0LL)) {
1526unpack_node_online(
const xmlNode *node_state)
1539 long long when_online = 0LL;
1542 || (when_online < 0)) {
1561unpack_node_terminate(
const pcmk_node_t *node,
const xmlNode *node_state)
1563 long long value = 0LL;
1571 return (value_i != 0);
1578 "node attribute for %s: %s",
1585 const xmlNode *node_state,
1588 gboolean online = FALSE;
1591 long long when_member = unpack_node_member(node_state,
scheduler);
1592 long long when_online = unpack_node_online(node_state);
1594 if (when_member <= 0) {
1595 crm_trace(
"Node %s is %sdown", pcmk__node_name(this_node),
1596 ((when_member < 0)?
"presumed " :
""));
1598 }
else if (when_online > 0) {
1602 crm_debug(
"Node %s is not ready to run resources: %s",
1603 pcmk__node_name(this_node), join);
1608 crm_trace(
"Node %s controller is down: "
1609 "member@%lld online@%lld join=%s expected=%s",
1610 pcmk__node_name(this_node), when_member, when_online,
1611 pcmk__s(join,
"<null>"), pcmk__s(exp_state,
"<null>"));
1616 crm_info(
"Node %s member@%lld online@%lld join=%s expected=%s",
1617 pcmk__node_name(this_node), when_member, when_online,
1618 pcmk__s(join,
"<null>"), pcmk__s(exp_state,
"<null>"));
1638 long long when_member,
long long when_online)
1641 && (when_member > 0) && (when_online <= 0)) {
1659 const xmlNode *node_state,
1662 bool termination_requested = unpack_node_terminate(this_node, node_state);
1665 long long when_member = unpack_node_member(node_state,
scheduler);
1666 long long when_online = unpack_node_online(node_state);
1686 crm_trace(
"Node %s member@%lld online@%lld join=%s expected=%s%s",
1687 pcmk__node_name(this_node), when_member, when_online,
1688 pcmk__s(join,
"<null>"), pcmk__s(exp_state,
"<null>"),
1689 (termination_requested?
" (termination requested)" :
""));
1692 crm_debug(
"%s is shutting down", pcmk__node_name(this_node));
1695 return (when_online > 0);
1698 if (when_member < 0) {
1700 "peer has not been seen by the cluster", FALSE);
1706 "peer failed Pacemaker membership criteria", FALSE);
1708 }
else if (termination_requested) {
1709 if ((when_member <= 0) && (when_online <= 0)
1711 crm_info(
"%s was fenced as requested", pcmk__node_name(this_node));
1719 if (pending_too_long(
scheduler, this_node, when_member, when_online)) {
1721 "peer pending timed out on joining the process group",
1724 }
else if ((when_member > 0) || (when_online > 0)) {
1725 crm_info(
"- %s is not ready to run resources",
1726 pcmk__node_name(this_node));
1731 crm_trace(
"%s is down or still coming up",
1732 pcmk__node_name(this_node));
1735 }
else if (when_member <= 0) {
1738 "peer is no longer part of the cluster", TRUE);
1740 }
else if (when_online <= 0) {
1742 "peer process is no longer available", FALSE);
1747 crm_info(
"%s is active", pcmk__node_name(this_node));
1751 crm_info(
"%s is not ready to run resources",
1752 pcmk__node_name(this_node));
1761 return (when_member > 0);
1771 const char *node_type =
"Remote";
1777 crm_trace(
"Pacemaker Remote node %s is considered OFFLINE because "
1778 "its connection resource has been removed from the CIB",
1785 if (launcher != NULL) {
1786 node_type =
"Guest";
1801 crm_trace(
"%s node %s shutting down because connection resource is stopping",
1802 node_type, this_node->
priv->
id);
1808 crm_trace(
"Guest node %s UNCLEAN because guest resource failed",
1814 crm_trace(
"%s node %s OFFLINE because connection resource failed",
1815 node_type, this_node->
priv->
id);
1819 || ((launcher != NULL)
1822 crm_trace(
"%s node %s OFFLINE because its resource is stopped",
1823 node_type, this_node->
priv->
id);
1827 }
else if (
host && (
host->details->online == FALSE)
1828 &&
host->details->unclean) {
1829 crm_trace(
"Guest node %s UNCLEAN because host is unclean",
1836 node_type, this_node->
priv->
id,
1842determine_online_status(
const xmlNode *node_state,
pcmk_node_t *this_node,
1845 gboolean online = FALSE;
1860 online = determine_online_status_no_fencing(
scheduler, node_state,
1864 online = determine_online_status_fencing(
scheduler, node_state,
1883 pcmk__node_name(this_node));
1886 crm_trace(
"%s is offline", pcmk__node_name(this_node));
1889 crm_info(
"%s is shutting down", pcmk__node_name(this_node));
1892 crm_info(
"%s is pending", pcmk__node_name(this_node));
1895 crm_info(
"%s is in standby", pcmk__node_name(this_node));
1898 crm_info(
"%s is in maintenance", pcmk__node_name(this_node));
1901 crm_info(
"%s is online", pcmk__node_name(this_node));
1916 if (!pcmk__str_empty(
id)) {
1917 const char *end =
id + strlen(
id) - 1;
1919 for (
const char *s = end; s >
id; --s) {
1933 return (s == end)? s : (s - 1);
1957 char *basename = NULL;
1960 basename = strndup(last_rsc_id, end - last_rsc_id + 1);
1979 size_t base_name_len = end - last_rsc_id + 1;
1984 memcpy(zero, last_rsc_id, base_name_len);
1985 zero[base_name_len] =
':';
1986 zero[base_name_len + 1] =
'0';
1991create_fake_resource(
const char *rsc_id,
const xmlNode *rsc_entry,
2008 crm_debug(
"Detected orphaned remote node %s", rsc_id);
2017 crm_trace(
"Setting node %s as shutting down due to orphaned connection resource", rsc_id);
2024 crm_trace(
"Launched resource %s was removed from the configuration",
2056 top->
id,
parent->id, rsc_id, pcmk__node_name(node));
2079 GList *rIter = NULL;
2082 gboolean skip_inactive = FALSE;
2088 rsc_id, pcmk__node_name(node),
parent->id);
2090 for (rIter =
parent->priv->children;
2091 (rIter != NULL) && (rsc == NULL); rIter = rIter->next) {
2093 GList *locations = NULL;
2120 if (pcmk__same_node((
pcmk_node_t *) locations->data, node)) {
2139 crm_notice(
"Active (now-)anonymous clone %s has "
2140 "multiple (orphan) instance histories on %s",
2141 parent->id, pcmk__node_name(node));
2142 skip_inactive = TRUE;
2149 g_list_free(locations);
2153 if (!skip_inactive && !inactive_instance
2163 if (inactive_instance != NULL) {
2167 if ((pending_node != NULL)
2168 && !pcmk__same_node(pending_node, node)) {
2169 inactive_instance = NULL;
2176 if ((rsc == NULL) && !skip_inactive && (inactive_instance != NULL)) {
2178 inactive_instance->
id);
2179 rsc = inactive_instance;
2197 && !pcmk__is_guest_or_bundle_node(node)
2234 crm_trace(
"%s is not known as %s either (orphan)",
2240 crm_trace(
"Resource history for %s is orphaned "
2241 "because it is no longer primitive", rsc_id);
2248 if (pcmk__is_anonymous_clone(
parent)) {
2250 if (pcmk__is_bundled(
parent)) {
2266 rsc_id, pcmk__node_name(node), rsc->
id,
2273process_orphan_resource(
const xmlNode *rsc_entry,
const pcmk_node_t *node,
2279 crm_debug(
"Detected orphan resource %s on %s",
2280 rsc_id, pcmk__node_name(node));
2281 rsc = create_fake_resource(rsc_id, rsc_entry,
scheduler);
2303 char *reason = NULL;
2306 bool known_active =
false;
2321 node->
priv->
id) == NULL) {
2327 pcmk__node_name(n));
2329 (gpointer) n->
priv->
id, n);
2342 gboolean should_fence = FALSE;
2351 if (pcmk__is_guest_or_bundle_node(node)) {
2353 should_fence = TRUE;
2356 if (pcmk__is_remote_node(node)
2369 " revoked if remote connection can "
2370 "be re-established elsewhere)",
2373 should_fence = TRUE;
2377 if (reason == NULL) {
2386 save_on_fail = on_fail;
2432 "__action_migration_auto__",
scheduler);
2450 if ((rsc->
priv->
launcher != NULL) && pcmk__is_bundled(rsc)) {
2461 }
else if (known_active) {
2473 if (pcmk__is_remote_node(tmpnode)
2480 "remote connection is unrecoverable", FALSE);
2502 if (pcmk_all_flags_set(rsc->
flags,
2513 crm_notice(
"Removed resource %s is active on %s and will be "
2514 "stopped when possible",
2515 rsc->
id, pcmk__node_name(node));
2517 crm_notice(
"Removed resource %s must be stopped manually on %s "
2519 " is set to false", rsc->
id, pcmk__node_name(node));
2555 GList *gIter = possible_matches;
2557 for (; gIter != NULL; gIter = gIter->next) {
2563 g_list_free(possible_matches);
2581 int start_index,
int stop_index,
2585 const char *task = NULL;
2586 const char *status = NULL;
2587 GList *gIter = sorted_op_list;
2591 rsc->
id, start_index, stop_index);
2593 for (; gIter != NULL; gIter = gIter->next) {
2594 xmlNode *rsc_op = (xmlNode *) gIter->data;
2596 guint interval_ms = 0;
2598 const char *
id = pcmk__xe_id(rsc_op);
2604 rsc->
id, pcmk__node_name(node));
2608 }
else if (start_index < stop_index && counter <= stop_index) {
2610 id, pcmk__node_name(node));
2613 }
else if (counter < start_index) {
2615 id, pcmk__node_name(node), counter);
2620 if (interval_ms == 0) {
2622 id, pcmk__node_name(node));
2629 id, pcmk__node_name(node));
2635 pcmk__rsc_trace(rsc,
"Creating %s on %s", key, pcmk__node_name(node));
2645 int implied_monitor_start = -1;
2646 int implied_clone_start = -1;
2647 const char *task = NULL;
2648 const char *status = NULL;
2653 for (
const GList *iter = sorted_op_list; iter != NULL; iter = iter->next) {
2654 const xmlNode *rsc_op = (
const xmlNode *) iter->data;
2663 *stop_index = counter;
2667 *start_index = counter;
2669 }
else if ((implied_monitor_start <= *stop_index)
2675 implied_monitor_start = counter;
2679 implied_clone_start = counter;
2683 if (*start_index == -1) {
2684 if (implied_clone_start != -1) {
2685 *start_index = implied_clone_start;
2686 }
else if (implied_monitor_start != -1) {
2687 *start_index = implied_monitor_start;
2697 time_t lock_time = 0;
2700 &lock_time) ==
pcmk_ok) && (lock_time != 0)) {
2706 rsc->
id, pcmk__node_name(node));
2726unpack_lrm_resource(
pcmk_node_t *node,
const xmlNode *lrm_resource,
2729 GList *gIter = NULL;
2730 int stop_index = -1;
2731 int start_index = -1;
2734 const char *rsc_id = pcmk__xe_id(lrm_resource);
2737 GList *op_list = NULL;
2738 GList *sorted_op_list = NULL;
2740 xmlNode *rsc_op = NULL;
2741 xmlNode *last_failure = NULL;
2746 if (rsc_id == NULL) {
2753 rsc_id, pcmk__node_name(node));
2762 op_list = g_list_prepend(op_list, rsc_op);
2766 if (op_list == NULL) {
2773 rsc = unpack_find_resource(
scheduler, node, rsc_id);
2775 if (op_list == NULL) {
2779 rsc = process_orphan_resource(lrm_resource, node,
scheduler);
2786 unpack_shutdown_lock(lrm_resource, rsc, node,
scheduler);
2794 for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
2795 xmlNode *rsc_op = (xmlNode *) gIter->data;
2797 unpack_rsc_op(rsc, node, rsc_op, &last_failure, &on_fail);
2802 process_recurring(node, rsc, start_index, stop_index, sorted_op_list,
2806 g_list_free(sorted_op_list);
2808 process_rsc_state(rsc, node, on_fail);
2812 || (req_role < rsc->priv->next_role)) {
2818 "%s: Not overwriting calculated next role %s"
2819 " with requested next role %s",
2833handle_removed_launched_resources(
const xmlNode *lrm_rsc_list,
2845 const char *launcher_id = NULL;
2849 if ((launcher_id == NULL) || (rsc_id == NULL)) {
2854 if (launcher == NULL) {
2865 rsc->
id, launcher_id);
2881unpack_node_lrm(
pcmk_node_t *node,
const xmlNode *xml,
2884 bool found_removed_launched_resource =
false;
2907 found_removed_launched_resource =
true;
2914 if (found_removed_launched_resource) {
2915 handle_removed_launched_resources(xml,
scheduler);
2932set_node_score(gpointer key, gpointer value, gpointer user_data)
2935 int *score = user_data;
2940#define XPATH_NODE_STATE "/" PCMK_XE_CIB "/" PCMK_XE_STATUS \
2941 "/" PCMK__XE_NODE_STATE
2942#define SUB_XPATH_LRM_RESOURCE "/" PCMK__XE_LRM \
2943 "/" PCMK__XE_LRM_RESOURCES \
2944 "/" PCMK__XE_LRM_RESOURCE
2945#define SUB_XPATH_LRM_RSC_OP "/" PCMK__XE_LRM_RSC_OP
2948find_lrm_op(
const char *resource,
const char *op,
const char *node,
const char *source,
2951 GString *xpath = NULL;
2952 xmlNode *xml = NULL;
2954 CRM_CHECK((resource != NULL) && (op != NULL) && (node != NULL),
2957 xpath = g_string_sized_new(256);
2970 }
else if ((source != NULL)
2976 g_string_append_c(xpath,
']');
2980 g_string_free(xpath, TRUE);
2982 if (xml && target_rc >= 0) {
2996find_lrm_resource(
const char *rsc_id,
const char *node_name,
2999 GString *xpath = NULL;
3000 xmlNode *xml = NULL;
3002 CRM_CHECK((rsc_id != NULL) && (node_name != NULL),
return NULL);
3004 xpath = g_string_sized_new(256);
3012 g_string_free(xpath, TRUE);
3029 xmlXPathObject *search;
3039 result = (pcmk__xpath_num_results(search) == 0);
3040 xmlXPathFreeObject(search);
3058monitor_not_running_after(
const char *rsc_id,
const char *node_name,
3083non_monitor_after(
const char *rsc_id,
const char *node_name,
3086 xmlNode *lrm_resource = NULL;
3088 lrm_resource = find_lrm_resource(rsc_id, node_name,
scheduler);
3089 if (lrm_resource == NULL) {
3097 const char * task = NULL;
3130newer_state_after_migrate(
const char *rsc_id,
const char *node_name,
3131 const xmlNode *migrate_to,
3132 const xmlNode *migrate_from,
3135 const xmlNode *xml_op = (migrate_from != NULL)? migrate_from : migrate_to;
3141 if ((xml_op != migrate_to) && (migrate_to != NULL)
3144 xml_op = migrate_to;
3151 return non_monitor_after(rsc_id, node_name, xml_op,
scheduler)
3152 || monitor_not_running_after(rsc_id, node_name, xml_op,
scheduler);
3168get_migration_node_names(
const xmlNode *entry,
const pcmk_node_t *source_node,
3170 const char **source_name,
const char **target_name)
3174 if ((*source_name == NULL) || (*target_name == NULL)) {
3181 if ((source_node != NULL)
3182 && !pcmk__str_eq(*source_name, source_node->
priv->
name,
3186 pcmk__xe_id(entry), *source_name,
3187 pcmk__node_name(source_node));
3191 if ((target_node != NULL)
3192 && !pcmk__str_eq(*target_name, target_node->
priv->
name,
3196 pcmk__xe_id(entry), *target_name,
3197 pcmk__node_name(target_node));
3220 rsc->
id, pcmk__node_name(node));
3234unpack_migrate_to_success(
struct action_history *history)
3270 xmlNode *migrate_from = NULL;
3271 const char *source = NULL;
3272 const char *
target = NULL;
3273 bool source_newer_op =
false;
3274 bool target_newer_state =
false;
3275 bool active_on_target =
false;
3279 if (get_migration_node_names(history->xml, history->node, NULL, &source,
3285 source_newer_op = non_monitor_after(history->rsc->
id, source, history->xml,
3291 if (migrate_from != NULL) {
3292 if (source_newer_op) {
3306 target_newer_state = newer_state_after_migrate(history->rsc->
id,
target,
3307 history->xml, migrate_from,
3309 if (source_newer_op && target_newer_state) {
3318 add_dangling_migration(history->rsc, history->node);
3328 active_on_target = !target_newer_state && (target_node != NULL)
3332 if (active_on_target) {
3350 && unknown_on_node(history->rsc,
target)) {
3354 if (active_on_target) {
3358 if ((source_node != NULL) && source_node->
details->
online) {
3369 }
else if (!source_newer_op) {
3384unpack_migrate_to_failure(
struct action_history *history)
3386 xmlNode *target_migrate_from = NULL;
3387 const char *source = NULL;
3388 const char *
target = NULL;
3392 if (get_migration_node_names(history->xml, history->node, NULL, &source,
3403 target_migrate_from = find_lrm_op(history->rsc->
id,
3412 !unknown_on_node(history->rsc,
target)
3416 && !newer_state_after_migrate(history->rsc->
id,
target, history->xml,
3428 }
else if (!non_monitor_after(history->rsc->
id, source, history->xml,
3438 (gpointer) history->node);
3449unpack_migrate_from_failure(
struct action_history *history)
3451 xmlNode *source_migrate_to = NULL;
3452 const char *source = NULL;
3453 const char *
target = NULL;
3457 if (get_migration_node_names(history->xml, NULL, history->node, &source,
3476 !unknown_on_node(history->rsc, source)
3480 && !newer_state_after_migrate(history->rsc->
id, source,
3481 source_migrate_to, history->xml,
3501record_failed_op(
struct action_history *history)
3510 xIter != NULL; xIter = xIter->next) {
3512 const char *key = pcmk__xe_history_key(xIter);
3518 crm_trace(
"Skipping duplicate entry %s on %s",
3519 history->key, pcmk__node_name(history->node));
3524 crm_trace(
"Adding entry for %s on %s to failed action list",
3525 history->key, pcmk__node_name(history->node));
3532last_change_str(
const xmlNode *xml_op)
3540 const char *p = strchr(when_s,
' ');
3543 if ((p != NULL) && (*(++p) !=
'\0')) {
3571 if (pcmk__is_anonymous_clone(
parent)) {
3581 crm_notice(
"%s will not be started under current conditions", rsc->
id);
3598unpack_failure_handling(
struct action_history *history,
3603 history->interval_ms,
true);
3607 history->interval_ms, config);
3612 history->interval_ms, on_fail_str);
3615 g_hash_table_destroy(meta);
3629unpack_rsc_op_failure(
struct action_history *history,
3631 enum rsc_role_e fail_role, xmlNode **last_failure,
3634 bool is_probe =
false;
3635 char *last_change_s = NULL;
3638 *last_failure = history->xml;
3641 last_change_s = last_change_str(history->xml);
3645 crm_trace(
"Unexpected result (%s%s%s) was recorded for "
3646 "%s of %s on %s at %s " QB_XS
" exit-status=%d id=%s",
3648 (pcmk__str_empty(history->exit_reason)?
"" :
": "),
3649 pcmk__s(history->exit_reason,
""),
3650 (is_probe?
"probe" : history->task), history->rsc->
id,
3651 pcmk__node_name(history->node), last_change_s,
3652 history->exit_status, history->id);
3655 "Unexpected result (%s%s%s) was recorded for %s of "
3656 "%s on %s at %s " QB_XS
" exit-status=%d id=%s",
3658 (pcmk__str_empty(history->exit_reason)?
"" :
": "),
3659 pcmk__s(history->exit_reason,
""),
3660 (is_probe?
"probe" : history->task), history->rsc->
id,
3661 pcmk__node_name(history->node), last_change_s,
3662 history->exit_status, history->id);
3664 if (is_probe && (history->exit_status !=
PCMK_OCF_OK)
3671 crm_notice(
"If it is not possible for %s to run on %s, see "
3674 history->rsc->
id, pcmk__node_name(history->node));
3677 record_failed_op(history);
3680 free(last_change_s);
3682 if (*on_fail < config_on_fail) {
3686 *on_fail = config_on_fail;
3694 unpack_migrate_to_failure(history);
3697 unpack_migrate_from_failure(history);
3728 set_active(history->rsc);
3732 "Resource %s: role=%s unclean=%s on_fail=%s fail_role=%s",
3745 ban_from_all_nodes(history->rsc);
3759block_if_unrecoverable(
struct action_history *history)
3761 char *last_change_s = NULL;
3770 last_change_s = last_change_str(history->xml);
3772 "No further recovery can be attempted for %s "
3773 "because %s on %s failed (%s%s%s) at %s "
3774 QB_XS
" rc=%d id=%s",
3775 history->rsc->
id, history->task,
3776 pcmk__node_name(history->node),
3778 (pcmk__str_empty(history->exit_reason)?
"" :
": "),
3779 pcmk__s(history->exit_reason,
""),
3780 last_change_s, history->exit_status, history->id);
3782 free(last_change_s);
3798remap_because(
struct action_history *history,
const char **why,
int value,
3801 if (history->execution_status != value) {
3802 history->execution_status = value;
3830remap_operation(
struct action_history *history,
3838 bool is_probe =
false;
3839 int orig_exit_status = history->exit_status;
3840 int orig_exec_status = history->execution_status;
3841 const char *why = NULL;
3842 const char *task = history->task;
3846 if (history->exit_status != orig_exit_status) {
3847 why =
"degraded result";
3850 record_failed_op(history);
3854 if (!pcmk__is_bundled(history->rsc)
3860 why =
"equivalent probe result";
3868 switch (history->execution_status) {
3877 "node-fatal error");
3889 if (history->expected_exit_status < 0) {
3899 "obsolete history format");
3901 "(corrupt or obsolete CIB?)",
3902 history->key, pcmk__node_name(history->node));
3904 }
else if (history->exit_status == history->expected_exit_status) {
3910 "%s on %s: expected %d (%s), got %d (%s%s%s)",
3911 history->key, pcmk__node_name(history->node),
3912 history->expected_exit_status,
3914 history->exit_status,
3916 (pcmk__str_empty(history->exit_reason)?
"" :
": "),
3917 pcmk__s(history->exit_reason,
""));
3920 switch (history->exit_status) {
3924 char *last_change_s = last_change_str(history->xml);
3928 "Probe found %s active on %s at %s",
3929 history->rsc->
id, pcmk__node_name(history->node),
3931 free(last_change_s);
3937 || (history->expected_exit_status == history->exit_status)
3954 && (history->exit_status != history->expected_exit_status)) {
3955 char *last_change_s = last_change_str(history->xml);
3959 "Probe found %s active and promoted on %s at %s",
3961 pcmk__node_name(history->node), last_change_s);
3962 free(last_change_s);
3965 || (history->exit_status == history->expected_exit_status)) {
3983 guint interval_ms = 0;
3987 if (interval_ms == 0) {
3989 block_if_unrecoverable(history);
4004 block_if_unrecoverable(history);
4011 char *last_change_s = last_change_str(history->xml);
4013 crm_info(
"Treating unknown exit status %d from %s of %s "
4014 "on %s at %s as failure",
4015 history->exit_status, task, history->rsc->
id,
4016 pcmk__node_name(history->node), last_change_s);
4018 "unknown exit status");
4019 free(last_change_s);
4027 "Remapped %s result from [%s: %s] to [%s: %s] "
4029 history->key, pcmk_exec_status_str(orig_exec_status),
4031 pcmk_exec_status_str(history->execution_status),
4038should_clear_for_param_change(
const xmlNode *xml_op,
const char *task,
4054 switch (digest_data->
rc) {
4056 crm_trace(
"Resource %s history entry %s on %s"
4057 " has no digest to compare",
4058 rsc->
id, pcmk__xe_history_key(xml_op),
4087should_ignore_failure_timeout(
const pcmk_resource_t *rsc,
const char *task,
4088 guint interval_ms,
bool is_last_failure)
4113 && (interval_ms != 0)
4121 if (is_last_failure) {
4122 crm_info(
"Waiting to clear monitor failure for remote node %s"
4123 " until fencing has occurred", rsc->
id);
4150check_operation_expiry(
struct action_history *history)
4152 bool expired =
false;
4153 bool is_last_failure =
pcmk__ends_with(history->id,
"_last_failure_0");
4154 time_t last_run = 0;
4155 int unexpired_fail_count = 0;
4156 const char *clear_reason = NULL;
4157 const guint expiration_sec =
4163 "Resource history entry %s on %s is not expired: "
4164 "Not Installed does not expire",
4165 history->id, pcmk__node_name(history->node));
4169 if ((expiration_sec > 0)
4178 time_t last_failure = 0;
4181 if ((now >= (last_run + expiration_sec))
4182 && !should_ignore_failure_timeout(history->rsc, history->task,
4183 history->interval_ms,
4195 crm_trace(
"%s@%lld is %sexpired @%lld with unexpired_failures=%d "
4196 "expiration=%s last-failure@%lld",
4197 history->id, (
long long) last_run, (expired?
"" :
"not "),
4198 (
long long) now, unexpired_fail_count,
4200 (
long long) last_failure);
4201 last_failure += expiration_sec + 1;
4202 if (unexpired_fail_count && (now < last_failure)) {
4204 "fail count expiration");
4213 if (unexpired_fail_count == 0) {
4215 clear_reason =
"it expired";
4225 "Resource history entry %s on %s is not "
4226 "expired: Unexpired fail count",
4227 history->id, pcmk__node_name(history->node));
4231 }
else if (is_last_failure
4236 clear_reason =
"reconnect interval is set";
4240 if (!expired && is_last_failure
4241 && should_clear_for_param_change(history->xml, history->task,
4242 history->rsc, history->node)) {
4243 clear_reason =
"resource parameters have changed";
4246 if (clear_reason != NULL) {
4263 crm_info(
"Clearing %s failure will wait until any scheduled "
4264 "fencing of %s completes",
4265 history->task, history->rsc->
id);
4266 order_after_remote_fencing(clear_op, history->rsc,
scheduler);
4270 if (expired && (history->interval_ms == 0)
4272 switch (history->exit_status) {
4280 "Resource history entry %s on %s is not "
4281 "expired: Probe result",
4282 history->id, pcmk__node_name(history->node));
4314update_resource_state(
struct action_history *history,
int exit_status,
4315 const xmlNode *last_failure,
4318 bool clear_past_failure =
false;
4321 || (!pcmk__is_bundled(history->rsc)
4326 clear_past_failure =
true;
4330 if ((last_failure != NULL)
4331 && pcmk__str_eq(history->key, pcmk__xe_history_key(last_failure),
4333 clear_past_failure =
true;
4336 set_active(history->rsc);
4341 clear_past_failure =
true;
4345 clear_past_failure =
true;
4350 clear_past_failure =
true;
4358 clear_past_failure =
true;
4365 clear_past_failure =
true;
4369 unpack_migrate_to_success(history);
4373 history->rsc->
id, pcmk__node_name(history->node));
4374 set_active(history->rsc);
4377 if (!clear_past_failure) {
4387 "%s (%s) is not cleared by a completed %s",
4399 "clear past failures");
4412 "clear past failures and reset remote");
4427can_affect_state(
struct action_history *history)
4445unpack_action_result(
struct action_history *history)
4448 &(history->execution_status)) < 0)
4454 history->id, history->rsc->
id,
4455 pcmk__node_name(history->node),
4462 &(history->exit_status)) < 0)
4463 || (history->exit_status < 0) || (history->exit_status >
CRM_EX_MAX)) {
4466 history->id, history->rsc->
id,
4467 pcmk__node_name(history->node),
4488process_expired_result(
struct action_history *history,
int orig_exit_status)
4490 if (!pcmk__is_bundled(history->rsc)
4492 && (orig_exit_status != history->expected_exit_status)) {
4497 crm_trace(
"Ignoring resource history entry %s for probe of %s on %s: "
4498 "Masked failure expired",
4499 history->id, history->rsc->
id,
4500 pcmk__node_name(history->node));
4504 if (history->exit_status == history->expected_exit_status) {
4508 if (history->interval_ms == 0) {
4509 crm_notice(
"Ignoring resource history entry %s for %s of %s on %s: "
4511 history->id, history->task, history->rsc->
id,
4512 pcmk__node_name(history->node));
4527 crm_notice(
"Rescheduling %s-interval %s of %s on %s "
4528 "after failure expired",
4530 history->rsc->
id, pcmk__node_name(history->node));
4532 "calculated-failure-timeout");
4549mask_probe_failure(
struct action_history *history,
int orig_exit_status,
4550 const xmlNode *last_failure,
4559 crm_notice(
"Treating probe result '%s' for %s on %s as 'not running'",
4561 pcmk__node_name(history->node));
4562 update_resource_state(history, history->expected_exit_status, last_failure,
4566 record_failed_op(history);
4584failure_is_newer(
const struct action_history *history,
4585 const xmlNode *last_failure)
4587 guint failure_interval_ms = 0U;
4588 long long failure_change = 0LL;
4589 long long this_change = 0LL;
4591 if (last_failure == NULL) {
4595 if (!pcmk__str_eq(history->task,
4602 &failure_interval_ms) !=
pcmk_ok)
4603 || (history->interval_ms != failure_interval_ms)) {
4612 || (failure_change < this_change)) {
4627process_pending_action(
struct action_history *history,
4628 const xmlNode *last_failure)
4639 if (failure_is_newer(history, last_failure)) {
4645 set_active(history->rsc);
4655 const char *migrate_target = NULL;
4681 history->rsc->private->pending_action = strdup(
"probe");
4682 history->rsc->private->pending_node = history->node;
4695 bool expired =
false;
4700 struct action_history history = {
4707 CRM_CHECK(rsc && node && xml_op,
return);
4709 history.id = pcmk__xe_id(xml_op);
4710 if (history.id == NULL) {
4712 "without ID", rsc->
id, pcmk__node_name(node));
4718 if (history.task == NULL) {
4721 history.id, rsc->
id, pcmk__node_name(node));
4725 if (!can_affect_state(&history)) {
4727 "Ignoring resource history entry %s for %s on %s "
4728 "with irrelevant action '%s'",
4729 history.id, rsc->
id, pcmk__node_name(node),
4734 if (unpack_action_result(&history) !=
pcmk_rc_ok) {
4739 history.key = pcmk__xe_history_key(xml_op);
4743 history.id, history.task, history.call_id,
4744 pcmk__node_name(node),
4745 pcmk_exec_status_str(history.execution_status),
4750 "%s is running on %s, which is unclean (further action "
4751 "depends on value of stop's on-fail attribute)",
4752 rsc->
id, pcmk__node_name(node));
4755 expired = check_operation_expiry(&history);
4756 old_rc = history.exit_status;
4758 remap_operation(&history, on_fail, expired);
4760 if (expired && (process_expired_result(&history, old_rc) ==
pcmk_rc_ok)) {
4765 mask_probe_failure(&history, old_rc, *last_failure, on_fail);
4773 switch (history.execution_status) {
4775 process_pending_action(&history, *last_failure);
4779 update_resource_state(&history, history.exit_status, *last_failure,
4784 unpack_failure_handling(&history, &failure_strategy, &fail_role);
4786 crm_warn(
"Cannot ignore failed %s of %s on %s: "
4787 "Resource agent doesn't exist "
4788 QB_XS
" status=%d rc=%d id=%s",
4789 history.task, rsc->
id, pcmk__node_name(node),
4790 history.execution_status, history.exit_status,
4799 unpack_rsc_op_failure(&history, failure_strategy, fail_role,
4800 last_failure, on_fail);
4804 if (pcmk__is_pacemaker_remote_node(node)
4830 unpack_failure_handling(&history, &failure_strategy, &fail_role);
4835 char *last_change_s = last_change_str(xml_op);
4837 crm_warn(
"Pretending failed %s (%s%s%s) of %s on %s at %s succeeded "
4840 (pcmk__str_empty(history.exit_reason)?
"" :
": "),
4841 pcmk__s(history.exit_reason,
""), rsc->
id,
4842 pcmk__node_name(node), last_change_s, history.id);
4843 free(last_change_s);
4845 update_resource_state(&history, history.expected_exit_status,
4846 *last_failure, on_fail);
4850 record_failed_op(&history);
4854 *on_fail = failure_strategy;
4858 unpack_rsc_op_failure(&history, failure_strategy, fail_role,
4859 last_failure, on_fail);
4862 uint8_t log_level = LOG_ERR;
4865 log_level = LOG_NOTICE;
4868 "Preventing %s from restarting on %s because "
4869 "of hard failure (%s%s%s) " QB_XS
" %s",
4870 parent->id, pcmk__node_name(node),
4872 (pcmk__str_empty(history.exit_reason)?
"" :
": "),
4873 pcmk__s(history.exit_reason,
""), history.id);
4879 "Preventing %s from restarting anywhere because "
4880 "of fatal failure (%s%s%s) " QB_XS
" %s",
4882 (pcmk__str_empty(history.exit_reason)?
"" :
": "),
4883 pcmk__s(history.exit_reason,
""), history.id);
4891 rsc->
id, pcmk__node_name(node), history.id,
4906insert_attr(gpointer key, gpointer value, gpointer user_data)
4908 GHashTable *table = user_data;
4910 g_hash_table_insert(table, key, value);
4915add_node_attrs(
const xmlNode *xml_obj,
pcmk_node_t *node,
bool overwrite,
4918 const char *cluster_name = NULL;
4955 &rule_input, unpacked, NULL,
scheduler);
4956 g_hash_table_foreach_steal(unpacked, insert_attr, node->
priv->
attrs);
4957 g_hash_table_destroy(unpacked);
4977 }
else if (cluster_name) {
4986extract_operations(
const char *node,
const char *rsc, xmlNode * rsc_entry, gboolean active_filter)
4989 int stop_index = -1;
4990 int start_index = -1;
4992 xmlNode *rsc_op = NULL;
4994 GList *gIter = NULL;
4995 GList *op_list = NULL;
4996 GList *sorted_op_list = NULL;
5000 sorted_op_list = NULL;
5008 op_list = g_list_prepend(op_list, rsc_op);
5011 if (op_list == NULL) {
5019 if (active_filter == FALSE) {
5020 return sorted_op_list;
5027 for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
5028 xmlNode *rsc_op = (xmlNode *) gIter->data;
5032 if (start_index < stop_index) {
5033 crm_trace(
"Skipping %s: not active", pcmk__xe_id(rsc_entry));
5036 }
else if (counter < start_index) {
5037 crm_trace(
"Skipping %s: old", pcmk__xe_id(rsc_op));
5040 op_list = g_list_append(op_list, rsc_op);
5043 g_list_free(sorted_op_list);
5051 GList *output = NULL;
5052 GList *intermediate = NULL;
5054 xmlNode *tmp = NULL;
5060 xmlNode *node_state = NULL;
5076 if(this_node == NULL) {
5080 }
else if (pcmk__is_pacemaker_remote_node(this_node)) {
5081 determine_remote_online_status(
scheduler, this_node);
5084 determine_online_status(node_state, this_node,
scheduler);
5093 xmlNode *lrm_rsc = NULL;
5112 intermediate = extract_operations(
uname, rsc_id, lrm_rsc, active_filter);
5113 output = g_list_concat(output, intermediate);
@ pcmk__ar_first_implies_then
gboolean decode_transition_key(const char *key, char **uuid, int *transition_id, int *action_id, int *target_rc)
Parse a transition key into its constituent parts.
#define PCMK_ACTION_PROMOTE
#define PCMK_ACTION_START
#define PCMK_ACTION_MIGRATE_FROM
#define PCMK_ACTION_MIGRATE_TO
#define PCMK_ACTION_MONITOR
#define PCMK_ACTION_DEMOTE
#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
const char * pcmk__on_fail_text(enum pcmk__on_fail on_fail)
const char * pcmk__node_attr(const pcmk_node_t *node, const char *name, const char *target, enum pcmk__rsc_node node_type)
pcmk_resource_t * pe__create_clone_child(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler)
guint pcmk__timeout_ms2s(guint timeout_ms)
int pcmk__effective_rc(int rc)
#define pcmk__assert_alloc(nmemb, size)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
int pe__unpack_resource(xmlNode *xml_obj, pcmk_resource_t **rsc, pcmk_resource_t *parent, pcmk_scheduler_t *scheduler)
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
enum pcmk_ipc_server type
#define CRMD_JOINSTATE_NACK
#define CRM_ATTR_SITE_NAME
#define CRMD_JOINSTATE_DOWN
#define CRMD_JOINSTATE_PENDING
#define CRM_ATTR_CLUSTER_NAME
#define CRMD_JOINSTATE_MEMBER
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
const char * pcmk__readable_interval(guint interval_ms)
#define CRM_TRACE_INIT_DATA(name)
#define crm_log_xml_info(xml, text)
#define crm_info(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
#define crm_warn(fmt, args...)
#define crm_log_xml_debug(xml, text)
#define CRM_LOG_ASSERT(expr)
#define crm_notice(fmt, args...)
#define CRM_CHECK(expr, failure_action)
#define crm_debug(fmt, args...)
#define crm_trace(fmt, args...)
#define pcmk__config_warn(fmt...)
#define pcmk__config_err(fmt...)
#define pcmk__warn_once(wo_flag, fmt...)
pcmk_scheduler_t * scheduler
#define PCMK_NODE_ATTR_STANDBY
#define PCMK_NODE_ATTR_TERMINATE
#define PCMK_NODE_ATTR_MAINTENANCE
#define PCMK__NODE_ATTR_RESOURCE_DISCOVERY_ENABLED
@ pcmk__node_remote_fenced
@ pcmk__node_remote_maint
@ pcmk__node_fail_standby
@ pcmk__node_remote_reset
@ pcmk__node_probes_allowed
#define pcmk__clear_node_flags(node, flags_to_clear)
#define pcmk__set_node_flags(node, flags_to_set)
@ pcmk__node_variant_remote
@ pcmk__node_variant_cluster
#define PCMK_OPT_STOP_ALL_RESOURCES
#define PCMK_META_INTERVAL
#define PCMK_VALUE_FENCE_LEGACY
#define PCMK_OPT_SYMMETRIC_CLUSTER
#define PCMK_META_ON_FAIL
#define PCMK_OPT_NODE_PENDING_TIMEOUT
#define PCMK_OPT_STARTUP_FENCING
#define PCMK_OPT_STOP_ORPHAN_RESOURCES
#define PCMK_OPT_SHUTDOWN_LOCK_LIMIT
#define PCMK_OPT_MAINTENANCE_MODE
#define PCMK_OPT_STOP_ORPHAN_ACTIONS
#define PCMK_OPT_NO_QUORUM_POLICY
#define PCMK_OPT_PRIORITY_FENCING_DELAY
#define PCMK_VALUE_OFFLINE
#define PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS
#define PCMK_META_REMOTE_CONNECT_TIMEOUT
#define PCMK_VALUE_DEMOTE
#define PCMK_OPT_FENCE_REMOTE_WITHOUT_QUORUM
#define PCMK_META_REMOTE_NODE
#define PCMK_OPT_HAVE_WATCHDOG
#define PCMK_VALUE_FREEZE
#define PCMK_OPT_CONCURRENT_FENCING
#define PCMK_OPT_START_FAILURE_IS_FATAL
#define PCMK_OPT_PLACEMENT_STRATEGY
#define PCMK_META_IS_MANAGED
#define PCMK_OPT_STONITH_ENABLED
#define PCMK_OPT_ENABLE_STARTUP_PROBES
#define PCMK_VALUE_REMOTE
#define PCMK_META_TARGET_ROLE
#define PCMK_OPT_CLUSTER_NAME
#define PCMK_VALUE_IGNORE
#define PCMK_VALUE_MEMBER
#define PCMK_META_REMOTE_PORT
#define PCMK_OPT_STONITH_TIMEOUT
#define PCMK_META_REMOTE_ALLOW_MIGRATE
#define PCMK_OPT_STONITH_WATCHDOG_TIMEOUT
#define PCMK_META_REMOTE_ADDR
#define PCMK_OPT_STONITH_ACTION
#define PCMK_OPT_SHUTDOWN_LOCK
#define PCMK_VALUE_ONLINE
const char * pcmk__cluster_option(GHashTable *options, const char *name)
#define PCMK__META_CONTAINER
#define PCMK__META_MIGRATE_SOURCE
void pcmk__validate_cluster_options(GHashTable *options)
#define PCMK__META_MIGRATE_TARGET
pcmk__action_result_t result
void pe__unpack_node_health_scores(pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL gint pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
bool pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
pcmk_action_t * pe__clear_failcount(pcmk_resource_t *rsc, const pcmk_node_t *node, const char *reason, pcmk_scheduler_t *scheduler)
Schedule a controller operation to clear a fail count.
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
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)
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)
GHashTable * pe__node_list2table(const GList *list)
gboolean get_target_role(const pcmk_resource_t *rsc, enum rsc_role_e *role)
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.
#define demote_action(rsc, node, optional)
void destroy_ticket(gpointer data)
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
pcmk__op_digest_t * rsc_action_digest_cmp(pcmk_resource_t *rsc, const xmlNode *xml_op, pcmk_node_t *node, pcmk_scheduler_t *scheduler)
bool pe__is_universal_clone(const pcmk_resource_t *rsc, const pcmk_scheduler_t *scheduler)
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
pcmk_resource_t * pe__find_bundle_replica(const pcmk_resource_t *bundle, const pcmk_node_t *node)
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
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)
pcmk__ticket_t * ticket_new(const char *ticket_id, pcmk_scheduler_t *scheduler)
int pe_get_failcount(const pcmk_node_t *node, pcmk_resource_t *rsc, time_t *last_failure, uint32_t flags, const xmlNode *xml_op)
void pe__free_digests(gpointer ptr)
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
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)
bool pe__bundle_needs_remote_name(pcmk_resource_t *rsc)
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)
void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why)
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 stop_action(rsc, node, optional)
int pe__is_newer_op(const xmlNode *xml_a, const xmlNode *xml_b)
void native_add_running(pcmk_resource_t *rsc, pcmk_node_t *node, pcmk_scheduler_t *scheduler, gboolean failed)
void pe__clear_resource_history(pcmk_resource_t *rsc, const pcmk_node_t *node)
bool pe__shutdown_requested(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)
bool xml_contains_remote_node(xmlNode *xml)
xmlNode * pe_create_remote_xml(xmlNode *parent, const char *uname, const char *container_id, const char *migrateable, const char *is_managed, const char *start_timeout, const char *server, const char *port)
bool pcmk_xe_mask_probe_failure(const xmlNode *xml_op)
Check whether an action history entry represents a maskable probe.
bool pcmk_is_probe(const char *task, guint interval)
Check whether an action name and interval represent a probe.
bool pcmk_xe_is_probe(const xmlNode *xml_op)
Check whether an action history entry represents a probe.
@ pcmk_rsc_match_clone_only
Match only clones and their instances, by either clone or instance ID.
@ pcmk__rsc_stop_if_failed
@ pcmk__rsc_removed_launched
@ pcmk__rsc_needs_fencing
@ pcmk__rsc_ignore_failure
@ pcmk__rsc_is_remote_connection
@ pcmk__rsc_start_pending
#define pcmk__set_rsc_flags(resource, flags_to_set)
@ pcmk__rsc_variant_primitive
Primitive resource.
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
@ CRM_EX_MAX
Ensure crm_exit_t can hold this.
@ PCMK_OCF_INSUFFICIENT_PRIV
Insufficient privileges.
@ PCMK_OCF_FAILED_PROMOTED
Service failed and possibly in promoted role.
@ PCMK_OCF_RUNNING_PROMOTED
Service active and promoted.
@ PCMK_OCF_DEGRADED_PROMOTED
Service promoted but more likely to fail soon.
@ PCMK_OCF_UNIMPLEMENT_FEATURE
Requested action not implemented.
@ PCMK_OCF_NOT_CONFIGURED
Parameter invalid (inherently)
@ PCMK_OCF_DEGRADED
Service active but more likely to fail soon.
@ PCMK_OCF_NOT_INSTALLED
Dependencies not available locally.
@ PCMK_OCF_UNKNOWN_ERROR
Unspecified error.
@ PCMK_OCF_INVALID_PARAM
Parameter invalid (in local context)
@ PCMK_OCF_NOT_RUNNING
Service safely stopped.
@ PCMK_OCF_UNKNOWN
Action is pending.
const char * crm_exit_str(crm_exit_t exit_code)
@ PCMK_EXEC_CANCELLED
Action was cancelled.
@ PCMK_EXEC_NO_SECRETS
Necessary CIB secrets are unavailable.
@ PCMK_EXEC_ERROR_FATAL
Execution failed, do not retry anywhere.
@ PCMK_EXEC_NOT_INSTALLED
Agent or dependency not available locally.
@ PCMK_EXEC_INVALID
Action cannot be attempted (e.g. shutdown)
@ PCMK_EXEC_DONE
Action completed, result is known.
@ PCMK_EXEC_ERROR
Execution failed, may be retried.
@ PCMK_EXEC_NOT_SUPPORTED
Agent does not implement requested action.
@ PCMK_EXEC_TIMEOUT
Action did not complete in time.
@ PCMK_EXEC_PENDING
Action is in progress.
@ PCMK_EXEC_UNKNOWN
Used only to initialize variables.
@ PCMK_EXEC_ERROR_HARD
Execution failed, do not retry on node.
@ PCMK_EXEC_MAX
Maximum value for this enum.
@ PCMK_EXEC_NO_FENCE_DEVICE
No fence device is configured for target.
@ PCMK_EXEC_NOT_CONNECTED
No connection to executor.
#define pcmk__assert(expr)
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.
@ 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_no_quorum_fence
Fence all nodes in partition.
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__sched_err(scheduler, fmt...)
#define pcmk__rsc_info(rsc, fmt, args...)
#define pcmk__rsc_trace(rsc, fmt, args...)
@ pcmk__check_last_failure
time_t pcmk__scheduler_epoch_time(pcmk_scheduler_t *scheduler)
#define pcmk__rsc_debug(rsc, fmt, args...)
#define pcmk__sched_warn(scheduler, fmt...)
#define pcmk__set_scheduler_flags(scheduler, flags_to_set)
void pcmk__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, const char *reason)
@ pcmk__sched_in_maintenance
@ pcmk__sched_enable_unfencing
@ pcmk__sched_stop_removed_resources
@ pcmk__sched_shutdown_lock
@ pcmk__sched_fencing_enabled
@ pcmk__sched_cancel_removed_actions
@ pcmk__sched_fence_remote_no_quorum
@ pcmk__sched_symmetric_cluster
@ pcmk__sched_start_failure_fatal
@ pcmk__sched_have_remote_nodes
@ pcmk__sched_concurrent_fencing
@ pcmk__sched_startup_fencing
@ pcmk__sched_have_fencing
@ pcmk__sched_probe_resources
@ pcmk__sched_location_only
void pcmk__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc, pcmk_node_t *node, enum pcmk__check_parameters)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
pcmk_node_t * pe_find_node_any(const GList *node_list, const char *id, const char *node_name)
Find a node by name or ID in a list of nodes.
pcmk_resource_t * pe_find_resource(GList *rsc_list, const char *id)
int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
gboolean crm_is_true(const char *s)
int crm_str_to_boolean(const char *s, int *ret)
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
void pcmk__str_update(char **str, const char *value)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
bool pcmk__ends_with(const char *s, const char *match)
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
GHashTable * digest_cache
pcmk_scheduler_t * scheduler
enum pcmk__digest_result rc
const pcmk_node_t * pending_node
guint failure_expiration_ms
GHashTable * probed_nodes
pcmk_node_t * partial_migration_target
const pcmk_node_t * lock_node
pcmk_scheduler_t * scheduler
pcmk_node_t * partial_migration_source
GList * dangling_migration_sources
enum pcmk__rsc_variant variant
enum rsc_role_e orig_role
pcmk_resource_t * launcher
enum rsc_role_e next_role
const pcmk__rsc_methods_t * fns
GHashTable * allowed_nodes
guint remote_reconnect_ms
pcmk__resource_private_t * priv
pcmk_resource_t *(* find_rsc)(pcmk_resource_t *rsc, const char *search, const pcmk_node_t *node, uint32_t flags)
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, uint32_t target)
guint priority_fencing_ms
const char * fence_action
const char * placement_strategy
GHashTable * ticket_constraints
pcmk__scheduler_private_t * priv
enum pe_quorum_policy no_quorum_policy
pcmk__node_private_t * priv
struct pcmk__node_details * details
struct pcmk__node_assignment * assign
#define pcmk__set_ticket_flags(ticket, flags_to_set)
#define pcmk__clear_ticket_flags(ticket, flags_to_clear)
#define set_config_flag(scheduler, option, flag)
#define XPATH_ENABLE_UNFENCING
void calculate_active_ops(const GList *sorted_op_list, int *start_index, int *stop_index)
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.
const char * pe_base_name_end(const char *id)
gboolean unpack_status(xmlNode *status, pcmk_scheduler_t *scheduler)
#define SUB_XPATH_LRM_RESOURCE
GList * find_operations(const char *rsc, const char *node, gboolean active_filter, pcmk_scheduler_t *scheduler)
gboolean unpack_remote_nodes(xmlNode *xml_resources, pcmk_scheduler_t *scheduler)
char * clone_zero(const char *last_rsc_id)
#define SUB_XPATH_LRM_RSC_OP
gboolean unpack_resources(const xmlNode *xml_resources, pcmk_scheduler_t *scheduler)
gboolean unpack_config(xmlNode *config, pcmk_scheduler_t *scheduler)
pcmk_node_t * pe_create_node(const char *id, const char *uname, const char *type, int score, pcmk_scheduler_t *scheduler)
char * clone_strip(const char *last_rsc_id)
gboolean unpack_nodes(xmlNode *xml_nodes, pcmk_scheduler_t *scheduler)
int pe__target_rc_from_xml(const xmlNode *xml_op)
gboolean unpack_tags(xmlNode *xml_tags, pcmk_scheduler_t *scheduler)
void pcmk__validate_fencing_topology(const xmlNode *xml)
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_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond 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.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
void int pcmk__xe_get_score(const xmlNode *xml, const char *name, int *score, int default_score)
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)
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
void pcmk__free_idref(gpointer data)
void pcmk__add_idref(GHashTable *table, const char *id, const char *referrer)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
@ pcmk__xaf_none
Flag has no effect.
#define PCMK_XE_UTILIZATION
#define PCMK_XE_FENCING_LEVEL
#define PCMK_XA_OPERATION
#define PCMK_XE_INSTANCE_ATTRIBUTES
#define PCMK_XA_LAST_RC_CHANGE
#define PCMK_XE_META_ATTRIBUTES
#define PCMK_XE_FENCING_TOPOLOGY
#define PCMK_XA_LAST_GRANTED
#define PCMK_XA_EXIT_REASON
#define PCMK_XE_PRIMITIVE
#define PCMK_XE_CLUSTER_PROPERTY_SET
#define PCMK_XA_RESOURCE_DISCOVERY
#define PCMK_XA_NO_QUORUM_PANIC
#define PCMK__XE_LRM_RSC_OP
#define PCMK__XE_LRM_RESOURCE
#define PCMK__XA_NODE_FENCED
#define PCMK__XE_TRANSIENT_ATTRIBUTES
#define PCMK__XE_LRM_RESOURCES
#define PCMK__XA_OP_RESTART_DIGEST
#define PCMK__XA_OP_STATUS
#define PCMK__XA_TRANSITION_KEY
#define PCMK__XE_NODE_STATE
#define PCMK__XA_NODE_IN_MAINTENANCE
#define PCMK__XE_TICKET_STATE
xmlXPathObject * pcmk__xpath_search(xmlDoc *doc, const char *path)
xmlNode * pcmk__xpath_find_one(xmlDoc *doc, const char *path, uint8_t level)