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