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