This source file includes following definitions.
- best_op
- pcmk__resource_delete
- pcmk_resource_delete
- 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/cib/internal.h>
17 #include <crm/common/mainloop.h>
18 #include <crm/common/results.h>
19 #include <crm/common/output_internal.h>
20 #include <crm/pengine/internal.h>
21
22 #include <pacemaker.h>
23 #include <pacemaker-internal.h>
24
25
26 #define XPATH_OP_HISTORY "//" PCMK_XE_STATUS \
27 "/" PCMK__XE_NODE_STATE \
28 "[@" PCMK_XA_UNAME "='%s']" \
29 "/" PCMK__XE_LRM "/" PCMK__XE_LRM_RESOURCES \
30 "/" PCMK__XE_LRM_RESOURCE "[@" PCMK_XA_ID "='%s']"
31
32 static xmlNode *
33 best_op(const pcmk_resource_t *rsc, const pcmk_node_t *node)
34 {
35 char *xpath = NULL;
36 xmlNode *history = NULL;
37 xmlNode *best = NULL;
38 bool best_effective_op = false;
39 guint best_interval = 0;
40 bool best_failure = false;
41 const char *best_digest = NULL;
42
43
44 xpath = crm_strdup_printf(XPATH_OP_HISTORY, node->details->uname, rsc->id);
45 history = get_xpath_object(xpath, rsc->cluster->input, LOG_NEVER);
46 free(xpath);
47
48
49 for (xmlNode *lrm_rsc_op = pcmk__xe_first_child(history,
50 PCMK__XE_LRM_RSC_OP, NULL,
51 NULL);
52 lrm_rsc_op != NULL; lrm_rsc_op = pcmk__xe_next_same(lrm_rsc_op)) {
53
54 const char *digest = crm_element_value(lrm_rsc_op,
55 PCMK__XA_OP_RESTART_DIGEST);
56 guint interval_ms = 0;
57 const char *task = crm_element_value(lrm_rsc_op, PCMK_XA_OPERATION);
58 bool effective_op = false;
59 bool failure = pcmk__ends_with(pcmk__xe_id(lrm_rsc_op),
60 "_last_failure_0");
61
62
63 crm_element_value_ms(lrm_rsc_op, PCMK_META_INTERVAL, &interval_ms);
64 effective_op = interval_ms == 0
65 && pcmk__strcase_any_of(task, PCMK_ACTION_MONITOR,
66 PCMK_ACTION_START,
67 PCMK_ACTION_PROMOTE,
68 PCMK_ACTION_MIGRATE_FROM, NULL);
69
70 if (best == NULL) {
71 goto is_best;
72 }
73
74 if (best_effective_op) {
75
76 if (!effective_op) {
77 continue;
78 }
79
80 } else if (best_interval != 0
81 && !effective_op
82 && interval_ms == 0) {
83 continue;
84 }
85
86
87 if (!best_failure && failure) {
88 continue;
89 }
90
91
92 if (best_digest != NULL && digest == NULL) {
93 continue;
94 }
95
96
97 if (pe__is_newer_op(best, lrm_rsc_op, true) > 0) {
98 continue;
99 }
100
101 is_best:
102 best = lrm_rsc_op;
103 best_effective_op = effective_op;
104 best_interval = interval_ms;
105 best_failure = failure;
106 best_digest = digest;
107 }
108 return best;
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122 int
123 pcmk__resource_delete(cib_t *cib, uint32_t cib_opts, const char *rsc_id,
124 const char *rsc_type)
125 {
126 int rc = pcmk_rc_ok;
127 xmlNode *msg_data = NULL;
128
129 if (cib == NULL) {
130 return ENOTCONN;
131 }
132
133 if (rsc_id == NULL || rsc_type == NULL) {
134 return EINVAL;
135 }
136
137 msg_data = pcmk__xe_create(NULL, rsc_type);
138 crm_xml_add(msg_data, PCMK_XA_ID, rsc_id);
139
140 rc = cib->cmds->remove(cib, PCMK_XE_RESOURCES, msg_data, cib_opts);
141 rc = pcmk_legacy2rc(rc);
142
143 free_xml(msg_data);
144 return rc;
145 }
146
147 int
148 pcmk_resource_delete(xmlNodePtr *xml, const char *rsc_id, const char *rsc_type)
149 {
150 pcmk__output_t *out = NULL;
151 int rc = pcmk_rc_ok;
152 uint32_t cib_opts = cib_sync_call;
153 cib_t *cib = NULL;
154
155 rc = pcmk__xml_output_new(&out, xml);
156 if (rc != pcmk_rc_ok) {
157 return rc;
158 }
159
160 cib = cib_new();
161 if (cib == NULL) {
162 rc = pcmk_rc_cib_corrupt;
163 goto done;
164 }
165
166 rc = cib->cmds->signon(cib, crm_system_name, cib_command);
167 rc = pcmk_legacy2rc(rc);
168
169 if (rc != pcmk_rc_ok) {
170 goto done;
171 }
172
173 rc = pcmk__resource_delete(cib, cib_opts, rsc_id, rsc_type);
174
175 done:
176 if (cib != NULL) {
177 cib__clean_up_connection(&cib);
178 }
179
180 pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
181 return rc;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195 int
196 pcmk__resource_digests(pcmk__output_t *out, pcmk_resource_t *rsc,
197 const pcmk_node_t *node, GHashTable *overrides)
198 {
199 const char *task = NULL;
200 xmlNode *xml_op = NULL;
201 pcmk__op_digest_t *digests = NULL;
202 guint interval_ms = 0;
203 int rc = pcmk_rc_ok;
204
205 if ((out == NULL) || (rsc == NULL) || (node == NULL)) {
206 return EINVAL;
207 }
208 if (!pcmk__is_primitive(rsc)) {
209
210 return EOPNOTSUPP;
211 }
212
213
214 xml_op = best_op(rsc, node);
215
216
217 if (xml_op != NULL) {
218 task = crm_element_value(xml_op, PCMK_XA_OPERATION);
219 crm_element_value_ms(xml_op, PCMK_META_INTERVAL, &interval_ms);
220 }
221 if (task == NULL) {
222 task = PCMK_ACTION_START;
223 interval_ms = 0;
224 }
225
226
227 digests = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
228 overrides, true, rsc->cluster);
229 rc = out->message(out, "digests", rsc, node, task, interval_ms, digests);
230
231 pe__free_digests(digests);
232 return rc;
233 }
234
235 int
236 pcmk_resource_digests(xmlNodePtr *xml, pcmk_resource_t *rsc,
237 const pcmk_node_t *node, GHashTable *overrides)
238 {
239 pcmk__output_t *out = NULL;
240 int rc = pcmk_rc_ok;
241
242 rc = pcmk__xml_output_new(&out, xml);
243 if (rc != pcmk_rc_ok) {
244 return rc;
245 }
246 pcmk__register_lib_messages(out);
247 rc = pcmk__resource_digests(out, rsc, node, overrides);
248 pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
249 return rc;
250 }