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/msg_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 add_hash_param(action->meta, XML_LRM_ATTR_MIGRATE_SOURCE,
32 source->details->uname);
33
34 add_hash_param(action->meta, XML_LRM_ATTR_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 pe_rsc_trace(rsc, "Creating actions to %smigrate %s from %s to %s",
54 ((rsc->partial_migration_target == NULL)? "" : "partially "),
55 rsc->id, pe__node_name(current),
56 pe__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 pe__set_action_flags(start, pcmk_action_migratable);
72 pe__set_action_flags(stop, pcmk_action_migratable);
73
74
75 pe__set_action_flags(start, pcmk_action_pseudo);
76
77 if (rsc->partial_migration_target == NULL) {
78 pe__set_action_flags(migrate_from, pcmk_action_migratable);
79 pe__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 pe__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 add_hash_param(migrate_to->meta, XML_OP_ATTR_PENDING, "true");
139 }
140 }
141
142 add_migration_meta(migrate_from, current, rsc->allocated_to);
143 }
144
145
146
147
148
149
150
151
152 void
153 pcmk__abort_dangling_migration(void *data, void *user_data)
154 {
155 const pcmk_node_t *dangling_source = (const pcmk_node_t *) data;
156 pcmk_resource_t *rsc = (pcmk_resource_t *) user_data;
157
158 pcmk_action_t *stop = NULL;
159 bool cleanup = pcmk_is_set(rsc->cluster->flags,
160 pcmk_sched_remove_after_stop);
161
162 pe_rsc_trace(rsc,
163 "Scheduling stop%s for %s on %s due to dangling migration",
164 (cleanup? " and cleanup" : ""), rsc->id,
165 pe__node_name(dangling_source));
166 stop = stop_action(rsc, dangling_source, FALSE);
167 pe__set_action_flags(stop, pcmk_action_migration_abort);
168 if (cleanup) {
169 pcmk__schedule_cleanup(rsc, dangling_source, false);
170 }
171 }
172
173
174
175
176
177
178
179
180
181
182 bool
183 pcmk__rsc_can_migrate(const pcmk_resource_t *rsc, const pcmk_node_t *current)
184 {
185 CRM_CHECK(rsc != NULL, return false);
186
187 if (!pcmk_is_set(rsc->flags, pcmk_rsc_migratable)) {
188 pe_rsc_trace(rsc, "%s cannot migrate because "
189 "the configuration does not allow it",
190 rsc->id);
191 return false;
192 }
193
194 if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
195 pe_rsc_trace(rsc, "%s cannot migrate because it is not managed",
196 rsc->id);
197 return false;
198 }
199
200 if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
201 pe_rsc_trace(rsc, "%s cannot migrate because it is failed",
202 rsc->id);
203 return false;
204 }
205
206 if (pcmk_is_set(rsc->flags, pcmk_rsc_start_pending)) {
207 pe_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 pe_rsc_trace(rsc, "%s cannot migrate because "
214 "its current node (%s) is unclean",
215 rsc->id, pe__node_name(current));
216 return false;
217 }
218
219 if ((rsc->allocated_to == NULL) || rsc->allocated_to->details->unclean) {
220 pe_rsc_trace(rsc, "%s cannot migrate because "
221 "its next node (%s) is unclean",
222 rsc->id, pe__node_name(rsc->allocated_to));
223 return false;
224 }
225
226 return true;
227 }
228
229
230
231
232
233
234
235
236
237
238 static char *
239 task_from_action_or_key(const pcmk_action_t *action, const char *key)
240 {
241 char *res = NULL;
242
243 if (action != NULL) {
244 res = strdup(action->task);
245 CRM_ASSERT(res != NULL);
246 } else if (key != NULL) {
247 parse_op_key(key, NULL, &res, NULL);
248 }
249 return res;
250 }
251
252
253
254
255
256
257
258
259
260
261
262 void
263 pcmk__order_migration_equivalents(pe__ordering_t *order)
264 {
265 char *first_task = NULL;
266 char *then_task = NULL;
267 bool then_migratable;
268 bool first_migratable;
269
270
271 if ((order->lh_rsc == NULL) || (order->rh_rsc == NULL)
272 || (order->lh_rsc == order->rh_rsc)
273 || is_parent(order->lh_rsc, order->rh_rsc)
274 || is_parent(order->rh_rsc, order->lh_rsc)) {
275 return;
276 }
277
278
279 first_migratable = pcmk_is_set(order->lh_rsc->flags, pcmk_rsc_migratable);
280 then_migratable = pcmk_is_set(order->rh_rsc->flags, pcmk_rsc_migratable);
281 if (!first_migratable && !then_migratable) {
282 return;
283 }
284
285
286 first_task = task_from_action_or_key(order->lh_action,
287 order->lh_action_task);
288 then_task = task_from_action_or_key(order->rh_action,
289 order->rh_action_task);
290
291 if (pcmk__str_eq(first_task, PCMK_ACTION_START, pcmk__str_none)
292 && pcmk__str_eq(then_task, PCMK_ACTION_START, pcmk__str_none)) {
293
294 uint32_t flags = pcmk__ar_ordered;
295
296 if (first_migratable && then_migratable) {
297
298
299 pcmk__new_ordering(order->lh_rsc,
300 pcmk__op_key(order->lh_rsc->id,
301 PCMK_ACTION_MIGRATE_FROM, 0),
302 NULL, order->rh_rsc,
303 pcmk__op_key(order->rh_rsc->id,
304 PCMK_ACTION_MIGRATE_TO, 0),
305 NULL, flags, order->lh_rsc->cluster);
306 }
307
308 if (then_migratable) {
309 if (first_migratable) {
310 pe__set_order_flags(flags, pcmk__ar_if_first_unmigratable);
311 }
312
313
314
315
316
317 pcmk__new_ordering(order->lh_rsc,
318 pcmk__op_key(order->lh_rsc->id,
319 PCMK_ACTION_START, 0),
320 NULL, order->rh_rsc,
321 pcmk__op_key(order->rh_rsc->id,
322 PCMK_ACTION_MIGRATE_TO, 0),
323 NULL, flags, order->lh_rsc->cluster);
324 }
325
326 } else if (then_migratable
327 && pcmk__str_eq(first_task, PCMK_ACTION_STOP, pcmk__str_none)
328 && pcmk__str_eq(then_task, PCMK_ACTION_STOP, pcmk__str_none)) {
329
330 uint32_t flags = pcmk__ar_ordered;
331
332 if (first_migratable) {
333 pe__set_order_flags(flags, pcmk__ar_if_first_unmigratable);
334 }
335
336
337
338
339 pcmk__new_ordering(order->lh_rsc,
340 pcmk__op_key(order->lh_rsc->id, PCMK_ACTION_STOP, 0),
341 NULL,
342 order->rh_rsc,
343 pcmk__op_key(order->rh_rsc->id,
344 PCMK_ACTION_MIGRATE_TO, 0),
345 NULL, flags, order->lh_rsc->cluster);
346
347
348 if (order->rh_rsc->partial_migration_target) {
349 pcmk__new_ordering(order->lh_rsc,
350 pcmk__op_key(order->lh_rsc->id, PCMK_ACTION_STOP,
351 0),
352 NULL, order->rh_rsc,
353 pcmk__op_key(order->rh_rsc->id,
354 PCMK_ACTION_MIGRATE_FROM, 0),
355 NULL, flags, order->lh_rsc->cluster);
356 }
357
358 } else if (pcmk__str_eq(first_task, PCMK_ACTION_PROMOTE, pcmk__str_none)
359 && pcmk__str_eq(then_task, PCMK_ACTION_START, pcmk__str_none)) {
360
361 uint32_t flags = pcmk__ar_ordered;
362
363 if (then_migratable) {
364
365
366 pcmk__new_ordering(order->lh_rsc,
367 pcmk__op_key(order->lh_rsc->id,
368 PCMK_ACTION_PROMOTE, 0),
369 NULL, order->rh_rsc,
370 pcmk__op_key(order->rh_rsc->id,
371 PCMK_ACTION_MIGRATE_TO, 0),
372 NULL, flags, order->lh_rsc->cluster);
373 }
374
375 } else if (pcmk__str_eq(first_task, PCMK_ACTION_DEMOTE, pcmk__str_none)
376 && pcmk__str_eq(then_task, PCMK_ACTION_STOP, pcmk__str_none)) {
377
378 uint32_t flags = pcmk__ar_ordered;
379
380 if (then_migratable) {
381
382
383 pcmk__new_ordering(order->lh_rsc,
384 pcmk__op_key(order->lh_rsc->id,
385 PCMK_ACTION_DEMOTE, 0),
386 NULL, order->rh_rsc,
387 pcmk__op_key(order->rh_rsc->id,
388 PCMK_ACTION_MIGRATE_TO, 0),
389 NULL, flags, order->lh_rsc->cluster);
390
391
392 if (order->rh_rsc->partial_migration_target) {
393 pcmk__new_ordering(order->lh_rsc,
394 pcmk__op_key(order->lh_rsc->id,
395 PCMK_ACTION_DEMOTE, 0),
396 NULL, order->rh_rsc,
397 pcmk__op_key(order->rh_rsc->id,
398 PCMK_ACTION_MIGRATE_FROM, 0),
399 NULL, flags, order->lh_rsc->cluster);
400 }
401 }
402 }
403
404 free(first_task);
405 free(then_task);
406 }