pacemaker  2.1.5-b7adf64e51
Scalable High-Availability cluster resource manager
pcmk_sched_bundle.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2022 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 <stdbool.h>
13 
14 #include <crm/msg_xml.h>
15 #include <pacemaker-internal.h>
16 
17 #include "libpacemaker_private.h"
18 
19 #define PE__VARIANT_BUNDLE 1
20 #include <lib/pengine/variant.h>
21 
22 static bool
23 is_bundle_node(pe__bundle_variant_data_t *data, pe_node_t *node)
24 {
25  for (GList *gIter = data->replicas; gIter != NULL; gIter = gIter->next) {
26  pe__bundle_replica_t *replica = gIter->data;
27 
28  if (node->details == replica->node->details) {
29  return TRUE;
30  }
31  }
32  return FALSE;
33 }
34 
35 void distribute_children(pe_resource_t *rsc, GList *children, GList *nodes,
36  int max, int per_host_max, pe_working_set_t * data_set);
37 
38 static GList *
39 get_container_list(const pe_resource_t *rsc)
40 {
41  GList *containers = NULL;
42 
43  if (rsc->variant == pe_container) {
44  pe__bundle_variant_data_t *data = NULL;
45 
46  get_bundle_variant_data(data, rsc);
47  for (GList *gIter = data->replicas; gIter != NULL;
48  gIter = gIter->next) {
49  pe__bundle_replica_t *replica = gIter->data;
50 
51  containers = g_list_append(containers, replica->container);
52  }
53  }
54  return containers;
55 }
56 
57 static inline GList *
58 get_containers_or_children(const pe_resource_t *rsc)
59 {
60  return (rsc->variant == pe_container)?
61  get_container_list(rsc) : rsc->children;
62 }
63 
73 pe_node_t *
75 {
76  GList *containers = NULL;
77  GList *nodes = NULL;
78  pe__bundle_variant_data_t *bundle_data = NULL;
79 
80  CRM_CHECK(rsc != NULL, return NULL);
81 
82  get_bundle_variant_data(bundle_data, rsc);
83 
85  containers = get_container_list(rsc);
86 
88  rsc, __func__, rsc->allowed_nodes, rsc->cluster);
89 
90  nodes = g_hash_table_get_values(rsc->allowed_nodes);
91  nodes = pcmk__sort_nodes(nodes, NULL);
92  containers = g_list_sort(containers, pcmk__cmp_instance);
93  distribute_children(rsc, containers, nodes, bundle_data->nreplicas,
94  bundle_data->nreplicas_per_host, rsc->cluster);
95  g_list_free(nodes);
96  g_list_free(containers);
97 
98  for (GList *gIter = bundle_data->replicas; gIter != NULL;
99  gIter = gIter->next) {
100  pe__bundle_replica_t *replica = gIter->data;
101  pe_node_t *container_host = NULL;
102 
103  CRM_ASSERT(replica);
104  if (replica->ip) {
105  pe_rsc_trace(rsc, "Allocating bundle %s IP %s",
106  rsc->id, replica->ip->id);
107  replica->ip->cmds->assign(replica->ip, prefer);
108  }
109 
110  container_host = replica->container->allocated_to;
111  if (replica->remote && pe__is_guest_or_remote_node(container_host)) {
112  /* We need 'nested' connection resources to be on the same
113  * host because pacemaker-remoted only supports a single
114  * active connection
115  */
116  pcmk__new_colocation("child-remote-with-docker-remote", NULL,
117  INFINITY, replica->remote,
118  container_host->details->remote_rsc, NULL,
119  NULL, true, rsc->cluster);
120  }
121 
122  if (replica->remote) {
123  pe_rsc_trace(rsc, "Allocating bundle %s connection %s",
124  rsc->id, replica->remote->id);
125  replica->remote->cmds->assign(replica->remote, prefer);
126  }
127 
128  // Explicitly allocate replicas' children before bundle child
129  if (replica->child) {
130  pe_node_t *node = NULL;
131  GHashTableIter iter;
132 
133  g_hash_table_iter_init(&iter, replica->child->allowed_nodes);
134  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
135  if (node->details != replica->node->details) {
136  node->weight = -INFINITY;
137  } else if (!pcmk__threshold_reached(replica->child, node,
138  NULL)) {
139  node->weight = INFINITY;
140  }
141  }
142 
143  pe__set_resource_flags(replica->child->parent, pe_rsc_allocating);
144  pe_rsc_trace(rsc, "Allocating bundle %s replica child %s",
145  rsc->id, replica->child->id);
146  replica->child->cmds->assign(replica->child, replica->node);
147  pe__clear_resource_flags(replica->child->parent,
149  }
150  }
151 
152  if (bundle_data->child) {
153  pe_node_t *node = NULL;
154  GHashTableIter iter;
155  g_hash_table_iter_init(&iter, bundle_data->child->allowed_nodes);
156  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
157  if (is_bundle_node(bundle_data, node)) {
158  node->weight = 0;
159  } else {
160  node->weight = -INFINITY;
161  }
162  }
163  pe_rsc_trace(rsc, "Allocating bundle %s child %s",
164  rsc->id, bundle_data->child->id);
165  bundle_data->child->cmds->assign(bundle_data->child, prefer);
166  }
167 
169  return NULL;
170 }
171 
172 
173 void
175 {
176  pe_action_t *action = NULL;
177  GList *containers = NULL;
178  pe__bundle_variant_data_t *bundle_data = NULL;
179 
180  CRM_CHECK(rsc != NULL, return);
181 
182  containers = get_container_list(rsc);
183  get_bundle_variant_data(bundle_data, rsc);
184  for (GList *gIter = bundle_data->replicas; gIter != NULL;
185  gIter = gIter->next) {
186  pe__bundle_replica_t *replica = gIter->data;
187 
188  CRM_ASSERT(replica);
189  if (replica->ip) {
190  replica->ip->cmds->create_actions(replica->ip);
191  }
192  if (replica->container) {
193  replica->container->cmds->create_actions(replica->container);
194  }
195  if (replica->remote) {
196  replica->remote->cmds->create_actions(replica->remote);
197  }
198  }
199 
200  clone_create_pseudo_actions(rsc, containers, NULL, NULL);
201 
202  if (bundle_data->child) {
203  bundle_data->child->cmds->create_actions(bundle_data->child);
204 
205  if (pcmk_is_set(bundle_data->child->flags, pe_rsc_promotable)) {
206  /* promote */
207  pe__new_rsc_pseudo_action(rsc, RSC_PROMOTE, true, true);
208  action = pe__new_rsc_pseudo_action(rsc, RSC_PROMOTED, true, true);
209  action->priority = INFINITY;
210 
211  /* demote */
212  pe__new_rsc_pseudo_action(rsc, RSC_DEMOTE, true, true);
213  action = pe__new_rsc_pseudo_action(rsc, RSC_DEMOTED, true, true);
214  action->priority = INFINITY;
215  }
216  }
217 
218  g_list_free(containers);
219 }
220 
221 void
223 {
224  pe__bundle_variant_data_t *bundle_data = NULL;
225 
226  CRM_CHECK(rsc != NULL, return);
227 
228  get_bundle_variant_data(bundle_data, rsc);
229 
230  if (bundle_data->child) {
231  pcmk__order_resource_actions(rsc, RSC_START, bundle_data->child,
233  pcmk__order_resource_actions(rsc, RSC_STOP, bundle_data->child,
235 
236  if (bundle_data->child->children) {
237  pcmk__order_resource_actions(bundle_data->child, RSC_STARTED, rsc,
238  RSC_STARTED,
240  pcmk__order_resource_actions(bundle_data->child, RSC_STOPPED, rsc,
241  RSC_STOPPED,
243  } else {
244  pcmk__order_resource_actions(bundle_data->child, RSC_START, rsc,
245  RSC_STARTED,
247  pcmk__order_resource_actions(bundle_data->child, RSC_STOP, rsc,
248  RSC_STOPPED,
250  }
251  }
252 
253  for (GList *gIter = bundle_data->replicas; gIter != NULL;
254  gIter = gIter->next) {
255  pe__bundle_replica_t *replica = gIter->data;
256 
257  CRM_ASSERT(replica);
258  CRM_ASSERT(replica->container);
259 
260  replica->container->cmds->internal_constraints(replica->container);
261 
262  pcmk__order_starts(rsc, replica->container,
264 
265  if (replica->child) {
266  pcmk__order_stops(rsc, replica->child,
268  }
269  pcmk__order_stops(rsc, replica->container,
271  pcmk__order_resource_actions(replica->container, RSC_START, rsc,
272  RSC_STARTED,
274  pcmk__order_resource_actions(replica->container, RSC_STOP, rsc,
275  RSC_STOPPED,
277 
278  if (replica->ip) {
279  replica->ip->cmds->internal_constraints(replica->ip);
280 
281  // Start IP then container
282  pcmk__order_starts(replica->ip, replica->container,
284  pcmk__order_stops(replica->container, replica->ip,
286 
287  pcmk__new_colocation("ip-with-docker", NULL, INFINITY, replica->ip,
288  replica->container, NULL, NULL, true,
289  rsc->cluster);
290  }
291 
292  if (replica->remote) {
293  /* This handles ordering and colocating remote relative to container
294  * (via "resource-with-container"). Since IP is also ordered and
295  * colocated relative to the container, we don't need to do anything
296  * explicit here with IP.
297  */
298  replica->remote->cmds->internal_constraints(replica->remote);
299  }
300 
301  if (replica->child) {
302  CRM_ASSERT(replica->remote);
303 
304  // "Start remote then child" is implicit in scheduler's remote logic
305  }
306 
307  }
308 
309  if (bundle_data->child) {
310  bundle_data->child->cmds->internal_constraints(bundle_data->child);
311  if (pcmk_is_set(bundle_data->child->flags, pe_rsc_promotable)) {
313 
314  /* child demoted before global demoted */
315  pcmk__order_resource_actions(bundle_data->child, RSC_DEMOTED, rsc,
316  RSC_DEMOTED,
318 
319  /* global demote before child demote */
320  pcmk__order_resource_actions(rsc, RSC_DEMOTE, bundle_data->child,
321  RSC_DEMOTE,
323 
324  /* child promoted before global promoted */
325  pcmk__order_resource_actions(bundle_data->child, RSC_PROMOTED, rsc,
326  RSC_PROMOTED,
328 
329  /* global promote before child promote */
330  pcmk__order_resource_actions(rsc, RSC_PROMOTE, bundle_data->child,
331  RSC_PROMOTE,
333  }
334  }
335 }
336 
337 static pe_resource_t *
338 compatible_replica_for_node(const pe_resource_t *rsc_lh,
339  const pe_node_t *candidate,
340  const pe_resource_t *rsc, enum rsc_role_e filter,
341  gboolean current)
342 {
343  pe__bundle_variant_data_t *bundle_data = NULL;
344 
345  CRM_CHECK(candidate != NULL, return NULL);
346  get_bundle_variant_data(bundle_data, rsc);
347 
348  crm_trace("Looking for compatible child from %s for %s on %s",
349  rsc_lh->id, rsc->id, pe__node_name(candidate));
350 
351  for (GList *gIter = bundle_data->replicas; gIter != NULL;
352  gIter = gIter->next) {
353  pe__bundle_replica_t *replica = gIter->data;
354 
355  if (is_child_compatible(replica->container, candidate, filter, current)) {
356  crm_trace("Pairing %s with %s on %s",
357  rsc_lh->id, replica->container->id,
358  pe__node_name(candidate));
359  return replica->container;
360  }
361  }
362 
363  crm_trace("Can't pair %s with %s", rsc_lh->id, rsc->id);
364  return NULL;
365 }
366 
367 static pe_resource_t *
368 compatible_replica(const pe_resource_t *rsc_lh, const pe_resource_t *rsc,
369  enum rsc_role_e filter, gboolean current,
371 {
372  GList *scratch = NULL;
373  pe_resource_t *pair = NULL;
374  pe_node_t *active_node_lh = NULL;
375 
376  active_node_lh = rsc_lh->fns->location(rsc_lh, NULL, current);
377  if (active_node_lh) {
378  return compatible_replica_for_node(rsc_lh, active_node_lh, rsc, filter,
379  current);
380  }
381 
382  scratch = g_hash_table_get_values(rsc_lh->allowed_nodes);
383  scratch = pcmk__sort_nodes(scratch, NULL);
384 
385  for (GList *gIter = scratch; gIter != NULL; gIter = gIter->next) {
386  pe_node_t *node = (pe_node_t *) gIter->data;
387 
388  pair = compatible_replica_for_node(rsc_lh, node, rsc, filter, current);
389  if (pair) {
390  goto done;
391  }
392  }
393 
394  pe_rsc_debug(rsc, "Can't pair %s with %s", rsc_lh->id, (rsc? rsc->id : "none"));
395  done:
396  g_list_free(scratch);
397  return pair;
398 }
399 
401 {
402  /* Strictly speaking, there should be a 'copies_per_node' addition
403  * to the resource function table and each case would be a
404  * function. However that would be serious overkill to return an
405  * int. In fact, it seems to me that both function tables
406  * could/should be replaced by resources.{c,h} full of
407  * rsc_{some_operation} functions containing a switch as below
408  * which calls out to functions named {variant}_{some_operation}
409  * as needed.
410  */
411  switch(rsc->variant) {
412  case pe_unknown:
413  return 0;
414  case pe_native:
415  case pe_group:
416  return 1;
417  case pe_clone:
418  {
419  const char *max_clones_node = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_NODEMAX);
420 
421  if (max_clones_node == NULL) {
422  return 1;
423 
424  } else {
425  int max_i;
426 
427  pcmk__scan_min_int(max_clones_node, &max_i, 0);
428  return max_i;
429  }
430  }
431  case pe_container:
432  {
433  pe__bundle_variant_data_t *data = NULL;
434  get_bundle_variant_data(data, rsc);
435  return data->nreplicas_per_host;
436  }
437  }
438  return 0;
439 }
440 
454 void
456  const pe_resource_t *primary,
457  const pcmk__colocation_t *colocation,
458  bool for_dependent)
459 {
460  GList *allocated_primaries = NULL;
461  pe__bundle_variant_data_t *bundle_data = NULL;
462 
463  /* This should never be called for the bundle itself as a dependent.
464  * Instead, we add its colocation constraints to its replicas and call the
465  * apply_coloc_score() for the replicas as dependents.
466  */
467  CRM_ASSERT(!for_dependent);
468 
469  CRM_CHECK((colocation != NULL) && (dependent != NULL) && (primary != NULL),
470  return);
471  CRM_ASSERT(dependent->variant == pe_native);
472 
473  if (pcmk_is_set(primary->flags, pe_rsc_provisional)) {
474  pe_rsc_trace(primary, "%s is still provisional", primary->id);
475  return;
476 
477  } else if (colocation->dependent->variant > pe_group) {
478  pe_resource_t *primary_replica = compatible_replica(dependent, primary,
480  FALSE,
481  dependent->cluster);
482 
483  if (primary_replica) {
484  pe_rsc_debug(primary, "Pairing %s with %s",
485  dependent->id, primary_replica->id);
486  dependent->cmds->apply_coloc_score(dependent, primary_replica,
487  colocation, true);
488 
489  } else if (colocation->score >= INFINITY) {
490  crm_notice("Cannot pair %s with instance of %s",
491  dependent->id, primary->id);
492  pcmk__assign_resource(dependent, NULL, true);
493 
494  } else {
495  pe_rsc_debug(primary, "Cannot pair %s with instance of %s",
496  dependent->id, primary->id);
497  }
498 
499  return;
500  }
501 
502  get_bundle_variant_data(bundle_data, primary);
503  pe_rsc_trace(primary, "Processing constraint %s: %s -> %s %d",
504  colocation->id, dependent->id, primary->id, colocation->score);
505 
506  for (GList *gIter = bundle_data->replicas; gIter != NULL;
507  gIter = gIter->next) {
508  pe__bundle_replica_t *replica = gIter->data;
509 
510  if (colocation->score < INFINITY) {
511  replica->container->cmds->apply_coloc_score(dependent,
512  replica->container,
513  colocation, false);
514 
515  } else {
516  pe_node_t *chosen = replica->container->fns->location(replica->container,
517  NULL, FALSE);
518 
519  if ((chosen == NULL)
520  || is_set_recursive(replica->container, pe_rsc_block, TRUE)) {
521  continue;
522  }
523  if ((colocation->primary_role >= RSC_ROLE_PROMOTED)
524  && (replica->child == NULL)) {
525  continue;
526  }
527  if ((colocation->primary_role >= RSC_ROLE_PROMOTED)
528  && (replica->child->next_role < RSC_ROLE_PROMOTED)) {
529  continue;
530  }
531 
532  pe_rsc_trace(primary, "Allowing %s: %s %d",
533  colocation->id, pe__node_name(chosen), chosen->weight);
534  allocated_primaries = g_list_prepend(allocated_primaries, chosen);
535  }
536  }
537 
538  if (colocation->score >= INFINITY) {
539  node_list_exclude(dependent->allowed_nodes, allocated_primaries, FALSE);
540  }
541  g_list_free(allocated_primaries);
542 }
543 
544 enum pe_action_flags
546 {
547  GList *containers = NULL;
548  enum pe_action_flags flags = 0;
549  pe__bundle_variant_data_t *data = NULL;
550 
551  get_bundle_variant_data(data, action->rsc);
552  if(data->child) {
553  enum action_tasks task = get_complex_task(data->child, action->task, TRUE);
554  switch(task) {
555  case no_action:
556  case action_notify:
557  case action_notified:
558  case action_promote:
559  case action_promoted:
560  case action_demote:
561  case action_demoted:
562  return summary_action_flags(action, data->child->children, node);
563  default:
564  break;
565  }
566  }
567 
568  containers = get_container_list(action->rsc);
569  flags = summary_action_flags(action, containers, node);
570  g_list_free(containers);
571  return flags;
572 }
573 
576  const pe_node_t *local_node,
577  const pe_resource_t *rsc, enum rsc_role_e filter,
578  gboolean current)
579 {
580  GList *gIter = NULL;
581  GList *children = NULL;
582 
583  if (local_node == NULL) {
584  crm_err("Can't colocate unrunnable child %s with %s", local_child->id, rsc->id);
585  return NULL;
586  }
587 
588  crm_trace("Looking for compatible child from %s for %s on %s",
589  local_child->id, rsc->id, pe__node_name(local_node));
590 
591  children = get_containers_or_children(rsc);
592  for (gIter = children; gIter != NULL; gIter = gIter->next) {
593  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
594 
595  if(is_child_compatible(child_rsc, local_node, filter, current)) {
596  crm_trace("Pairing %s with %s on %s",
597  local_child->id, child_rsc->id, pe__node_name(local_node));
598  return child_rsc;
599  }
600  }
601 
602  crm_trace("Can't pair %s with %s", local_child->id, rsc->id);
603  if(children != rsc->children) {
604  g_list_free(children);
605  }
606  return NULL;
607 }
608 
609 static pe__bundle_replica_t *
610 replica_for_container(const pe_resource_t *rsc, const pe_resource_t *container,
611  const pe_node_t *node)
612 {
613  if (rsc->variant == pe_container) {
614  const pe__bundle_variant_data_t *data = NULL;
615 
616  get_bundle_variant_data(data, rsc);
617  for (GList *gIter = data->replicas; gIter != NULL;
618  gIter = gIter->next) {
619  pe__bundle_replica_t *replica = gIter->data;
620 
621  if (replica->child
622  && (container == replica->container)
623  && pe__same_node(node, replica->node)) {
624  return replica;
625  }
626  }
627  }
628  return NULL;
629 }
630 
631 static uint32_t
632 multi_update_interleave_actions(pe_action_t *first, pe_action_t *then,
633  const pe_node_t *node, uint32_t filter,
634  uint32_t type, pe_working_set_t *data_set)
635 {
636  GList *gIter = NULL;
637  GList *children = NULL;
638  gboolean current = FALSE;
639  uint32_t changed = pcmk__updated_none;
640 
641  /* Fix this - lazy */
642  if (pcmk__ends_with(first->uuid, "_stopped_0")
643  || pcmk__ends_with(first->uuid, "_demoted_0")) {
644  current = TRUE;
645  }
646 
647  children = get_containers_or_children(then->rsc);
648  for (gIter = children; gIter != NULL; gIter = gIter->next) {
649  pe_resource_t *then_child = gIter->data;
650  pe_resource_t *first_child = find_compatible_child(then_child,
651  first->rsc,
653  current);
654  if (first_child == NULL && current) {
655  crm_trace("Ignore");
656 
657  } else if (first_child == NULL) {
658  crm_debug("No match found for %s (%d / %s / %s)", then_child->id, current, first->uuid, then->uuid);
659 
660  /* Me no like this hack - but what else can we do?
661  *
662  * If there is no-one active or about to be active
663  * on the same node as then_child, then they must
664  * not be allowed to start
665  */
666  if (pcmk_any_flags_set(type, pe_order_runnable_left|pe_order_implies_then) /* Mandatory */ ) {
667  pe_rsc_info(then->rsc, "Inhibiting %s from being active", then_child->id);
668  if (pcmk__assign_resource(then_child, NULL, true)) {
670  }
671  }
672 
673  } else {
674  pe_action_t *first_action = NULL;
675  pe_action_t *then_action = NULL;
676 
677  enum action_tasks task = clone_child_action(first);
678  const char *first_task = task2text(task);
679 
680  pe__bundle_replica_t *first_replica = NULL;
681  pe__bundle_replica_t *then_replica = NULL;
682 
683  first_replica = replica_for_container(first->rsc, first_child,
684  node);
685  if (strstr(first->task, "stop") && first_replica && first_replica->child) {
686  /* Except for 'stopped' we should be looking at the
687  * in-container resource, actions for the child will
688  * happen later and are therefor more likely to align
689  * with the user's intent.
690  */
691  first_action = find_first_action(first_replica->child->actions,
692  NULL, task2text(task), node);
693  } else {
694  first_action = find_first_action(first_child->actions, NULL, task2text(task), node);
695  }
696 
697  then_replica = replica_for_container(then->rsc, then_child, node);
698  if (strstr(then->task, "mote")
699  && then_replica && then_replica->child) {
700  /* Promote/demote actions will never be found for the
701  * container resource, look in the child instead
702  *
703  * Alternatively treat:
704  * 'XXXX then promote YYYY' as 'XXXX then start container for YYYY', and
705  * 'demote XXXX then stop YYYY' as 'stop container for XXXX then stop YYYY'
706  */
707  then_action = find_first_action(then_replica->child->actions,
708  NULL, then->task, node);
709  } else {
710  then_action = find_first_action(then_child->actions, NULL, then->task, node);
711  }
712 
713  if (first_action == NULL) {
714  if (!pcmk_is_set(first_child->flags, pe_rsc_orphan)
715  && !pcmk__str_any_of(first_task, RSC_STOP, RSC_DEMOTE, NULL)) {
716  crm_err("Internal error: No action found for %s in %s (first)",
717  first_task, first_child->id);
718 
719  } else {
720  crm_trace("No action found for %s in %s%s (first)",
721  first_task, first_child->id,
722  pcmk_is_set(first_child->flags, pe_rsc_orphan)? " (ORPHAN)" : "");
723  }
724  continue;
725  }
726 
727  /* We're only interested if 'then' is neither stopping nor being demoted */
728  if (then_action == NULL) {
729  if (!pcmk_is_set(then_child->flags, pe_rsc_orphan)
730  && !pcmk__str_any_of(then->task, RSC_STOP, RSC_DEMOTE, NULL)) {
731  crm_err("Internal error: No action found for %s in %s (then)",
732  then->task, then_child->id);
733 
734  } else {
735  crm_trace("No action found for %s in %s%s (then)",
736  then->task, then_child->id,
737  pcmk_is_set(then_child->flags, pe_rsc_orphan)? " (ORPHAN)" : "");
738  }
739  continue;
740  }
741 
742  if (order_actions(first_action, then_action, type)) {
743  crm_debug("Created constraint for %s (%d) -> %s (%d) %.6x",
744  first_action->uuid,
745  pcmk_is_set(first_action->flags, pe_action_optional),
746  then_action->uuid,
747  pcmk_is_set(then_action->flags, pe_action_optional),
748  type);
749  pcmk__set_updated_flags(changed, first,
751  }
752  if(first_action && then_action) {
753  changed |= then_child->cmds->update_ordered_actions(first_action,
754  then_action,
755  node,
756  first_child->cmds->action_flags(first_action, node),
757  filter,
758  type,
759  data_set);
760  } else {
761  crm_err("Nothing found either for %s (%p) or %s (%p) %s",
762  first_child->id, first_action,
763  then_child->id, then_action, task2text(task));
764  }
765  }
766  }
767 
768  if(children != then->rsc->children) {
769  g_list_free(children);
770  }
771  return changed;
772 }
773 
774 static bool
775 can_interleave_actions(pe_action_t *first, pe_action_t *then)
776 {
777  bool interleave = FALSE;
778  pe_resource_t *rsc = NULL;
779  const char *interleave_s = NULL;
780 
781  if(first->rsc == NULL || then->rsc == NULL) {
782  crm_trace("Not interleaving %s with %s (both must be resources)", first->uuid, then->uuid);
783  return FALSE;
784  } else if(first->rsc == then->rsc) {
785  crm_trace("Not interleaving %s with %s (must belong to different resources)", first->uuid, then->uuid);
786  return FALSE;
787  } else if(first->rsc->variant < pe_clone || then->rsc->variant < pe_clone) {
788  crm_trace("Not interleaving %s with %s (both sides must be clones or bundles)", first->uuid, then->uuid);
789  return FALSE;
790  }
791 
792  if (pcmk__ends_with(then->uuid, "_stop_0")
793  || pcmk__ends_with(then->uuid, "_demote_0")) {
794  rsc = first->rsc;
795  } else {
796  rsc = then->rsc;
797  }
798 
799  interleave_s = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERLEAVE);
800  interleave = crm_is_true(interleave_s);
801  crm_trace("Interleave %s -> %s: %s (based on %s)",
802  first->uuid, then->uuid, interleave ? "yes" : "no", rsc->id);
803 
804  return interleave;
805 }
806 
829 uint32_t
831  const pe_node_t *node, uint32_t flags,
832  uint32_t filter, uint32_t type,
834 {
835  uint32_t changed = pcmk__updated_none;
836 
837  crm_trace("%s -> %s", first->uuid, then->uuid);
838 
839  if(can_interleave_actions(first, then)) {
840  changed = multi_update_interleave_actions(first, then, node, filter,
841  type, data_set);
842 
843  } else if(then->rsc) {
844  GList *gIter = NULL;
845  GList *children = NULL;
846 
847  // Handle the 'primitive' ordering case
848  changed |= pcmk__update_ordered_actions(first, then, node, flags,
849  filter, type, data_set);
850 
851  // Now any children (or containers in the case of a bundle)
852  children = get_containers_or_children(then->rsc);
853  for (gIter = children; gIter != NULL; gIter = gIter->next) {
854  pe_resource_t *then_child = (pe_resource_t *) gIter->data;
855  uint32_t then_child_changed = pcmk__updated_none;
856  pe_action_t *then_child_action = find_first_action(then_child->actions, NULL, then->task, node);
857 
858  if (then_child_action) {
859  uint32_t then_child_flags = then_child->cmds->action_flags(then_child_action,
860  node);
861 
862  if (pcmk_is_set(then_child_flags, pe_action_runnable)) {
863  then_child_changed |= then_child->cmds->update_ordered_actions(first,
864  then_child_action,
865  node,
866  flags,
867  filter,
868  type,
869  data_set);
870  }
871  changed |= then_child_changed;
872  if (pcmk_is_set(then_child_changed, pcmk__updated_then)) {
873  for (GList *lpc = then_child_action->actions_after; lpc != NULL; lpc = lpc->next) {
874  pe_action_wrapper_t *next = (pe_action_wrapper_t *) lpc->data;
875 
877  data_set);
878  }
879  }
880  }
881  }
882 
883  if(children != then->rsc->children) {
884  g_list_free(children);
885  }
886  }
887  return changed;
888 }
889 
890 void
892 {
893  pe__bundle_variant_data_t *bundle_data = NULL;
894  get_bundle_variant_data(bundle_data, rsc);
895 
896  pcmk__apply_location(rsc, constraint);
897 
898  for (GList *gIter = bundle_data->replicas; gIter != NULL;
899  gIter = gIter->next) {
900  pe__bundle_replica_t *replica = gIter->data;
901 
902  if (replica->container) {
903  replica->container->cmds->apply_location(replica->container,
904  constraint);
905  }
906  if (replica->ip) {
907  replica->ip->cmds->apply_location(replica->ip, constraint);
908  }
909  }
910 
911  if (bundle_data->child
912  && ((constraint->role_filter == RSC_ROLE_UNPROMOTED)
913  || (constraint->role_filter == RSC_ROLE_PROMOTED))) {
914  bundle_data->child->cmds->apply_location(bundle_data->child,
915  constraint);
916  bundle_data->child->rsc_location = g_list_prepend(bundle_data->child->rsc_location,
917  constraint);
918  }
919 }
920 
927 void
929 {
930  pe__bundle_variant_data_t *bundle_data = NULL;
931 
932  CRM_CHECK(rsc != NULL, return);
933 
934  get_bundle_variant_data(bundle_data, rsc);
935 
936  if (bundle_data->child) {
937  bundle_data->child->cmds->add_actions_to_graph(bundle_data->child);
938  }
939 
940  for (GList *gIter = bundle_data->replicas; gIter != NULL;
941  gIter = gIter->next) {
942  pe__bundle_replica_t *replica = gIter->data;
943 
944  CRM_ASSERT(replica);
945  if (replica->remote && replica->container
946  && pe__bundle_needs_remote_name(replica->remote, rsc->cluster)) {
947 
948  /* REMOTE_CONTAINER_HACK: Allow remote nodes to run containers that
949  * run pacemaker-remoted inside, without needing a separate IP for
950  * the container. This is done by configuring the inner remote's
951  * connection host as the magic string "#uname", then
952  * replacing it with the underlying host when needed.
953  */
954  xmlNode *nvpair = get_xpath_object("//nvpair[@name='" XML_RSC_ATTR_REMOTE_RA_ADDR "']",
955  replica->remote->xml, LOG_ERR);
956  const char *calculated_addr = NULL;
957 
958  // Replace the value in replica->remote->xml (if appropriate)
959  calculated_addr = pe__add_bundle_remote_name(replica->remote,
960  rsc->cluster,
961  nvpair, "value");
962  if (calculated_addr) {
963  /* Since this is for the bundle as a resource, and not any
964  * particular action, replace the value in the default
965  * parameters (not evaluated for node). create_graph_action()
966  * will grab it from there to replace it in node-evaluated
967  * parameters.
968  */
969  GHashTable *params = pe_rsc_params(replica->remote,
970  NULL, rsc->cluster);
971 
972  g_hash_table_replace(params,
974  strdup(calculated_addr));
975  } else {
976  /* The only way to get here is if the remote connection is
977  * neither currently running nor scheduled to run. That means we
978  * won't be doing any operations that require addr (only start
979  * requires it; we additionally use it to compare digests when
980  * unpacking status, promote, and migrate_from history, but
981  * that's already happened by this point).
982  */
983  crm_info("Unable to determine address for bundle %s remote connection",
984  rsc->id);
985  }
986  }
987  if (replica->ip) {
988  replica->ip->cmds->add_actions_to_graph(replica->ip);
989  }
990  if (replica->container) {
991  replica->container->cmds->add_actions_to_graph(replica->container);
992  }
993  if (replica->remote) {
994  replica->remote->cmds->add_actions_to_graph(replica->remote);
995  }
996  }
997 }
998 
1009 bool
1011 {
1012  bool any_created = false;
1013  pe__bundle_variant_data_t *bundle_data = NULL;
1014 
1015  CRM_CHECK(rsc != NULL, return false);
1016 
1017  get_bundle_variant_data(bundle_data, rsc);
1018  for (GList *gIter = bundle_data->replicas; gIter != NULL;
1019  gIter = gIter->next) {
1020  pe__bundle_replica_t *replica = gIter->data;
1021 
1022  CRM_ASSERT(replica);
1023  if ((replica->ip != NULL)
1024  && replica->ip->cmds->create_probe(replica->ip, node)) {
1025  any_created = true;
1026  }
1027  if ((replica->child != NULL) && (node->details == replica->node->details)
1028  && replica->child->cmds->create_probe(replica->child, node)) {
1029  any_created = true;
1030  }
1031  if ((replica->container != NULL)
1032  && replica->container->cmds->create_probe(replica->container,
1033  node)) {
1034  any_created = true;
1035 
1036  /* If we're limited to one replica per host (due to
1037  * the lack of an IP range probably), then we don't
1038  * want any of our peer containers starting until
1039  * we've established that no other copies are already
1040  * running.
1041  *
1042  * Partly this is to ensure that nreplicas_per_host is
1043  * observed, but also to ensure that the containers
1044  * don't fail to start because the necessary port
1045  * mappings (which won't include an IP for uniqueness)
1046  * are already taken
1047  */
1048 
1049  for (GList *tIter = bundle_data->replicas;
1050  tIter && (bundle_data->nreplicas_per_host == 1);
1051  tIter = tIter->next) {
1052  pe__bundle_replica_t *other = tIter->data;
1053 
1054  if ((other != replica) && (other != NULL)
1055  && (other->container != NULL)) {
1056 
1057  pcmk__new_ordering(replica->container,
1058  pcmk__op_key(replica->container->id, RSC_STATUS, 0),
1059  NULL, other->container,
1060  pcmk__op_key(other->container->id, RSC_START, 0),
1061  NULL,
1063  rsc->cluster);
1064  }
1065  }
1066  }
1067  if ((replica->container != NULL) && (replica->remote != NULL)
1068  && replica->remote->cmds->create_probe(replica->remote, node)) {
1069 
1070  /* Do not probe the remote resource until we know where the
1071  * container is running. This is required for REMOTE_CONTAINER_HACK
1072  * to correctly probe remote resources.
1073  */
1074  char *probe_uuid = pcmk__op_key(replica->remote->id, RSC_STATUS,
1075  0);
1076  pe_action_t *probe = find_first_action(replica->remote->actions,
1077  probe_uuid, NULL, node);
1078 
1079  free(probe_uuid);
1080  if (probe != NULL) {
1081  any_created = true;
1082  crm_trace("Ordering %s probe on %s",
1083  replica->remote->id, pe__node_name(node));
1084  pcmk__new_ordering(replica->container,
1085  pcmk__op_key(replica->container->id, RSC_START, 0),
1086  NULL, replica->remote, NULL, probe,
1087  pe_order_probe, rsc->cluster);
1088  }
1089  }
1090  }
1091  return any_created;
1092 }
1093 
1094 void
1096 {
1097  pe__bundle_variant_data_t *bundle_data = NULL;
1098 
1099  CRM_CHECK(rsc != NULL, return);
1100 
1101  get_bundle_variant_data(bundle_data, rsc);
1102  for (GList *gIter = bundle_data->replicas; gIter != NULL;
1103  gIter = gIter->next) {
1104  pe__bundle_replica_t *replica = gIter->data;
1105 
1106  CRM_ASSERT(replica);
1107  if (replica->ip != NULL) {
1108  replica->ip->cmds->output_actions(replica->ip);
1109  }
1110  if (replica->container != NULL) {
1111  replica->container->cmds->output_actions(replica->container);
1112  }
1113  if (replica->remote != NULL) {
1114  replica->remote->cmds->output_actions(replica->remote);
1115  }
1116  if (replica->child != NULL) {
1117  replica->child->cmds->output_actions(replica->child);
1118  }
1119  }
1120 }
1121 
1122 // Bundle implementation of resource_alloc_functions_t:add_utilization()
1123 void
1125  const pe_resource_t *orig_rsc, GList *all_rscs,
1126  GHashTable *utilization)
1127 {
1128  pe__bundle_variant_data_t *bundle_data = NULL;
1129  pe__bundle_replica_t *replica = NULL;
1130 
1131  if (!pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
1132  return;
1133  }
1134 
1135  get_bundle_variant_data(bundle_data, rsc);
1136  if (bundle_data->replicas == NULL) {
1137  return;
1138  }
1139 
1140  /* All bundle replicas are identical, so using the utilization of the first
1141  * is sufficient for any. Only the implicit container resource can have
1142  * utilization values.
1143  */
1144  replica = (pe__bundle_replica_t *) bundle_data->replicas->data;
1145  if (replica->container != NULL) {
1146  replica->container->cmds->add_utilization(replica->container, orig_rsc,
1147  all_rscs, utilization);
1148  }
1149 }
1150 
1151 // Bundle implementation of resource_alloc_functions_t:shutdown_lock()
1152 void
1154 {
1155  return; // Bundles currently don't support shutdown locks
1156 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
void pcmk__bundle_internal_constraints(pe_resource_t *rsc)
enum rsc_role_e role_filter
Definition: internal.h:189
const char * task2text(enum action_tasks task)
Definition: common.c:401
void pcmk__output_bundle_actions(pe_resource_t *rsc)
#define pcmk__order_starts(rsc1, rsc2, flags)
#define RSC_STOP
Definition: crm.h:202
#define crm_notice(fmt, args...)
Definition: logging.h:361
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:46
char data[0]
Definition: cpg.c:55
#define INFINITY
Definition: crm.h:99
enum pe_action_flags pcmk__bundle_action_flags(pe_action_t *action, const pe_node_t *node)
G_GNUC_INTERNAL uint32_t pcmk__update_ordered_actions(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
Definition: internal.h:394
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:127
pe_resource_t * container
Definition: pe_types.h:387
GList * children
Definition: pe_types.h:384
resource_alloc_functions_t * cmds
Definition: pe_types.h:341
#define pcmk__order_stops(rsc1, rsc2, flags)
G_GNUC_INTERNAL bool pcmk__threshold_reached(pe_resource_t *rsc, pe_node_t *node, pe_resource_t **failed)
pe_resource_t * rsc
Definition: pe_types.h:406
void pcmk__bundle_add_utilization(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
pe_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pe_node_t *on_node)
Definition: pe_actions.c:1296
pe_resource_t * remote_rsc
Definition: pe_types.h:237
void pcmk__bundle_apply_coloc_score(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
GHashTable * meta
Definition: pe_types.h:380
resource_object_functions_t * fns
Definition: pe_types.h:340
bool pe__bundle_needs_remote_name(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: bundle.c:690
pe_resource_t * dependent
void node_list_exclude(GHashTable *list, GList *list2, gboolean merge_scores)
Definition: utils.c:108
G_GNUC_INTERNAL GList * pcmk__sort_nodes(GList *nodes, pe_node_t *active_node)
void clone_create_pseudo_actions(pe_resource_t *rsc, GList *children, notify_data_t **start_notify, notify_data_t **stop_notify)
pe_action_t * pe__new_rsc_pseudo_action(pe_resource_t *rsc, const char *task, bool optional, bool runnable)
Definition: pe_actions.c:1647
enum crm_ais_msg_types type
Definition: cpg.c:48
#define RSC_START
Definition: crm.h:199
pe_action_t * action
Definition: pe_types.h:530
pe_resource_t * find_compatible_child_by_node(const pe_resource_t *local_child, const pe_node_t *local_node, const pe_resource_t *rsc, enum rsc_role_e filter, gboolean current)
bool pcmk__ends_with(const char *s, const char *match)
Definition: strings.c:536
void pcmk__bundle_expand(pe_resource_t *rsc)
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:214
#define XML_RSC_ATTR_REMOTE_RA_ADDR
Definition: msg_xml.h:250
const char * action
Definition: pcmk_fence.c:30
gboolean is_child_compatible(const pe_resource_t *child_rsc, const pe_node_t *local_node, enum rsc_role_e filter, gboolean current)
G_GNUC_INTERNAL void pcmk__new_colocation(const char *id, const char *node_attr, int score, pe_resource_t *dependent, pe_resource_t *primary, const char *dependent_role, const char *primary_role, bool influence, pe_working_set_t *data_set)
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:74
enum pe_action_flags(* action_flags)(pe_action_t *action, const pe_node_t *node)
void distribute_children(pe_resource_t *rsc, GList *children, GList *nodes, int max, int per_host_max, pe_working_set_t *data_set)
#define pe_rsc_provisional
Definition: pe_types.h:266
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition: pe_types.h:55
int weight
Definition: pe_types.h:249
pe_action_flags
Definition: pe_types.h:298
pe_resource_t * find_compatible_child(const pe_resource_t *local_child, const pe_resource_t *rsc, enum rsc_role_e filter, gboolean current)
#define crm_debug(fmt, args...)
Definition: logging.h:364
char * task
Definition: pe_types.h:410
#define crm_trace(fmt, args...)
Definition: logging.h:365
enum action_tasks get_complex_task(pe_resource_t *rsc, const char *name, gboolean allow_non_atomic)
Definition: pe_actions.c:1262
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
uint32_t pcmk__multi_update_actions(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
struct pe_node_shared_s * details
Definition: pe_types.h:252
G_GNUC_INTERNAL gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition: utils.c:474
unsigned long long flags
Definition: pe_types.h:355
#define pe_rsc_promotable
Definition: pe_types.h:264
pe_working_set_t * data_set
enum action_tasks clone_child_action(pe_action_t *action)
GList * actions
Definition: pe_types.h:366
void pcmk__bundle_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
G_GNUC_INTERNAL void pcmk__new_ordering(pe_resource_t *first_rsc, char *first_task, pe_action_t *first_action, pe_resource_t *then_rsc, char *then_task, pe_action_t *then_action, uint32_t flags, pe_working_set_t *data_set)
#define XML_RSC_ATTR_INCARNATION_NODEMAX
Definition: msg_xml.h:231
pe_node_t * pcmk__bundle_allocate(pe_resource_t *rsc, const pe_node_t *prefer)
bool is_set_recursive(const pe_resource_t *rsc, long long flag, bool any)
Definition: clone.c:496
char * uuid
Definition: pe_types.h:411
#define pe_rsc_allocating
Definition: pe_types.h:267
enum pe_obj_types variant
Definition: pe_types.h:338
void pcmk__bundle_shutdown_lock(pe_resource_t *rsc)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:952
#define RSC_DEMOTED
Definition: crm.h:208
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:45
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
void(* apply_coloc_score)(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
const char * pe__add_bundle_remote_name(pe_resource_t *rsc, pe_working_set_t *data_set, xmlNode *xml, const char *field)
Definition: bundle.c:708
G_GNUC_INTERNAL void pcmk__apply_location(pe_resource_t *rsc, pe__location_t *constraint)
G_GNUC_INTERNAL void pcmk__update_action_for_orderings(pe_action_t *action, pe_working_set_t *data_set)
#define RSC_STARTED
Definition: crm.h:200
int copies_per_node(pe_resource_t *rsc)
#define pcmk__set_updated_flags(au_flags, action, flags_to_set)
#define crm_err(fmt, args...)
Definition: logging.h:359
#define CRM_ASSERT(expr)
Definition: results.h:42
#define RSC_STATUS
Definition: crm.h:213
#define RSC_PROMOTE
Definition: crm.h:205
G_GNUC_INTERNAL bool pcmk__assign_resource(pe_resource_t *rsc, pe_node_t *node, bool force)
GHashTable * pe_rsc_params(pe_resource_t *rsc, const pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters.
Definition: complex.c:429
G_GNUC_INTERNAL void pcmk__promotable_restart_ordering(pe_resource_t *rsc)
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:80
rsc_role_e
Possible roles that a resource can be in.
Definition: common.h:92
#define pe_rsc_block
Definition: pe_types.h:258
enum pe_action_flags flags
Definition: pe_types.h:415
pe_working_set_t * cluster
Definition: pe_types.h:335
#define RSC_STOPPED
Definition: crm.h:203
#define RSC_PROMOTED
Definition: crm.h:206
gboolean crm_is_true(const char *s)
Definition: strings.c:416
enum pe_action_flags summary_action_flags(pe_action_t *action, GList *children, const pe_node_t *node)
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:47
unsigned long long flags
Definition: pe_types.h:153
uint32_t(* update_ordered_actions)(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
#define XML_RSC_ATTR_INTERLEAVE
Definition: msg_xml.h:227
#define pe_flag_show_scores
Definition: pe_types.h:134
#define crm_info(fmt, args...)
Definition: logging.h:362
bool pcmk__bundle_create_probe(pe_resource_t *rsc, pe_node_t *node)
#define pe_rsc_orphan
Definition: pe_types.h:256
uint64_t flags
Definition: remote.c:215
action_tasks
Definition: common.h:61
void pcmk__bundle_create_actions(pe_resource_t *rsc)
#define RSC_DEMOTE
Definition: crm.h:207
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:45
char * id
Definition: pe_types.h:329
GHashTable * allowed_nodes
Definition: pe_types.h:375