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