pacemaker  2.0.5-ba59be712
Scalable High-Availability cluster resource manager
pcmk_sched_bundle.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU General Public License version 2
7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
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  /* Migration threshold of 0 means never force away */
68  if (rsc->migration_threshold == 0) {
69  return FALSE;
70  }
71 
72  // If we're ignoring failures, also ignore the migration threshold
74  return FALSE;
75  }
76 
77  /* If there are no failures, there's no need to force away */
78  fail_count = pe_get_failcount(node, rsc, NULL,
80  data_set);
81  if (fail_count <= 0) {
82  return FALSE;
83  }
84 
85  /* How many more times recovery will be tried on this node */
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 *
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 
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  /* We need 'nested' connection resources to be on the same
140  * host because pacemaker-remoted only supports a single
141  * active connection
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  // Explicitly allocate replicas' children before bundle child
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,
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 
198  return NULL;
199 }
200 
201 
202 void
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  /* promote */
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  /* demote */
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
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,
264  new_rsc_order(rsc, RSC_STOP, bundle_data->child, RSC_STOP,
266 
267  if (bundle_data->child->children) {
268  new_rsc_order(bundle_data->child, RSC_STARTED, rsc, RSC_STARTED,
270  new_rsc_order(bundle_data->child, RSC_STOPPED, rsc, RSC_STOPPED,
272  } else {
273  new_rsc_order(bundle_data->child, RSC_START, rsc, RSC_STARTED,
275  new_rsc_order(bundle_data->child, RSC_STOP, rsc, RSC_STOPPED,
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,
292 
293  if (replica->child) {
294  order_stop_stop(rsc, replica->child,
296  }
297  order_stop_stop(rsc, replica->container,
299  new_rsc_order(replica->container, RSC_START, rsc, RSC_STARTED,
301  new_rsc_order(replica->container, RSC_STOP, rsc, RSC_STOPPED,
303 
304  if (replica->ip) {
305  replica->ip->cmds->internal_constraints(replica->ip, data_set);
306 
307  // Start ip then container
308  new_rsc_order(replica->ip, RSC_START, replica->container, RSC_START,
310  new_rsc_order(replica->container, RSC_STOP, replica->ip, RSC_STOP,
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  /* This handles ordering and colocating remote relative to container
319  * (via "resource-with-container"). Since IP is also ordered and
320  * colocated relative to the container, we don't need to do anything
321  * explicit here with IP.
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  // "Start remote then child" is implicit in scheduler's remote logic
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  /* child demoted before global demoted */
341  new_rsc_order(bundle_data->child, RSC_DEMOTED, rsc, RSC_DEMOTED,
343 
344  /* global demote before child demote */
345  new_rsc_order(rsc, RSC_DEMOTE, bundle_data->child, RSC_DEMOTE,
347 
348  /* child promoted before global promoted */
349  new_rsc_order(bundle_data->child, RSC_PROMOTED, rsc, RSC_PROMOTED,
351 
352  /* global promote before child promote */
353  new_rsc_order(rsc, RSC_PROMOTE, bundle_data->child, RSC_PROMOTE,
355  }
356 
357  } else {
358 // int type = pe_order_optional | pe_order_implies_then | pe_order_restart;
359 // custom_action_order(rsc, pcmk__op_key(rsc->id, RSC_STOP, 0), NULL,
360 // rsc, pcmk__op_key(rsc->id, RSC_START, 0), NULL, pe_order_optional, data_set);
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
428  rsc_colocation_t *constraint,
429  pe_working_set_t *data_set)
430 {
431  /* -- Never called --
432  *
433  * Instead we add the colocation constraints to the child and call from there
434  */
435  CRM_ASSERT(FALSE);
436 }
437 
439 {
440  /* Strictly speaking, there should be a 'copies_per_node' addition
441  * to the resource function table and each case would be a
442  * function. However that would be serious overkill to return an
443  * int. In fact, it seems to me that both function tables
444  * could/should be replaced by resources.{c,h} full of
445  * rsc_{some_operation} functions containing a switch as below
446  * which calls out to functions named {variant}_{some_operation}
447  * as needed.
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
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
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 
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  /* Fix this - lazy */
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,
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  /* Me no like this hack - but what else can we do?
669  *
670  * If there is no-one active or about to be active
671  * on the same node as then_child, then they must
672  * not be allowed to start
673  */
674  if (type & (pe_order_runnable_left | pe_order_implies_then) /* Mandatory */ ) {
675  pe_rsc_info(then->rsc, "Inhibiting %s from being active", then_child->id);
676  if(assign_node(then_child, NULL, TRUE)) {
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  /* Except for 'stopped' we should be looking at the
695  * in-container resource, actions for the child will
696  * happen later and are therefor more likely to align
697  * with the user's intent.
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  /* Promote/demote actions will never be found for the
709  * container resource, look in the child instead
710  *
711  * Alternatively treat:
712  * 'XXXX then promote YYYY' as 'XXXX then start container for YYYY', and
713  * 'demote XXXX then stop YYYY' as 'stop container for XXXX then stop YYYY'
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  /* We're only interested if 'then' is neither stopping nor being demoted */
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,
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
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  // Handle the 'primitive' ordering case
831  changed |= native_update_actions(first, then, node, flags, filter,
832  type, data_set);
833 
834  // Now any children (or containers in the case of a bundle)
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
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
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  /* REMOTE_CONTAINER_HACK: Allow remote nodes to run containers that
917  * run pacemaker-remoted inside, without needing a separate IP for
918  * the container. This is done by configuring the inner remote's
919  * connection host as the magic string "#uname", then
920  * replacing it with the underlying host when needed.
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,
933  strdup(calculated_addr));
934  } else {
935  /* The only way to get here is if the remote connection is
936  * neither currently running nor scheduled to run. That means we
937  * won't be doing any operations that require addr (only start
938  * requires it; we additionally use it to compare digests when
939  * unpacking status, promote, and migrate_from history, but
940  * that's already happened by this point).
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
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  /* If we're limited to one replica per host (due to
992  * the lack of an IP range probably), then we don't
993  * want any of our peer containers starting until
994  * we've established that no other copies are already
995  * running.
996  *
997  * Partly this is to ensure that nreplicas_per_host is
998  * observed, but also to ensure that the containers
999  * don't fail to start because the necessary port
1000  * mappings (which won't include an IP for uniqueness)
1001  * are already taken
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,
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  /* Do not probe the remote resource until we know where the
1029  * container is running. This is required for REMOTE_CONTAINER_HACK
1030  * to correctly probe remote resources.
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
1054 {
1055 }
1056 
1057 void
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 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:215
gboolean rsc_colocation_new(const char *id, const char *node_attr, int score, pe_resource_t *rsc_lh, pe_resource_t *rsc_rh, const char *state_lh, const char *state_rh, pe_working_set_t *data_set)
pe_node_t * pcmk__bundle_allocate(pe_resource_t *rsc, pe_node_t *prefer, pe_working_set_t *data_set)
enum rsc_role_e role_filter
Definition: internal.h:170
const char * task2text(enum action_tasks task)
Definition: common.c:410
#define RSC_STOP
Definition: crm.h:199
bool is_set_recursive(pe_resource_t *rsc, long long flag, bool any)
Definition: clone.c:339
#define crm_notice(fmt, args...)
Definition: logging.h:349
bool pe__is_guest_or_remote_node(const pe_node_t *node)
Definition: remote.c:41
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:19
#define INFINITY
Definition: crm.h:95
GList * sort_nodes_by_weight(GList *nodes, pe_node_t *active_node, pe_working_set_t *data_set)
enum pe_action_flags summary_action_flags(pe_action_t *action, GListPtr children, pe_node_t *node)
pe_resource_t * container
Definition: pe_types.h:367
resource_alloc_functions_t * cmds
Definition: pe_types.h:320
enum pe_graph_flags(* update_actions)(pe_action_t *, pe_action_t *, pe_node_t *, enum pe_action_flags, enum pe_action_flags, enum pe_ordering, pe_working_set_t *data_set)
pe_resource_t * rsc
Definition: pe_types.h:391
#define pe__show_node_weights(level, rsc, text, nodes)
Definition: internal.h:393
gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
void pcmk__bundle_create_actions(pe_resource_t *rsc, pe_working_set_t *data_set)
pe_resource_t * remote_rsc
Definition: pe_types.h:219
GHashTable * meta
Definition: pe_types.h:360
void pcmk__bundle_rsc_colocation_rh(pe_resource_t *rsc_lh, pe_resource_t *rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
resource_object_functions_t * fns
Definition: pe_types.h:319
enum pe_graph_flags pcmk__multi_update_actions(pe_action_t *first, pe_action_t *then, pe_node_t *node, enum pe_action_flags flags, enum pe_action_flags filter, enum pe_ordering type, pe_working_set_t *data_set)
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:134
enum pe_graph_flags native_update_actions(pe_action_t *first, pe_action_t *then, pe_node_t *node, enum pe_action_flags flags, enum pe_action_flags filter, enum pe_ordering type, pe_working_set_t *data_set)
gboolean pcmk__bundle_create_probe(pe_resource_t *rsc, pe_node_t *node, pe_action_t *complete, gboolean force, pe_working_set_t *data_set)
enum pe_action_flags pcmk__bundle_action_flags(pe_action_t *action, pe_node_t *node)
void native_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
gboolean show_scores
#define RSC_START
Definition: crm.h:196
int migration_threshold
Definition: pe_types.h:331
pe_action_t * action
Definition: pe_types.h:510
bool pcmk__ends_with(const char *s, const char *match)
Definition: strings.c:504
gboolean is_child_compatible(pe_resource_t *child_rsc, pe_node_t *local_node, enum rsc_role_e filter, gboolean current)
bool pe__bundle_needs_remote_name(pe_resource_t *rsc)
Definition: bundle.c:957
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:213
#define XML_RSC_ATTR_REMOTE_RA_ADDR
Definition: msg_xml.h:218
const char * action
Definition: pcmk_fence.c:30
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:47
#define pe_rsc_provisional
Definition: pe_types.h:247
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition: pe_types.h:53
int weight
Definition: pe_types.h:230
#define crm_warn(fmt, args...)
Definition: logging.h:348
void LogActions(pe_resource_t *rsc, pe_working_set_t *data_set, gboolean terminal)
pe_action_flags
Definition: pe_types.h:279
#define order_stop_stop(rsc1, rsc2, type)
pe_action_t * create_pseudo_resource_op(pe_resource_t *rsc, const char *task, bool optional, bool runnable, pe_working_set_t *data_set)
#define crm_debug(fmt, args...)
Definition: logging.h:352
pe_resource_t * find_compatible_child_by_node(pe_resource_t *local_child, pe_node_t *local_node, pe_resource_t *rsc, enum rsc_role_e filter, gboolean current)
char * task
Definition: pe_types.h:395
const char * pe__add_bundle_remote_name(pe_resource_t *rsc, xmlNode *xml, const char *field)
Definition: bundle.c:987
gboolean update_action(pe_action_t *action, pe_working_set_t *data_set)
int custom_action_order(pe_resource_t *lh_rsc, char *lh_task, pe_action_t *lh_action, pe_resource_t *rh_rsc, char *rh_task, pe_action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set)
#define crm_trace(fmt, args...)
Definition: logging.h:353
enum action_tasks get_complex_task(pe_resource_t *rsc, const char *name, gboolean allow_non_atomic)
Definition: utils.c:1480
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:196
void promote_demote_constraints(pe_resource_t *rsc, pe_working_set_t *data_set)
struct pe_node_shared_s * details
Definition: pe_types.h:233
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition: utils.c:1883
unsigned long long flags
Definition: pe_types.h:335
const char * uname
Definition: pe_types.h:198
#define pe_rsc_promotable
Definition: pe_types.h:245
enum action_tasks clone_child_action(pe_action_t *action)
bool assign_node(pe_resource_t *rsc, pe_node_t *node, gboolean force)
#define pe__set_graph_flags(graph_flags, gr_action, flags_to_set)
Definition: internal.h:125
pe_graph_flags
Definition: pe_types.h:271
void pcmk__bundle_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
#define XML_RSC_ATTR_INCARNATION_NODEMAX
Definition: msg_xml.h:196
char * uuid
Definition: pe_types.h:396
pe_resource_t * rsc_lh
enum pe_action_flags(* action_flags)(pe_action_t *, pe_node_t *)
#define pe_rsc_allocating
Definition: pe_types.h:248
enum pe_obj_types variant
Definition: pe_types.h:317
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:866
int new_rsc_order(pe_resource_t *lh_rsc, const char *lh_task, pe_resource_t *rh_rsc, const char *rh_task, enum pe_ordering type, pe_working_set_t *data_set)
#define RSC_DEMOTED
Definition: crm.h:205
void pcmk__bundle_rsc_colocation_lh(pe_resource_t *rsc, pe_resource_t *rsc_rh, rsc_colocation_t *constraint, pe_working_set_t *data_set)
GListPtr actions
Definition: pe_types.h:346
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition: operations.c:44
pe_resource_t * find_compatible_child(pe_resource_t *local_child, pe_resource_t *rsc, enum rsc_role_e filter, gboolean current, pe_working_set_t *data_set)
void(* rsc_colocation_lh)(pe_resource_t *, pe_resource_t *, rsc_colocation_t *, pe_working_set_t *)
void pcmk__bundle_expand(pe_resource_t *rsc, pe_working_set_t *data_set)
#define RSC_STARTED
Definition: crm.h:197
GListPtr children
Definition: pe_types.h:364
int copies_per_node(pe_resource_t *rsc)
#define crm_err(fmt, args...)
Definition: logging.h:347
#define CRM_ASSERT(expr)
Definition: results.h:42
#define RSC_STATUS
Definition: crm.h:210
void node_list_exclude(GHashTable *list, GListPtr list2, gboolean merge_scores)
Definition: utils.c:158
void pcmk__bundle_log_actions(pe_resource_t *rsc, pe_working_set_t *data_set, gboolean terminal)
#define RSC_PROMOTE
Definition: crm.h:202
void clone_create_pseudo_actions(pe_resource_t *rsc, GListPtr children, notify_data_t **start_notify, notify_data_t **stop_notify, pe_working_set_t *data_set)
void pcmk__bundle_append_meta(pe_resource_t *rsc, xmlNode *xml)
char data[0]
Definition: internal.h:90
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:53
rsc_role_e
Definition: common.h:91
#define pe_rsc_block
Definition: pe_types.h:239
enum pe_action_flags flags
Definition: pe_types.h:400
#define pe_rsc_failure_ignored
Definition: pe_types.h:263
#define order_start_start(rsc1, rsc2, type)
#define RSC_STOPPED
Definition: crm.h:200
void pcmk__bundle_internal_constraints(pe_resource_t *rsc, pe_working_set_t *data_set)
const char * id
#define RSC_PROMOTED
Definition: crm.h:203
gboolean crm_is_true(const char *s)
Definition: strings.c:392
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:20
pe_action_t * find_first_action(GListPtr input, const char *uuid, const char *task, pe_node_t *on_node)
Definition: utils.c:1503
#define pe_err(fmt...)
Definition: internal.h:22
#define XML_RSC_ATTR_INTERLEAVE
Definition: msg_xml.h:192
GList * GListPtr
Definition: crm.h:214
#define crm_info(fmt, args...)
Definition: logging.h:350
#define pe_rsc_orphan
Definition: pe_types.h:237
pe_ordering
Definition: pe_types.h:464
uint64_t flags
Definition: remote.c:149
int pe_get_failcount(pe_node_t *node, pe_resource_t *rsc, time_t *last_failure, uint32_t flags, xmlNode *xml_op, pe_working_set_t *data_set)
Definition: failcounts.c:251
action_tasks
Definition: common.h:62
enum crm_ais_msg_types type
Definition: internal.h:83
#define RSC_DEMOTE
Definition: crm.h:204
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:18
void distribute_children(pe_resource_t *rsc, GListPtr children, GListPtr nodes, int max, int per_host_max, pe_working_set_t *data_set)
char * id
Definition: pe_types.h:308
GHashTable * allowed_nodes
Definition: pe_types.h:355