This source file includes following definitions.
- handle_cib_disconnect
- do_cib_updated
- controld_disconnect_cib_manager
- do_cib_control
- cib_op_timeout
- crmd_cib_smart_opt
- cib_delete_callback
- controld_node_state_deletion_strings
- controld_delete_node_state
- controld_delete_resource_history
- build_parameter_list
- append_restart_list
- append_secure_list
- controld_add_resource_history_xml_as
- controld_record_pending_op
- cib_rsc_callback
- should_preserve_lock
- controld_update_cib
- controld_update_resource_history
- controld_delete_action_history
- controld_cib_delete_last_failure
- controld_delete_action_history_by_key
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 #include <crm/lrmd_internal.h>
19
20 #include <pacemaker-controld.h>
21
22
23 static int pending_rsc_update = 0;
24
25
26
27
28
29
30
31 static void
32 handle_cib_disconnect(gpointer user_data)
33 {
34 CRM_LOG_ASSERT(user_data == controld_globals.cib_conn);
35
36 controld_trigger_fsa();
37 controld_globals.cib_conn->state = cib_disconnected;
38
39 if (pcmk_is_set(controld_globals.fsa_input_register, R_CIB_CONNECTED)) {
40
41 crm_crit("Lost connection to the CIB manager, shutting down");
42 register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL);
43 controld_clear_fsa_input_flags(R_CIB_CONNECTED);
44
45 } else {
46 crm_info("Disconnected from the CIB manager");
47 }
48 }
49
50 static void
51 do_cib_updated(const char *event, xmlNode * msg)
52 {
53 const xmlNode *patchset = NULL;
54 const char *client_name = NULL;
55
56 crm_debug("Received CIB diff notification: DC=%s", pcmk__btoa(AM_I_DC));
57
58 if (cib__get_notify_patchset(msg, &patchset) != pcmk_rc_ok) {
59 return;
60 }
61
62 if (cib__element_in_patchset(patchset, XML_CIB_TAG_ALERTS)
63 || cib__element_in_patchset(patchset, XML_CIB_TAG_CRMCONFIG)) {
64
65 controld_trigger_config();
66 }
67
68 if (!AM_I_DC) {
69
70 return;
71 }
72
73 client_name = crm_element_value(msg, F_CIB_CLIENTNAME);
74 if (!cib__client_triggers_refresh(client_name)) {
75
76 return;
77 }
78
79 if (cib__element_in_patchset(patchset, XML_CIB_TAG_NODES)
80 || cib__element_in_patchset(patchset, XML_CIB_TAG_STATUS)) {
81
82
83
84
85
86 if (client_name == NULL) {
87 client_name = crm_element_value(msg, F_CIB_CLIENTID);
88 }
89 crm_notice("Populating nodes and starting an election after %s event "
90 "triggered by %s",
91 event, pcmk__s(client_name, "(unidentified client)"));
92
93 populate_cib_nodes(node_update_quick|node_update_all, __func__);
94 register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
95 }
96 }
97
98 void
99 controld_disconnect_cib_manager(void)
100 {
101 cib_t *cib_conn = controld_globals.cib_conn;
102
103 CRM_ASSERT(cib_conn != NULL);
104
105 crm_debug("Disconnecting from the CIB manager");
106
107 controld_clear_fsa_input_flags(R_CIB_CONNECTED);
108
109 cib_conn->cmds->del_notify_callback(cib_conn, T_CIB_DIFF_NOTIFY,
110 do_cib_updated);
111 cib_free_callbacks(cib_conn);
112
113 if (cib_conn->state != cib_disconnected) {
114 cib_conn->cmds->set_secondary(cib_conn,
115 cib_scope_local|cib_discard_reply);
116 cib_conn->cmds->signoff(cib_conn);
117 }
118 }
119
120
121 void
122 do_cib_control(long long action,
123 enum crmd_fsa_cause cause,
124 enum crmd_fsa_state cur_state,
125 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
126 {
127 static int cib_retries = 0;
128
129 cib_t *cib_conn = controld_globals.cib_conn;
130
131 void (*dnotify_fn) (gpointer user_data) = handle_cib_disconnect;
132 void (*update_cb) (const char *event, xmlNodePtr msg) = do_cib_updated;
133
134 int rc = pcmk_ok;
135
136 CRM_ASSERT(cib_conn != NULL);
137
138 if (pcmk_is_set(action, A_CIB_STOP)) {
139 if ((cib_conn->state != cib_disconnected)
140 && (pending_rsc_update != 0)) {
141
142 crm_info("Waiting for resource update %d to complete",
143 pending_rsc_update);
144 crmd_fsa_stall(FALSE);
145 return;
146 }
147 controld_disconnect_cib_manager();
148 }
149
150 if (!pcmk_is_set(action, A_CIB_START)) {
151 return;
152 }
153
154 if (cur_state == S_STOPPING) {
155 crm_err("Ignoring request to connect to the CIB manager after "
156 "shutdown");
157 return;
158 }
159
160 rc = cib_conn->cmds->signon(cib_conn, CRM_SYSTEM_CRMD,
161 cib_command_nonblocking);
162
163 if (rc != pcmk_ok) {
164
165 sleep(1);
166 rc = cib_conn->cmds->signon(cib_conn, CRM_SYSTEM_CRMD,
167 cib_command_nonblocking);
168 }
169
170 if (rc != pcmk_ok) {
171 crm_info("Could not connect to the CIB manager: %s", pcmk_strerror(rc));
172
173 } else if (cib_conn->cmds->set_connection_dnotify(cib_conn,
174 dnotify_fn) != pcmk_ok) {
175 crm_err("Could not set dnotify callback");
176
177 } else if (cib_conn->cmds->add_notify_callback(cib_conn,
178 T_CIB_DIFF_NOTIFY,
179 update_cb) != pcmk_ok) {
180 crm_err("Could not set CIB notification callback (update)");
181
182 } else {
183 controld_set_fsa_input_flags(R_CIB_CONNECTED);
184 cib_retries = 0;
185 }
186
187 if (!pcmk_is_set(controld_globals.fsa_input_register, R_CIB_CONNECTED)) {
188 cib_retries++;
189
190 if (cib_retries < 30) {
191 crm_warn("Couldn't complete CIB registration %d times... "
192 "pause and retry", cib_retries);
193 controld_start_wait_timer();
194 crmd_fsa_stall(FALSE);
195
196 } else {
197 crm_err("Could not complete CIB registration %d times... "
198 "hard error", cib_retries);
199 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
200 }
201 }
202 }
203
204 #define MIN_CIB_OP_TIMEOUT (30)
205
206
207
208
209
210
211
212
213
214 unsigned int
215 cib_op_timeout(void)
216 {
217
218 static int env_timeout = -1;
219 unsigned int calculated_timeout = 0;
220
221 if (env_timeout == -1) {
222 const char *env = pcmk__env_option(PCMK__ENV_CIB_TIMEOUT);
223
224 pcmk__scan_min_int(env, &env_timeout, MIN_CIB_OP_TIMEOUT);
225 crm_trace("Minimum CIB op timeout: %ds (environment: %s)",
226 env_timeout, (env? env : "none"));
227 }
228
229 calculated_timeout = 1 + crm_active_peers();
230 if (crm_remote_peer_cache) {
231 calculated_timeout += g_hash_table_size(crm_remote_peer_cache);
232 }
233 calculated_timeout *= 10;
234
235 calculated_timeout = QB_MAX(calculated_timeout, env_timeout);
236 crm_trace("Calculated timeout: %us", calculated_timeout);
237
238 if (controld_globals.cib_conn) {
239 controld_globals.cib_conn->call_timeout = calculated_timeout;
240 }
241 return calculated_timeout;
242 }
243
244
245
246
247
248
249
250 int
251 crmd_cib_smart_opt(void)
252 {
253 int call_opt = cib_none;
254
255 if ((controld_globals.fsa_state == S_ELECTION)
256 || (controld_globals.fsa_state == S_PENDING)) {
257 crm_info("Sending update to local CIB in state: %s",
258 fsa_state2string(controld_globals.fsa_state));
259 cib__set_call_options(call_opt, "update", cib_scope_local);
260 }
261 return call_opt;
262 }
263
264 static void
265 cib_delete_callback(xmlNode *msg, int call_id, int rc, xmlNode *output,
266 void *user_data)
267 {
268 char *desc = user_data;
269
270 if (rc == 0) {
271 crm_debug("Deletion of %s (via CIB call %d) succeeded", desc, call_id);
272 } else {
273 crm_warn("Deletion of %s (via CIB call %d) failed: %s " CRM_XS " rc=%d",
274 desc, call_id, pcmk_strerror(rc), rc);
275 }
276 }
277
278
279
280
281 #define XPATH_NODE_STATE "//" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']"
282
283
284 #define XPATH_NODE_LRM XPATH_NODE_STATE "/" XML_CIB_TAG_LRM
285
286
287
288
289 #define XPATH_NODE_LRM_UNLOCKED XPATH_NODE_STATE "//" XML_LRM_TAG_RSC_OP \
290 "|" XPATH_NODE_STATE \
291 "//" XML_LRM_TAG_RESOURCE \
292 "[not(@" XML_CONFIG_ATTR_SHUTDOWN_LOCK ") " \
293 "or " XML_CONFIG_ATTR_SHUTDOWN_LOCK "<%lld]"
294
295
296 #define XPATH_NODE_ATTRS XPATH_NODE_STATE "/" XML_TAG_TRANSIENT_NODEATTRS
297
298
299 #define XPATH_NODE_ALL XPATH_NODE_STATE "/*"
300
301
302
303
304
305 #define XPATH_NODE_ALL_UNLOCKED XPATH_NODE_LRM_UNLOCKED "|" XPATH_NODE_ATTRS
306
307
308
309
310
311
312
313
314
315
316 void
317 controld_node_state_deletion_strings(const char *uname,
318 enum controld_section_e section,
319 char **xpath, char **desc)
320 {
321 const char *desc_pre = NULL;
322
323
324 long long expire = (long long) time(NULL)
325 - controld_globals.shutdown_lock_limit;
326
327 switch (section) {
328 case controld_section_lrm:
329 *xpath = crm_strdup_printf(XPATH_NODE_LRM, uname);
330 desc_pre = "resource history";
331 break;
332 case controld_section_lrm_unlocked:
333 *xpath = crm_strdup_printf(XPATH_NODE_LRM_UNLOCKED,
334 uname, uname, expire);
335 desc_pre = "resource history (other than shutdown locks)";
336 break;
337 case controld_section_attrs:
338 *xpath = crm_strdup_printf(XPATH_NODE_ATTRS, uname);
339 desc_pre = "transient attributes";
340 break;
341 case controld_section_all:
342 *xpath = crm_strdup_printf(XPATH_NODE_ALL, uname);
343 desc_pre = "all state";
344 break;
345 case controld_section_all_unlocked:
346 *xpath = crm_strdup_printf(XPATH_NODE_ALL_UNLOCKED,
347 uname, uname, expire, uname);
348 desc_pre = "all state (other than shutdown locks)";
349 break;
350 default:
351
352 CRM_ASSERT(false);
353 break;
354 }
355
356 if (desc != NULL) {
357 *desc = crm_strdup_printf("%s for node %s", desc_pre, uname);
358 }
359 }
360
361
362
363
364
365
366
367
368
369 void
370 controld_delete_node_state(const char *uname, enum controld_section_e section,
371 int options)
372 {
373 cib_t *cib = controld_globals.cib_conn;
374 char *xpath = NULL;
375 char *desc = NULL;
376 int cib_rc = pcmk_ok;
377
378 CRM_ASSERT((uname != NULL) && (cib != NULL));
379
380 controld_node_state_deletion_strings(uname, section, &xpath, &desc);
381
382 cib__set_call_options(options, "node state deletion",
383 cib_xpath|cib_multiple);
384 cib_rc = cib->cmds->remove(cib, xpath, NULL, options);
385 fsa_register_cib_callback(cib_rc, desc, cib_delete_callback);
386 crm_info("Deleting %s (via CIB call %d) " CRM_XS " xpath=%s",
387 desc, cib_rc, xpath);
388
389
390 free(xpath);
391 }
392
393
394 #define XPATH_RESOURCE_HISTORY "//" XML_CIB_TAG_STATE \
395 "[@" XML_ATTR_UNAME "='%s']/" \
396 XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES \
397 "/" XML_LRM_TAG_RESOURCE \
398 "[@" XML_ATTR_ID "='%s']"
399
400
401
402
403
404
405
406
407
408
409
410
411
412 int
413 controld_delete_resource_history(const char *rsc_id, const char *node,
414 const char *user_name, int call_options)
415 {
416 char *desc = NULL;
417 char *xpath = NULL;
418 int rc = pcmk_rc_ok;
419 cib_t *cib = controld_globals.cib_conn;
420
421 CRM_CHECK((rsc_id != NULL) && (node != NULL), return EINVAL);
422
423 desc = crm_strdup_printf("resource history for %s on %s", rsc_id, node);
424 if (cib == NULL) {
425 crm_err("Unable to clear %s: no CIB connection", desc);
426 free(desc);
427 return ENOTCONN;
428 }
429
430
431 xpath = crm_strdup_printf(XPATH_RESOURCE_HISTORY, node, rsc_id);
432
433 cib->cmds->set_user(cib, user_name);
434 rc = cib->cmds->remove(cib, xpath, NULL, call_options|cib_xpath);
435 cib->cmds->set_user(cib, NULL);
436
437 if (rc < 0) {
438 rc = pcmk_legacy2rc(rc);
439 crm_err("Could not delete resource status of %s on %s%s%s: %s "
440 CRM_XS " rc=%d", rsc_id, node,
441 (user_name? " for user " : ""), (user_name? user_name : ""),
442 pcmk_rc_str(rc), rc);
443 free(desc);
444 free(xpath);
445 return rc;
446 }
447
448 if (pcmk_is_set(call_options, cib_sync_call)) {
449 if (pcmk_is_set(call_options, cib_dryrun)) {
450 crm_debug("Deletion of %s would succeed", desc);
451 } else {
452 crm_debug("Deletion of %s succeeded", desc);
453 }
454 free(desc);
455
456 } else {
457 crm_info("Clearing %s (via CIB call %d) " CRM_XS " xpath=%s",
458 desc, rc, xpath);
459 fsa_register_cib_callback(rc, desc, cib_delete_callback);
460
461 }
462
463 free(xpath);
464 return pcmk_rc_ok;
465 }
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486 static GString *
487 build_parameter_list(const lrmd_event_data_t *op,
488 const struct ra_metadata_s *metadata,
489 enum ra_param_flags_e param_type, xmlNode **result)
490 {
491 GString *list = NULL;
492
493 *result = create_xml_node(NULL, XML_TAG_PARAMS);
494
495
496
497
498 if (param_type == ra_param_private
499 && compare_version(controld_globals.dc_version, "3.16.0") >= 0) {
500 g_hash_table_foreach(op->params, hash2field, *result);
501 pcmk__filter_op_for_digest(*result);
502 }
503
504 for (GList *iter = metadata->ra_params; iter != NULL; iter = iter->next) {
505 struct ra_param_s *param = (struct ra_param_s *) iter->data;
506
507 bool accept_for_list = false;
508 bool accept_for_xml = false;
509
510 switch (param_type) {
511 case ra_param_reloadable:
512 accept_for_list = !pcmk_is_set(param->rap_flags, param_type);
513 accept_for_xml = accept_for_list;
514 break;
515
516 case ra_param_unique:
517 accept_for_list = pcmk_is_set(param->rap_flags, param_type);
518 accept_for_xml = accept_for_list;
519 break;
520
521 case ra_param_private:
522 accept_for_list = pcmk_is_set(param->rap_flags, param_type);
523 accept_for_xml = !accept_for_list;
524 break;
525 }
526
527 if (accept_for_list) {
528 crm_trace("Attr %s is %s", param->rap_name, ra_param_flag2text(param_type));
529
530 if (list == NULL) {
531
532 pcmk__add_word(&list, 256, " ");
533 }
534 pcmk__add_word(&list, 0, param->rap_name);
535
536 } else {
537 crm_trace("Rejecting %s for %s", param->rap_name, ra_param_flag2text(param_type));
538 }
539
540 if (accept_for_xml) {
541 const char *v = g_hash_table_lookup(op->params, param->rap_name);
542
543 if (v != NULL) {
544 crm_trace("Adding attr %s=%s to the xml result", param->rap_name, v);
545 crm_xml_add(*result, param->rap_name, v);
546 }
547
548 } else {
549 crm_trace("Removing attr %s from the xml result", param->rap_name);
550 xml_remove_prop(*result, param->rap_name);
551 }
552 }
553
554 if (list != NULL) {
555
556 pcmk__add_word(&list, 0, " ");
557 }
558 return list;
559 }
560
561 static void
562 append_restart_list(lrmd_event_data_t *op, struct ra_metadata_s *metadata,
563 xmlNode *update, const char *version)
564 {
565 GString *list = NULL;
566 char *digest = NULL;
567 xmlNode *restart = NULL;
568
569 CRM_LOG_ASSERT(op->params != NULL);
570
571 if (op->interval_ms > 0) {
572
573 return;
574 }
575
576 if (pcmk_is_set(metadata->ra_flags, ra_supports_reload_agent)) {
577
578 list = build_parameter_list(op, metadata, ra_param_reloadable,
579 &restart);
580
581 } else if (pcmk_is_set(metadata->ra_flags, ra_supports_legacy_reload)) {
582
583
584
585
586
587
588 list = build_parameter_list(op, metadata, ra_param_unique, &restart);
589
590 } else {
591
592 return;
593 }
594
595 digest = calculate_operation_digest(restart, version);
596
597
598 crm_xml_add(update, XML_LRM_ATTR_OP_RESTART,
599 (list == NULL)? "" : (const char *) list->str);
600 crm_xml_add(update, XML_LRM_ATTR_RESTART_DIGEST, digest);
601
602 if ((list != NULL) && (list->len > 0)) {
603 crm_trace("%s: %s, %s", op->rsc_id, digest, (const char *) list->str);
604 } else {
605 crm_trace("%s: %s", op->rsc_id, digest);
606 }
607
608 if (list != NULL) {
609 g_string_free(list, TRUE);
610 }
611 free_xml(restart);
612 free(digest);
613 }
614
615 static void
616 append_secure_list(lrmd_event_data_t *op, struct ra_metadata_s *metadata,
617 xmlNode *update, const char *version)
618 {
619 GString *list = NULL;
620 char *digest = NULL;
621 xmlNode *secure = NULL;
622
623 CRM_LOG_ASSERT(op->params != NULL);
624
625
626
627
628
629
630 list = build_parameter_list(op, metadata, ra_param_private, &secure);
631
632 if (list != NULL) {
633 digest = calculate_operation_digest(secure, version);
634 crm_xml_add(update, XML_LRM_ATTR_OP_SECURE, (const char *) list->str);
635 crm_xml_add(update, XML_LRM_ATTR_SECURE_DIGEST, digest);
636
637 crm_trace("%s: %s, %s", op->rsc_id, digest, (const char *) list->str);
638 g_string_free(list, TRUE);
639 } else {
640 crm_trace("%s: no secure parameters", op->rsc_id);
641 }
642
643 free_xml(secure);
644 free(digest);
645 }
646
647
648
649
650
651
652
653
654
655
656
657 void
658 controld_add_resource_history_xml_as(const char *func, xmlNode *parent,
659 const lrmd_rsc_info_t *rsc,
660 lrmd_event_data_t *op,
661 const char *node_name)
662 {
663 int target_rc = 0;
664 xmlNode *xml_op = NULL;
665 struct ra_metadata_s *metadata = NULL;
666 const char *caller_version = NULL;
667 lrm_state_t *lrm_state = NULL;
668
669 if (op == NULL) {
670 return;
671 }
672
673 target_rc = rsc_op_expected_rc(op);
674
675 caller_version = g_hash_table_lookup(op->params, XML_ATTR_CRM_VERSION);
676 CRM_CHECK(caller_version != NULL, caller_version = CRM_FEATURE_SET);
677
678 xml_op = pcmk__create_history_xml(parent, op, caller_version, target_rc,
679 controld_globals.our_nodename, func);
680 if (xml_op == NULL) {
681 return;
682 }
683
684 if ((rsc == NULL) || (op->params == NULL)
685 || !crm_op_needs_metadata(rsc->standard, op->op_type)) {
686
687 crm_trace("No digests needed for %s action on %s (params=%p rsc=%p)",
688 op->op_type, op->rsc_id, op->params, rsc);
689 return;
690 }
691
692 lrm_state = lrm_state_find(node_name);
693 if (lrm_state == NULL) {
694 crm_warn("Cannot calculate digests for operation " PCMK__OP_FMT
695 " because we have no connection to executor for %s",
696 op->rsc_id, op->op_type, op->interval_ms, node_name);
697 return;
698 }
699
700
701
702
703
704
705 metadata = controld_get_rsc_metadata(lrm_state, rsc,
706 controld_metadata_from_agent
707 |controld_metadata_from_cache);
708 if (metadata == NULL) {
709 return;
710 }
711
712 crm_trace("Including additional digests for %s:%s:%s",
713 rsc->standard, rsc->provider, rsc->type);
714 append_restart_list(op, metadata, xml_op, caller_version);
715 append_secure_list(op, metadata, xml_op, caller_version);
716
717 return;
718 }
719
720
721
722
723
724
725
726
727
728
729
730 bool
731 controld_record_pending_op(const char *node_name, const lrmd_rsc_info_t *rsc,
732 lrmd_event_data_t *op)
733 {
734 const char *record_pending = NULL;
735
736 CRM_CHECK((node_name != NULL) && (rsc != NULL) && (op != NULL),
737 return false);
738
739
740 if ((op->op_type == NULL) || (op->params == NULL)
741 || !controld_action_is_recordable(op->op_type)) {
742 return false;
743 }
744
745
746 record_pending = crm_meta_value(op->params, XML_OP_ATTR_PENDING);
747 if ((record_pending != NULL) && !crm_is_true(record_pending)) {
748 return false;
749 }
750
751 op->call_id = -1;
752 op->t_run = time(NULL);
753 op->t_rcchange = op->t_run;
754
755 lrmd__set_result(op, PCMK_OCF_UNKNOWN, PCMK_EXEC_PENDING, NULL);
756
757 crm_debug("Recording pending %s-interval %s for %s on %s in the CIB",
758 pcmk__readable_interval(op->interval_ms), op->op_type, op->rsc_id,
759 node_name);
760 controld_update_resource_history(node_name, rsc, op, 0);
761 return true;
762 }
763
764 static void
765 cib_rsc_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
766 {
767 switch (rc) {
768 case pcmk_ok:
769 case -pcmk_err_diff_failed:
770 case -pcmk_err_diff_resync:
771 crm_trace("Resource history update completed (call=%d rc=%d)",
772 call_id, rc);
773 break;
774 default:
775 if (call_id > 0) {
776 crm_warn("Resource history update %d failed: %s "
777 CRM_XS " rc=%d", call_id, pcmk_strerror(rc), rc);
778 } else {
779 crm_warn("Resource history update failed: %s " CRM_XS " rc=%d",
780 pcmk_strerror(rc), rc);
781 }
782 }
783
784 if (call_id == pending_rsc_update) {
785 pending_rsc_update = 0;
786 controld_trigger_fsa();
787 }
788 }
789
790
791
792
793
794 static bool
795 should_preserve_lock(lrmd_event_data_t *op)
796 {
797 if (!pcmk_is_set(controld_globals.flags, controld_shutdown_lock_enabled)) {
798 return false;
799 }
800 if (!strcmp(op->op_type, PCMK_ACTION_STOP) && (op->rc == PCMK_OCF_OK)) {
801 return true;
802 }
803 if (!strcmp(op->op_type, PCMK_ACTION_MONITOR)
804 && (op->rc == PCMK_OCF_NOT_RUNNING)) {
805 return true;
806 }
807 return false;
808 }
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824 int
825 controld_update_cib(const char *section, xmlNode *data, int options,
826 void (*callback)(xmlNode *, int, int, xmlNode *, void *))
827 {
828 cib_t *cib = controld_globals.cib_conn;
829 int cib_rc = -ENOTCONN;
830
831 CRM_ASSERT(data != NULL);
832
833 if (cib != NULL) {
834 cib_rc = cib->cmds->modify(cib, section, data, options);
835 if (cib_rc >= 0) {
836 crm_debug("Submitted CIB update %d for %s section",
837 cib_rc, section);
838 }
839 }
840
841 if (callback == NULL) {
842 if (cib_rc < 0) {
843 crm_err("Failed to update CIB %s section: %s",
844 section, pcmk_rc_str(pcmk_legacy2rc(cib_rc)));
845 }
846
847 } else {
848 if ((cib_rc >= 0) && (callback == cib_rsc_callback)) {
849
850
851
852
853 pending_rsc_update = cib_rc;
854 }
855 fsa_register_cib_callback(cib_rc, NULL, callback);
856 }
857
858 return (cib_rc >= 0)? pcmk_rc_ok : pcmk_legacy2rc(cib_rc);
859 }
860
861
862
863
864
865
866
867
868
869
870
871
872
873 void
874 controld_update_resource_history(const char *node_name,
875 const lrmd_rsc_info_t *rsc,
876 lrmd_event_data_t *op, time_t lock_time)
877 {
878 xmlNode *update = NULL;
879 xmlNode *xml = NULL;
880 int call_opt = crmd_cib_smart_opt();
881 const char *node_id = NULL;
882 const char *container = NULL;
883
884 CRM_CHECK((node_name != NULL) && (op != NULL), return);
885
886 if (rsc == NULL) {
887 crm_warn("Resource %s no longer exists in the executor", op->rsc_id);
888 controld_ack_event_directly(NULL, NULL, rsc, op, op->rsc_id);
889 return;
890 }
891
892
893 update = create_xml_node(NULL, XML_CIB_TAG_STATUS);
894
895
896 xml = create_xml_node(update, XML_CIB_TAG_STATE);
897 if (pcmk__str_eq(node_name, controld_globals.our_nodename,
898 pcmk__str_casei)) {
899 node_id = controld_globals.our_uuid;
900 } else {
901 node_id = node_name;
902 pcmk__xe_set_bool_attr(xml, XML_NODE_IS_REMOTE, true);
903 }
904 crm_xml_add(xml, XML_ATTR_ID, node_id);
905 crm_xml_add(xml, XML_ATTR_UNAME, node_name);
906 crm_xml_add(xml, XML_ATTR_ORIGIN, __func__);
907
908
909 xml = create_xml_node(xml, XML_CIB_TAG_LRM);
910 crm_xml_add(xml, XML_ATTR_ID, node_id);
911
912
913 xml = create_xml_node(xml, XML_LRM_TAG_RESOURCES);
914
915
916 xml = create_xml_node(xml, XML_LRM_TAG_RESOURCE);
917 crm_xml_add(xml, XML_ATTR_ID, op->rsc_id);
918 crm_xml_add(xml, XML_AGENT_ATTR_CLASS, rsc->standard);
919 crm_xml_add(xml, XML_AGENT_ATTR_PROVIDER, rsc->provider);
920 crm_xml_add(xml, XML_ATTR_TYPE, rsc->type);
921 if (lock_time != 0) {
922
923
924
925 if (!should_preserve_lock(op)) {
926 lock_time = 0;
927 }
928 crm_xml_add_ll(xml, XML_CONFIG_ATTR_SHUTDOWN_LOCK,
929 (long long) lock_time);
930 }
931 if (op->params != NULL) {
932 container = g_hash_table_lookup(op->params,
933 CRM_META "_" XML_RSC_ATTR_CONTAINER);
934 if (container != NULL) {
935 crm_trace("Resource %s is a part of container resource %s",
936 op->rsc_id, container);
937 crm_xml_add(xml, XML_RSC_ATTR_CONTAINER, container);
938 }
939 }
940
941
942 controld_add_resource_history_xml(xml, rsc, op, node_name);
943
944
945
946
947
948 crm_log_xml_trace(update, __func__);
949 controld_update_cib(XML_CIB_TAG_STATUS, update, call_opt, cib_rsc_callback);
950 free_xml(update);
951 }
952
953
954
955
956
957
958
959 void
960 controld_delete_action_history(const lrmd_event_data_t *op)
961 {
962 xmlNode *xml_top = NULL;
963
964 CRM_CHECK(op != NULL, return);
965
966 xml_top = create_xml_node(NULL, XML_LRM_TAG_RSC_OP);
967 crm_xml_add_int(xml_top, XML_LRM_ATTR_CALLID, op->call_id);
968 crm_xml_add(xml_top, XML_ATTR_TRANSITION_KEY, op->user_data);
969
970 if (op->interval_ms > 0) {
971 char *op_id = pcmk__op_key(op->rsc_id, op->op_type, op->interval_ms);
972
973
974 crm_xml_add(xml_top, XML_ATTR_ID, op_id);
975 free(op_id);
976 }
977
978 crm_debug("Erasing resource operation history for " PCMK__OP_FMT " (call=%d)",
979 op->rsc_id, op->op_type, op->interval_ms, op->call_id);
980
981 controld_globals.cib_conn->cmds->remove(controld_globals.cib_conn,
982 XML_CIB_TAG_STATUS, xml_top,
983 cib_none);
984 crm_log_xml_trace(xml_top, "op:cancel");
985 free_xml(xml_top);
986 }
987
988
989 #define XPATH_HISTORY \
990 "/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS \
991 "/" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']" \
992 "/" XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES \
993 "/" XML_LRM_TAG_RESOURCE "[@" XML_ATTR_ID "='%s']" \
994 "/" XML_LRM_TAG_RSC_OP
995
996
997 #define XPATH_HISTORY_ID XPATH_HISTORY \
998 "[@" XML_ATTR_ID "='%s']"
999
1000
1001 #define XPATH_HISTORY_CALL XPATH_HISTORY \
1002 "[@" XML_ATTR_ID "='%s' and @" XML_LRM_ATTR_CALLID "='%d']"
1003
1004
1005 #define XPATH_HISTORY_ORIG XPATH_HISTORY \
1006 "[@" XML_ATTR_ID "='%s' and @" XML_LRM_ATTR_TASK_KEY "='%s']"
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017 void
1018 controld_cib_delete_last_failure(const char *rsc_id, const char *node,
1019 const char *action, guint interval_ms)
1020 {
1021 char *xpath = NULL;
1022 char *last_failure_key = NULL;
1023 CRM_CHECK((rsc_id != NULL) && (node != NULL), return);
1024
1025
1026 last_failure_key = pcmk__op_key(rsc_id, "last_failure", 0);
1027 if (action == NULL) {
1028 xpath = crm_strdup_printf(XPATH_HISTORY_ID, node, rsc_id,
1029 last_failure_key);
1030 } else {
1031 char *action_key = pcmk__op_key(rsc_id, action, interval_ms);
1032
1033 xpath = crm_strdup_printf(XPATH_HISTORY_ORIG, node, rsc_id,
1034 last_failure_key, action_key);
1035 free(action_key);
1036 }
1037 free(last_failure_key);
1038
1039 controld_globals.cib_conn->cmds->remove(controld_globals.cib_conn, xpath,
1040 NULL, cib_xpath);
1041 free(xpath);
1042 }
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053 void
1054 controld_delete_action_history_by_key(const char *rsc_id, const char *node,
1055 const char *key, int call_id)
1056 {
1057 char *xpath = NULL;
1058
1059 CRM_CHECK((rsc_id != NULL) && (node != NULL) && (key != NULL), return);
1060
1061 if (call_id > 0) {
1062 xpath = crm_strdup_printf(XPATH_HISTORY_CALL, node, rsc_id, key,
1063 call_id);
1064 } else {
1065 xpath = crm_strdup_printf(XPATH_HISTORY_ID, node, rsc_id, key);
1066 }
1067 controld_globals.cib_conn->cmds->remove(controld_globals.cib_conn, xpath,
1068 NULL, cib_xpath);
1069 free(xpath);
1070 }