This source file includes following definitions.
- stop_te_timer
- te_graph_trigger
- trigger_graph_processing
- abort_timer_popped
- abort_after_delay
- abort_transition_graph
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/crm.h>
12 #include <crm/msg_xml.h>
13 #include <crm/common/xml.h>
14
15 #include <pacemaker-controld.h>
16
17 gboolean
18 stop_te_timer(crm_action_timer_t * timer)
19 {
20 if (timer == NULL) {
21 return FALSE;
22 }
23 if (timer->source_id != 0) {
24 crm_trace("Stopping action timer");
25 g_source_remove(timer->source_id);
26 timer->source_id = 0;
27 } else {
28 crm_trace("Action timer was already stopped");
29 return FALSE;
30 }
31 return TRUE;
32 }
33
34 gboolean
35 te_graph_trigger(gpointer user_data)
36 {
37 enum transition_status graph_rc = -1;
38
39 if (transition_graph == NULL) {
40 crm_debug("Nothing to do");
41 return TRUE;
42 }
43
44 crm_trace("Invoking graph %d in state %s", transition_graph->id, fsa_state2string(fsa_state));
45
46 switch (fsa_state) {
47 case S_STARTING:
48 case S_PENDING:
49 case S_NOT_DC:
50 case S_HALT:
51 case S_ILLEGAL:
52 case S_STOPPING:
53 case S_TERMINATE:
54 return TRUE;
55 default:
56 break;
57 }
58
59 if (transition_graph->complete == FALSE) {
60 int limit = transition_graph->batch_limit;
61
62 transition_graph->batch_limit = throttle_get_total_job_limit(limit);
63 graph_rc = run_graph(transition_graph);
64 transition_graph->batch_limit = limit;
65
66
67
68
69 if (graph_rc == transition_active) {
70 crm_trace("Transition not yet complete");
71 return TRUE;
72
73 } else if (graph_rc == transition_pending) {
74 crm_trace("Transition not yet complete - no actions fired");
75 return TRUE;
76 }
77
78 if (graph_rc != transition_complete) {
79 crm_warn("Transition failed: %s", transition_status(graph_rc));
80 print_graph(LOG_NOTICE, transition_graph);
81 }
82 }
83
84 crm_debug("Transition %d is now complete", transition_graph->id);
85 transition_graph->complete = TRUE;
86 notify_crmd(transition_graph);
87
88 return TRUE;
89 }
90
91 void
92 trigger_graph_processing(const char *fn, int line)
93 {
94 crm_trace("%s:%d - Triggered graph processing", fn, line);
95 mainloop_set_trigger(transition_trigger);
96 }
97
98 static struct abort_timer_s {
99 bool aborted;
100 guint id;
101 int priority;
102 enum transition_action action;
103 const char *text;
104 } abort_timer = { 0, };
105
106 static gboolean
107 abort_timer_popped(gpointer data)
108 {
109 if (AM_I_DC && (abort_timer.aborted == FALSE)) {
110 abort_transition(abort_timer.priority, abort_timer.action,
111 abort_timer.text, NULL);
112 }
113 abort_timer.id = 0;
114 return FALSE;
115 }
116
117
118
119
120
121
122
123 void
124 abort_after_delay(int abort_priority, enum transition_action abort_action,
125 const char *abort_text, guint delay_ms)
126 {
127 if (abort_timer.id) {
128
129 g_source_remove(abort_timer.id);
130 }
131 abort_timer.aborted = FALSE;
132 abort_timer.priority = abort_priority;
133 abort_timer.action = abort_action;
134 abort_timer.text = abort_text;
135 abort_timer.id = g_timeout_add(delay_ms, abort_timer_popped, NULL);
136 }
137
138 void
139 abort_transition_graph(int abort_priority, enum transition_action abort_action,
140 const char *abort_text, xmlNode * reason, const char *fn, int line)
141 {
142 int add[] = { 0, 0, 0 };
143 int del[] = { 0, 0, 0 };
144 int level = LOG_INFO;
145 xmlNode *diff = NULL;
146 xmlNode *change = NULL;
147
148 CRM_CHECK(transition_graph != NULL, return);
149
150 switch (fsa_state) {
151 case S_STARTING:
152 case S_PENDING:
153 case S_NOT_DC:
154 case S_HALT:
155 case S_ILLEGAL:
156 case S_STOPPING:
157 case S_TERMINATE:
158 crm_info("Abort %s suppressed: state=%s (complete=%d)",
159 abort_text, fsa_state2string(fsa_state), transition_graph->complete);
160 return;
161 default:
162 break;
163 }
164
165 abort_timer.aborted = TRUE;
166 controld_expect_sched_reply(NULL);
167
168 if (transition_graph->complete == FALSE) {
169 if(update_abort_priority(transition_graph, abort_priority, abort_action, abort_text)) {
170 level = LOG_NOTICE;
171 }
172 }
173
174 if(reason) {
175 xmlNode *search = NULL;
176
177 for(search = reason; search; search = search->parent) {
178 if (pcmk__str_eq(XML_TAG_DIFF, TYPE(search), pcmk__str_casei)) {
179 diff = search;
180 break;
181 }
182 }
183
184 if(diff) {
185 xml_patch_versions(diff, add, del);
186 for(search = reason; search; search = search->parent) {
187 if (pcmk__str_eq(XML_DIFF_CHANGE, TYPE(search), pcmk__str_casei)) {
188 change = search;
189 break;
190 }
191 }
192 }
193 }
194
195 if(reason == NULL) {
196 do_crm_log(level, "Transition %d aborted: %s "CRM_XS" source=%s:%d complete=%s",
197 transition_graph->id, abort_text, fn, line,
198 pcmk__btoa(transition_graph->complete));
199
200 } else if(change == NULL) {
201 char *local_path = xml_get_path(reason);
202
203 do_crm_log(level, "Transition %d aborted by %s.%s: %s "
204 CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
205 transition_graph->id, TYPE(reason), ID(reason), abort_text,
206 add[0], add[1], add[2], fn, line, local_path,
207 pcmk__btoa(transition_graph->complete));
208 free(local_path);
209
210 } else {
211 const char *kind = NULL;
212 const char *op = crm_element_value(change, XML_DIFF_OP);
213 const char *path = crm_element_value(change, XML_DIFF_PATH);
214
215 if(change == reason) {
216 if(strcmp(op, "create") == 0) {
217 reason = reason->children;
218
219 } else if(strcmp(op, "modify") == 0) {
220 reason = first_named_child(reason, XML_DIFF_RESULT);
221 if(reason) {
222 reason = reason->children;
223 }
224 }
225 }
226
227 kind = TYPE(reason);
228 if(strcmp(op, "delete") == 0) {
229 const char *shortpath = strrchr(path, '/');
230
231 do_crm_log(level, "Transition %d aborted by deletion of %s: %s "
232 CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
233 transition_graph->id,
234 (shortpath? (shortpath + 1) : path), abort_text,
235 add[0], add[1], add[2], fn, line, path,
236 pcmk__btoa(transition_graph->complete));
237
238 } else if (pcmk__str_eq(XML_CIB_TAG_NVPAIR, kind, pcmk__str_casei)) {
239 do_crm_log(level, "Transition %d aborted by %s doing %s %s=%s: %s "
240 CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
241 transition_graph->id,
242 crm_element_value(reason, XML_ATTR_ID), op,
243 crm_element_value(reason, XML_NVPAIR_ATTR_NAME),
244 crm_element_value(reason, XML_NVPAIR_ATTR_VALUE),
245 abort_text, add[0], add[1], add[2], fn, line, path,
246 pcmk__btoa(transition_graph->complete));
247
248 } else if (pcmk__str_eq(XML_LRM_TAG_RSC_OP, kind, pcmk__str_casei)) {
249 const char *magic = crm_element_value(reason, XML_ATTR_TRANSITION_MAGIC);
250
251 do_crm_log(level, "Transition %d aborted by operation %s '%s' on %s: %s "
252 CRM_XS " magic=%s cib=%d.%d.%d source=%s:%d complete=%s",
253 transition_graph->id,
254 crm_element_value(reason, XML_LRM_ATTR_TASK_KEY), op,
255 crm_element_value(reason, XML_LRM_ATTR_TARGET), abort_text,
256 magic, add[0], add[1], add[2], fn, line,
257 pcmk__btoa(transition_graph->complete));
258
259 } else if (pcmk__strcase_any_of(kind, XML_CIB_TAG_STATE, XML_CIB_TAG_NODE, NULL)) {
260 const char *uname = crm_peer_uname(ID(reason));
261
262 do_crm_log(level, "Transition %d aborted by %s '%s' on %s: %s "
263 CRM_XS " cib=%d.%d.%d source=%s:%d complete=%s",
264 transition_graph->id,
265 kind, op, (uname? uname : ID(reason)), abort_text,
266 add[0], add[1], add[2], fn, line,
267 pcmk__btoa(transition_graph->complete));
268
269 } else {
270 const char *id = ID(reason);
271
272 do_crm_log(level, "Transition %d aborted by %s.%s '%s': %s "
273 CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
274 transition_graph->id,
275 TYPE(reason), (id? id : ""), (op? op : "change"),
276 abort_text, add[0], add[1], add[2], fn, line, path,
277 pcmk__btoa(transition_graph->complete));
278 }
279 }
280
281 if (transition_graph->complete) {
282 if (transition_timer->period_ms > 0) {
283 controld_stop_timer(transition_timer);
284 controld_start_timer(transition_timer);
285 } else {
286 register_fsa_input(C_FSA_INTERNAL, I_PE_CALC, NULL);
287 }
288 return;
289 }
290
291 mainloop_set_trigger(transition_trigger);
292 }