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