pacemaker  2.1.3-ea053b43a
Scalable High-Availability cluster resource manager
pcmk_resource.c
Go to the documentation of this file.
1 /*
2  * Copyright 2021 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU General Public License version 2
7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <errno.h>
13 #include <glib.h>
14 #include <libxml/tree.h>
15 
16 #include <crm/common/mainloop.h>
17 #include <crm/common/results.h>
19 #include <crm/pengine/internal.h>
20 
21 #include <pacemaker.h>
22 #include <pacemaker-internal.h>
23 
24 // Search path for resource operation history (takes node name and resource ID)
25 #define XPATH_OP_HISTORY "//" XML_CIB_TAG_STATUS \
26  "/" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']" \
27  "/" XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES \
28  "/" XML_LRM_TAG_RESOURCE "[@" XML_ATTR_ID "='%s']"
29 
30 static xmlNode *
31 best_op(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
32 {
33  char *xpath = NULL;
34  xmlNode *history = NULL;
35  xmlNode *best = NULL;
36 
37  // Find node's resource history
38  xpath = crm_strdup_printf(XPATH_OP_HISTORY, node->details->uname, rsc->id);
39  history = get_xpath_object(xpath, data_set->input, LOG_NEVER);
40  free(xpath);
41 
42  // Examine each history entry
43  for (xmlNode *lrm_rsc_op = first_named_child(history, XML_LRM_TAG_RSC_OP);
44  lrm_rsc_op != NULL; lrm_rsc_op = crm_next_same_xml(lrm_rsc_op)) {
45 
46  const char *digest = crm_element_value(lrm_rsc_op,
48  guint interval_ms = 0;
49 
50  crm_element_value_ms(lrm_rsc_op, XML_LRM_ATTR_INTERVAL, &interval_ms);
51 
52  if (pcmk__ends_with(ID(lrm_rsc_op), "_last_failure_0")
53  || (interval_ms != 0)) {
54 
55  // Only use last failure or recurring op if nothing else available
56  if (best == NULL) {
57  best = lrm_rsc_op;
58  }
59  continue;
60  }
61 
62  best = lrm_rsc_op;
63  if (digest != NULL) {
64  // Any non-recurring action with a restart digest is sufficient
65  break;
66  }
67  }
68  return best;
69 }
70 
83 int
85  pe_node_t *node, GHashTable *overrides,
87 {
88  const char *task = NULL;
89  xmlNode *xml_op = NULL;
90  op_digest_cache_t *digests = NULL;
91  guint interval_ms = 0;
92  int rc = pcmk_rc_ok;
93 
94  if ((out == NULL) || (rsc == NULL) || (node == NULL) || (data_set == NULL)) {
95  return EINVAL;
96  }
97  if (rsc->variant != pe_native) {
98  // Only primitives get operation digests
99  return EOPNOTSUPP;
100  }
101 
102  // Find XML of operation history to use
103  xml_op = best_op(rsc, node, data_set);
104 
105  // Generate an operation key
106  if (xml_op != NULL) {
107  task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
108  crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
109  }
110  if (task == NULL) { // Assume start if no history is available
111  task = RSC_START;
112  interval_ms = 0;
113  }
114 
115  // Calculate and show digests
116  digests = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
117  overrides, true, data_set);
118  rc = out->message(out, "digests", rsc, node, task, interval_ms, digests);
119 
120  pe__free_digests(digests);
121  return rc;
122 }
123 
124 int
125 pcmk_resource_digests(xmlNodePtr *xml, pe_resource_t *rsc,
126  pe_node_t *node, GHashTable *overrides,
128 {
129  pcmk__output_t *out = NULL;
130  int rc = pcmk_rc_ok;
131 
132  rc = pcmk__out_prologue(&out, xml);
133  if (rc != pcmk_rc_ok) {
134  return rc;
135  }
137  rc = pcmk__resource_digests(out, rsc, node, overrides, data_set);
138  pcmk__out_epilogue(out, xml, rc);
139  return rc;
140 }
int(* message)(pcmk__output_t *out, const char *message_id,...)
#define XPATH_OP_HISTORY
Definition: pcmk_resource.c:25
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2794
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:297
High Level API.
#define RSC_START
Definition: crm.h:201
bool pcmk__ends_with(const char *s, const char *match)
Definition: strings.c:536
#define LOG_NEVER
Definition: logging.h:47
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:214
Wrappers for and extensions to glib mainloop.
op_digest_cache_t * pe__calculate_digests(pe_resource_t *rsc, const char *task, guint *interval_ms, pe_node_t *node, xmlNode *xml_op, GHashTable *overrides, bool calc_secure, pe_working_set_t *data_set)
Definition: pe_digest.c:321
int pcmk__out_prologue(pcmk__output_t **out, xmlNodePtr *xml)
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:303
Formatted output for pacemaker tools.
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:622
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:529
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
struct pe_node_shared_s * details
Definition: pe_types.h:252
const char * uname
Definition: pe_types.h:216
void pcmk__register_lib_messages(pcmk__output_t *out)
Definition: pcmk_output.c:1920
pe_working_set_t * data_set
#define XML_LRM_ATTR_RESTART_DIGEST
Definition: msg_xml.h:319
void pe__free_digests(gpointer ptr)
Definition: pe_digest.c:34
enum pe_obj_types variant
Definition: pe_types.h:345
xmlNode * input
Definition: pe_types.h:144
void pcmk__out_epilogue(pcmk__output_t *out, xmlNodePtr *xml, int retval)
Function and executable result codes.
This structure contains everything that makes up a single output formatter.
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:301
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:271
#define ID(x)
Definition: msg_xml.h:460
int pcmk_resource_digests(xmlNodePtr *xml, pe_resource_t *rsc, pe_node_t *node, GHashTable *overrides, pe_working_set_t *data_set)
Calculate and output resource operation digests.
int pcmk__resource_digests(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node, GHashTable *overrides, pe_working_set_t *data_set)
Definition: pcmk_resource.c:84
char * id
Definition: pe_types.h:336
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2820