pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
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>
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
30static xmlNode *
31best_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
83int
85 pe_node_t *node, GHashTable *overrides,
86 pe_working_set_t *data_set)
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
124int
126 pe_node_t *node, GHashTable *overrides,
127 pe_working_set_t *data_set)
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}
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define RSC_START
Definition crm.h:201
#define LOG_NEVER
Definition logging.h:46
Wrappers for and extensions to glib mainloop.
#define XML_LRM_TAG_RSC_OP
Definition msg_xml.h:265
#define ID(x)
Definition msg_xml.h:456
#define XML_LRM_ATTR_INTERVAL
Definition msg_xml.h:291
#define XML_LRM_ATTR_RESTART_DIGEST
Definition msg_xml.h:313
#define XML_LRM_ATTR_TASK
Definition msg_xml.h:297
#define XML_LRM_ATTR_INTERVAL_MS
Definition msg_xml.h:295
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:530
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition nvpair.c:623
Formatted output for pacemaker tools.
High Level API.
int rc
Definition pcmk_fence.c:35
#define XPATH_OP_HISTORY
int pcmk__resource_digests(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node, GHashTable *overrides, pe_working_set_t *data_set)
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__out_prologue(pcmk__output_t **out, xmlNodePtr *xml)
void pcmk__register_lib_messages(pcmk__output_t *out)
void pcmk__out_epilogue(pcmk__output_t *out, xmlNodePtr *xml, int retval)
@ pe_native
Definition pe_types.h:37
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
void pe__free_digests(gpointer ptr)
Definition pe_digest.c:34
Function and executable result codes.
@ pcmk_rc_ok
Definition results.h:142
bool pcmk__ends_with(const char *s, const char *match)
Definition strings.c:535
This structure contains everything that makes up a single output formatter.
int(* message)(pcmk__output_t *out, const char *message_id,...)
struct pe_node_shared_s * details
Definition pe_types.h:244
const char * uname
Definition pe_types.h:209
enum pe_obj_types variant
Definition pe_types.h:331
xmlNode * input
Definition pe_types.h:137
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition xml.c:2790
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition xpath.c:214
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition xml.c:2816