This source file includes following definitions.
- do_cib_updated
- do_cib_replaced
- controld_disconnect_cib_manager
- do_cib_control
- crmd_cib_smart_opt
- controld_action_is_recordable
- cib_delete_callback
- controld_delete_node_state
- controld_delete_resource_history
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <unistd.h>
13
14 #include <crm/common/alerts_internal.h>
15 #include <crm/common/xml.h>
16 #include <crm/crm.h>
17 #include <crm/msg_xml.h>
18
19 #include <pacemaker-controld.h>
20
21 int cib_retries = 0;
22
23 void
24 do_cib_updated(const char *event, xmlNode * msg)
25 {
26 if (pcmk__alert_in_patchset(msg, TRUE)) {
27 mainloop_set_trigger(config_read);
28 }
29 }
30
31 void
32 do_cib_replaced(const char *event, xmlNode * msg)
33 {
34 uint32_t change_section = cib_change_section_nodes
35 |cib_change_section_status;
36 long long value = 0;
37
38 crm_debug("Updating the CIB after a replace: DC=%s", pcmk__btoa(AM_I_DC));
39 if (AM_I_DC == FALSE) {
40 return;
41
42 } else if ((fsa_state == S_FINALIZE_JOIN)
43 && pcmk_is_set(fsa_input_register, R_CIB_ASKED)) {
44
45 return;
46 }
47
48 if ((crm_element_value_ll(msg, F_CIB_CHANGE_SECTION, &value) < 0)
49 || (value < 0) || (value > UINT32_MAX)) {
50
51 crm_trace("Couldn't parse '%s' from message", F_CIB_CHANGE_SECTION);
52 } else {
53 change_section = (uint32_t) value;
54 }
55
56 if (pcmk_any_flags_set(change_section, cib_change_section_nodes
57 |cib_change_section_status)) {
58
59
60 populate_cib_nodes(node_update_quick|node_update_all, __func__);
61
62 register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
63 }
64 }
65
66 void
67 controld_disconnect_cib_manager(void)
68 {
69 CRM_ASSERT(fsa_cib_conn != NULL);
70
71 crm_info("Disconnecting from the CIB manager");
72
73 controld_clear_fsa_input_flags(R_CIB_CONNECTED);
74
75 fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_REPLACE_NOTIFY, do_cib_replaced);
76 fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated);
77 cib_free_callbacks(fsa_cib_conn);
78 if (fsa_cib_conn->state != cib_disconnected) {
79 fsa_cib_conn->cmds->set_secondary(fsa_cib_conn,
80 cib_scope_local|cib_discard_reply);
81 fsa_cib_conn->cmds->signoff(fsa_cib_conn);
82 }
83
84 crm_notice("Disconnected from the CIB manager");
85 }
86
87
88 void
89 do_cib_control(long long action,
90 enum crmd_fsa_cause cause,
91 enum crmd_fsa_state cur_state,
92 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
93 {
94 CRM_ASSERT(fsa_cib_conn != NULL);
95
96 if (action & A_CIB_STOP) {
97
98 if (fsa_cib_conn->state != cib_disconnected && last_resource_update != 0) {
99 crm_info("Waiting for resource update %d to complete", last_resource_update);
100 crmd_fsa_stall(FALSE);
101 return;
102 }
103
104 controld_disconnect_cib_manager();
105
106 }
107
108 if (action & A_CIB_START) {
109 int rc = pcmk_ok;
110
111 if (cur_state == S_STOPPING) {
112 crm_err("Ignoring request to connect to the CIB manager after shutdown");
113 return;
114 }
115
116 rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command_nonblocking);
117
118 if (rc != pcmk_ok) {
119
120 sleep(1);
121 rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command_nonblocking);
122 }
123
124 if (rc != pcmk_ok) {
125 crm_info("Could not connect to the CIB manager: %s", pcmk_strerror(rc));
126
127 } else if (pcmk_ok !=
128 fsa_cib_conn->cmds->set_connection_dnotify(fsa_cib_conn,
129 crmd_cib_connection_destroy)) {
130 crm_err("Could not set dnotify callback");
131
132 } else if (pcmk_ok !=
133 fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_REPLACE_NOTIFY,
134 do_cib_replaced)) {
135 crm_err("Could not set CIB notification callback (replace)");
136
137 } else if (pcmk_ok !=
138 fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY,
139 do_cib_updated)) {
140 crm_err("Could not set CIB notification callback (update)");
141
142 } else {
143 controld_set_fsa_input_flags(R_CIB_CONNECTED);
144 cib_retries = 0;
145 }
146
147 if (!pcmk_is_set(fsa_input_register, R_CIB_CONNECTED)) {
148
149 cib_retries++;
150 crm_warn("Couldn't complete CIB registration %d"
151 " times... pause and retry", cib_retries);
152
153 if (cib_retries < 30) {
154 controld_start_timer(wait_timer);
155 crmd_fsa_stall(FALSE);
156
157 } else {
158 crm_err("Could not complete CIB"
159 " registration %d times..." " hard error", cib_retries);
160 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
161 }
162 }
163 }
164 }
165
166
167
168
169
170
171
172 int
173 crmd_cib_smart_opt(void)
174 {
175 int call_opt = cib_quorum_override;
176
177 if (fsa_state == S_ELECTION || fsa_state == S_PENDING) {
178 crm_info("Sending update to local CIB in state: %s", fsa_state2string(fsa_state));
179 cib__set_call_options(call_opt, "update", cib_scope_local);
180 }
181 return call_opt;
182 }
183
184
185
186
187
188
189
190
191
192 bool
193 controld_action_is_recordable(const char *action)
194 {
195 return !pcmk__strcase_any_of(action, CRMD_ACTION_CANCEL, CRMD_ACTION_DELETE,
196 CRMD_ACTION_NOTIFY, CRMD_ACTION_METADATA, NULL);
197 }
198
199 static void
200 cib_delete_callback(xmlNode *msg, int call_id, int rc, xmlNode *output,
201 void *user_data)
202 {
203 char *desc = user_data;
204
205 if (rc == 0) {
206 crm_debug("Deletion of %s (via CIB call %d) succeeded", desc, call_id);
207 } else {
208 crm_warn("Deletion of %s (via CIB call %d) failed: %s " CRM_XS " rc=%d",
209 desc, call_id, pcmk_strerror(rc), rc);
210 }
211 }
212
213
214
215
216 #define XPATH_NODE_STATE "//" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']"
217
218
219 #define XPATH_NODE_LRM XPATH_NODE_STATE "/" XML_CIB_TAG_LRM
220
221
222 #define XPATH_NODE_LRM_UNLOCKED XPATH_NODE_STATE "//" XML_LRM_TAG_RSC_OP \
223 "|" XPATH_NODE_STATE \
224 "//" XML_LRM_TAG_RESOURCE \
225 "[not(@" XML_CONFIG_ATTR_SHUTDOWN_LOCK ")]"
226
227
228 #define XPATH_NODE_ATTRS XPATH_NODE_STATE "/" XML_TAG_TRANSIENT_NODEATTRS
229
230
231 #define XPATH_NODE_ALL XPATH_NODE_STATE "/*"
232
233
234 #define XPATH_NODE_ALL_UNLOCKED XPATH_NODE_LRM_UNLOCKED "|" XPATH_NODE_ATTRS
235
236
237
238
239
240
241
242
243
244 void
245 controld_delete_node_state(const char *uname, enum controld_section_e section,
246 int options)
247 {
248 char *xpath = NULL;
249 char *desc = NULL;
250
251 CRM_CHECK(uname != NULL, return);
252 switch (section) {
253 case controld_section_lrm:
254 xpath = crm_strdup_printf(XPATH_NODE_LRM, uname);
255 desc = crm_strdup_printf("resource history for node %s", uname);
256 break;
257 case controld_section_lrm_unlocked:
258 xpath = crm_strdup_printf(XPATH_NODE_LRM_UNLOCKED, uname, uname);
259 desc = crm_strdup_printf("resource history (other than shutdown "
260 "locks) for node %s", uname);
261 break;
262 case controld_section_attrs:
263 xpath = crm_strdup_printf(XPATH_NODE_ATTRS, uname);
264 desc = crm_strdup_printf("transient attributes for node %s", uname);
265 break;
266 case controld_section_all:
267 xpath = crm_strdup_printf(XPATH_NODE_ALL, uname);
268 desc = crm_strdup_printf("all state for node %s", uname);
269 break;
270 case controld_section_all_unlocked:
271 xpath = crm_strdup_printf(XPATH_NODE_ALL_UNLOCKED,
272 uname, uname, uname);
273 desc = crm_strdup_printf("all state (other than shutdown locks) "
274 "for node %s", uname);
275 break;
276 }
277
278 if (fsa_cib_conn == NULL) {
279 crm_warn("Unable to delete %s: no CIB connection", desc);
280 free(desc);
281 } else {
282 int call_id;
283
284 cib__set_call_options(options, "node state deletion",
285 cib_quorum_override|cib_xpath|cib_multiple);
286 call_id = fsa_cib_conn->cmds->remove(fsa_cib_conn, xpath, NULL, options);
287 crm_info("Deleting %s (via CIB call %d) " CRM_XS " xpath=%s",
288 desc, call_id, xpath);
289 fsa_register_cib_callback(call_id, FALSE, desc, cib_delete_callback);
290
291 }
292 free(xpath);
293 }
294
295
296 #define XPATH_RESOURCE_HISTORY "//" XML_CIB_TAG_STATE \
297 "[@" XML_ATTR_UNAME "='%s']/" \
298 XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES \
299 "/" XML_LRM_TAG_RESOURCE \
300 "[@" XML_ATTR_ID "='%s']"
301
302
303
304
305
306
307
308
309
310
311
312
313
314 int
315 controld_delete_resource_history(const char *rsc_id, const char *node,
316 const char *user_name, int call_options)
317 {
318 char *desc = NULL;
319 char *xpath = NULL;
320 int rc = pcmk_rc_ok;
321
322 CRM_CHECK((rsc_id != NULL) && (node != NULL), return EINVAL);
323
324 desc = crm_strdup_printf("resource history for %s on %s", rsc_id, node);
325 if (fsa_cib_conn == NULL) {
326 crm_err("Unable to clear %s: no CIB connection", desc);
327 free(desc);
328 return ENOTCONN;
329 }
330
331
332 xpath = crm_strdup_printf(XPATH_RESOURCE_HISTORY, node, rsc_id);
333 rc = cib_internal_op(fsa_cib_conn, PCMK__CIB_REQUEST_DELETE, NULL, xpath,
334 NULL, NULL, call_options|cib_xpath, user_name);
335
336 if (rc < 0) {
337 rc = pcmk_legacy2rc(rc);
338 crm_err("Could not delete resource status of %s on %s%s%s: %s "
339 CRM_XS " rc=%d", rsc_id, node,
340 (user_name? " for user " : ""), (user_name? user_name : ""),
341 pcmk_rc_str(rc), rc);
342 free(desc);
343 free(xpath);
344 return rc;
345 }
346
347 if (pcmk_is_set(call_options, cib_sync_call)) {
348 if (pcmk_is_set(call_options, cib_dryrun)) {
349 crm_debug("Deletion of %s would succeed", desc);
350 } else {
351 crm_debug("Deletion of %s succeeded", desc);
352 }
353 free(desc);
354
355 } else {
356 crm_info("Clearing %s (via CIB call %d) " CRM_XS " xpath=%s",
357 desc, rc, xpath);
358 fsa_register_cib_callback(rc, FALSE, desc, cib_delete_callback);
359
360 }
361
362 free(xpath);
363 return pcmk_rc_ok;
364 }