1 /*
2 * Copyright 2004-2026 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU General Public License version 2
7 * or later (GPLv2+) WITHOUT ANY WARRANTY.
8 */
9
10 #include <crm_internal.h>
11
12 #include <stdbool.h>
13
14 #include <crm/crm.h>
15 #include <crm/common/xml.h>
16
17 #include <pacemaker-controld.h>
18
19 static pcmk__graph_t *
20 create_blank_graph(void)
21 {
22 pcmk__graph_t *graph = pcmk__unpack_graph(NULL, NULL);
23
24 graph->complete = true;
25 graph->abort_reason = "DC Takeover";
26 graph->completion_action = pcmk__graph_restart;
27 return graph;
28 }
29
30 // A_TE_START, A_TE_STOP, O_TE_RESTART
31 void
32 do_te_control(long long action, enum crmd_fsa_cause cause,
33 enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input,
34 fsa_data_t *msg_data)
35 {
36 cib_t *cib_conn = controld_globals.cib_conn;
37
|
(1) Event path: |
Condition "pcmk__is_set(action, 70368744177664UL /* 1UL << 46 */)", taking true branch. |
38 if (pcmk__is_set(action, A_TE_STOP)) {
|
CID (unavailable; MK=3f10c91452afa4a18b2b7ec68f5203ee) (#1 of 1): Inconsistent C union access (INCONSISTENT_UNION_ACCESS): |
|
(2) Event assign_union_field: |
The union field "in" of "_pp" is written. |
|
(3) Event inconsistent_union_field_access: |
In "_pp.out", the union field used: "out" is inconsistent with the field most recently stored: "in". |
39 g_clear_pointer(&controld_globals.transition_graph, pcmk__free_graph);
40
41 if (cib_conn != NULL) {
42 cib_conn->cmds->del_notify_callback(cib_conn,
43 PCMK__VALUE_CIB_DIFF_NOTIFY,
44 te_update_diff);
45 }
46
47 controld_clear_fsa_input_flags(R_TE_CONNECTED);
48 pcmk__info("Transitioner is now inactive");
49 }
50
51 if (!pcmk__is_set(action, A_TE_START)) {
52 return;
53 }
54
55 if (pcmk__is_set(controld_globals.fsa_input_register, R_TE_CONNECTED)) {
56 pcmk__debug("The transitioner is already active");
57 return;
58 }
59
60 if (cur_state == S_STOPPING) {
61 pcmk__info("Ignoring request to start the transitioner while shutting "
62 "down");
63 return;
64 }
65
66 if ((cib_conn == NULL)
67 || (cib_conn->cmds->add_notify_callback(cib_conn,
68 PCMK__VALUE_CIB_DIFF_NOTIFY,
69 te_update_diff) != pcmk_ok)) {
70 pcmk__err("Could not set CIB notification callback");
71 return;
72 }
73
74 if (controld_globals.te_uuid == NULL) {
75 controld_globals.te_uuid = pcmk__generate_uuid();
76 pcmk__info("Registering TE UUID: %s", controld_globals.te_uuid);
77 }
78
79 controld_register_graph_functions();
80 pcmk__free_graph(controld_globals.transition_graph);
81 controld_globals.transition_graph = create_blank_graph();
82 controld_set_fsa_input_flags(R_TE_CONNECTED);
83 pcmk__debug("Transitioner is now active");
84 }
85
86 // A_TE_INVOKE, A_TE_CANCEL
87 void
88 do_te_invoke(long long action, enum crmd_fsa_cause cause,
89 enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input,
90 fsa_data_t *msg_data)
91 {
92 ha_msg_input_t *input = NULL;
93 xmlNode *graph_data = NULL;
94 const char *ref = NULL;
95 const char *graph_input = NULL;
96
97 if (!AM_I_DC) {
98 pcmk__notice("Not invoking the TE because we are not the DC");
99 return;
100 }
101
102 if (pcmk__is_set(action, A_TE_INVOKE)
103 && (controld_globals.fsa_state != S_TRANSITION_ENGINE)) {
104
105 pcmk__notice("No need to invoke the TE (%s) while in state %s",
106 fsa_action2string(action),
107 fsa_state2string(controld_globals.fsa_state));
108 return;
109 }
110
111 if (pcmk__is_set(action, A_TE_CANCEL)) {
112 pcmk__debug("Cancelling the transition: %sactive",
113 (controld_globals.transition_graph->complete? "in" : ""));
114
115 abort_transition(PCMK_SCORE_INFINITY, pcmk__graph_restart,
116 "Peer cancelled", NULL);
117 if (!controld_globals.transition_graph->complete) {
118 controld_fsa_stall(msg_data, action);
119 }
120 return;
121 }
122
123 if (pcmk__is_set(action, A_TE_HALT)) {
124 abort_transition(PCMK_SCORE_INFINITY, pcmk__graph_wait, "Peer halt",
125 NULL);
126 if (!controld_globals.transition_graph->complete) {
127 controld_fsa_stall(msg_data, action);
128 }
129 return;
130 }
131
132 if (!pcmk__is_set(action, A_TE_INVOKE)) {
133 return;
134 }
135
136 pcmk__assert((msg_data != NULL) && (msg_data->data != NULL));
137
138 input = msg_data->data;
139 graph_data = input->xml;
140 if (graph_data == NULL) {
141 pcmk__log_xml_err(input->msg, "Bad command");
142 register_fsa_error(I_FAIL, msg_data);
143 return;
144 }
145
146 if (!controld_globals.transition_graph->complete) {
147 pcmk__info("Another transition is already active");
148 abort_transition(PCMK_SCORE_INFINITY, pcmk__graph_restart,
149 "Transition active", NULL);
150 return;
151 }
152
153 ref = pcmk__xe_get(input->msg, PCMK_XA_REFERENCE);
154
155 if ((controld_globals.fsa_pe_ref == NULL)
156 || !pcmk__str_eq(controld_globals.fsa_pe_ref, ref,
157 pcmk__str_none)) {
158 pcmk__info("Transition is redundant: %s expected but %s received",
159 pcmk__s(controld_globals.fsa_pe_ref, "no reference"),
160 pcmk__s(ref, "no reference"));
161 abort_transition(PCMK_SCORE_INFINITY, pcmk__graph_restart,
162 "Transition redundant", NULL);
163 }
164
165 if (controld_is_started_transition_timer()) {
166 pcmk__debug("The transitioner wait for a transition timer");
167 return;
168 }
169
170 CRM_CHECK(graph_data != NULL,
171 pcmk__err("Input raised by %s is invalid", msg_data->origin);
172 pcmk__log_xml_err(input->msg, "Bad command");
173 return);
174
175 graph_input = pcmk__xe_get(input->msg, PCMK__XA_CRM_TGRAPH_IN);
176 pcmk__free_graph(controld_globals.transition_graph);
177 controld_globals.transition_graph = pcmk__unpack_graph(graph_data,
178 graph_input);
179
180 CRM_CHECK(controld_globals.transition_graph != NULL,
181 controld_globals.transition_graph = create_blank_graph();
182 return);
183
184 pcmk__info("Processing graph %d (ref=%s) derived from %s",
185 controld_globals.transition_graph->id, ref, graph_input);
186
187 te_reset_job_counts();
188
189 trigger_graph();
190 pcmk__log_graph(LOG_TRACE, controld_globals.transition_graph);
191
192 if (graph_data != input->xml) {
193 pcmk__xml_free(graph_data);
194 }
195 }
196