This source file includes following definitions.
- is_bundle_node
- get_container_list
- get_containers_or_children
- migration_threshold_reached
- pcmk__bundle_allocate
- pcmk__bundle_create_actions
- pcmk__bundle_internal_constraints
- compatible_replica_for_node
- compatible_replica
- pcmk__bundle_rsc_colocation_lh
- copies_per_node
- pcmk__bundle_rsc_colocation_rh
- pcmk__bundle_action_flags
- find_compatible_child_by_node
- replica_for_container
- multi_update_interleave_actions
- can_interleave_actions
- pcmk__multi_update_actions
- pcmk__bundle_rsc_location
- pcmk__bundle_expand
- pcmk__bundle_create_probe
- pcmk__bundle_append_meta
- pcmk__bundle_log_actions
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/msg_xml.h>
13 #include <pacemaker-internal.h>
14
15 #define PE__VARIANT_BUNDLE 1
16 #include <lib/pengine/variant.h>
17
18 static bool
19 is_bundle_node(pe__bundle_variant_data_t *data, pe_node_t *node)
20 {
21 for (GList *gIter = data->replicas; gIter != NULL; gIter = gIter->next) {
22 pe__bundle_replica_t *replica = gIter->data;
23
24 if (node->details == replica->node->details) {
25 return TRUE;
26 }
27 }
28 return FALSE;
29 }
30
31 gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set);
32 void distribute_children(pe_resource_t *rsc, GListPtr children, GListPtr nodes,
33 int max, int per_host_max, pe_working_set_t * data_set);
34
35 static GList *
36 get_container_list(pe_resource_t *rsc)
37 {
38 GList *containers = NULL;
39
40 if (rsc->variant == pe_container) {
41 pe__bundle_variant_data_t *data = NULL;
42
43 get_bundle_variant_data(data, rsc);
44 for (GList *gIter = data->replicas; gIter != NULL;
45 gIter = gIter->next) {
46 pe__bundle_replica_t *replica = gIter->data;
47
48 containers = g_list_append(containers, replica->container);
49 }
50 }
51 return containers;
52 }
53
54 static inline GList *
55 get_containers_or_children(pe_resource_t *rsc)
56 {
57 return (rsc->variant == pe_container)?
58 get_container_list(rsc) : rsc->children;
59 }
60
61 static bool
62 migration_threshold_reached(pe_resource_t *rsc, pe_node_t *node,
63 pe_working_set_t *data_set)
64 {
65 int fail_count, countdown;
66
67
68 if (rsc->migration_threshold == 0) {
69 return FALSE;
70 }
71
72
73 if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
74 return FALSE;
75 }
76
77
78 fail_count = pe_get_failcount(node, rsc, NULL,
79 pe_fc_effective|pe_fc_fillers, NULL,
80 data_set);
81 if (fail_count <= 0) {
82 return FALSE;
83 }
84
85
86 countdown = QB_MAX(rsc->migration_threshold - fail_count, 0);
87
88 if (countdown == 0) {
89 crm_warn("Forcing %s away from %s after %d failures (max=%d)",
90 rsc->id, node->details->uname, fail_count,
91 rsc->migration_threshold);
92 return TRUE;
93 }
94
95 crm_info("%s can fail %d more times on %s before being forced off",
96 rsc->id, countdown, node->details->uname);
97 return FALSE;
98 }
99
100 pe_node_t *
101 pcmk__bundle_allocate(pe_resource_t *rsc, pe_node_t *prefer,
102 pe_working_set_t *data_set)
103 {
104 GListPtr containers = NULL;
105 GListPtr nodes = NULL;
106 pe__bundle_variant_data_t *bundle_data = NULL;
107
108 CRM_CHECK(rsc != NULL, return NULL);
109
110 get_bundle_variant_data(bundle_data, rsc);
111
112 pe__set_resource_flags(rsc, pe_rsc_allocating);
113 containers = get_container_list(rsc);
114
115 pe__show_node_weights(!show_scores, rsc, __func__, rsc->allowed_nodes);
116
117 nodes = g_hash_table_get_values(rsc->allowed_nodes);
118 nodes = sort_nodes_by_weight(nodes, NULL, data_set);
119 containers = g_list_sort_with_data(containers, sort_clone_instance, data_set);
120 distribute_children(rsc, containers, nodes, bundle_data->nreplicas,
121 bundle_data->nreplicas_per_host, data_set);
122 g_list_free(nodes);
123 g_list_free(containers);
124
125 for (GList *gIter = bundle_data->replicas; gIter != NULL;
126 gIter = gIter->next) {
127 pe__bundle_replica_t *replica = gIter->data;
128 pe_node_t *container_host = NULL;
129
130 CRM_ASSERT(replica);
131 if (replica->ip) {
132 pe_rsc_trace(rsc, "Allocating bundle %s IP %s",
133 rsc->id, replica->ip->id);
134 replica->ip->cmds->allocate(replica->ip, prefer, data_set);
135 }
136
137 container_host = replica->container->allocated_to;
138 if (replica->remote && pe__is_guest_or_remote_node(container_host)) {
139
140
141
142
143 rsc_colocation_new("child-remote-with-docker-remote", NULL,
144 INFINITY, replica->remote,
145 container_host->details->remote_rsc, NULL, NULL,
146 data_set);
147 }
148
149 if (replica->remote) {
150 pe_rsc_trace(rsc, "Allocating bundle %s connection %s",
151 rsc->id, replica->remote->id);
152 replica->remote->cmds->allocate(replica->remote, prefer,
153 data_set);
154 }
155
156
157 if (replica->child) {
158 pe_node_t *node = NULL;
159 GHashTableIter iter;
160
161 g_hash_table_iter_init(&iter, replica->child->allowed_nodes);
162 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
163 if (node->details != replica->node->details) {
164 node->weight = -INFINITY;
165 } else if (!migration_threshold_reached(replica->child, node,
166 data_set)) {
167 node->weight = INFINITY;
168 }
169 }
170
171 pe__set_resource_flags(replica->child->parent, pe_rsc_allocating);
172 pe_rsc_trace(rsc, "Allocating bundle %s replica child %s",
173 rsc->id, replica->child->id);
174 replica->child->cmds->allocate(replica->child, replica->node,
175 data_set);
176 pe__clear_resource_flags(replica->child->parent,
177 pe_rsc_allocating);
178 }
179 }
180
181 if (bundle_data->child) {
182 pe_node_t *node = NULL;
183 GHashTableIter iter;
184 g_hash_table_iter_init(&iter, bundle_data->child->allowed_nodes);
185 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
186 if (is_bundle_node(bundle_data, node)) {
187 node->weight = 0;
188 } else {
189 node->weight = -INFINITY;
190 }
191 }
192 pe_rsc_trace(rsc, "Allocating bundle %s child %s",
193 rsc->id, bundle_data->child->id);
194 bundle_data->child->cmds->allocate(bundle_data->child, prefer, data_set);
195 }
196
197 pe__clear_resource_flags(rsc, pe_rsc_allocating|pe_rsc_provisional);
198 return NULL;
199 }
200
201
202 void
203 pcmk__bundle_create_actions(pe_resource_t *rsc, pe_working_set_t *data_set)
204 {
205 pe_action_t *action = NULL;
206 GListPtr containers = NULL;
207 pe__bundle_variant_data_t *bundle_data = NULL;
208
209 CRM_CHECK(rsc != NULL, return);
210
211 containers = get_container_list(rsc);
212 get_bundle_variant_data(bundle_data, rsc);
213 for (GList *gIter = bundle_data->replicas; gIter != NULL;
214 gIter = gIter->next) {
215 pe__bundle_replica_t *replica = gIter->data;
216
217 CRM_ASSERT(replica);
218 if (replica->ip) {
219 replica->ip->cmds->create_actions(replica->ip, data_set);
220 }
221 if (replica->container) {
222 replica->container->cmds->create_actions(replica->container,
223 data_set);
224 }
225 if (replica->remote) {
226 replica->remote->cmds->create_actions(replica->remote, data_set);
227 }
228 }
229
230 clone_create_pseudo_actions(rsc, containers, NULL, NULL, data_set);
231
232 if (bundle_data->child) {
233 bundle_data->child->cmds->create_actions(bundle_data->child, data_set);
234
235 if (pcmk_is_set(bundle_data->child->flags, pe_rsc_promotable)) {
236
237 create_pseudo_resource_op(rsc, RSC_PROMOTE, TRUE, TRUE, data_set);
238 action = create_pseudo_resource_op(rsc, RSC_PROMOTED, TRUE, TRUE, data_set);
239 action->priority = INFINITY;
240
241
242 create_pseudo_resource_op(rsc, RSC_DEMOTE, TRUE, TRUE, data_set);
243 action = create_pseudo_resource_op(rsc, RSC_DEMOTED, TRUE, TRUE, data_set);
244 action->priority = INFINITY;
245 }
246 }
247
248 g_list_free(containers);
249 }
250
251 void
252 pcmk__bundle_internal_constraints(pe_resource_t *rsc,
253 pe_working_set_t *data_set)
254 {
255 pe__bundle_variant_data_t *bundle_data = NULL;
256
257 CRM_CHECK(rsc != NULL, return);
258
259 get_bundle_variant_data(bundle_data, rsc);
260
261 if (bundle_data->child) {
262 new_rsc_order(rsc, RSC_START, bundle_data->child, RSC_START,
263 pe_order_implies_first_printed, data_set);
264 new_rsc_order(rsc, RSC_STOP, bundle_data->child, RSC_STOP,
265 pe_order_implies_first_printed, data_set);
266
267 if (bundle_data->child->children) {
268 new_rsc_order(bundle_data->child, RSC_STARTED, rsc, RSC_STARTED,
269 pe_order_implies_then_printed, data_set);
270 new_rsc_order(bundle_data->child, RSC_STOPPED, rsc, RSC_STOPPED,
271 pe_order_implies_then_printed, data_set);
272 } else {
273 new_rsc_order(bundle_data->child, RSC_START, rsc, RSC_STARTED,
274 pe_order_implies_then_printed, data_set);
275 new_rsc_order(bundle_data->child, RSC_STOP, rsc, RSC_STOPPED,
276 pe_order_implies_then_printed, data_set);
277 }
278 }
279
280 for (GList *gIter = bundle_data->replicas; gIter != NULL;
281 gIter = gIter->next) {
282 pe__bundle_replica_t *replica = gIter->data;
283
284 CRM_ASSERT(replica);
285 CRM_ASSERT(replica->container);
286
287 replica->container->cmds->internal_constraints(replica->container,
288 data_set);
289
290 order_start_start(rsc, replica->container,
291 pe_order_runnable_left|pe_order_implies_first_printed);
292
293 if (replica->child) {
294 order_stop_stop(rsc, replica->child,
295 pe_order_implies_first_printed);
296 }
297 order_stop_stop(rsc, replica->container,
298 pe_order_implies_first_printed);
299 new_rsc_order(replica->container, RSC_START, rsc, RSC_STARTED,
300 pe_order_implies_then_printed, data_set);
301 new_rsc_order(replica->container, RSC_STOP, rsc, RSC_STOPPED,
302 pe_order_implies_then_printed, data_set);
303
304 if (replica->ip) {
305 replica->ip->cmds->internal_constraints(replica->ip, data_set);
306
307
308 new_rsc_order(replica->ip, RSC_START, replica->container, RSC_START,
309 pe_order_runnable_left|pe_order_preserve, data_set);
310 new_rsc_order(replica->container, RSC_STOP, replica->ip, RSC_STOP,
311 pe_order_implies_first|pe_order_preserve, data_set);
312
313 rsc_colocation_new("ip-with-docker", NULL, INFINITY, replica->ip,
314 replica->container, NULL, NULL, data_set);
315 }
316
317 if (replica->remote) {
318
319
320
321
322
323 replica->remote->cmds->internal_constraints(replica->remote,
324 data_set);
325 }
326
327 if (replica->child) {
328 CRM_ASSERT(replica->remote);
329
330
331 }
332
333 }
334
335 if (bundle_data->child) {
336 bundle_data->child->cmds->internal_constraints(bundle_data->child, data_set);
337 if (pcmk_is_set(bundle_data->child->flags, pe_rsc_promotable)) {
338 promote_demote_constraints(rsc, data_set);
339
340
341 new_rsc_order(bundle_data->child, RSC_DEMOTED, rsc, RSC_DEMOTED,
342 pe_order_implies_then_printed, data_set);
343
344
345 new_rsc_order(rsc, RSC_DEMOTE, bundle_data->child, RSC_DEMOTE,
346 pe_order_implies_first_printed, data_set);
347
348
349 new_rsc_order(bundle_data->child, RSC_PROMOTED, rsc, RSC_PROMOTED,
350 pe_order_implies_then_printed, data_set);
351
352
353 new_rsc_order(rsc, RSC_PROMOTE, bundle_data->child, RSC_PROMOTE,
354 pe_order_implies_first_printed, data_set);
355 }
356
357 } else {
358
359
360
361 }
362 }
363
364 static pe_resource_t *
365 compatible_replica_for_node(pe_resource_t *rsc_lh, pe_node_t *candidate,
366 pe_resource_t *rsc, enum rsc_role_e filter,
367 gboolean current)
368 {
369 pe__bundle_variant_data_t *bundle_data = NULL;
370
371 CRM_CHECK(candidate != NULL, return NULL);
372 get_bundle_variant_data(bundle_data, rsc);
373
374 crm_trace("Looking for compatible child from %s for %s on %s",
375 rsc_lh->id, rsc->id, candidate->details->uname);
376
377 for (GList *gIter = bundle_data->replicas; gIter != NULL;
378 gIter = gIter->next) {
379 pe__bundle_replica_t *replica = gIter->data;
380
381 if (is_child_compatible(replica->container, candidate, filter, current)) {
382 crm_trace("Pairing %s with %s on %s",
383 rsc_lh->id, replica->container->id,
384 candidate->details->uname);
385 return replica->container;
386 }
387 }
388
389 crm_trace("Can't pair %s with %s", rsc_lh->id, rsc->id);
390 return NULL;
391 }
392
393 static pe_resource_t *
394 compatible_replica(pe_resource_t *rsc_lh, pe_resource_t *rsc,
395 enum rsc_role_e filter, gboolean current,
396 pe_working_set_t *data_set)
397 {
398 GListPtr scratch = NULL;
399 pe_resource_t *pair = NULL;
400 pe_node_t *active_node_lh = NULL;
401
402 active_node_lh = rsc_lh->fns->location(rsc_lh, NULL, current);
403 if (active_node_lh) {
404 return compatible_replica_for_node(rsc_lh, active_node_lh, rsc, filter,
405 current);
406 }
407
408 scratch = g_hash_table_get_values(rsc_lh->allowed_nodes);
409 scratch = sort_nodes_by_weight(scratch, NULL, data_set);
410
411 for (GListPtr gIter = scratch; gIter != NULL; gIter = gIter->next) {
412 pe_node_t *node = (pe_node_t *) gIter->data;
413
414 pair = compatible_replica_for_node(rsc_lh, node, rsc, filter, current);
415 if (pair) {
416 goto done;
417 }
418 }
419
420 pe_rsc_debug(rsc, "Can't pair %s with %s", rsc_lh->id, (rsc? rsc->id : "none"));
421 done:
422 g_list_free(scratch);
423 return pair;
424 }
425
426 void
427 pcmk__bundle_rsc_colocation_lh(pe_resource_t *rsc, pe_resource_t *rsc_rh,
428 rsc_colocation_t *constraint,
429 pe_working_set_t *data_set)
430 {
431
432
433
434
435 CRM_ASSERT(FALSE);
436 }
437
438 int copies_per_node(pe_resource_t * rsc)
439 {
440
441
442
443
444
445
446
447
448
449 switch(rsc->variant) {
450 case pe_unknown:
451 return 0;
452 case pe_native:
453 case pe_group:
454 return 1;
455 case pe_clone:
456 {
457 const char *max_clones_node = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_NODEMAX);
458 return crm_parse_int(max_clones_node, "1");
459 }
460 case pe_container:
461 {
462 pe__bundle_variant_data_t *data = NULL;
463 get_bundle_variant_data(data, rsc);
464 return data->nreplicas_per_host;
465 }
466 }
467 return 0;
468 }
469
470 void
471 pcmk__bundle_rsc_colocation_rh(pe_resource_t *rsc_lh, pe_resource_t *rsc,
472 rsc_colocation_t *constraint,
473 pe_working_set_t *data_set)
474 {
475 GListPtr allocated_rhs = NULL;
476 pe__bundle_variant_data_t *bundle_data = NULL;
477
478 CRM_CHECK(constraint != NULL, return);
479 CRM_CHECK(rsc_lh != NULL, pe_err("rsc_lh was NULL for %s", constraint->id); return);
480 CRM_CHECK(rsc != NULL, pe_err("rsc was NULL for %s", constraint->id); return);
481 CRM_ASSERT(rsc_lh->variant == pe_native);
482
483 if (constraint->score == 0) {
484 return;
485 }
486 if (pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
487 pe_rsc_trace(rsc, "%s is still provisional", rsc->id);
488 return;
489
490 } else if(constraint->rsc_lh->variant > pe_group) {
491 pe_resource_t *rh_child = compatible_replica(rsc_lh, rsc,
492 RSC_ROLE_UNKNOWN, FALSE,
493 data_set);
494
495 if (rh_child) {
496 pe_rsc_debug(rsc, "Pairing %s with %s", rsc_lh->id, rh_child->id);
497 rsc_lh->cmds->rsc_colocation_lh(rsc_lh, rh_child, constraint,
498 data_set);
499
500 } else if (constraint->score >= INFINITY) {
501 crm_notice("Cannot pair %s with instance of %s", rsc_lh->id, rsc->id);
502 assign_node(rsc_lh, NULL, TRUE);
503
504 } else {
505 pe_rsc_debug(rsc, "Cannot pair %s with instance of %s", rsc_lh->id, rsc->id);
506 }
507
508 return;
509 }
510
511 get_bundle_variant_data(bundle_data, rsc);
512 pe_rsc_trace(rsc, "Processing constraint %s: %s -> %s %d",
513 constraint->id, rsc_lh->id, rsc->id, constraint->score);
514
515 for (GList *gIter = bundle_data->replicas; gIter != NULL;
516 gIter = gIter->next) {
517 pe__bundle_replica_t *replica = gIter->data;
518
519 if (constraint->score < INFINITY) {
520 replica->container->cmds->rsc_colocation_rh(rsc_lh,
521 replica->container,
522 constraint, data_set);
523
524 } else {
525 pe_node_t *chosen = replica->container->fns->location(replica->container,
526 NULL, FALSE);
527
528 if ((chosen == NULL)
529 || is_set_recursive(replica->container, pe_rsc_block, TRUE)) {
530 continue;
531 }
532 if ((constraint->role_rh >= RSC_ROLE_MASTER)
533 && (replica->child == NULL)) {
534 continue;
535 }
536 if ((constraint->role_rh >= RSC_ROLE_MASTER)
537 && (replica->child->next_role < RSC_ROLE_MASTER)) {
538 continue;
539 }
540
541 pe_rsc_trace(rsc, "Allowing %s: %s %d", constraint->id, chosen->details->uname, chosen->weight);
542 allocated_rhs = g_list_prepend(allocated_rhs, chosen);
543 }
544 }
545
546 if (constraint->score >= INFINITY) {
547 node_list_exclude(rsc_lh->allowed_nodes, allocated_rhs, FALSE);
548 }
549 g_list_free(allocated_rhs);
550 }
551
552 enum pe_action_flags
553 pcmk__bundle_action_flags(pe_action_t *action, pe_node_t *node)
554 {
555 GListPtr containers = NULL;
556 enum pe_action_flags flags = 0;
557 pe__bundle_variant_data_t *data = NULL;
558
559 get_bundle_variant_data(data, action->rsc);
560 if(data->child) {
561 enum action_tasks task = get_complex_task(data->child, action->task, TRUE);
562 switch(task) {
563 case no_action:
564 case action_notify:
565 case action_notified:
566 case action_promote:
567 case action_promoted:
568 case action_demote:
569 case action_demoted:
570 return summary_action_flags(action, data->child->children, node);
571 default:
572 break;
573 }
574 }
575
576 containers = get_container_list(action->rsc);
577 flags = summary_action_flags(action, containers, node);
578 g_list_free(containers);
579 return flags;
580 }
581
582 pe_resource_t *
583 find_compatible_child_by_node(pe_resource_t * local_child, pe_node_t * local_node, pe_resource_t * rsc,
584 enum rsc_role_e filter, gboolean current)
585 {
586 GListPtr gIter = NULL;
587 GListPtr children = NULL;
588
589 if (local_node == NULL) {
590 crm_err("Can't colocate unrunnable child %s with %s", local_child->id, rsc->id);
591 return NULL;
592 }
593
594 crm_trace("Looking for compatible child from %s for %s on %s",
595 local_child->id, rsc->id, local_node->details->uname);
596
597 children = get_containers_or_children(rsc);
598 for (gIter = children; gIter != NULL; gIter = gIter->next) {
599 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
600
601 if(is_child_compatible(child_rsc, local_node, filter, current)) {
602 crm_trace("Pairing %s with %s on %s",
603 local_child->id, child_rsc->id, local_node->details->uname);
604 return child_rsc;
605 }
606 }
607
608 crm_trace("Can't pair %s with %s", local_child->id, rsc->id);
609 if(children != rsc->children) {
610 g_list_free(children);
611 }
612 return NULL;
613 }
614
615 static pe__bundle_replica_t *
616 replica_for_container(pe_resource_t *rsc, pe_resource_t *container,
617 pe_node_t *node)
618 {
619 if (rsc->variant == pe_container) {
620 pe__bundle_variant_data_t *data = NULL;
621
622 get_bundle_variant_data(data, rsc);
623 for (GList *gIter = data->replicas; gIter != NULL;
624 gIter = gIter->next) {
625 pe__bundle_replica_t *replica = gIter->data;
626
627 if (replica->child
628 && (container == replica->container)
629 && (node->details == replica->node->details)) {
630 return replica;
631 }
632 }
633 }
634 return NULL;
635 }
636
637 static enum pe_graph_flags
638 multi_update_interleave_actions(pe_action_t *first, pe_action_t *then,
639 pe_node_t *node, enum pe_action_flags flags,
640 enum pe_action_flags filter,
641 enum pe_ordering type,
642 pe_working_set_t *data_set)
643 {
644 GListPtr gIter = NULL;
645 GListPtr children = NULL;
646 gboolean current = FALSE;
647 enum pe_graph_flags changed = pe_graph_none;
648
649
650 if (pcmk__ends_with(first->uuid, "_stopped_0")
651 || pcmk__ends_with(first->uuid, "_demoted_0")) {
652 current = TRUE;
653 }
654
655 children = get_containers_or_children(then->rsc);
656 for (gIter = children; gIter != NULL; gIter = gIter->next) {
657 pe_resource_t *then_child = gIter->data;
658 pe_resource_t *first_child = find_compatible_child(then_child,
659 first->rsc,
660 RSC_ROLE_UNKNOWN,
661 current, data_set);
662 if (first_child == NULL && current) {
663 crm_trace("Ignore");
664
665 } else if (first_child == NULL) {
666 crm_debug("No match found for %s (%d / %s / %s)", then_child->id, current, first->uuid, then->uuid);
667
668
669
670
671
672
673
674 if (type & (pe_order_runnable_left | pe_order_implies_then) ) {
675 pe_rsc_info(then->rsc, "Inhibiting %s from being active", then_child->id);
676 if(assign_node(then_child, NULL, TRUE)) {
677 pe__set_graph_flags(changed, first, pe_graph_updated_then);
678 }
679 }
680
681 } else {
682 pe_action_t *first_action = NULL;
683 pe_action_t *then_action = NULL;
684
685 enum action_tasks task = clone_child_action(first);
686 const char *first_task = task2text(task);
687
688 pe__bundle_replica_t *first_replica = NULL;
689 pe__bundle_replica_t *then_replica = NULL;
690
691 first_replica = replica_for_container(first->rsc, first_child,
692 node);
693 if (strstr(first->task, "stop") && first_replica && first_replica->child) {
694
695
696
697
698
699 first_action = find_first_action(first_replica->child->actions,
700 NULL, task2text(task), node);
701 } else {
702 first_action = find_first_action(first_child->actions, NULL, task2text(task), node);
703 }
704
705 then_replica = replica_for_container(then->rsc, then_child, node);
706 if (strstr(then->task, "mote")
707 && then_replica && then_replica->child) {
708
709
710
711
712
713
714
715 then_action = find_first_action(then_replica->child->actions,
716 NULL, then->task, node);
717 } else {
718 then_action = find_first_action(then_child->actions, NULL, then->task, node);
719 }
720
721 if (first_action == NULL) {
722 if (!pcmk_is_set(first_child->flags, pe_rsc_orphan)
723 && !pcmk__str_any_of(first_task, RSC_STOP, RSC_DEMOTE, NULL)) {
724 crm_err("Internal error: No action found for %s in %s (first)",
725 first_task, first_child->id);
726
727 } else {
728 crm_trace("No action found for %s in %s%s (first)",
729 first_task, first_child->id,
730 pcmk_is_set(first_child->flags, pe_rsc_orphan)? " (ORPHAN)" : "");
731 }
732 continue;
733 }
734
735
736 if (then_action == NULL) {
737 if (!pcmk_is_set(then_child->flags, pe_rsc_orphan)
738 && !pcmk__str_any_of(then->task, RSC_STOP, RSC_DEMOTE, NULL)) {
739 crm_err("Internal error: No action found for %s in %s (then)",
740 then->task, then_child->id);
741
742 } else {
743 crm_trace("No action found for %s in %s%s (then)",
744 then->task, then_child->id,
745 pcmk_is_set(then_child->flags, pe_rsc_orphan)? " (ORPHAN)" : "");
746 }
747 continue;
748 }
749
750 if (order_actions(first_action, then_action, type)) {
751 crm_debug("Created constraint for %s (%d) -> %s (%d) %.6x",
752 first_action->uuid,
753 pcmk_is_set(first_action->flags, pe_action_optional),
754 then_action->uuid,
755 pcmk_is_set(then_action->flags, pe_action_optional),
756 type);
757 pe__set_graph_flags(changed, first,
758 pe_graph_updated_first|pe_graph_updated_then);
759 }
760 if(first_action && then_action) {
761 changed |= then_child->cmds->update_actions(first_action,
762 then_action, node,
763 first_child->cmds->action_flags(first_action, node),
764 filter, type, data_set);
765 } else {
766 crm_err("Nothing found either for %s (%p) or %s (%p) %s",
767 first_child->id, first_action,
768 then_child->id, then_action, task2text(task));
769 }
770 }
771 }
772
773 if(children != then->rsc->children) {
774 g_list_free(children);
775 }
776 return changed;
777 }
778
779 static bool
780 can_interleave_actions(pe_action_t *first, pe_action_t *then)
781 {
782 bool interleave = FALSE;
783 pe_resource_t *rsc = NULL;
784 const char *interleave_s = NULL;
785
786 if(first->rsc == NULL || then->rsc == NULL) {
787 crm_trace("Not interleaving %s with %s (both must be resources)", first->uuid, then->uuid);
788 return FALSE;
789 } else if(first->rsc == then->rsc) {
790 crm_trace("Not interleaving %s with %s (must belong to different resources)", first->uuid, then->uuid);
791 return FALSE;
792 } else if(first->rsc->variant < pe_clone || then->rsc->variant < pe_clone) {
793 crm_trace("Not interleaving %s with %s (both sides must be clones or bundles)", first->uuid, then->uuid);
794 return FALSE;
795 }
796
797 if (pcmk__ends_with(then->uuid, "_stop_0")
798 || pcmk__ends_with(then->uuid, "_demote_0")) {
799 rsc = first->rsc;
800 } else {
801 rsc = then->rsc;
802 }
803
804 interleave_s = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERLEAVE);
805 interleave = crm_is_true(interleave_s);
806 crm_trace("Interleave %s -> %s: %s (based on %s)",
807 first->uuid, then->uuid, interleave ? "yes" : "no", rsc->id);
808
809 return interleave;
810 }
811
812 enum pe_graph_flags
813 pcmk__multi_update_actions(pe_action_t *first, pe_action_t *then,
814 pe_node_t *node, enum pe_action_flags flags,
815 enum pe_action_flags filter, enum pe_ordering type,
816 pe_working_set_t *data_set)
817 {
818 enum pe_graph_flags changed = pe_graph_none;
819
820 crm_trace("%s -> %s", first->uuid, then->uuid);
821
822 if(can_interleave_actions(first, then)) {
823 changed = multi_update_interleave_actions(first, then, node, flags,
824 filter, type, data_set);
825
826 } else if(then->rsc) {
827 GListPtr gIter = NULL;
828 GListPtr children = NULL;
829
830
831 changed |= native_update_actions(first, then, node, flags, filter,
832 type, data_set);
833
834
835 children = get_containers_or_children(then->rsc);
836 for (gIter = children; gIter != NULL; gIter = gIter->next) {
837 pe_resource_t *then_child = (pe_resource_t *) gIter->data;
838 enum pe_graph_flags then_child_changed = pe_graph_none;
839 pe_action_t *then_child_action = find_first_action(then_child->actions, NULL, then->task, node);
840
841 if (then_child_action) {
842 enum pe_action_flags then_child_flags = then_child->cmds->action_flags(then_child_action, node);
843
844 if (pcmk_is_set(then_child_flags, pe_action_runnable)) {
845 then_child_changed |= then_child->cmds->update_actions(first,
846 then_child_action, node, flags, filter, type, data_set);
847 }
848 changed |= then_child_changed;
849 if (then_child_changed & pe_graph_updated_then) {
850 for (GListPtr lpc = then_child_action->actions_after; lpc != NULL; lpc = lpc->next) {
851 pe_action_wrapper_t *next = (pe_action_wrapper_t *) lpc->data;
852 update_action(next->action, data_set);
853 }
854 }
855 }
856 }
857
858 if(children != then->rsc->children) {
859 g_list_free(children);
860 }
861 }
862 return changed;
863 }
864
865 void
866 pcmk__bundle_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
867 {
868 pe__bundle_variant_data_t *bundle_data = NULL;
869 get_bundle_variant_data(bundle_data, rsc);
870
871 native_rsc_location(rsc, constraint);
872
873 for (GList *gIter = bundle_data->replicas; gIter != NULL;
874 gIter = gIter->next) {
875 pe__bundle_replica_t *replica = gIter->data;
876
877 if (replica->container) {
878 replica->container->cmds->rsc_location(replica->container,
879 constraint);
880 }
881 if (replica->ip) {
882 replica->ip->cmds->rsc_location(replica->ip, constraint);
883 }
884 }
885
886 if (bundle_data->child
887 && ((constraint->role_filter == RSC_ROLE_SLAVE)
888 || (constraint->role_filter == RSC_ROLE_MASTER))) {
889 bundle_data->child->cmds->rsc_location(bundle_data->child, constraint);
890 bundle_data->child->rsc_location = g_list_prepend(bundle_data->child->rsc_location,
891 constraint);
892 }
893 }
894
895 void
896 pcmk__bundle_expand(pe_resource_t *rsc, pe_working_set_t * data_set)
897 {
898 pe__bundle_variant_data_t *bundle_data = NULL;
899
900 CRM_CHECK(rsc != NULL, return);
901
902 get_bundle_variant_data(bundle_data, rsc);
903
904 if (bundle_data->child) {
905 bundle_data->child->cmds->expand(bundle_data->child, data_set);
906 }
907
908 for (GList *gIter = bundle_data->replicas; gIter != NULL;
909 gIter = gIter->next) {
910 pe__bundle_replica_t *replica = gIter->data;
911
912 CRM_ASSERT(replica);
913 if (replica->remote && replica->container
914 && pe__bundle_needs_remote_name(replica->remote)) {
915
916
917
918
919
920
921
922 xmlNode *nvpair = get_xpath_object("//nvpair[@name='" XML_RSC_ATTR_REMOTE_RA_ADDR "']",
923 replica->remote->xml, LOG_ERR);
924 const char *calculated_addr = NULL;
925
926 calculated_addr = pe__add_bundle_remote_name(replica->remote,
927 nvpair, "value");
928 if (calculated_addr) {
929 crm_trace("Set address for bundle connection %s to bundle host %s",
930 replica->remote->id, calculated_addr);
931 g_hash_table_replace(replica->remote->parameters,
932 strdup(XML_RSC_ATTR_REMOTE_RA_ADDR),
933 strdup(calculated_addr));
934 } else {
935
936
937
938
939
940
941
942 crm_info("Unable to determine address for bundle %s remote connection",
943 rsc->id);
944 }
945 }
946 if (replica->ip) {
947 replica->ip->cmds->expand(replica->ip, data_set);
948 }
949 if (replica->container) {
950 replica->container->cmds->expand(replica->container, data_set);
951 }
952 if (replica->remote) {
953 replica->remote->cmds->expand(replica->remote, data_set);
954 }
955 }
956 }
957
958 gboolean
959 pcmk__bundle_create_probe(pe_resource_t *rsc, pe_node_t *node,
960 pe_action_t *complete, gboolean force,
961 pe_working_set_t * data_set)
962 {
963 bool any_created = FALSE;
964 pe__bundle_variant_data_t *bundle_data = NULL;
965
966 CRM_CHECK(rsc != NULL, return FALSE);
967
968 get_bundle_variant_data(bundle_data, rsc);
969 for (GList *gIter = bundle_data->replicas; gIter != NULL;
970 gIter = gIter->next) {
971 pe__bundle_replica_t *replica = gIter->data;
972
973 CRM_ASSERT(replica);
974 if (replica->ip) {
975 any_created |= replica->ip->cmds->create_probe(replica->ip, node,
976 complete, force,
977 data_set);
978 }
979 if (replica->child && (node->details == replica->node->details)) {
980 any_created |= replica->child->cmds->create_probe(replica->child,
981 node, complete,
982 force, data_set);
983 }
984 if (replica->container) {
985 bool created = replica->container->cmds->create_probe(replica->container,
986 node, complete,
987 force, data_set);
988
989 if(created) {
990 any_created = TRUE;
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004 for (GList *tIter = bundle_data->replicas;
1005 tIter && (bundle_data->nreplicas_per_host == 1);
1006 tIter = tIter->next) {
1007 pe__bundle_replica_t *other = tIter->data;
1008
1009 if ((other != replica) && (other != NULL)
1010 && (other->container != NULL)) {
1011
1012 custom_action_order(replica->container,
1013 pcmk__op_key(replica->container->id, RSC_STATUS, 0),
1014 NULL, other->container,
1015 pcmk__op_key(other->container->id, RSC_START, 0),
1016 NULL,
1017 pe_order_optional|pe_order_same_node,
1018 data_set);
1019 }
1020 }
1021 }
1022 }
1023 if (replica->container && replica->remote
1024 && replica->remote->cmds->create_probe(replica->remote, node,
1025 complete, force,
1026 data_set)) {
1027
1028
1029
1030
1031
1032 char *probe_uuid = pcmk__op_key(replica->remote->id, RSC_STATUS,
1033 0);
1034 pe_action_t *probe = find_first_action(replica->remote->actions,
1035 probe_uuid, NULL, node);
1036
1037 free(probe_uuid);
1038 if (probe) {
1039 any_created = TRUE;
1040 crm_trace("Ordering %s probe on %s",
1041 replica->remote->id, node->details->uname);
1042 custom_action_order(replica->container,
1043 pcmk__op_key(replica->container->id, RSC_START, 0),
1044 NULL, replica->remote, NULL, probe,
1045 pe_order_probe, data_set);
1046 }
1047 }
1048 }
1049 return any_created;
1050 }
1051
1052 void
1053 pcmk__bundle_append_meta(pe_resource_t *rsc, xmlNode *xml)
1054 {
1055 }
1056
1057 void
1058 pcmk__bundle_log_actions(pe_resource_t *rsc, pe_working_set_t *data_set,
1059 gboolean terminal)
1060 {
1061 pe__bundle_variant_data_t *bundle_data = NULL;
1062
1063 CRM_CHECK(rsc != NULL, return);
1064
1065 get_bundle_variant_data(bundle_data, rsc);
1066 for (GList *gIter = bundle_data->replicas; gIter != NULL;
1067 gIter = gIter->next) {
1068 pe__bundle_replica_t *replica = gIter->data;
1069
1070 CRM_ASSERT(replica);
1071 if (replica->ip) {
1072 LogActions(replica->ip, data_set, terminal);
1073 }
1074 if (replica->container) {
1075 LogActions(replica->container, data_set, terminal);
1076 }
1077 if (replica->remote) {
1078 LogActions(replica->remote, data_set, terminal);
1079 }
1080 if (replica->child) {
1081 LogActions(replica->child, data_set, terminal);
1082 }
1083 }
1084 }