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->priv->name, rsc->id);
45 history = get_xpath_object(xpath, rsc->priv->scheduler->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;
53 lrm_rsc_op = pcmk__xe_next(lrm_rsc_op, PCMK__XE_LRM_RSC_OP)) {
54
55 const char *digest = crm_element_value(lrm_rsc_op,
56 PCMK__XA_OP_RESTART_DIGEST);
57 guint interval_ms = 0;
58 const char *task = crm_element_value(lrm_rsc_op, PCMK_XA_OPERATION);
59 bool effective_op = false;
60 bool failure = pcmk__ends_with(pcmk__xe_id(lrm_rsc_op),
61 "_last_failure_0");
62
63
64 crm_element_value_ms(lrm_rsc_op, PCMK_META_INTERVAL, &interval_ms);
65 effective_op = interval_ms == 0
66 && pcmk__strcase_any_of(task, PCMK_ACTION_MONITOR,
67 PCMK_ACTION_START,
68 PCMK_ACTION_PROMOTE,
69 PCMK_ACTION_MIGRATE_FROM, NULL);
70
71 if (best == NULL) {
72 goto is_best;
73 }
74
75 if (best_effective_op) {
76
77 if (!effective_op) {
78 continue;
79 }
80
81 } else if (best_interval != 0
82 && !effective_op
83 && interval_ms == 0) {
84 continue;
85 }
86
87
88 if (!best_failure && failure) {
89 continue;
90 }
91
92
93 if (best_digest != NULL && digest == NULL) {
94 continue;
95 }
96
97
98 if (pe__is_newer_op(best, lrm_rsc_op) > 0) {
99 continue;
100 }
101
102 is_best:
103 best = lrm_rsc_op;
104 best_effective_op = effective_op;
105 best_interval = interval_ms;
106 best_failure = failure;
107 best_digest = digest;
108 }
109 return best;
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123 int
124 pcmk__resource_delete(cib_t *cib, uint32_t cib_opts, const char *rsc_id,
125 const char *rsc_type)
126 {
127 int rc = pcmk_rc_ok;
128 xmlNode *msg_data = NULL;
129
130 if (cib == NULL) {
131 return ENOTCONN;
132 }
133
134 if (rsc_id == NULL || rsc_type == NULL) {
135 return EINVAL;
136 }
137
138 msg_data = pcmk__xe_create(NULL, rsc_type);
139 crm_xml_add(msg_data, PCMK_XA_ID, rsc_id);
140
141 rc = cib->cmds->remove(cib, PCMK_XE_RESOURCES, msg_data, cib_opts);
142 rc = pcmk_legacy2rc(rc);
143
144 pcmk__xml_free(msg_data);
145 return rc;
146 }
147
148 int
149 pcmk_resource_delete(xmlNodePtr *xml, const char *rsc_id, const char *rsc_type)
150 {
151 pcmk__output_t *out = NULL;
152 int rc = pcmk_rc_ok;
153 uint32_t cib_opts = cib_sync_call;
154 cib_t *cib = NULL;
155
156 rc = pcmk__xml_output_new(&out, xml);
157 if (rc != pcmk_rc_ok) {
158 return rc;
159 }
160
161 cib = cib_new();
162 if (cib == NULL) {
163 rc = pcmk_rc_cib_corrupt;
164 goto done;
165 }
166
167 rc = cib->cmds->signon(cib, crm_system_name, cib_command);
168 rc = pcmk_legacy2rc(rc);
169
170 if (rc != pcmk_rc_ok) {
171 goto done;
172 }
173
174 rc = pcmk__resource_delete(cib, cib_opts, rsc_id, rsc_type);
175
176 done:
177 if (cib != NULL) {
178 cib__clean_up_connection(&cib);
179 }
180
181 pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
182 return rc;
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196 int
197 pcmk__resource_digests(pcmk__output_t *out, pcmk_resource_t *rsc,
198 const pcmk_node_t *node, GHashTable *overrides)
199 {
200 const char *task = NULL;
201 xmlNode *xml_op = NULL;
202 pcmk__op_digest_t *digests = NULL;
203 guint interval_ms = 0;
204 int rc = pcmk_rc_ok;
205
206 if ((out == NULL) || (rsc == NULL) || (node == NULL)) {
207 return EINVAL;
208 }
209
210 if (!pcmk__is_primitive(rsc)) {
211
212 return EOPNOTSUPP;
213 }
214
215
216 xml_op = best_op(rsc, node);
217
218
219 if (xml_op != NULL) {
220 task = crm_element_value(xml_op, PCMK_XA_OPERATION);
221 crm_element_value_ms(xml_op, PCMK_META_INTERVAL, &interval_ms);
222 }
223 if (task == NULL) {
224 task = PCMK_ACTION_START;
225 interval_ms = 0;
226 }
227
228
229 digests = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
230 overrides, true, rsc->priv->scheduler);
231 rc = out->message(out, "digests", rsc, node, task, interval_ms, digests);
232
233 pe__free_digests(digests);
234 return rc;
235 }
236
237 int
238 pcmk_resource_digests(xmlNodePtr *xml, pcmk_resource_t *rsc,
239 const pcmk_node_t *node, GHashTable *overrides)
240 {
241 pcmk__output_t *out = NULL;
242 int rc = pcmk_rc_ok;
243
244 rc = pcmk__xml_output_new(&out, xml);
245 if (rc != pcmk_rc_ok) {
246 return rc;
247 }
248 pcmk__register_lib_messages(out);
249 rc = pcmk__resource_digests(out, rsc, node, overrides);
250 pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
251 return rc;
252 }