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(pe_action_t *action, const pe_node_t *source,
29 const pe_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(pe_resource_t *rsc, const pe_node_t *current)
47 {
48 pe_action_t *migrate_to = NULL;
49 pe_action_t *migrate_from = NULL;
50 pe_action_t *start = NULL;
51 pe_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, RSC_MIGRATE, 0),
62 RSC_MIGRATE, current, TRUE, TRUE,
63 rsc->cluster);
64 }
65 migrate_from = custom_action(rsc, pcmk__op_key(rsc->id, RSC_MIGRATED, 0),
66 RSC_MIGRATED, rsc->allocated_to, TRUE, TRUE,
67 rsc->cluster);
68
69 if ((migrate_from != NULL)
70 && ((migrate_to != NULL) || (rsc->partial_migration_target != NULL))) {
71
72 pe__set_action_flags(start, pe_action_migrate_runnable);
73 pe__set_action_flags(stop, pe_action_migrate_runnable);
74
75
76 pe__set_action_flags(start, pe_action_pseudo);
77
78 if (rsc->partial_migration_target == NULL) {
79 pe__set_action_flags(migrate_from, pe_action_migrate_runnable);
80
81 if (migrate_to != NULL) {
82 pe__set_action_flags(migrate_to, pe_action_migrate_runnable);
83 migrate_to->needs = start->needs;
84 }
85
86
87 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, RSC_STATUS, 0), NULL,
88 rsc, pcmk__op_key(rsc->id, RSC_MIGRATE, 0),
89 NULL, pe_order_optional, rsc->cluster);
90 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, RSC_MIGRATE, 0), NULL,
91 rsc, pcmk__op_key(rsc->id, RSC_MIGRATED, 0),
92 NULL,
93 pe_order_optional|pe_order_implies_first_migratable,
94 rsc->cluster);
95 } else {
96 pe__set_action_flags(migrate_from, pe_action_migrate_runnable);
97 migrate_from->needs = start->needs;
98
99
100 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, RSC_STATUS, 0), NULL,
101 rsc, pcmk__op_key(rsc->id, RSC_MIGRATED, 0),
102 NULL, pe_order_optional, rsc->cluster);
103 }
104
105
106 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, RSC_MIGRATED, 0), NULL,
107 rsc, pcmk__op_key(rsc->id, RSC_STOP, 0), NULL,
108 pe_order_optional|pe_order_implies_first_migratable,
109 rsc->cluster);
110 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, RSC_MIGRATED, 0), NULL,
111 rsc, pcmk__op_key(rsc->id, RSC_START, 0), NULL,
112 pe_order_optional|pe_order_implies_first_migratable|pe_order_pseudo_left,
113 rsc->cluster);
114 }
115
116 if (migrate_to != NULL) {
117 add_migration_meta(migrate_to, current, rsc->allocated_to);
118
119 if (!rsc->is_remote_node) {
120
121
122
123
124
125
126
127
128
129
130
131 add_hash_param(migrate_to->meta, XML_OP_ATTR_PENDING, "true");
132 }
133 }
134
135 if (migrate_from != NULL) {
136 add_migration_meta(migrate_from, current, rsc->allocated_to);
137 }
138 }
139
140
141
142
143
144
145
146
147 void
148 pcmk__abort_dangling_migration(void *data, void *user_data)
149 {
150 const pe_node_t *dangling_source = (const pe_node_t *) data;
151 pe_resource_t *rsc = (pe_resource_t *) user_data;
152
153 pe_action_t *stop = NULL;
154 bool cleanup = pcmk_is_set(rsc->cluster->flags, pe_flag_remove_after_stop);
155
156 pe_rsc_trace(rsc,
157 "Scheduling stop%s for %s on %s due to dangling migration",
158 (cleanup? " and cleanup" : ""), rsc->id,
159 pe__node_name(dangling_source));
160 stop = stop_action(rsc, dangling_source, FALSE);
161 pe__set_action_flags(stop, pe_action_dangle);
162 if (cleanup) {
163 pcmk__schedule_cleanup(rsc, dangling_source, false);
164 }
165 }
166
167
168
169
170
171
172
173
174
175
176 bool
177 pcmk__rsc_can_migrate(const pe_resource_t *rsc, const pe_node_t *current)
178 {
179 CRM_CHECK(rsc != NULL, return false);
180
181 if (!pcmk_is_set(rsc->flags, pe_rsc_allow_migrate)) {
182 pe_rsc_trace(rsc, "%s cannot migrate because "
183 "the configuration does not allow it",
184 rsc->id);
185 return false;
186 }
187
188 if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
189 pe_rsc_trace(rsc, "%s cannot migrate because it is not managed",
190 rsc->id);
191 return false;
192 }
193
194 if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
195 pe_rsc_trace(rsc, "%s cannot migrate because it is failed",
196 rsc->id);
197 return false;
198 }
199
200 if (pcmk_is_set(rsc->flags, pe_rsc_start_pending)) {
201 pe_rsc_trace(rsc, "%s cannot migrate because it has a start pending",
202 rsc->id);
203 return false;
204 }
205
206 if ((current == NULL) || current->details->unclean) {
207 pe_rsc_trace(rsc, "%s cannot migrate because "
208 "its current node (%s) is unclean",
209 rsc->id, pe__node_name(current));
210 return false;
211 }
212
213 if ((rsc->allocated_to == NULL) || rsc->allocated_to->details->unclean) {
214 pe_rsc_trace(rsc, "%s cannot migrate because "
215 "its next node (%s) is unclean",
216 rsc->id, pe__node_name(rsc->allocated_to));
217 return false;
218 }
219
220 return true;
221 }
222
223
224
225
226
227
228
229
230
231
232 static char *
233 task_from_action_or_key(const pe_action_t *action, const char *key)
234 {
235 char *res = NULL;
236
237 if (action != NULL) {
238 res = strdup(action->task);
239 CRM_ASSERT(res != NULL);
240 } else if (key != NULL) {
241 parse_op_key(key, NULL, &res, NULL);
242 }
243 return res;
244 }
245
246
247
248
249
250
251
252
253
254
255
256 void
257 pcmk__order_migration_equivalents(pe__ordering_t *order)
258 {
259 char *first_task = NULL;
260 char *then_task = NULL;
261 bool then_migratable;
262 bool first_migratable;
263
264
265 if ((order->lh_rsc == NULL) || (order->rh_rsc == NULL)
266 || (order->lh_rsc == order->rh_rsc)
267 || is_parent(order->lh_rsc, order->rh_rsc)
268 || is_parent(order->rh_rsc, order->lh_rsc)) {
269 return;
270 }
271
272
273 first_migratable = pcmk_is_set(order->lh_rsc->flags, pe_rsc_allow_migrate);
274 then_migratable = pcmk_is_set(order->rh_rsc->flags, pe_rsc_allow_migrate);
275 if (!first_migratable && !then_migratable) {
276 return;
277 }
278
279
280 first_task = task_from_action_or_key(order->lh_action,
281 order->lh_action_task);
282 then_task = task_from_action_or_key(order->rh_action,
283 order->rh_action_task);
284
285 if (pcmk__str_eq(first_task, RSC_START, pcmk__str_none)
286 && pcmk__str_eq(then_task, RSC_START, pcmk__str_none)) {
287
288 uint32_t flags = pe_order_optional;
289
290 if (first_migratable && then_migratable) {
291
292
293 pcmk__new_ordering(order->lh_rsc,
294 pcmk__op_key(order->lh_rsc->id, RSC_MIGRATED, 0),
295 NULL, order->rh_rsc,
296 pcmk__op_key(order->rh_rsc->id, RSC_MIGRATE, 0),
297 NULL, flags, order->lh_rsc->cluster);
298 }
299
300 if (then_migratable) {
301 if (first_migratable) {
302 pe__set_order_flags(flags, pe_order_apply_first_non_migratable);
303 }
304
305
306
307
308
309 pcmk__new_ordering(order->lh_rsc,
310 pcmk__op_key(order->lh_rsc->id, RSC_START, 0),
311 NULL, order->rh_rsc,
312 pcmk__op_key(order->rh_rsc->id, RSC_MIGRATE, 0),
313 NULL, flags, order->lh_rsc->cluster);
314 }
315
316 } else if (then_migratable
317 && pcmk__str_eq(first_task, RSC_STOP, pcmk__str_none)
318 && pcmk__str_eq(then_task, RSC_STOP, pcmk__str_none)) {
319
320 uint32_t flags = pe_order_optional;
321
322 if (first_migratable) {
323 pe__set_order_flags(flags, pe_order_apply_first_non_migratable);
324 }
325
326
327
328
329 pcmk__new_ordering(order->lh_rsc,
330 pcmk__op_key(order->lh_rsc->id, RSC_STOP, 0), NULL,
331 order->rh_rsc,
332 pcmk__op_key(order->rh_rsc->id, RSC_MIGRATE, 0),
333 NULL, flags, order->lh_rsc->cluster);
334
335
336 if (order->rh_rsc->partial_migration_target) {
337 pcmk__new_ordering(order->lh_rsc,
338 pcmk__op_key(order->lh_rsc->id, RSC_STOP, 0),
339 NULL, order->rh_rsc,
340 pcmk__op_key(order->rh_rsc->id, RSC_MIGRATED, 0),
341 NULL, flags, order->lh_rsc->cluster);
342 }
343
344 } else if (pcmk__str_eq(first_task, RSC_PROMOTE, pcmk__str_none)
345 && pcmk__str_eq(then_task, RSC_START, pcmk__str_none)) {
346
347 uint32_t flags = pe_order_optional;
348
349 if (then_migratable) {
350
351
352 pcmk__new_ordering(order->lh_rsc,
353 pcmk__op_key(order->lh_rsc->id, RSC_PROMOTE, 0),
354 NULL, order->rh_rsc,
355 pcmk__op_key(order->rh_rsc->id, RSC_MIGRATE, 0),
356 NULL, flags, order->lh_rsc->cluster);
357 }
358
359 } else if (pcmk__str_eq(first_task, RSC_DEMOTE, pcmk__str_none)
360 && pcmk__str_eq(then_task, RSC_STOP, pcmk__str_none)) {
361
362 uint32_t flags = pe_order_optional;
363
364 if (then_migratable) {
365
366
367 pcmk__new_ordering(order->lh_rsc,
368 pcmk__op_key(order->lh_rsc->id, RSC_DEMOTE, 0),
369 NULL, order->rh_rsc,
370 pcmk__op_key(order->rh_rsc->id, RSC_MIGRATE, 0),
371 NULL, flags, order->lh_rsc->cluster);
372
373
374 if (order->rh_rsc->partial_migration_target) {
375 pcmk__new_ordering(order->lh_rsc,
376 pcmk__op_key(order->lh_rsc->id, RSC_DEMOTE, 0),
377 NULL, order->rh_rsc,
378 pcmk__op_key(order->rh_rsc->id, RSC_MIGRATED, 0),
379 NULL, flags, order->lh_rsc->cluster);
380 }
381 }
382 }
383
384 free(first_task);
385 free(then_task);
386 }