This source file includes following definitions.
- add_migration_meta
- pcmk__create_migration_actions
- pcmk__abort_dangling_migration
- pcmk__rsc_can_migrate
- task_from_action_or_key
- pcmk__order_migration_equivalents
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdbool.h>
13
14 #include <crm/common/xml.h>
15 #include <pacemaker-internal.h>
16
17 #include "libpacemaker_private.h"
18
19
20
21
22
23
24
25
26
27 static void
28 add_migration_meta(pcmk_action_t *action, const pcmk_node_t *source,
29 const pcmk_node_t *target)
30 {
31 pcmk__insert_meta(action, PCMK__META_MIGRATE_SOURCE,
32 source->details->uname);
33
34 pcmk__insert_meta(action, PCMK__META_MIGRATE_TARGET,
35 target->details->uname);
36 }
37
38
39
40
41
42
43
44
45 void
46 pcmk__create_migration_actions(pcmk_resource_t *rsc, const pcmk_node_t *current)
47 {
48 pcmk_action_t *migrate_to = NULL;
49 pcmk_action_t *migrate_from = NULL;
50 pcmk_action_t *start = NULL;
51 pcmk_action_t *stop = NULL;
52
53 pcmk__rsc_trace(rsc, "Creating actions to %smigrate %s from %s to %s",
54 ((rsc->partial_migration_target == NULL)? "" : "partially "),
55 rsc->id, pcmk__node_name(current),
56 pcmk__node_name(rsc->allocated_to));
57 start = start_action(rsc, rsc->allocated_to, TRUE);
58 stop = stop_action(rsc, current, TRUE);
59
60 if (rsc->partial_migration_target == NULL) {
61 migrate_to = custom_action(rsc, pcmk__op_key(rsc->id,
62 PCMK_ACTION_MIGRATE_TO, 0),
63 PCMK_ACTION_MIGRATE_TO, current, TRUE,
64 rsc->cluster);
65 }
66 migrate_from = custom_action(rsc, pcmk__op_key(rsc->id,
67 PCMK_ACTION_MIGRATE_FROM, 0),
68 PCMK_ACTION_MIGRATE_FROM, rsc->allocated_to,
69 TRUE, rsc->cluster);
70
71 pcmk__set_action_flags(start, pcmk_action_migratable);
72 pcmk__set_action_flags(stop, pcmk_action_migratable);
73
74
75 pcmk__set_action_flags(start, pcmk_action_pseudo);
76
77 if (rsc->partial_migration_target == NULL) {
78 pcmk__set_action_flags(migrate_from, pcmk_action_migratable);
79 pcmk__set_action_flags(migrate_to, pcmk_action_migratable);
80 migrate_to->needs = start->needs;
81
82
83 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MONITOR, 0),
84 NULL,
85 rsc,
86 pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_TO, 0),
87 NULL, pcmk__ar_ordered, rsc->cluster);
88 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_TO, 0),
89 NULL,
90 rsc,
91 pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
92 NULL,
93 pcmk__ar_ordered|pcmk__ar_unmigratable_then_blocks,
94 rsc->cluster);
95 } else {
96 pcmk__set_action_flags(migrate_from, pcmk_action_migratable);
97 migrate_from->needs = start->needs;
98
99
100 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MONITOR, 0),
101 NULL,
102 rsc,
103 pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
104 NULL, pcmk__ar_ordered, rsc->cluster);
105 }
106
107
108 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
109 NULL,
110 rsc, pcmk__op_key(rsc->id, PCMK_ACTION_STOP, 0),
111 NULL,
112 pcmk__ar_ordered|pcmk__ar_unmigratable_then_blocks,
113 rsc->cluster);
114 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
115 NULL,
116 rsc, pcmk__op_key(rsc->id, PCMK_ACTION_START, 0),
117 NULL,
118 pcmk__ar_ordered
119 |pcmk__ar_unmigratable_then_blocks
120 |pcmk__ar_first_else_then,
121 rsc->cluster);
122
123 if (migrate_to != NULL) {
124 add_migration_meta(migrate_to, current, rsc->allocated_to);
125
126 if (!rsc->is_remote_node) {
127
128
129
130
131
132
133
134
135
136
137
138 pcmk__insert_meta(migrate_to,
139 PCMK_META_RECORD_PENDING, PCMK_VALUE_TRUE);
140 }
141 }
142
143 add_migration_meta(migrate_from, current, rsc->allocated_to);
144 }
145
146
147
148
149
150
151
152
153 void
154 pcmk__abort_dangling_migration(void *data, void *user_data)
155 {
156 const pcmk_node_t *dangling_source = (const pcmk_node_t *) data;
157 pcmk_resource_t *rsc = (pcmk_resource_t *) user_data;
158
159 pcmk_action_t *stop = NULL;
160 bool cleanup = pcmk_is_set(rsc->cluster->flags,
161 pcmk_sched_remove_after_stop);
162
163 pcmk__rsc_trace(rsc,
164 "Scheduling stop%s for %s on %s due to dangling migration",
165 (cleanup? " and cleanup" : ""), rsc->id,
166 pcmk__node_name(dangling_source));
167 stop = stop_action(rsc, dangling_source, FALSE);
168 pcmk__set_action_flags(stop, pcmk_action_migration_abort);
169 if (cleanup) {
170 pcmk__schedule_cleanup(rsc, dangling_source, false);
171 }
172 }
173
174
175
176
177
178
179
180
181
182
183 bool
184 pcmk__rsc_can_migrate(const pcmk_resource_t *rsc, const pcmk_node_t *current)
185 {
186 CRM_CHECK(rsc != NULL, return false);
187
188 if (!pcmk_is_set(rsc->flags, pcmk_rsc_migratable)) {
189 pcmk__rsc_trace(rsc,
190 "%s cannot migrate because "
191 "the configuration does not allow it", rsc->id);
192 return false;
193 }
194
195 if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
196 pcmk__rsc_trace(rsc, "%s cannot migrate because it is not managed",
197 rsc->id);
198 return false;
199 }
200
201 if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
202 pcmk__rsc_trace(rsc, "%s cannot migrate because it is failed", rsc->id);
203 return false;
204 }
205
206 if (pcmk_is_set(rsc->flags, pcmk_rsc_start_pending)) {
207 pcmk__rsc_trace(rsc, "%s cannot migrate because it has a start pending",
208 rsc->id);
209 return false;
210 }
211
212 if ((current == NULL) || current->details->unclean) {
213 pcmk__rsc_trace(rsc,
214 "%s cannot migrate because "
215 "its current node (%s) is unclean",
216 rsc->id, pcmk__node_name(current));
217 return false;
218 }
219
220 if ((rsc->allocated_to == NULL) || rsc->allocated_to->details->unclean) {
221 pcmk__rsc_trace(rsc,
222 "%s cannot migrate because "
223 "its next node (%s) is unclean",
224 rsc->id, pcmk__node_name(rsc->allocated_to));
225 return false;
226 }
227
228 return true;
229 }
230
231
232
233
234
235
236
237
238
239
240 static char *
241 task_from_action_or_key(const pcmk_action_t *action, const char *key)
242 {
243 char *res = NULL;
244
245 if (action != NULL) {
246 res = pcmk__str_copy(action->task);
247 } else if (key != NULL) {
248 parse_op_key(key, NULL, &res, NULL);
249 }
250 return res;
251 }
252
253
254
255
256
257
258
259
260
261
262
263 void
264 pcmk__order_migration_equivalents(pcmk__action_relation_t *order)
265 {
266 char *first_task = NULL;
267 char *then_task = NULL;
268 bool then_migratable;
269 bool first_migratable;
270
271
272 if ((order->rsc1 == NULL) || (order->rsc2 == NULL)
273 || (order->rsc1 == order->rsc2)
274 || is_parent(order->rsc1, order->rsc2)
275 || is_parent(order->rsc2, order->rsc1)) {
276 return;
277 }
278
279
280 first_migratable = pcmk_is_set(order->rsc1->flags, pcmk_rsc_migratable);
281 then_migratable = pcmk_is_set(order->rsc2->flags, pcmk_rsc_migratable);
282 if (!first_migratable && !then_migratable) {
283 return;
284 }
285
286
287 first_task = task_from_action_or_key(order->action1, order->task1);
288 then_task = task_from_action_or_key(order->action2, order->task2);
289
290 if (pcmk__str_eq(first_task, PCMK_ACTION_START, pcmk__str_none)
291 && pcmk__str_eq(then_task, PCMK_ACTION_START, pcmk__str_none)) {
292
293 uint32_t flags = pcmk__ar_ordered;
294
295 if (first_migratable && then_migratable) {
296
297
298 pcmk__new_ordering(order->rsc1,
299 pcmk__op_key(order->rsc1->id,
300 PCMK_ACTION_MIGRATE_FROM, 0),
301 NULL, order->rsc2,
302 pcmk__op_key(order->rsc2->id,
303 PCMK_ACTION_MIGRATE_TO, 0),
304 NULL, flags, order->rsc1->cluster);
305 }
306
307 if (then_migratable) {
308 if (first_migratable) {
309 pcmk__set_relation_flags(flags, pcmk__ar_if_first_unmigratable);
310 }
311
312
313
314
315
316 pcmk__new_ordering(order->rsc1,
317 pcmk__op_key(order->rsc1->id,
318 PCMK_ACTION_START, 0),
319 NULL, order->rsc2,
320 pcmk__op_key(order->rsc2->id,
321 PCMK_ACTION_MIGRATE_TO, 0),
322 NULL, flags, order->rsc1->cluster);
323 }
324
325 } else if (then_migratable
326 && pcmk__str_eq(first_task, PCMK_ACTION_STOP, pcmk__str_none)
327 && pcmk__str_eq(then_task, PCMK_ACTION_STOP, pcmk__str_none)) {
328
329 uint32_t flags = pcmk__ar_ordered;
330
331 if (first_migratable) {
332 pcmk__set_relation_flags(flags, pcmk__ar_if_first_unmigratable);
333 }
334
335
336
337
338 pcmk__new_ordering(order->rsc1,
339 pcmk__op_key(order->rsc1->id, PCMK_ACTION_STOP, 0),
340 NULL,
341 order->rsc2,
342 pcmk__op_key(order->rsc2->id,
343 PCMK_ACTION_MIGRATE_TO, 0),
344 NULL, flags, order->rsc1->cluster);
345
346
347 if (order->rsc2->partial_migration_target != NULL) {
348 pcmk__new_ordering(order->rsc1,
349 pcmk__op_key(order->rsc1->id, PCMK_ACTION_STOP,
350 0),
351 NULL, order->rsc2,
352 pcmk__op_key(order->rsc2->id,
353 PCMK_ACTION_MIGRATE_FROM, 0),
354 NULL, flags, order->rsc1->cluster);
355 }
356
357 } else if (pcmk__str_eq(first_task, PCMK_ACTION_PROMOTE, pcmk__str_none)
358 && pcmk__str_eq(then_task, PCMK_ACTION_START, pcmk__str_none)) {
359
360 uint32_t flags = pcmk__ar_ordered;
361
362 if (then_migratable) {
363
364
365 pcmk__new_ordering(order->rsc1,
366 pcmk__op_key(order->rsc1->id,
367 PCMK_ACTION_PROMOTE, 0),
368 NULL, order->rsc2,
369 pcmk__op_key(order->rsc2->id,
370 PCMK_ACTION_MIGRATE_TO, 0),
371 NULL, flags, order->rsc1->cluster);
372 }
373
374 } else if (pcmk__str_eq(first_task, PCMK_ACTION_DEMOTE, pcmk__str_none)
375 && pcmk__str_eq(then_task, PCMK_ACTION_STOP, pcmk__str_none)) {
376
377 uint32_t flags = pcmk__ar_ordered;
378
379 if (then_migratable) {
380
381
382 pcmk__new_ordering(order->rsc1,
383 pcmk__op_key(order->rsc1->id,
384 PCMK_ACTION_DEMOTE, 0),
385 NULL, order->rsc2,
386 pcmk__op_key(order->rsc2->id,
387 PCMK_ACTION_MIGRATE_TO, 0),
388 NULL, flags, order->rsc1->cluster);
389
390
391 if (order->rsc2->partial_migration_target != NULL) {
392 pcmk__new_ordering(order->rsc1,
393 pcmk__op_key(order->rsc1->id,
394 PCMK_ACTION_DEMOTE, 0),
395 NULL, order->rsc2,
396 pcmk__op_key(order->rsc2->id,
397 PCMK_ACTION_MIGRATE_FROM, 0),
398 NULL, flags, order->rsc1->cluster);
399 }
400 }
401 }
402
403 free(first_task);
404 free(then_task);
405 }