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->priv->name);
33
34 pcmk__insert_meta(action, PCMK__META_MIGRATE_TARGET,
35 target->priv->name);
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 const pcmk_node_t *target_node = rsc->priv->partial_migration_target;
53
54 pcmk__rsc_trace(rsc, "Creating actions to %smigrate %s from %s to %s",
55 ((target_node == NULL)? "" : "partially "),
56 rsc->id, pcmk__node_name(current),
57 pcmk__node_name(rsc->priv->assigned_node));
58 start = start_action(rsc, rsc->priv->assigned_node, TRUE);
59 stop = stop_action(rsc, current, TRUE);
60
61 if (target_node == NULL) {
62 migrate_to = custom_action(rsc, pcmk__op_key(rsc->id,
63 PCMK_ACTION_MIGRATE_TO, 0),
64 PCMK_ACTION_MIGRATE_TO, current, TRUE,
65 rsc->priv->scheduler);
66 }
67 migrate_from = custom_action(rsc, pcmk__op_key(rsc->id,
68 PCMK_ACTION_MIGRATE_FROM, 0),
69 PCMK_ACTION_MIGRATE_FROM,
70 rsc->priv->assigned_node, TRUE,
71 rsc->priv->scheduler);
72
73 pcmk__set_action_flags(start, pcmk__action_migratable);
74 pcmk__set_action_flags(stop, pcmk__action_migratable);
75
76
77 pcmk__set_action_flags(start, pcmk__action_pseudo);
78
79 if (target_node == NULL) {
80 pcmk__set_action_flags(migrate_from, pcmk__action_migratable);
81 pcmk__set_action_flags(migrate_to, pcmk__action_migratable);
82 migrate_to->needs = start->needs;
83
84
85 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MONITOR, 0),
86 NULL,
87 rsc,
88 pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_TO, 0),
89 NULL, pcmk__ar_ordered, rsc->priv->scheduler);
90 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_TO, 0),
91 NULL,
92 rsc,
93 pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
94 NULL,
95 pcmk__ar_ordered|pcmk__ar_unmigratable_then_blocks,
96 rsc->priv->scheduler);
97 } else {
98 pcmk__set_action_flags(migrate_from, pcmk__action_migratable);
99 migrate_from->needs = start->needs;
100
101
102 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MONITOR, 0),
103 NULL,
104 rsc,
105 pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
106 NULL, pcmk__ar_ordered, rsc->priv->scheduler);
107 }
108
109
110 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
111 NULL,
112 rsc, pcmk__op_key(rsc->id, PCMK_ACTION_STOP, 0),
113 NULL,
114 pcmk__ar_ordered|pcmk__ar_unmigratable_then_blocks,
115 rsc->priv->scheduler);
116 pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
117 NULL,
118 rsc, pcmk__op_key(rsc->id, PCMK_ACTION_START, 0),
119 NULL,
120 pcmk__ar_ordered
121 |pcmk__ar_unmigratable_then_blocks
122 |pcmk__ar_first_else_then,
123 rsc->priv->scheduler);
124
125 if (migrate_to != NULL) {
126 add_migration_meta(migrate_to, current, rsc->priv->assigned_node);
127
128 if (!pcmk_is_set(rsc->flags, pcmk__rsc_is_remote_connection)) {
129
130
131
132
133
134
135
136
137
138
139
140 pcmk__insert_meta(migrate_to,
141 PCMK_META_RECORD_PENDING, PCMK_VALUE_TRUE);
142 }
143 }
144
145 add_migration_meta(migrate_from, current, rsc->priv->assigned_node);
146 }
147
148
149
150
151
152
153
154
155 void
156 pcmk__abort_dangling_migration(void *data, void *user_data)
157 {
158 const pcmk_node_t *dangling_source = (const pcmk_node_t *) data;
159 pcmk_resource_t *rsc = (pcmk_resource_t *) user_data;
160
161 pcmk_action_t *stop = NULL;
162
163 pcmk__rsc_trace(rsc,
164 "Scheduling stop for %s on %s due to dangling migration",
165 rsc->id, pcmk__node_name(dangling_source));
166 stop = stop_action(rsc, dangling_source, FALSE);
167 pcmk__set_action_flags(stop, pcmk__action_migration_abort);
168 }
169
170
171
172
173
174
175
176
177
178
179 bool
180 pcmk__rsc_can_migrate(const pcmk_resource_t *rsc, const pcmk_node_t *current)
181 {
182 CRM_CHECK(rsc != NULL, return false);
183
184 if (!pcmk_is_set(rsc->flags, pcmk__rsc_migratable)) {
185 pcmk__rsc_trace(rsc,
186 "%s cannot migrate because "
187 "the configuration does not allow it", rsc->id);
188 return false;
189 }
190
191 if (!pcmk_is_set(rsc->flags, pcmk__rsc_managed)) {
192 pcmk__rsc_trace(rsc, "%s cannot migrate because it is not managed",
193 rsc->id);
194 return false;
195 }
196
197 if (pcmk_is_set(rsc->flags, pcmk__rsc_failed)) {
198 pcmk__rsc_trace(rsc, "%s cannot migrate because it is failed", rsc->id);
199 return false;
200 }
201
202 if (pcmk_is_set(rsc->flags, pcmk__rsc_start_pending)) {
203 pcmk__rsc_trace(rsc, "%s cannot migrate because it has a start pending",
204 rsc->id);
205 return false;
206 }
207
208 if ((current == NULL) || current->details->unclean) {
209 pcmk__rsc_trace(rsc,
210 "%s cannot migrate because "
211 "its current node (%s) is unclean",
212 rsc->id, pcmk__node_name(current));
213 return false;
214 }
215
216 if ((rsc->priv->assigned_node == NULL)
217 || rsc->priv->assigned_node->details->unclean) {
218
219 pcmk__rsc_trace(rsc,
220 "%s cannot migrate because "
221 "its next node (%s) is unclean",
222 rsc->id, pcmk__node_name(rsc->priv->assigned_node));
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 = pcmk__str_copy(action->task);
245 } else if (key != NULL) {
246 parse_op_key(key, NULL, &res, NULL);
247 }
248 return res;
249 }
250
251
252
253
254
255
256
257
258
259
260
261 void
262 pcmk__order_migration_equivalents(pcmk__action_relation_t *order)
263 {
264 char *first_task = NULL;
265 char *then_task = NULL;
266 bool then_migratable;
267 bool first_migratable;
268
269
270 if ((order->rsc1 == NULL) || (order->rsc2 == NULL)
271 || (order->rsc1 == order->rsc2)
272 || is_parent(order->rsc1, order->rsc2)
273 || is_parent(order->rsc2, order->rsc1)) {
274 return;
275 }
276
277
278 first_migratable = pcmk_is_set(order->rsc1->flags, pcmk__rsc_migratable);
279 then_migratable = pcmk_is_set(order->rsc2->flags, pcmk__rsc_migratable);
280 if (!first_migratable && !then_migratable) {
281 return;
282 }
283
284
285 first_task = task_from_action_or_key(order->action1, order->task1);
286 then_task = task_from_action_or_key(order->action2, order->task2);
287
288 if (pcmk__str_eq(first_task, PCMK_ACTION_START, pcmk__str_none)
289 && pcmk__str_eq(then_task, PCMK_ACTION_START, pcmk__str_none)) {
290
291 uint32_t flags = pcmk__ar_ordered;
292
293 if (first_migratable && then_migratable) {
294
295
296 pcmk__new_ordering(order->rsc1,
297 pcmk__op_key(order->rsc1->id,
298 PCMK_ACTION_MIGRATE_FROM, 0),
299 NULL, order->rsc2,
300 pcmk__op_key(order->rsc2->id,
301 PCMK_ACTION_MIGRATE_TO, 0),
302 NULL, flags, order->rsc1->priv->scheduler);
303 }
304
305 if (then_migratable) {
306 if (first_migratable) {
307 pcmk__set_relation_flags(flags, pcmk__ar_if_first_unmigratable);
308 }
309
310
311
312
313
314 pcmk__new_ordering(order->rsc1,
315 pcmk__op_key(order->rsc1->id,
316 PCMK_ACTION_START, 0),
317 NULL, order->rsc2,
318 pcmk__op_key(order->rsc2->id,
319 PCMK_ACTION_MIGRATE_TO, 0),
320 NULL, flags, order->rsc1->priv->scheduler);
321 }
322
323 } else if (then_migratable
324 && pcmk__str_eq(first_task, PCMK_ACTION_STOP, pcmk__str_none)
325 && pcmk__str_eq(then_task, PCMK_ACTION_STOP, pcmk__str_none)) {
326
327 uint32_t flags = pcmk__ar_ordered;
328
329 if (first_migratable) {
330 pcmk__set_relation_flags(flags, pcmk__ar_if_first_unmigratable);
331 }
332
333
334
335
336 pcmk__new_ordering(order->rsc1,
337 pcmk__op_key(order->rsc1->id, PCMK_ACTION_STOP, 0),
338 NULL,
339 order->rsc2,
340 pcmk__op_key(order->rsc2->id,
341 PCMK_ACTION_MIGRATE_TO, 0),
342 NULL, flags, order->rsc1->priv->scheduler);
343
344
345 if (order->rsc2->priv->partial_migration_target != NULL) {
346 pcmk__new_ordering(order->rsc1,
347 pcmk__op_key(order->rsc1->id, PCMK_ACTION_STOP,
348 0),
349 NULL, order->rsc2,
350 pcmk__op_key(order->rsc2->id,
351 PCMK_ACTION_MIGRATE_FROM, 0),
352 NULL, flags, order->rsc1->priv->scheduler);
353 }
354
355 } else if (pcmk__str_eq(first_task, PCMK_ACTION_PROMOTE, pcmk__str_none)
356 && pcmk__str_eq(then_task, PCMK_ACTION_START, pcmk__str_none)) {
357
358 uint32_t flags = pcmk__ar_ordered;
359
360 if (then_migratable) {
361
362
363 pcmk__new_ordering(order->rsc1,
364 pcmk__op_key(order->rsc1->id,
365 PCMK_ACTION_PROMOTE, 0),
366 NULL, order->rsc2,
367 pcmk__op_key(order->rsc2->id,
368 PCMK_ACTION_MIGRATE_TO, 0),
369 NULL, flags, order->rsc1->priv->scheduler);
370 }
371
372 } else if (pcmk__str_eq(first_task, PCMK_ACTION_DEMOTE, pcmk__str_none)
373 && pcmk__str_eq(then_task, PCMK_ACTION_STOP, pcmk__str_none)) {
374
375 uint32_t flags = pcmk__ar_ordered;
376
377 if (then_migratable) {
378
379
380 pcmk__new_ordering(order->rsc1,
381 pcmk__op_key(order->rsc1->id,
382 PCMK_ACTION_DEMOTE, 0),
383 NULL, order->rsc2,
384 pcmk__op_key(order->rsc2->id,
385 PCMK_ACTION_MIGRATE_TO, 0),
386 NULL, flags, order->rsc1->priv->scheduler);
387
388
389 if (order->rsc2->priv->partial_migration_target != NULL) {
390 pcmk__new_ordering(order->rsc1,
391 pcmk__op_key(order->rsc1->id,
392 PCMK_ACTION_DEMOTE, 0),
393 NULL, order->rsc2,
394 pcmk__op_key(order->rsc2->id,
395 PCMK_ACTION_MIGRATE_FROM, 0),
396 NULL, flags,
397 order->rsc1->priv->scheduler);
398 }
399 }
400 }
401
402 free(first_task);
403 free(then_task);
404 }