This source file includes following definitions.
- best_op
- pcmk__resource_digests
- pcmk_resource_digests
1
2
3
4
5
6
7
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>
18 #include <crm/common/output_internal.h>
19 #include <crm/pengine/internal.h>
20
21 #include <pacemaker.h>
22 #include <pacemaker-internal.h>
23
24
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(const pcmk_resource_t *rsc, const pcmk_node_t *node)
32 {
33 char *xpath = NULL;
34 xmlNode *history = NULL;
35 xmlNode *best = NULL;
36 bool best_effective_op = false;
37 guint best_interval = 0;
38 bool best_failure = false;
39 const char *best_digest = NULL;
40
41
42 xpath = crm_strdup_printf(XPATH_OP_HISTORY, node->details->uname, rsc->id);
43 history = get_xpath_object(xpath, rsc->cluster->input, LOG_NEVER);
44 free(xpath);
45
46
47 for (xmlNode *lrm_rsc_op = first_named_child(history, XML_LRM_TAG_RSC_OP);
48 lrm_rsc_op != NULL; lrm_rsc_op = crm_next_same_xml(lrm_rsc_op)) {
49
50 const char *digest = crm_element_value(lrm_rsc_op,
51 XML_LRM_ATTR_RESTART_DIGEST);
52 guint interval_ms = 0;
53 const char *task = crm_element_value(lrm_rsc_op, XML_LRM_ATTR_TASK);
54 bool effective_op = false;
55 bool failure = pcmk__ends_with(ID(lrm_rsc_op), "_last_failure_0");
56
57
58 crm_element_value_ms(lrm_rsc_op, XML_LRM_ATTR_INTERVAL, &interval_ms);
59 effective_op = interval_ms == 0
60 && pcmk__strcase_any_of(task, PCMK_ACTION_MONITOR,
61 PCMK_ACTION_START,
62 PCMK_ACTION_PROMOTE,
63 PCMK_ACTION_MIGRATE_FROM, NULL);
64
65 if (best == NULL) {
66 goto is_best;
67 }
68
69 if (best_effective_op) {
70
71 if (!effective_op) {
72 continue;
73 }
74
75 } else if (best_interval != 0
76 && !effective_op
77 && interval_ms == 0) {
78 continue;
79 }
80
81
82 if (!best_failure && failure) {
83 continue;
84 }
85
86
87 if (best_digest != NULL && digest == NULL) {
88 continue;
89 }
90
91
92 if (pe__is_newer_op(best, lrm_rsc_op, true) > 0) {
93 continue;
94 }
95
96 is_best:
97 best = lrm_rsc_op;
98 best_effective_op = effective_op;
99 best_interval = interval_ms;
100 best_failure = failure;
101 best_digest = digest;
102 }
103 return best;
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117 int
118 pcmk__resource_digests(pcmk__output_t *out, pcmk_resource_t *rsc,
119 const pcmk_node_t *node, GHashTable *overrides)
120 {
121 const char *task = NULL;
122 xmlNode *xml_op = NULL;
123 op_digest_cache_t *digests = NULL;
124 guint interval_ms = 0;
125 int rc = pcmk_rc_ok;
126
127 if ((out == NULL) || (rsc == NULL) || (node == NULL)) {
128 return EINVAL;
129 }
130 if (rsc->variant != pcmk_rsc_variant_primitive) {
131
132 return EOPNOTSUPP;
133 }
134
135
136 xml_op = best_op(rsc, node);
137
138
139 if (xml_op != NULL) {
140 task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
141 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
142 }
143 if (task == NULL) {
144 task = PCMK_ACTION_START;
145 interval_ms = 0;
146 }
147
148
149 digests = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
150 overrides, true, rsc->cluster);
151 rc = out->message(out, "digests", rsc, node, task, interval_ms, digests);
152
153 pe__free_digests(digests);
154 return rc;
155 }
156
157 int
158 pcmk_resource_digests(xmlNodePtr *xml, pcmk_resource_t *rsc,
159 const pcmk_node_t *node, GHashTable *overrides,
160 pcmk_scheduler_t *scheduler)
161 {
162 pcmk__output_t *out = NULL;
163 int rc = pcmk_rc_ok;
164
165 rc = pcmk__xml_output_new(&out, xml);
166 if (rc != pcmk_rc_ok) {
167 return rc;
168 }
169 pcmk__register_lib_messages(out);
170 rc = pcmk__resource_digests(out, rsc, node, overrides);
171 pcmk__xml_output_finish(out, xml);
172 return rc;
173 }