30 struct action_history {
39 const char *exit_reason;
42 int expected_exit_status;
51 #define set_config_flag(scheduler, option, flag) do { \ 52 GHashTable *config_hash = (scheduler)->priv->options; \ 53 const char *scf_value = pcmk__cluster_option(config_hash, (option)); \ 55 if (scf_value != NULL) { \ 56 if (crm_is_true(scf_value)) { \ 57 (scheduler)->flags = pcmk__set_flags_as(__func__, __LINE__, \ 58 LOG_TRACE, "Scheduler", \ 59 crm_system_name, (scheduler)->flags, \ 62 (scheduler)->flags = pcmk__clear_flags_as(__func__, __LINE__, \ 63 LOG_TRACE, "Scheduler", \ 64 crm_system_name, (scheduler)->flags, \ 71 xmlNode *xml_op, xmlNode **last_failure,
75 static void add_node_attrs(
const xmlNode *xml_obj,
pcmk_node_t *node,
77 static void determine_online_status(
const xmlNode *node_state,
81 static void unpack_node_lrm(
pcmk_node_t *node,
const xmlNode *xml,
97 return pcmk__is_pacemaker_remote_node(node)
115 const char *reason,
bool priority_delay)
119 if (pcmk__is_guest_or_bundle_node(node)) {
126 "(otherwise would because %s): " 127 "its guest resource %s is unmanaged",
128 pcmk__node_name(node), reason, rsc->
id);
131 "Guest node %s will be fenced " 132 "(by recovering its guest resource %s): %s",
133 pcmk__node_name(node), rsc->
id, reason);
145 }
else if (is_dangling_guest_node(node)) {
146 crm_info(
"Cleaning up dangling connection for guest node %s: " 147 "fencing was already done because %s, " 148 "and guest resource no longer exists",
149 pcmk__node_name(node), reason);
153 }
else if (pcmk__is_remote_node(node)) {
158 "(otherwise would because %s): connection is unmanaged",
159 pcmk__node_name(node), reason);
163 pcmk__node_name(node),
172 crm_trace(
"Cluster node %s %s because %s",
173 pcmk__node_name(node),
179 pcmk__node_name(node),
190 #define XPATH_UNFENCING_NVPAIR PCMK_XE_NVPAIR \ 191 "[(@" PCMK_XA_NAME "='" PCMK_STONITH_PROVIDES "'" \ 192 "or @" PCMK_XA_NAME "='" PCMK_META_REQUIRES "') " \ 193 "and @" PCMK_XA_VALUE "='" PCMK_VALUE_UNFENCING "']" 196 #define XPATH_ENABLE_UNFENCING \ 197 "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RESOURCES \ 198 "//" PCMK_XE_META_ATTRIBUTES "/" XPATH_UNFENCING_NVPAIR \ 199 "|/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RSC_DEFAULTS \ 200 "/" PCMK_XE_META_ATTRIBUTES "/" XPATH_UNFENCING_NVPAIR 205 xmlXPathObjectPtr
result = NULL;
219 const char *value = NULL;
241 crm_info(
"Startup probes: disabled (dangerous)");
246 crm_info(
"Watchdog-based self-fencing will be performed via SBD if " 261 crm_debug(
"Default fencing action timeout: %s",
267 crm_debug(
"STONITH of failed nodes is enabled");
269 crm_debug(
"STONITH of failed nodes is disabled");
279 crm_debug(
"Concurrent fencing is enabled");
281 crm_debug(
"Concurrent fencing is disabled");
288 crm_trace(
"Priority fencing delay is %s",
294 crm_debug(
"Stop all active resources: %s",
300 crm_debug(
"Cluster is symmetric" " - resources can run anywhere by default");
326 " to 'stop': cluster has never had quorum");
331 " to 'stop' because fencing is disabled");
341 crm_debug(
"On loss of quorum: Freeze resources");
344 crm_debug(
"On loss of quorum: Stop ALL resources");
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",
468 if (new_node == NULL) {
477 if ((new_node->
assign == NULL) || (new_node->
details == NULL)
478 || (new_node->
priv == NULL)) {
481 free(new_node->
priv);
502 if (pcmk__is_pacemaker_remote_node(new_node)) {
517 xmlNode *attr_set = NULL;
518 xmlNode *attr = NULL;
520 const char *container_id = pcmk__xe_id(xml_obj);
521 const char *remote_name = NULL;
522 const char *remote_server = NULL;
523 const char *remote_port = NULL;
524 const char *connect_timeout =
"60s";
525 const char *remote_allow_migrate=NULL;
526 const char *is_managed = NULL;
547 remote_server = value;
553 connect_timeout = value;
556 remote_allow_migrate = value;
564 if (remote_name == NULL) {
573 remote_allow_migrate, is_managed,
574 connect_timeout, remote_server, remote_port);
603 xmlNode *xml_obj = NULL;
605 const char *
id = NULL;
606 const char *
uname = NULL;
607 const char *
type = NULL;
624 "> entry in configuration without id");
630 "because '%s' is not a valid score: %s",
631 pcmk__s(
uname,
"without name"),
637 if (new_node == NULL) {
641 handle_startup_fencing(
scheduler, new_node);
643 add_node_attrs(xml_obj, new_node, FALSE,
scheduler);
655 const char *launcher_id = NULL;
658 g_list_foreach(rsc->
priv->
children, (GFunc) unpack_launcher,
664 if ((launcher_id != NULL)
669 if (launcher != NULL) {
674 rsc->
id, launcher_id);
677 rsc->
id, launcher_id);
685 xmlNode *xml_obj = NULL;
693 const char *new_node_id = NULL;
699 new_node_id = pcmk__xe_id(xml_obj);
705 crm_trace(
"Found remote node %s defined by resource %s",
706 new_node_id, pcmk__xe_id(xml_obj));
721 new_node_id = expand_remote_rsc_meta(xml_obj, xml_resources,
725 crm_trace(
"Found guest node %s in resource %s",
726 new_node_id, pcmk__xe_id(xml_obj));
737 xmlNode *xml_obj2 = NULL;
739 xml_obj2 != NULL; xml_obj2 =
pcmk__xe_next(xml_obj2, NULL)) {
741 new_node_id = expand_remote_rsc_meta(xml_obj2, xml_resources,
746 crm_trace(
"Found guest node %s in resource %s inside group %s",
747 new_node_id, pcmk__xe_id(xml_obj2),
748 pcmk__xe_id(xml_obj));
783 pcmk__rsc_trace(new_rsc,
"Linking remote connection resource %s to %s",
784 new_rsc->
id, pcmk__node_name(remote_node));
791 handle_startup_fencing(
scheduler, remote_node);
817 xmlNode *xml_obj = NULL;
826 const char *
id = pcmk__xe_id(xml_obj);
828 if (pcmk__str_empty(
id)) {
836 NULL, NULL) == FALSE) {
852 "because configuration is invalid",
858 gIter != NULL; gIter = gIter->next) {
874 pcmk__config_err(
"Resource start-up disabled since no STONITH resources have been defined");
877 pcmk__config_err(
"NOTE: Clusters with shared data need STONITH to ensure data integrity");
902 const char *
id = pcmk__xe_id(level);
905 if (pcmk__str_empty(
id)) {
927 xmlNode *xml_tag = NULL;
934 xmlNode *xml_obj_ref = NULL;
935 const char *tag_id = pcmk__xe_id(xml_tag);
937 if (tag_id == NULL) {
939 (
const char *) xml_tag->name);
948 const char *obj_ref = pcmk__xe_id(xml_obj_ref);
950 if (obj_ref == NULL) {
952 xml_obj_ref->name, tag_id);
973 unpack_ticket_state(xmlNode *xml_ticket,
void *userdata)
977 const char *ticket_id = NULL;
978 const char *granted = NULL;
979 const char *last_granted = NULL;
980 const char *standby = NULL;
981 xmlAttrPtr xIter = NULL;
985 ticket_id = pcmk__xe_id(xml_ticket);
986 if (pcmk__str_empty(ticket_id)) {
990 crm_trace(
"Processing ticket state for %s", ticket_id);
994 if (ticket == NULL) {
996 if (ticket == NULL) {
1001 for (xIter = xml_ticket->properties; xIter; xIter = xIter->next) {
1002 const char *prop_name = (
const char *)xIter->name;
1003 const char *prop_value = pcmk__xml_attr_value(xIter);
1017 crm_info(
"We do not have ticket '%s'", ticket->
id);
1022 long long last_granted_ll = 0LL;
1023 int rc =
pcmk__scan_ll(last_granted, &last_granted_ll, 0LL);
1027 " value '%s' in state for ticket %s: %s",
1028 last_granted_ll, last_granted, ticket->
id,
1038 crm_info(
"Granted ticket '%s' is in standby-mode", ticket->
id);
1044 crm_trace(
"Done with ticket state for %s", ticket_id);
1050 unpack_handle_remote_attrs(
pcmk_node_t *this_node,
const xmlNode *state,
1053 const char *discovery = NULL;
1054 const xmlNode *attrs = NULL;
1062 if ((this_node == NULL) || !pcmk__is_pacemaker_remote_node(this_node)) {
1065 crm_trace(
"Processing Pacemaker Remote node %s",
1066 pcmk__node_name(this_node));
1083 add_node_attrs(attrs, this_node, TRUE,
scheduler);
1086 crm_info(
"%s is shutting down", pcmk__node_name(this_node));
1092 crm_info(
"%s is in standby mode", pcmk__node_name(this_node));
1099 crm_info(
"%s is in maintenance mode", pcmk__node_name(this_node));
1106 if ((discovery != NULL) && !
crm_is_true(discovery)) {
1110 " node attribute is deprecated and will be removed" 1111 " (and behave as 'true') in a future release.");
1113 if (pcmk__is_remote_node(this_node)
1117 " attribute on Pacemaker Remote node %s" 1118 " because fencing is disabled",
1119 pcmk__node_name(this_node));
1126 crm_info(
"%s has resource discovery disabled",
1127 pcmk__node_name(this_node));
1142 unpack_transient_attributes(
const xmlNode *state,
pcmk_node_t *node,
1145 const char *discovery = NULL;
1150 add_node_attrs(attrs, node, TRUE,
scheduler);
1154 crm_info(
"%s is in standby mode", pcmk__node_name(node));
1160 crm_info(
"%s is in maintenance mode", pcmk__node_name(node));
1167 if ((discovery != NULL) && !
crm_is_true(discovery)) {
1170 " attribute for %s because disabling resource" 1171 " discovery is not allowed for cluster nodes",
1172 pcmk__node_name(node));
1191 const char *
id = NULL;
1192 const char *
uname = NULL;
1204 if (
uname == NULL) {
1217 if (this_node == NULL) {
1218 crm_notice(
"Ignoring recorded state for removed node with name %s and " 1223 if (pcmk__is_pacemaker_remote_node(this_node)) {
1224 int remote_fenced = 0;
1233 if (remote_fenced) {
1241 unpack_transient_attributes(state, this_node,
scheduler);
1249 crm_trace(
"Determining online status of cluster node %s (id %s)",
1250 pcmk__node_name(this_node),
id);
1251 determine_online_status(state, this_node,
scheduler);
1283 unpack_node_history(
const xmlNode *status,
bool fence,
1294 const char *
id = pcmk__xe_id(state);
1298 if ((
id == NULL) || (
uname == NULL)) {
1300 crm_trace(
"Not unpacking resource history from malformed " 1306 if (this_node == NULL) {
1308 crm_trace(
"Not unpacking resource history for node %s because " 1309 "no longer in configuration",
id);
1314 crm_trace(
"Not unpacking resource history for node %s because " 1315 "already unpacked",
id);
1322 }
else if (pcmk__is_guest_or_bundle_node(this_node)) {
1332 crm_trace(
"Not unpacking resource history for guest node %s " 1333 "because launcher and connection are not known to " 1338 }
else if (pcmk__is_remote_node(this_node)) {
1349 crm_trace(
"Not unpacking resource history for remote node %s " 1350 "because connection is not known to be up",
id);
1363 crm_trace(
"Not unpacking resource history for offline " 1364 "cluster node %s",
id);
1368 if (pcmk__is_pacemaker_remote_node(this_node)) {
1369 determine_remote_online_status(
scheduler, this_node);
1370 unpack_handle_remote_attrs(this_node, state,
scheduler);
1373 crm_trace(
"Unpacking resource history for %snode %s",
1374 (fence?
"unseen " :
""),
id);
1377 unpack_node_lrm(this_node, state,
scheduler);
1390 xmlNode *state = NULL;
1411 while (unpack_node_history(status, FALSE,
scheduler) == EAGAIN) {
1412 crm_trace(
"Another pass through node resource histories is needed");
1416 unpack_node_history(status,
1426 item != NULL; item = item->next) {
1429 pcmk_node_t *node = pcmk__current_node(container);
1443 for (GList *gIter =
scheduler->
nodes; gIter != NULL; gIter = gIter->next) {
1446 if (!pcmk__is_pacemaker_remote_node(this_node)) {
1455 determine_remote_online_status(
scheduler, this_node);
1479 if (member_time == NULL) {
1495 long long when_member = 0LL;
1498 0LL) !=
pcmk_rc_ok) || (when_member < 0LL)) {
1517 unpack_node_online(
const xmlNode *node_state)
1530 long long when_online = 0LL;
1533 || (when_online < 0)) {
1552 unpack_node_terminate(
const pcmk_node_t *node,
const xmlNode *node_state)
1554 long long value = 0LL;
1562 return (value_i != 0);
1569 "node attribute for %s: %s",
1576 const xmlNode *node_state,
1579 gboolean online = FALSE;
1582 long long when_member = unpack_node_member(node_state,
scheduler);
1583 long long when_online = unpack_node_online(node_state);
1585 if (when_member <= 0) {
1586 crm_trace(
"Node %s is %sdown", pcmk__node_name(this_node),
1587 ((when_member < 0)?
"presumed " :
""));
1589 }
else if (when_online > 0) {
1593 crm_debug(
"Node %s is not ready to run resources: %s",
1594 pcmk__node_name(this_node), join);
1599 crm_trace(
"Node %s controller is down: " 1600 "member@%lld online@%lld join=%s expected=%s",
1601 pcmk__node_name(this_node), when_member, when_online,
1602 pcmk__s(join,
"<null>"), pcmk__s(exp_state,
"<null>"));
1607 crm_info(
"Node %s member@%lld online@%lld join=%s expected=%s",
1608 pcmk__node_name(this_node), when_member, when_online,
1609 pcmk__s(join,
"<null>"), pcmk__s(exp_state,
"<null>"));
1629 long long when_member,
long long when_online)
1632 && (when_member > 0) && (when_online <= 0)) {
1650 const xmlNode *node_state,
1653 bool termination_requested = unpack_node_terminate(this_node, node_state);
1656 long long when_member = unpack_node_member(node_state,
scheduler);
1657 long long when_online = unpack_node_online(node_state);
1677 crm_trace(
"Node %s member@%lld online@%lld join=%s expected=%s%s",
1678 pcmk__node_name(this_node), when_member, when_online,
1679 pcmk__s(join,
"<null>"), pcmk__s(exp_state,
"<null>"),
1680 (termination_requested?
" (termination requested)" :
""));
1683 crm_debug(
"%s is shutting down", pcmk__node_name(this_node));
1686 return (when_online > 0);
1689 if (when_member < 0) {
1691 "peer has not been seen by the cluster", FALSE);
1697 "peer failed Pacemaker membership criteria", FALSE);
1699 }
else if (termination_requested) {
1700 if ((when_member <= 0) && (when_online <= 0)
1702 crm_info(
"%s was fenced as requested", pcmk__node_name(this_node));
1710 if (pending_too_long(
scheduler, this_node, when_member, when_online)) {
1712 "peer pending timed out on joining the process group",
1715 }
else if ((when_member > 0) || (when_online > 0)) {
1716 crm_info(
"- %s is not ready to run resources",
1717 pcmk__node_name(this_node));
1722 crm_trace(
"%s is down or still coming up",
1723 pcmk__node_name(this_node));
1726 }
else if (when_member <= 0) {
1729 "peer is no longer part of the cluster", TRUE);
1731 }
else if (when_online <= 0) {
1733 "peer process is no longer available", FALSE);
1738 crm_info(
"%s is active", pcmk__node_name(this_node));
1742 crm_info(
"%s is not ready to run resources",
1743 pcmk__node_name(this_node));
1752 return (when_member > 0);
1762 const char *node_type =
"Remote";
1768 crm_trace(
"Pacemaker Remote node %s is considered OFFLINE because " 1769 "its connection resource has been removed from the CIB",
1776 if (launcher != NULL) {
1777 node_type =
"Guest";
1792 crm_trace(
"%s node %s shutting down because connection resource is stopping",
1793 node_type, this_node->
priv->
id);
1799 crm_trace(
"Guest node %s UNCLEAN because guest resource failed",
1805 crm_trace(
"%s node %s OFFLINE because connection resource failed",
1806 node_type, this_node->
priv->
id);
1810 || ((launcher != NULL)
1813 crm_trace(
"%s node %s OFFLINE because its resource is stopped",
1814 node_type, this_node->
priv->
id);
1818 }
else if (
host && (
host->details->online == FALSE)
1819 &&
host->details->unclean) {
1820 crm_trace(
"Guest node %s UNCLEAN because host is unclean",
1827 node_type, this_node->
priv->
id,
1833 determine_online_status(
const xmlNode *node_state,
pcmk_node_t *this_node,
1836 gboolean online = FALSE;
1851 online = determine_online_status_no_fencing(
scheduler, node_state,
1855 online = determine_online_status_fencing(
scheduler, node_state,
1874 pcmk__node_name(this_node));
1877 crm_trace(
"%s is offline", pcmk__node_name(this_node));
1880 crm_info(
"%s is shutting down", pcmk__node_name(this_node));
1883 crm_info(
"%s is pending", pcmk__node_name(this_node));
1886 crm_info(
"%s is in standby", pcmk__node_name(this_node));
1889 crm_info(
"%s is in maintenance", pcmk__node_name(this_node));
1892 crm_info(
"%s is online", pcmk__node_name(this_node));
1907 if (!pcmk__str_empty(
id)) {
1908 const char *end =
id + strlen(
id) - 1;
1910 for (
const char *s = end; s >
id; --s) {
1924 return (s == end)? s : (s - 1);
1948 char *basename = NULL;
1951 basename = strndup(last_rsc_id, end - last_rsc_id + 1);
1970 size_t base_name_len = end - last_rsc_id + 1;
1975 memcpy(zero, last_rsc_id, base_name_len);
1976 zero[base_name_len] =
':';
1977 zero[base_name_len + 1] =
'0';
1982 create_fake_resource(
const char *rsc_id,
const xmlNode *rsc_entry,
1999 crm_debug(
"Detected orphaned remote node %s", rsc_id);
2008 crm_trace(
"Setting node %s as shutting down due to orphaned connection resource", rsc_id);
2015 crm_trace(
"Launched resource %s was removed from the configuration",
2047 top->
id,
parent->id, rsc_id, pcmk__node_name(node));
2070 GList *rIter = NULL;
2073 gboolean skip_inactive = FALSE;
2079 rsc_id, pcmk__node_name(node),
parent->id);
2081 for (rIter =
parent->priv->children;
2082 (rIter != NULL) && (rsc == NULL); rIter = rIter->next) {
2084 GList *locations = NULL;
2111 if (pcmk__same_node((
pcmk_node_t *) locations->data, node)) {
2119 rsc =
parent->priv->fns->find_rsc(child, rsc_id, NULL,
2130 crm_notice(
"Active (now-)anonymous clone %s has " 2131 "multiple (orphan) instance histories on %s",
2132 parent->id, pcmk__node_name(node));
2133 skip_inactive = TRUE;
2140 g_list_free(locations);
2144 if (!skip_inactive && !inactive_instance
2148 parent->priv->fns->find_rsc(child, rsc_id, NULL,
2154 if (inactive_instance != NULL) {
2158 if ((pending_node != NULL)
2159 && !pcmk__same_node(pending_node, node)) {
2160 inactive_instance = NULL;
2167 if ((rsc == NULL) && !skip_inactive && (inactive_instance != NULL)) {
2169 inactive_instance->
id);
2170 rsc = inactive_instance;
2188 && !pcmk__is_guest_or_bundle_node(node)
2225 crm_trace(
"%s is not known as %s either (orphan)",
2231 crm_trace(
"Resource history for %s is orphaned " 2232 "because it is no longer primitive", rsc_id);
2239 if (pcmk__is_anonymous_clone(
parent)) {
2241 if (pcmk__is_bundled(
parent)) {
2257 rsc_id, pcmk__node_name(node), rsc->
id,
2264 process_orphan_resource(
const xmlNode *rsc_entry,
const pcmk_node_t *node,
2270 crm_debug(
"Detected orphan resource %s on %s",
2271 rsc_id, pcmk__node_name(node));
2272 rsc = create_fake_resource(rsc_id, rsc_entry,
scheduler);
2294 char *reason = NULL;
2297 bool known_active =
false;
2312 node->
priv->
id) == NULL) {
2318 pcmk__node_name(n));
2320 (gpointer) n->
priv->
id, n);
2333 gboolean should_fence = FALSE;
2342 if (pcmk__is_guest_or_bundle_node(node)) {
2344 should_fence = TRUE;
2347 if (pcmk__is_remote_node(node)
2360 " revoked if remote connection can " 2361 "be re-established elsewhere)",
2364 should_fence = TRUE;
2368 if (reason == NULL) {
2377 save_on_fail = on_fail;
2423 "__action_migration_auto__",
scheduler);
2441 if ((rsc->
priv->
launcher != NULL) && pcmk__is_bundled(rsc)) {
2452 }
else if (known_active) {
2464 if (pcmk__is_remote_node(tmpnode)
2471 "remote connection is unrecoverable", FALSE);
2493 if (pcmk_all_flags_set(rsc->
flags,
2504 crm_notice(
"Removed resource %s is active on %s and will be " 2505 "stopped when possible",
2506 rsc->
id, pcmk__node_name(node));
2508 crm_notice(
"Removed resource %s must be stopped manually on %s " 2510 " is set to false", rsc->
id, pcmk__node_name(node));
2542 GList *gIter = possible_matches;
2544 for (; gIter != NULL; gIter = gIter->next) {
2550 g_list_free(possible_matches);
2568 int start_index,
int stop_index,
2572 const char *task = NULL;
2573 const char *status = NULL;
2574 GList *gIter = sorted_op_list;
2578 rsc->
id, start_index, stop_index);
2580 for (; gIter != NULL; gIter = gIter->next) {
2581 xmlNode *rsc_op = (xmlNode *) gIter->data;
2583 guint interval_ms = 0;
2585 const char *
id = pcmk__xe_id(rsc_op);
2591 rsc->
id, pcmk__node_name(node));
2595 }
else if (start_index < stop_index && counter <= stop_index) {
2597 id, pcmk__node_name(node));
2600 }
else if (counter < start_index) {
2602 id, pcmk__node_name(node), counter);
2607 if (interval_ms == 0) {
2609 id, pcmk__node_name(node));
2616 id, pcmk__node_name(node));
2622 pcmk__rsc_trace(rsc,
"Creating %s on %s", key, pcmk__node_name(node));
2632 int implied_monitor_start = -1;
2633 int implied_clone_start = -1;
2634 const char *task = NULL;
2635 const char *status = NULL;
2640 for (
const GList *iter = sorted_op_list; iter != NULL; iter = iter->next) {
2641 const xmlNode *rsc_op = (
const xmlNode *) iter->data;
2650 *stop_index = counter;
2654 *start_index = counter;
2656 }
else if ((implied_monitor_start <= *stop_index)
2662 implied_monitor_start = counter;
2666 implied_clone_start = counter;
2670 if (*start_index == -1) {
2671 if (implied_clone_start != -1) {
2672 *start_index = implied_clone_start;
2673 }
else if (implied_monitor_start != -1) {
2674 *start_index = implied_monitor_start;
2684 time_t lock_time = 0;
2687 &lock_time) ==
pcmk_ok) && (lock_time != 0)) {
2693 rsc->
id, pcmk__node_name(node));
2713 unpack_lrm_resource(
pcmk_node_t *node,
const xmlNode *lrm_resource,
2716 GList *gIter = NULL;
2717 int stop_index = -1;
2718 int start_index = -1;
2721 const char *rsc_id = pcmk__xe_id(lrm_resource);
2724 GList *op_list = NULL;
2725 GList *sorted_op_list = NULL;
2727 xmlNode *rsc_op = NULL;
2728 xmlNode *last_failure = NULL;
2733 if (rsc_id == NULL) {
2740 rsc_id, pcmk__node_name(node));
2749 op_list = g_list_prepend(op_list, rsc_op);
2753 if (op_list == NULL) {
2760 rsc = unpack_find_resource(
scheduler, node, rsc_id);
2762 if (op_list == NULL) {
2766 rsc = process_orphan_resource(lrm_resource, node,
scheduler);
2773 unpack_shutdown_lock(lrm_resource, rsc, node,
scheduler);
2781 for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
2782 xmlNode *rsc_op = (xmlNode *) gIter->data;
2784 unpack_rsc_op(rsc, node, rsc_op, &last_failure, &on_fail);
2789 process_recurring(node, rsc, start_index, stop_index, sorted_op_list,
2793 g_list_free(sorted_op_list);
2795 process_rsc_state(rsc, node, on_fail);
2799 || (req_role < rsc->priv->next_role)) {
2805 "%s: Not overwriting calculated next role %s" 2806 " with requested next role %s",
2820 handle_removed_launched_resources(
const xmlNode *lrm_rsc_list,
2832 const char *launcher_id = NULL;
2836 if ((launcher_id == NULL) || (rsc_id == NULL)) {
2841 if (launcher == NULL) {
2852 rsc->
id, launcher_id);
2868 unpack_node_lrm(
pcmk_node_t *node,
const xmlNode *xml,
2871 bool found_removed_launched_resource =
false;
2894 found_removed_launched_resource =
true;
2901 if (found_removed_launched_resource) {
2902 handle_removed_launched_resources(xml,
scheduler);
2919 set_node_score(gpointer key, gpointer value, gpointer user_data)
2922 int *score = user_data;
2927 #define XPATH_NODE_STATE "/" PCMK_XE_CIB "/" PCMK_XE_STATUS \ 2928 "/" PCMK__XE_NODE_STATE 2929 #define SUB_XPATH_LRM_RESOURCE "/" PCMK__XE_LRM \ 2930 "/" PCMK__XE_LRM_RESOURCES \ 2931 "/" PCMK__XE_LRM_RESOURCE 2932 #define SUB_XPATH_LRM_RSC_OP "/" PCMK__XE_LRM_RSC_OP 2935 find_lrm_op(
const char *resource,
const char *op,
const char *node,
const char *source,
2938 GString *xpath = NULL;
2939 xmlNode *xml = NULL;
2941 CRM_CHECK((resource != NULL) && (op != NULL) && (node != NULL),
2944 xpath = g_string_sized_new(256);
2957 }
else if ((source != NULL)
2963 g_string_append_c(xpath,
']');
2968 g_string_free(xpath, TRUE);
2970 if (xml && target_rc >= 0) {
2984 find_lrm_resource(
const char *rsc_id,
const char *node_name,
2987 GString *xpath = NULL;
2988 xmlNode *xml = NULL;
2990 CRM_CHECK((rsc_id != NULL) && (node_name != NULL),
return NULL);
2992 xpath = g_string_sized_new(256);
3001 g_string_free(xpath, TRUE);
3018 xmlXPathObjectPtr search;
3028 result = (numXpathResults(search) == 0);
3047 monitor_not_running_after(
const char *rsc_id,
const char *node_name,
3072 non_monitor_after(
const char *rsc_id,
const char *node_name,
3075 xmlNode *lrm_resource = NULL;
3077 lrm_resource = find_lrm_resource(rsc_id, node_name,
scheduler);
3078 if (lrm_resource == NULL) {
3086 const char * task = NULL;
3119 newer_state_after_migrate(
const char *rsc_id,
const char *node_name,
3120 const xmlNode *migrate_to,
3121 const xmlNode *migrate_from,
3124 const xmlNode *xml_op = (migrate_from != NULL)? migrate_from : migrate_to;
3130 if ((xml_op != migrate_to) && (migrate_to != NULL)
3133 xml_op = migrate_to;
3140 return non_monitor_after(rsc_id, node_name, xml_op,
scheduler)
3141 || monitor_not_running_after(rsc_id, node_name, xml_op,
scheduler);
3157 get_migration_node_names(
const xmlNode *entry,
const pcmk_node_t *source_node,
3159 const char **source_name,
const char **target_name)
3163 if ((*source_name == NULL) || (*target_name == NULL)) {
3170 if ((source_node != NULL)
3171 && !pcmk__str_eq(*source_name, source_node->
priv->
name,
3175 pcmk__xe_id(entry), *source_name,
3176 pcmk__node_name(source_node));
3180 if ((target_node != NULL)
3181 && !pcmk__str_eq(*target_name, target_node->
priv->
name,
3185 pcmk__xe_id(entry), *target_name,
3186 pcmk__node_name(target_node));
3209 rsc->
id, pcmk__node_name(node));
3223 unpack_migrate_to_success(
struct action_history *history)
3259 xmlNode *migrate_from = NULL;
3260 const char *source = NULL;
3261 const char *
target = NULL;
3262 bool source_newer_op =
false;
3263 bool target_newer_state =
false;
3264 bool active_on_target =
false;
3268 if (get_migration_node_names(history->xml, history->node, NULL, &source,
3274 source_newer_op = non_monitor_after(history->rsc->id, source, history->xml,
3280 if (migrate_from != NULL) {
3281 if (source_newer_op) {
3295 target_newer_state = newer_state_after_migrate(history->rsc->id,
target,
3296 history->xml, migrate_from,
3298 if (source_newer_op && target_newer_state) {
3307 add_dangling_migration(history->rsc, history->node);
3317 active_on_target = !target_newer_state && (target_node != NULL)
3321 if (active_on_target) {
3339 && unknown_on_node(history->rsc,
target)) {
3343 if (active_on_target) {
3347 if ((source_node != NULL) && source_node->
details->
online) {
3354 history->rsc->priv->partial_migration_target = target_node;
3355 history->rsc->priv->partial_migration_source = source_node;
3358 }
else if (!source_newer_op) {
3373 unpack_migrate_to_failure(
struct action_history *history)
3375 xmlNode *target_migrate_from = NULL;
3376 const char *source = NULL;
3377 const char *
target = NULL;
3381 if (get_migration_node_names(history->xml, history->node, NULL, &source,
3392 target_migrate_from = find_lrm_op(history->rsc->id,
3401 !unknown_on_node(history->rsc,
target)
3405 && !newer_state_after_migrate(history->rsc->id,
target, history->xml,
3417 }
else if (!non_monitor_after(history->rsc->id, source, history->xml,
3425 history->rsc->priv->dangling_migration_sources =
3426 g_list_prepend(history->rsc->priv->dangling_migration_sources,
3427 (gpointer) history->node);
3438 unpack_migrate_from_failure(
struct action_history *history)
3440 xmlNode *source_migrate_to = NULL;
3441 const char *source = NULL;
3442 const char *
target = NULL;
3446 if (get_migration_node_names(history->xml, NULL, history->node, &source,
3465 !unknown_on_node(history->rsc, source)
3469 && !newer_state_after_migrate(history->rsc->id, source,
3470 source_migrate_to, history->xml,
3490 record_failed_op(
struct action_history *history)
3494 if (!(history->node->details->online)) {
3499 xIter != NULL; xIter = xIter->next) {
3501 const char *key = pcmk__xe_history_key(xIter);
3505 && pcmk__str_eq(
uname, history->node->priv->name,
3507 crm_trace(
"Skipping duplicate entry %s on %s",
3508 history->key, pcmk__node_name(history->node));
3513 crm_trace(
"Adding entry for %s on %s to failed action list",
3514 history->key, pcmk__node_name(history->node));
3521 last_change_str(
const xmlNode *xml_op)
3529 const char *p = strchr(when_s,
' ');
3532 if ((p != NULL) && (*(++p) !=
'\0')) {
3560 if (pcmk__is_anonymous_clone(
parent)) {
3570 crm_notice(
"%s will not be started under current conditions", rsc->
id);
3587 unpack_failure_handling(
struct action_history *history,
3592 history->interval_ms,
true);
3596 history->interval_ms, config);
3601 history->interval_ms, on_fail_str);
3604 g_hash_table_destroy(meta);
3618 unpack_rsc_op_failure(
struct action_history *history,
3620 enum rsc_role_e fail_role, xmlNode **last_failure,
3623 bool is_probe =
false;
3624 char *last_change_s = NULL;
3627 *last_failure = history->xml;
3630 last_change_s = last_change_str(history->xml);
3634 crm_trace(
"Unexpected result (%s%s%s) was recorded for " 3635 "%s of %s on %s at %s " QB_XS
" exit-status=%d id=%s",
3637 (pcmk__str_empty(history->exit_reason)?
"" :
": "),
3638 pcmk__s(history->exit_reason,
""),
3639 (is_probe?
"probe" : history->task), history->rsc->id,
3640 pcmk__node_name(history->node), last_change_s,
3641 history->exit_status, history->id);
3644 "Unexpected result (%s%s%s) was recorded for %s of " 3645 "%s on %s at %s " QB_XS
" exit-status=%d id=%s",
3647 (pcmk__str_empty(history->exit_reason)?
"" :
": "),
3648 pcmk__s(history->exit_reason,
""),
3649 (is_probe?
"probe" : history->task), history->rsc->id,
3650 pcmk__node_name(history->node), last_change_s,
3651 history->exit_status, history->id);
3653 if (is_probe && (history->exit_status !=
PCMK_OCF_OK)
3660 crm_notice(
"If it is not possible for %s to run on %s, see " 3663 history->rsc->id, pcmk__node_name(history->node));
3666 record_failed_op(history);
3669 free(last_change_s);
3671 if (*on_fail < config_on_fail) {
3675 *on_fail = config_on_fail;
3683 unpack_migrate_to_failure(history);
3686 unpack_migrate_from_failure(history);
3712 pcmk__rsc_trace(history->rsc,
"Leaving %s stopped", history->rsc->id);
3717 set_active(history->rsc);
3721 "Resource %s: role=%s unclean=%s on_fail=%s fail_role=%s",
3724 pcmk__btoa(history->node->details->unclean),
3729 && (history->rsc->priv->next_role < fail_role)) {
3734 ban_from_all_nodes(history->rsc);
3748 block_if_unrecoverable(
struct action_history *history)
3750 char *last_change_s = NULL;
3755 if (
pe_can_fence(history->node->priv->scheduler, history->node)) {
3759 last_change_s = last_change_str(history->xml);
3761 "No further recovery can be attempted for %s " 3762 "because %s on %s failed (%s%s%s) at %s " 3763 QB_XS
" rc=%d id=%s",
3764 history->rsc->id, history->task,
3765 pcmk__node_name(history->node),
3767 (pcmk__str_empty(history->exit_reason)?
"" :
": "),
3768 pcmk__s(history->exit_reason,
""),
3769 last_change_s, history->exit_status, history->id);
3771 free(last_change_s);
3787 remap_because(
struct action_history *history,
const char **why,
int value,
3790 if (history->execution_status != value) {
3791 history->execution_status = value;
3819 remap_operation(
struct action_history *history,
3822 bool is_probe =
false;
3823 int orig_exit_status = history->exit_status;
3824 int orig_exec_status = history->execution_status;
3825 const char *why = NULL;
3826 const char *task = history->task;
3830 if (history->exit_status != orig_exit_status) {
3831 why =
"degraded result";
3832 if (!expired && (!history->node->details->shutdown
3833 || history->node->details->online)) {
3834 record_failed_op(history);
3838 if (!pcmk__is_bundled(history->rsc)
3844 why =
"equivalent probe result";
3852 switch (history->execution_status) {
3861 "node-fatal error");
3873 if (history->expected_exit_status < 0) {
3883 "obsolete history format");
3885 "(corrupt or obsolete CIB?)",
3886 history->key, pcmk__node_name(history->node));
3888 }
else if (history->exit_status == history->expected_exit_status) {
3894 "%s on %s: expected %d (%s), got %d (%s%s%s)",
3895 history->key, pcmk__node_name(history->node),
3896 history->expected_exit_status,
3898 history->exit_status,
3900 (pcmk__str_empty(history->exit_reason)?
"" :
": "),
3901 pcmk__s(history->exit_reason,
""));
3904 switch (history->exit_status) {
3908 char *last_change_s = last_change_str(history->xml);
3912 "Probe found %s active on %s at %s",
3913 history->rsc->id, pcmk__node_name(history->node),
3915 free(last_change_s);
3921 || (history->expected_exit_status == history->exit_status)
3938 && (history->exit_status != history->expected_exit_status)) {
3939 char *last_change_s = last_change_str(history->xml);
3943 "Probe found %s active and promoted on %s at %s",
3945 pcmk__node_name(history->node), last_change_s);
3946 free(last_change_s);
3949 || (history->exit_status == history->expected_exit_status)) {
3967 guint interval_ms = 0;
3971 if (interval_ms == 0) {
3973 block_if_unrecoverable(history);
3988 block_if_unrecoverable(history);
3995 char *last_change_s = last_change_str(history->xml);
3997 crm_info(
"Treating unknown exit status %d from %s of %s " 3998 "on %s at %s as failure",
3999 history->exit_status, task, history->rsc->id,
4000 pcmk__node_name(history->node), last_change_s);
4002 "unknown exit status");
4003 free(last_change_s);
4011 "Remapped %s result from [%s: %s] to [%s: %s] " 4013 history->key, pcmk_exec_status_str(orig_exec_status),
4015 pcmk_exec_status_str(history->execution_status),
4022 should_clear_for_param_change(
const xmlNode *xml_op,
const char *task,
4039 switch (digest_data->
rc) {
4041 crm_trace(
"Resource %s history entry %s on %s" 4042 " has no digest to compare",
4043 rsc->
id, pcmk__xe_history_key(xml_op),
4072 should_ignore_failure_timeout(
const pcmk_resource_t *rsc,
const char *task,
4073 guint interval_ms,
bool is_last_failure)
4098 && (interval_ms != 0)
4106 if (is_last_failure) {
4107 crm_info(
"Waiting to clear monitor failure for remote node %s" 4108 " until fencing has occurred", rsc->
id);
4135 check_operation_expiry(
struct action_history *history)
4137 bool expired =
false;
4138 bool is_last_failure =
pcmk__ends_with(history->id,
"_last_failure_0");
4139 time_t last_run = 0;
4140 int unexpired_fail_count = 0;
4141 const char *clear_reason = NULL;
4142 const guint expiration_sec =
4148 "Resource history entry %s on %s is not expired: " 4149 "Not Installed does not expire",
4150 history->id, pcmk__node_name(history->node));
4154 if ((expiration_sec > 0)
4163 time_t last_failure = 0;
4166 if ((now >= (last_run + expiration_sec))
4167 && !should_ignore_failure_timeout(history->rsc, history->task,
4168 history->interval_ms,
4180 crm_trace(
"%s@%lld is %sexpired @%lld with unexpired_failures=%d " 4181 "expiration=%s last-failure@%lld",
4182 history->id, (
long long) last_run, (expired?
"" :
"not "),
4183 (
long long) now, unexpired_fail_count,
4185 (
long long) last_failure);
4186 last_failure += expiration_sec + 1;
4187 if (unexpired_fail_count && (now < last_failure)) {
4189 "fail count expiration");
4198 if (unexpired_fail_count == 0) {
4200 clear_reason =
"it expired";
4210 "Resource history entry %s on %s is not " 4211 "expired: Unexpired fail count",
4212 history->id, pcmk__node_name(history->node));
4216 }
else if (is_last_failure
4217 && (history->rsc->priv->remote_reconnect_ms > 0U)) {
4221 clear_reason =
"reconnect interval is set";
4225 if (!expired && is_last_failure
4226 && should_clear_for_param_change(history->xml, history->task,
4227 history->rsc, history->node)) {
4228 clear_reason =
"resource parameters have changed";
4231 if (clear_reason != NULL) {
4239 && (history->rsc->priv->remote_reconnect_ms > 0)) {
4248 crm_info(
"Clearing %s failure will wait until any scheduled " 4249 "fencing of %s completes",
4250 history->task, history->rsc->id);
4251 order_after_remote_fencing(clear_op, history->rsc,
scheduler);
4255 if (expired && (history->interval_ms == 0)
4257 switch (history->exit_status) {
4265 "Resource history entry %s on %s is not " 4266 "expired: Probe result",
4267 history->id, pcmk__node_name(history->node));
4299 update_resource_state(
struct action_history *history,
int exit_status,
4300 const xmlNode *last_failure,
4303 bool clear_past_failure =
false;
4306 || (!pcmk__is_bundled(history->rsc)
4311 clear_past_failure =
true;
4315 if ((last_failure != NULL)
4316 && pcmk__str_eq(history->key, pcmk__xe_history_key(last_failure),
4318 clear_past_failure =
true;
4321 set_active(history->rsc);
4326 clear_past_failure =
true;
4330 clear_past_failure =
true;
4335 clear_past_failure =
true;
4343 clear_past_failure =
true;
4350 clear_past_failure =
true;
4354 unpack_migrate_to_success(history);
4358 history->rsc->id, pcmk__node_name(history->node));
4359 set_active(history->rsc);
4362 if (!clear_past_failure) {
4372 "%s (%s) is not cleared by a completed %s",
4384 "clear past failures");
4388 if (history->rsc->priv->remote_reconnect_ms == 0U) {
4397 "clear past failures and reset remote");
4412 can_affect_state(
struct action_history *history)
4430 unpack_action_result(
struct action_history *history)
4433 &(history->execution_status)) < 0)
4439 history->id, history->rsc->id,
4440 pcmk__node_name(history->node),
4447 &(history->exit_status)) < 0)
4448 || (history->exit_status < 0) || (history->exit_status >
CRM_EX_MAX)) {
4451 history->id, history->rsc->id,
4452 pcmk__node_name(history->node),
4473 process_expired_result(
struct action_history *history,
int orig_exit_status)
4475 if (!pcmk__is_bundled(history->rsc)
4477 && (orig_exit_status != history->expected_exit_status)) {
4482 crm_trace(
"Ignoring resource history entry %s for probe of %s on %s: " 4483 "Masked failure expired",
4484 history->id, history->rsc->id,
4485 pcmk__node_name(history->node));
4489 if (history->exit_status == history->expected_exit_status) {
4493 if (history->interval_ms == 0) {
4494 crm_notice(
"Ignoring resource history entry %s for %s of %s on %s: " 4496 history->id, history->task, history->rsc->id,
4497 pcmk__node_name(history->node));
4501 if (history->node->details->online && !history->node->details->unclean) {
4512 crm_notice(
"Rescheduling %s-interval %s of %s on %s " 4513 "after failure expired",
4515 history->rsc->id, pcmk__node_name(history->node));
4517 "calculated-failure-timeout");
4534 mask_probe_failure(
struct action_history *history,
int orig_exit_status,
4535 const xmlNode *last_failure,
4544 crm_notice(
"Treating probe result '%s' for %s on %s as 'not running'",
4546 pcmk__node_name(history->node));
4547 update_resource_state(history, history->expected_exit_status, last_failure,
4551 record_failed_op(history);
4569 failure_is_newer(
const struct action_history *history,
4570 const xmlNode *last_failure)
4572 guint failure_interval_ms = 0U;
4573 long long failure_change = 0LL;
4574 long long this_change = 0LL;
4576 if (last_failure == NULL) {
4580 if (!pcmk__str_eq(history->task,
4587 &failure_interval_ms) !=
pcmk_ok)
4588 || (history->interval_ms != failure_interval_ms)) {
4597 || (failure_change < this_change)) {
4612 process_pending_action(
struct action_history *history,
4613 const xmlNode *last_failure)
4624 if (failure_is_newer(history, last_failure)) {
4630 set_active(history->rsc);
4636 && history->node->details->unclean) {
4640 const char *migrate_target = NULL;
4652 if (history->rsc->priv->pending_action != NULL) {
4666 history->rsc->private->pending_action = strdup(
"probe");
4667 history->rsc->private->pending_node = history->node;
4670 history->rsc->priv->pending_action = strdup(history->task);
4671 history->rsc->priv->pending_node = history->node;
4680 bool expired =
false;
4685 struct action_history history = {
4692 CRM_CHECK(rsc && node && xml_op,
return);
4694 history.id = pcmk__xe_id(xml_op);
4695 if (history.id == NULL) {
4697 "without ID", rsc->
id, pcmk__node_name(node));
4703 if (history.task == NULL) {
4706 history.id, rsc->
id, pcmk__node_name(node));
4710 if (!can_affect_state(&history)) {
4712 "Ignoring resource history entry %s for %s on %s " 4713 "with irrelevant action '%s'",
4714 history.id, rsc->
id, pcmk__node_name(node),
4719 if (unpack_action_result(&history) !=
pcmk_rc_ok) {
4724 history.key = pcmk__xe_history_key(xml_op);
4728 history.id, history.task, history.call_id,
4729 pcmk__node_name(node),
4730 pcmk_exec_status_str(history.execution_status),
4735 "%s is running on %s, which is unclean (further action " 4736 "depends on value of stop's on-fail attribute)",
4737 rsc->
id, pcmk__node_name(node));
4740 expired = check_operation_expiry(&history);
4741 old_rc = history.exit_status;
4743 remap_operation(&history, on_fail, expired);
4745 if (expired && (process_expired_result(&history, old_rc) ==
pcmk_rc_ok)) {
4750 mask_probe_failure(&history, old_rc, *last_failure, on_fail);
4758 switch (history.execution_status) {
4760 process_pending_action(&history, *last_failure);
4764 update_resource_state(&history, history.exit_status, *last_failure,
4769 unpack_failure_handling(&history, &failure_strategy, &fail_role);
4771 crm_warn(
"Cannot ignore failed %s of %s on %s: " 4772 "Resource agent doesn't exist " 4773 QB_XS
" status=%d rc=%d id=%s",
4774 history.task, rsc->
id, pcmk__node_name(node),
4775 history.execution_status, history.exit_status,
4784 unpack_rsc_op_failure(&history, failure_strategy, fail_role,
4785 last_failure, on_fail);
4789 if (pcmk__is_pacemaker_remote_node(node)
4815 unpack_failure_handling(&history, &failure_strategy, &fail_role);
4820 char *last_change_s = last_change_str(xml_op);
4822 crm_warn(
"Pretending failed %s (%s%s%s) of %s on %s at %s succeeded " 4825 (pcmk__str_empty(history.exit_reason)?
"" :
": "),
4826 pcmk__s(history.exit_reason,
""), rsc->
id,
4827 pcmk__node_name(node), last_change_s, history.id);
4828 free(last_change_s);
4830 update_resource_state(&history, history.expected_exit_status,
4831 *last_failure, on_fail);
4835 record_failed_op(&history);
4839 *on_fail = failure_strategy;
4843 unpack_rsc_op_failure(&history, failure_strategy, fail_role,
4844 last_failure, on_fail);
4847 uint8_t log_level = LOG_ERR;
4850 log_level = LOG_NOTICE;
4853 "Preventing %s from restarting on %s because " 4854 "of hard failure (%s%s%s) " QB_XS
" %s",
4855 parent->id, pcmk__node_name(node),
4857 (pcmk__str_empty(history.exit_reason)?
"" :
": "),
4858 pcmk__s(history.exit_reason,
""), history.id);
4864 "Preventing %s from restarting anywhere because " 4865 "of fatal failure (%s%s%s) " QB_XS
" %s",
4867 (pcmk__str_empty(history.exit_reason)?
"" :
": "),
4868 pcmk__s(history.exit_reason,
""), history.id);
4876 rsc->
id, pcmk__node_name(node), history.id,
4891 insert_attr(gpointer key, gpointer value, gpointer user_data)
4893 GHashTable *table = user_data;
4895 g_hash_table_insert(table, key, value);
4900 add_node_attrs(
const xmlNode *xml_obj,
pcmk_node_t *node,
bool overwrite,
4903 const char *cluster_name = NULL;
4946 g_hash_table_foreach_steal(unpacked, insert_attr, node->
priv->
attrs);
4947 g_hash_table_destroy(unpacked);
4967 }
else if (cluster_name) {
4976 extract_operations(
const char *node,
const char *rsc, xmlNode * rsc_entry, gboolean active_filter)
4979 int stop_index = -1;
4980 int start_index = -1;
4982 xmlNode *rsc_op = NULL;
4984 GList *gIter = NULL;
4985 GList *op_list = NULL;
4986 GList *sorted_op_list = NULL;
4990 sorted_op_list = NULL;
4998 op_list = g_list_prepend(op_list, rsc_op);
5001 if (op_list == NULL) {
5009 if (active_filter == FALSE) {
5010 return sorted_op_list;
5017 for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
5018 xmlNode *rsc_op = (xmlNode *) gIter->data;
5022 if (start_index < stop_index) {
5023 crm_trace(
"Skipping %s: not active", pcmk__xe_id(rsc_entry));
5026 }
else if (counter < start_index) {
5027 crm_trace(
"Skipping %s: old", pcmk__xe_id(rsc_op));
5030 op_list = g_list_append(op_list, rsc_op);
5033 g_list_free(sorted_op_list);
5041 GList *output = NULL;
5042 GList *intermediate = NULL;
5044 xmlNode *tmp = NULL;
5050 xmlNode *node_state = NULL;
5066 if(this_node == NULL) {
5070 }
else if (pcmk__is_pacemaker_remote_node(this_node)) {
5071 determine_remote_online_status(
scheduler, this_node);
5074 determine_online_status(node_state, this_node,
scheduler);
5083 xmlNode *lrm_rsc = NULL;
5102 intermediate = extract_operations(
uname, rsc_id, lrm_rsc, active_filter);
5103 output = g_list_concat(output, intermediate);
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
#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.
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
bool pe__shutdown_requested(const pcmk_node_t *node)
#define PCMK_XE_FENCING_TOPOLOGY
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
Service failed and possibly in promoted role.
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...)
#define pcmk__sched_err(scheduler, fmt...)
#define PCMK__XE_LRM_RESOURCES
No connection to executor.
gboolean unpack_nodes(xmlNode *xml_nodes, pcmk_scheduler_t *scheduler)
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_OPT_STONITH_ENABLED
void pcmk__free_idref(gpointer data)
#define PCMK__XE_TICKET_STATE
Service active and promoted.
bool pe__is_universal_clone(const pcmk_resource_t *rsc, const pcmk_scheduler_t *scheduler)
pcmk_resource_t * pe__find_bundle_replica(const pcmk_resource_t *bundle, const pcmk_node_t *node)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
#define stop_action(rsc, node, optional)
enum pcmk_ipc_server type
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
#define PCMK_OPT_CONCURRENT_FENCING
#define PCMK_XE_PRIMITIVE
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
#define pcmk__config_warn(fmt...)
#define pcmk__rsc_trace(rsc, fmt, args...)
pcmk__op_digest_t * rsc_action_digest_cmp(pcmk_resource_t *rsc, const xmlNode *xml_op, pcmk_node_t *node, pcmk_scheduler_t *scheduler)
Match only clones and their instances, by either clone or instance ID.
#define PCMK_XA_RESOURCE_DISCOVERY
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
pcmk_resource_t * pe_find_resource(GList *rsc_list, const char *id)
#define pcmk__rsc_info(rsc, fmt, args...)
#define PCMK_OPT_SHUTDOWN_LOCK
pcmk_resource_t * pe__create_clone_child(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler)
#define pcmk__set_rsc_flags(resource, flags_to_set)
gboolean get_target_role(const pcmk_resource_t *rsc, enum rsc_role_e *role)
#define pcmk__config_err(fmt...)
#define PCMK_ACTION_MONITOR
#define PCMK_XA_EXIT_REASON
#define PCMK_XA_NO_QUORUM_PANIC
#define set_config_flag(scheduler, option, flag)
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 pcmk__add_idref(GHashTable *table, const char *id, const char *referrer)
pcmk__scheduler_private_t * priv
#define PCMK_ACTION_MIGRATE_TO
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, uint32_t target)
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
#define SUB_XPATH_LRM_RSC_OP
GHashTable * ticket_constraints
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
#define PCMK_OPT_CLUSTER_NAME
Necessary CIB secrets are unavailable.
Stop all resources in partition.
#define PCMK__XA_OP_RESTART_DIGEST
#define CRM_LOG_ASSERT(expr)
Service promoted but more likely to fail soon.
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.
#define CRMD_JOINSTATE_NACK
#define CRM_ATTR_CLUSTER_NAME
const pcmk__rsc_methods_t * fns
Ensure crm_exit_t can hold this.
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 pcmk__validate_cluster_options(GHashTable *options)
const char * pcmk__cluster_option(GHashTable *options, const char *name)
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.
Action did not complete in time.
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
#define PCMK_NODE_ATTR_MAINTENANCE
#define PCMK_OPT_STOP_ORPHAN_ACTIONS
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)
Execution failed, do not retry on node.
bool pcmk__ends_with(const char *s, const char *match)
#define PCMK_META_REMOTE_CONNECT_TIMEOUT
#define PCMK_OPT_STONITH_ACTION
#define PCMK_XA_OPERATION
int pe__unpack_resource(xmlNode *xml_obj, pcmk_resource_t **rsc, pcmk_resource_t *parent, pcmk_scheduler_t *scheduler)
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
gboolean unpack_resources(const xmlNode *xml_resources, 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)
No fence device is configured for target.
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
#define PCMK_OPT_ENABLE_STARTUP_PROBES
#define PCMK_META_REMOTE_ALLOW_MIGRATE
enum pe_quorum_policy no_quorum_policy
#define PCMK_META_IS_MANAGED
pcmk_node_t * partial_migration_source
#define PCMK__XE_TRANSIENT_ATTRIBUTES
int pcmk__effective_rc(int rc)
#define PCMK__META_MIGRATE_TARGET
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
#define PCMK_META_REMOTE_ADDR
#define pcmk__rsc_debug(rsc, fmt, args...)
bool pcmk_xe_is_probe(const xmlNode *xml_op)
Check whether an action history entry represents a probe.
#define demote_action(rsc, node, optional)
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.
pcmk__node_private_t * priv
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)
#define PCMK_OPT_PLACEMENT_STRATEGY
#define PCMK_ACTION_DEMOTE
#define PCMK__XE_LRM_RESOURCE
#define PCMK__XA_TRANSITION_KEY
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
#define CRMD_JOINSTATE_DOWN
Maximum value for this enum.
#define crm_warn(fmt, args...)
void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why)
const char * crm_exit_str(crm_exit_t exit_code)
char * clone_zero(const char *last_rsc_id)
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
#define crm_debug(fmt, args...)
pcmk_scheduler_t * scheduler
Used only to initialize variables.
#define PCMK_OPT_STOP_ALL_RESOURCES
const char * pe_base_name_end(const char *id)
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
Parameter invalid (in local context)
#define PCMK_XE_UTILIZATION
Parameter invalid (inherently)
enum pcmk__rsc_variant variant
int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
#define pcmk__clear_node_flags(node, flags_to_clear)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define crm_trace(fmt, args...)
#define CRMD_JOINSTATE_MEMBER
#define do_crm_log(level, fmt, args...)
Log a message.
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
bool xml_contains_remote_node(xmlNode *xml)
#define PCMK_VALUE_MEMBER
Demote promotable resources and stop all others.
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
#define PCMK_OPT_MAINTENANCE_MODE
#define PCMK_META_REMOTE_NODE
bool pe__bundle_needs_remote_name(pcmk_resource_t *rsc)
#define PCMK_OPT_SHUTDOWN_LOCK_LIMIT
#define crm_log_xml_debug(xml, text)
#define PCMK_XE_CLUSTER_PROPERTY_SET
#define PCMK_ACTION_START
pcmk__resource_private_t * priv
#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.
#define PCMK_OPT_STARTUP_FENCING
#define PCMK_META_TARGET_ROLE
enum rsc_role_e next_role
pcmk_resource_t *(* find_rsc)(pcmk_resource_t *rsc, const char *search, const pcmk_node_t *node, int flags)
Action completed, result is known.
GHashTable * pe__node_list2table(const GList *list)
#define PCMK_NODE_ATTR_TERMINATE
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
Act as if partition still holds quorum.
GHashTable * digest_cache
Execution failed, do not retry anywhere.
#define PCMK_NODE_ATTR_STANDBY
pcmk_scheduler_t * scheduler
void pe__free_digests(gpointer ptr)
const char * fence_action
Fence all nodes in partition.
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
#define PCMK_OPT_NODE_PENDING_TIMEOUT
Dependencies not available locally.
bool pcmk_is_probe(const char *task, guint interval)
Check whether an action name and interval represent a probe.
#define PCMK_OPT_START_FAILURE_IS_FATAL
#define PCMK__NODE_ATTR_RESOURCE_DISCOVERY_ENABLED
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
const pcmk_node_t * pending_node
#define pcmk__str_copy(str)
const pcmk_node_t * lock_node
#define pcmk__warn_once(wo_flag, fmt...)
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
void pe__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, const char *reason)
gboolean unpack_config(xmlNode *config, pcmk_scheduler_t *scheduler)
bool pcmk_xe_mask_probe_failure(const xmlNode *xml_op)
Check whether an action history entry represents a maskable probe.
#define PCMK_VALUE_FENCE_LEGACY
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)
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.
#define PCMK_XE_META_ATTRIBUTES
GHashTable * allowed_nodes
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.
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
#define pcmk__assert(expr)
void int pcmk__xe_get_score(const xmlNode *xml, const char *name, int *score, int default_score)
#define pcmk__sched_warn(scheduler, fmt...)
#define PCMK_VALUE_ONLINE
Requested action not implemented.
#define PCMK_OPT_STONITH_TIMEOUT
#define pcmk__set_node_flags(node, flags_to_set)
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
int pe__target_rc_from_xml(const xmlNode *xml_op)
xmlNode * pcmk__find_action_config(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, bool include_disabled)
const char * pcmk__on_fail_text(enum pcmk__on_fail on_fail)
Service active but more likely to fail soon.
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
#define PCMK_META_INTERVAL
#define PCMK_XA_LAST_RC_CHANGE
Agent does not implement requested action.
#define PCMK_XE_FENCING_LEVEL
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
pcmk__action_result_t result
#define PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS
gboolean unpack_tags(xmlNode *xml_tags, pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL gint pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
gboolean unpack_remote_nodes(xmlNode *xml_resources, pcmk_scheduler_t *scheduler)
#define PCMK_OPT_SYMMETRIC_CLUSTER
void pe__unpack_node_health_scores(pcmk_scheduler_t *scheduler)
guint remote_reconnect_ms
pcmk_scheduler_t * scheduler
#define PCMK__XE_LRM_RSC_OP
enum pcmk__node_variant variant
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
#define PCMK_META_REMOTE_PORT
#define pcmk__clear_ticket_flags(ticket, flags_to_clear)
enum rsc_role_e orig_role
pcmk_resource_t * launcher
#define pcmk__set_ticket_flags(ticket, flags_to_set)
const char * placement_strategy
void pcmk__validate_fencing_topology(const xmlNode *xml)
#define PCMK_OPT_STOP_ORPHAN_RESOURCES
#define PCMK_ACTION_MIGRATE_FROM
const char * pcmk__node_attr(const pcmk_node_t *node, const char *name, const char *target, enum pcmk__rsc_node node_type)
#define PCMK__XA_OP_STATUS
pcmk_node_t * pe_create_node(const char *id, const char *uname, const char *type, int score, pcmk_scheduler_t *scheduler)
#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.
guint pcmk__timeout_ms2s(guint timeout_ms)
#define crm_log_xml_info(xml, text)
#define PCMK_ACTION_PROMOTE
#define PCMK_OPT_NO_QUORUM_POLICY
#define PCMK_OPT_HAVE_WATCHDOG
gboolean crm_is_true(const char *s)
#define CRMD_JOINSTATE_PENDING
#define PCMK__XE_NODE_STATE
#define PCMK_XA_LAST_GRANTED
CRM_TRACE_INIT_DATA(pe_status)
Agent or dependency not available locally.
void pe__clear_resource_history(pcmk_resource_t *rsc, const pcmk_node_t *node)
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)
void calculate_active_ops(const GList *sorted_op_list, int *start_index, int *stop_index)
GList * find_operations(const char *rsc, const char *node, gboolean active_filter, pcmk_scheduler_t *scheduler)
gboolean unpack_status(xmlNode *status, pcmk_scheduler_t *scheduler)
void destroy_ticket(gpointer data)
int crm_str_to_boolean(const char *s, int *ret)
GList * dangling_migration_sources
const char * pcmk__readable_interval(guint interval_ms)
#define SUB_XPATH_LRM_RESOURCE
#define PCMK__META_CONTAINER
#define CRM_ATTR_SITE_NAME
pcmk__ticket_t * ticket_new(const char *ticket_id, pcmk_scheduler_t *scheduler)
Resource role is unknown.
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__META_MIGRATE_SOURCE
#define PCMK_VALUE_FREEZE
Action cannot be attempted (e.g. shutdown)
struct pcmk__node_details * details
#define pcmk__assert_alloc(nmemb, size)
time_t get_effective_time(pcmk_scheduler_t *scheduler)
void freeXpathObject(xmlXPathObjectPtr xpathObj)
#define PCMK_VALUE_OFFLINE
#define PCMK_XE_INSTANCE_ATTRIBUTES
void pe__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc, pcmk_node_t *node, enum pcmk__check_parameters, pcmk_scheduler_t *scheduler)
#define XPATH_ENABLE_UNFENCING
#define PCMK_VALUE_REMOTE
Execution failed, may be retried.
#define crm_info(fmt, args...)
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
#define pcmk__set_scheduler_flags(scheduler, flags_to_set)
GHashTable * probed_nodes
#define PCMK_VALUE_DEMOTE
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__XA_NODE_FENCED
char * clone_strip(const char *last_rsc_id)
#define PCMK_OPT_STONITH_WATCHDOG_TIMEOUT
enum pcmk__digest_result rc
#define PCMK__XA_NODE_IN_MAINTENANCE
guint priority_fencing_ms
pcmk_node_t * partial_migration_target
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
struct pcmk__node_assignment * assign