pacemaker  2.0.2-debe490
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcmk_sched_bundle.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2019 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(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(resource_t *rsc, 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
73  if (is_set(rsc->flags, pe_rsc_failure_ignored)) {
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  dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __FUNCTION__, 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  replica->ip->cmds->allocate(replica->ip, prefer, data_set);
133  }
134 
135  container_host = replica->container->allocated_to;
136  if (replica->remote && pe__is_guest_or_remote_node(container_host)) {
137  /* We need 'nested' connection resources to be on the same
138  * host because pacemaker-remoted only supports a single
139  * active connection
140  */
141  rsc_colocation_new("child-remote-with-docker-remote", NULL,
142  INFINITY, replica->remote,
143  container_host->details->remote_rsc, NULL, NULL,
144  data_set);
145  }
146 
147  if (replica->remote) {
148  replica->remote->cmds->allocate(replica->remote, prefer,
149  data_set);
150  }
151 
152  // Explicitly allocate replicas' children before bundle child
153  if (replica->child) {
154  pe_node_t *node = NULL;
155  GHashTableIter iter;
156 
157  g_hash_table_iter_init(&iter, replica->child->allowed_nodes);
158  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
159  if (node->details != replica->node->details) {
160  node->weight = -INFINITY;
161  } else if (!migration_threshold_reached(replica->child, node,
162  data_set)) {
163  node->weight = INFINITY;
164  }
165  }
166 
167  set_bit(replica->child->parent->flags, pe_rsc_allocating);
168  replica->child->cmds->allocate(replica->child, replica->node,
169  data_set);
170  clear_bit(replica->child->parent->flags, pe_rsc_allocating);
171  }
172  }
173 
174  if (bundle_data->child) {
175  pe_node_t *node = NULL;
176  GHashTableIter iter;
177  g_hash_table_iter_init(&iter, bundle_data->child->allowed_nodes);
178  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
179  if (is_bundle_node(bundle_data, node)) {
180  node->weight = 0;
181  } else {
182  node->weight = -INFINITY;
183  }
184  }
185  bundle_data->child->cmds->allocate(bundle_data->child, prefer, data_set);
186  }
187 
190  return NULL;
191 }
192 
193 
194 void
196 {
197  pe_action_t *action = NULL;
198  GListPtr containers = NULL;
199  pe__bundle_variant_data_t *bundle_data = NULL;
200 
201  CRM_CHECK(rsc != NULL, return);
202 
203  containers = get_container_list(rsc);
204  get_bundle_variant_data(bundle_data, rsc);
205  for (GList *gIter = bundle_data->replicas; gIter != NULL;
206  gIter = gIter->next) {
207  pe__bundle_replica_t *replica = gIter->data;
208 
209  CRM_ASSERT(replica);
210  if (replica->ip) {
211  replica->ip->cmds->create_actions(replica->ip, data_set);
212  }
213  if (replica->container) {
214  replica->container->cmds->create_actions(replica->container,
215  data_set);
216  }
217  if (replica->remote) {
218  replica->remote->cmds->create_actions(replica->remote, data_set);
219  }
220  }
221 
222  clone_create_pseudo_actions(rsc, containers, NULL, NULL, data_set);
223 
224  if (bundle_data->child) {
225  bundle_data->child->cmds->create_actions(bundle_data->child, data_set);
226 
227  if (is_set(bundle_data->child->flags, pe_rsc_promotable)) {
228  /* promote */
229  action = create_pseudo_resource_op(rsc, RSC_PROMOTE, TRUE, TRUE, data_set);
230  action = create_pseudo_resource_op(rsc, RSC_PROMOTED, TRUE, TRUE, data_set);
231  action->priority = INFINITY;
232 
233  /* demote */
234  action = create_pseudo_resource_op(rsc, RSC_DEMOTE, TRUE, TRUE, data_set);
235  action = create_pseudo_resource_op(rsc, RSC_DEMOTED, TRUE, TRUE, data_set);
236  action->priority = INFINITY;
237  }
238  }
239 
240  g_list_free(containers);
241 }
242 
243 void
245  pe_working_set_t *data_set)
246 {
247  pe__bundle_variant_data_t *bundle_data = NULL;
248 
249  CRM_CHECK(rsc != NULL, return);
250 
251  get_bundle_variant_data(bundle_data, rsc);
252 
253  if (bundle_data->child) {
254  new_rsc_order(rsc, RSC_START, bundle_data->child, RSC_START,
256  new_rsc_order(rsc, RSC_STOP, bundle_data->child, RSC_STOP,
258 
259  if (bundle_data->child->children) {
260  new_rsc_order(bundle_data->child, RSC_STARTED, rsc, RSC_STARTED,
262  new_rsc_order(bundle_data->child, RSC_STOPPED, rsc, RSC_STOPPED,
264  } else {
265  new_rsc_order(bundle_data->child, RSC_START, rsc, RSC_STARTED,
267  new_rsc_order(bundle_data->child, RSC_STOP, rsc, RSC_STOPPED,
269  }
270  }
271 
272  for (GList *gIter = bundle_data->replicas; gIter != NULL;
273  gIter = gIter->next) {
274  pe__bundle_replica_t *replica = gIter->data;
275 
276  CRM_ASSERT(replica);
277  CRM_ASSERT(replica->container);
278 
279  replica->container->cmds->internal_constraints(replica->container,
280  data_set);
281 
282  order_start_start(rsc, replica->container,
284 
285  if (replica->child) {
286  order_stop_stop(rsc, replica->child,
288  }
289  order_stop_stop(rsc, replica->container,
291  new_rsc_order(replica->container, RSC_START, rsc, RSC_STARTED,
293  new_rsc_order(replica->container, RSC_STOP, rsc, RSC_STOPPED,
295 
296  if (replica->ip) {
297  replica->ip->cmds->internal_constraints(replica->ip, data_set);
298 
299  // Start ip then container
300  new_rsc_order(replica->ip, RSC_START, replica->container, RSC_START,
302  new_rsc_order(replica->container, RSC_STOP, replica->ip, RSC_STOP,
304 
305  rsc_colocation_new("ip-with-docker", NULL, INFINITY, replica->ip,
306  replica->container, NULL, NULL, data_set);
307  }
308 
309  if (replica->remote) {
310  /* This handles ordering and colocating remote relative to container
311  * (via "resource-with-container"). Since IP is also ordered and
312  * colocated relative to the container, we don't need to do anything
313  * explicit here with IP.
314  */
315  replica->remote->cmds->internal_constraints(replica->remote,
316  data_set);
317  }
318 
319  if (replica->child) {
320  CRM_ASSERT(replica->remote);
321 
322  // "Start remote then child" is implicit in scheduler's remote logic
323  }
324 
325  }
326 
327  if (bundle_data->child) {
328  bundle_data->child->cmds->internal_constraints(bundle_data->child, data_set);
329  if (is_set(bundle_data->child->flags, pe_rsc_promotable)) {
330  promote_demote_constraints(rsc, data_set);
331 
332  /* child demoted before global demoted */
333  new_rsc_order(bundle_data->child, RSC_DEMOTED, rsc, RSC_DEMOTED,
335 
336  /* global demote before child demote */
337  new_rsc_order(rsc, RSC_DEMOTE, bundle_data->child, RSC_DEMOTE,
339 
340  /* child promoted before global promoted */
341  new_rsc_order(bundle_data->child, RSC_PROMOTED, rsc, RSC_PROMOTED,
343 
344  /* global promote before child promote */
345  new_rsc_order(rsc, RSC_PROMOTE, bundle_data->child, RSC_PROMOTE,
347  }
348 
349  } else {
350 // int type = pe_order_optional | pe_order_implies_then | pe_order_restart;
351 // custom_action_order(rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL,
352 // rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, pe_order_optional, data_set);
353  }
354 }
355 
356 static pe_resource_t *
357 compatible_replica_for_node(pe_resource_t *rsc_lh, pe_node_t *candidate,
358  pe_resource_t *rsc, enum rsc_role_e filter,
359  gboolean current)
360 {
361  pe__bundle_variant_data_t *bundle_data = NULL;
362 
363  CRM_CHECK(candidate != NULL, return NULL);
364  get_bundle_variant_data(bundle_data, rsc);
365 
366  crm_trace("Looking for compatible child from %s for %s on %s",
367  rsc_lh->id, rsc->id, candidate->details->uname);
368 
369  for (GList *gIter = bundle_data->replicas; gIter != NULL;
370  gIter = gIter->next) {
371  pe__bundle_replica_t *replica = gIter->data;
372 
373  if (is_child_compatible(replica->container, candidate, filter, current)) {
374  crm_trace("Pairing %s with %s on %s",
375  rsc_lh->id, replica->container->id,
376  candidate->details->uname);
377  return replica->container;
378  }
379  }
380 
381  crm_trace("Can't pair %s with %s", rsc_lh->id, rsc->id);
382  return NULL;
383 }
384 
385 static pe_resource_t *
386 compatible_replica(pe_resource_t *rsc_lh, pe_resource_t *rsc,
387  enum rsc_role_e filter, gboolean current,
388  pe_working_set_t *data_set)
389 {
390  GListPtr scratch = NULL;
391  resource_t *pair = NULL;
392  node_t *active_node_lh = NULL;
393 
394  active_node_lh = rsc_lh->fns->location(rsc_lh, NULL, current);
395  if (active_node_lh) {
396  return compatible_replica_for_node(rsc_lh, active_node_lh, rsc, filter,
397  current);
398  }
399 
400  scratch = g_hash_table_get_values(rsc_lh->allowed_nodes);
401  scratch = sort_nodes_by_weight(scratch, NULL, data_set);
402 
403  for (GListPtr gIter = scratch; gIter != NULL; gIter = gIter->next) {
404  node_t *node = (node_t *) gIter->data;
405 
406  pair = compatible_replica_for_node(rsc_lh, node, rsc, filter, current);
407  if (pair) {
408  goto done;
409  }
410  }
411 
412  pe_rsc_debug(rsc, "Can't pair %s with %s", rsc_lh->id, (rsc? rsc->id : "none"));
413  done:
414  g_list_free(scratch);
415  return pair;
416 }
417 
418 void
420  rsc_colocation_t *constraint,
421  pe_working_set_t *data_set)
422 {
423  /* -- Never called --
424  *
425  * Instead we add the colocation constraints to the child and call from there
426  */
427  CRM_ASSERT(FALSE);
428 }
429 
431 {
432  /* Strictly speaking, there should be a 'copies_per_node' addition
433  * to the resource function table and each case would be a
434  * function. However that would be serious overkill to return an
435  * int. In fact, it seems to me that both function tables
436  * could/should be replaced by resources.{c,h} full of
437  * rsc_{some_operation} functions containing a switch as below
438  * which calls out to functions named {variant}_{some_operation}
439  * as needed.
440  */
441  switch(rsc->variant) {
442  case pe_unknown:
443  return 0;
444  case pe_native:
445  case pe_group:
446  return 1;
447  case pe_clone:
448  {
449  const char *max_clones_node = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_NODEMAX);
450  return crm_parse_int(max_clones_node, "1");
451  }
452  case pe_container:
453  {
454  pe__bundle_variant_data_t *data = NULL;
455  get_bundle_variant_data(data, rsc);
456  return data->nreplicas_per_host;
457  }
458  }
459  return 0;
460 }
461 
462 void
464  rsc_colocation_t *constraint,
465  pe_working_set_t *data_set)
466 {
467  GListPtr allocated_rhs = NULL;
468  pe__bundle_variant_data_t *bundle_data = NULL;
469 
470  CRM_CHECK(constraint != NULL, return);
471  CRM_CHECK(rsc_lh != NULL, pe_err("rsc_lh was NULL for %s", constraint->id); return);
472  CRM_CHECK(rsc != NULL, pe_err("rsc was NULL for %s", constraint->id); return);
473  CRM_ASSERT(rsc_lh->variant == pe_native);
474 
475  if (is_set(rsc->flags, pe_rsc_provisional)) {
476  pe_rsc_trace(rsc, "%s is still provisional", rsc->id);
477  return;
478 
479  } else if(constraint->rsc_lh->variant > pe_group) {
480  resource_t *rh_child = compatible_replica(rsc_lh, rsc,
481  RSC_ROLE_UNKNOWN, FALSE,
482  data_set);
483 
484  if (rh_child) {
485  pe_rsc_debug(rsc, "Pairing %s with %s", rsc_lh->id, rh_child->id);
486  rsc_lh->cmds->rsc_colocation_lh(rsc_lh, rh_child, constraint,
487  data_set);
488 
489  } else if (constraint->score >= INFINITY) {
490  crm_notice("Cannot pair %s with instance of %s", rsc_lh->id, rsc->id);
491  assign_node(rsc_lh, NULL, TRUE);
492 
493  } else {
494  pe_rsc_debug(rsc, "Cannot pair %s with instance of %s", rsc_lh->id, rsc->id);
495  }
496 
497  return;
498  }
499 
500  get_bundle_variant_data(bundle_data, rsc);
501  pe_rsc_trace(rsc, "Processing constraint %s: %s -> %s %d",
502  constraint->id, rsc_lh->id, rsc->id, constraint->score);
503 
504  for (GList *gIter = bundle_data->replicas; gIter != NULL;
505  gIter = gIter->next) {
506  pe__bundle_replica_t *replica = gIter->data;
507 
508  if (constraint->score < INFINITY) {
509  replica->container->cmds->rsc_colocation_rh(rsc_lh,
510  replica->container,
511  constraint, data_set);
512 
513  } else {
514  node_t *chosen = replica->container->fns->location(replica->container,
515  NULL, FALSE);
516 
517  if ((chosen == NULL)
518  || is_set_recursive(replica->container, pe_rsc_block, TRUE)) {
519  continue;
520  }
521  if ((constraint->role_rh >= RSC_ROLE_MASTER)
522  && (replica->child == NULL)) {
523  continue;
524  }
525  if ((constraint->role_rh >= RSC_ROLE_MASTER)
526  && (replica->child->next_role < RSC_ROLE_MASTER)) {
527  continue;
528  }
529 
530  pe_rsc_trace(rsc, "Allowing %s: %s %d", constraint->id, chosen->details->uname, chosen->weight);
531  allocated_rhs = g_list_prepend(allocated_rhs, chosen);
532  }
533  }
534 
535  if (constraint->score >= INFINITY) {
536  node_list_exclude(rsc_lh->allowed_nodes, allocated_rhs, FALSE);
537  }
538  g_list_free(allocated_rhs);
539 }
540 
541 enum pe_action_flags
543 {
544  GListPtr containers = NULL;
545  enum pe_action_flags flags = 0;
546  pe__bundle_variant_data_t *data = NULL;
547 
548  get_bundle_variant_data(data, action->rsc);
549  if(data->child) {
550  enum action_tasks task = get_complex_task(data->child, action->task, TRUE);
551  switch(task) {
552  case no_action:
553  case action_notify:
554  case action_notified:
555  case action_promote:
556  case action_promoted:
557  case action_demote:
558  case action_demoted:
559  return summary_action_flags(action, data->child->children, node);
560  default:
561  break;
562  }
563  }
564 
565  containers = get_container_list(action->rsc);
566  flags = summary_action_flags(action, containers, node);
567  g_list_free(containers);
568  return flags;
569 }
570 
571 resource_t *
572 find_compatible_child_by_node(resource_t * local_child, node_t * local_node, resource_t * rsc,
573  enum rsc_role_e filter, gboolean current)
574 {
575  GListPtr gIter = NULL;
576  GListPtr children = NULL;
577 
578  if (local_node == NULL) {
579  crm_err("Can't colocate unrunnable child %s with %s", local_child->id, rsc->id);
580  return NULL;
581  }
582 
583  crm_trace("Looking for compatible child from %s for %s on %s",
584  local_child->id, rsc->id, local_node->details->uname);
585 
586  children = get_containers_or_children(rsc);
587  for (gIter = children; gIter != NULL; gIter = gIter->next) {
588  resource_t *child_rsc = (resource_t *) gIter->data;
589 
590  if(is_child_compatible(child_rsc, local_node, filter, current)) {
591  crm_trace("Pairing %s with %s on %s",
592  local_child->id, child_rsc->id, local_node->details->uname);
593  return child_rsc;
594  }
595  }
596 
597  crm_trace("Can't pair %s with %s", local_child->id, rsc->id);
598  if(children != rsc->children) {
599  g_list_free(children);
600  }
601  return NULL;
602 }
603 
604 static pe__bundle_replica_t *
605 replica_for_container(pe_resource_t *rsc, pe_resource_t *container,
606  pe_node_t *node)
607 {
608  if (rsc->variant == pe_container) {
609  pe__bundle_variant_data_t *data = NULL;
610 
611  get_bundle_variant_data(data, rsc);
612  for (GList *gIter = data->replicas; gIter != NULL;
613  gIter = gIter->next) {
614  pe__bundle_replica_t *replica = gIter->data;
615 
616  if (replica->child
617  && (container == replica->container)
618  && (node->details == replica->node->details)) {
619  return replica;
620  }
621  }
622  }
623  return NULL;
624 }
625 
626 static enum pe_graph_flags
627 multi_update_interleave_actions(pe_action_t *first, pe_action_t *then,
628  pe_node_t *node, enum pe_action_flags flags,
629  enum pe_action_flags filter,
630  enum pe_ordering type,
631  pe_working_set_t *data_set)
632 {
633  GListPtr gIter = NULL;
634  GListPtr children = NULL;
635  gboolean current = FALSE;
636  enum pe_graph_flags changed = pe_graph_none;
637 
638  /* Fix this - lazy */
639  if (crm_ends_with(first->uuid, "_stopped_0")
640  || crm_ends_with(first->uuid, "_demoted_0")) {
641  current = TRUE;
642  }
643 
644  children = get_containers_or_children(then->rsc);
645  for (gIter = children; gIter != NULL; gIter = gIter->next) {
646  pe_resource_t *then_child = gIter->data;
647  pe_resource_t *first_child = find_compatible_child(then_child,
648  first->rsc,
650  current, data_set);
651  if (first_child == NULL && current) {
652  crm_trace("Ignore");
653 
654  } else if (first_child == NULL) {
655  crm_debug("No match found for %s (%d / %s / %s)", then_child->id, current, first->uuid, then->uuid);
656 
657  /* Me no like this hack - but what else can we do?
658  *
659  * If there is no-one active or about to be active
660  * on the same node as then_child, then they must
661  * not be allowed to start
662  */
663  if (type & (pe_order_runnable_left | pe_order_implies_then) /* Mandatory */ ) {
664  pe_rsc_info(then->rsc, "Inhibiting %s from being active", then_child->id);
665  if(assign_node(then_child, NULL, TRUE)) {
666  changed |= pe_graph_updated_then;
667  }
668  }
669 
670  } else {
671  pe_action_t *first_action = NULL;
672  pe_action_t *then_action = NULL;
673 
674  enum action_tasks task = clone_child_action(first);
675  const char *first_task = task2text(task);
676 
677  pe__bundle_replica_t *first_replica = NULL;
678  pe__bundle_replica_t *then_replica = NULL;
679 
680  first_replica = replica_for_container(first->rsc, first_child,
681  node);
682  if (strstr(first->task, "stop") && first_replica && first_replica->child) {
683  /* Except for 'stopped' we should be looking at the
684  * in-container resource, actions for the child will
685  * happen later and are therefor more likely to align
686  * with the user's intent.
687  */
688  first_action = find_first_action(first_replica->child->actions,
689  NULL, task2text(task), node);
690  } else {
691  first_action = find_first_action(first_child->actions, NULL, task2text(task), node);
692  }
693 
694  then_replica = replica_for_container(then->rsc, then_child, node);
695  if (strstr(then->task, "mote")
696  && then_replica && then_replica->child) {
697  /* Promote/demote actions will never be found for the
698  * container resource, look in the child instead
699  *
700  * Alternatively treat:
701  * 'XXXX then promote YYYY' as 'XXXX then start container for YYYY', and
702  * 'demote XXXX then stop YYYY' as 'stop container for XXXX then stop YYYY'
703  */
704  then_action = find_first_action(then_replica->child->actions,
705  NULL, then->task, node);
706  } else {
707  then_action = find_first_action(then_child->actions, NULL, then->task, node);
708  }
709 
710  if (first_action == NULL) {
711  if (is_not_set(first_child->flags, pe_rsc_orphan)
712  && crm_str_eq(first_task, RSC_STOP, TRUE) == FALSE
713  && crm_str_eq(first_task, RSC_DEMOTE, TRUE) == FALSE) {
714  crm_err("Internal error: No action found for %s in %s (first)",
715  first_task, first_child->id);
716 
717  } else {
718  crm_trace("No action found for %s in %s%s (first)",
719  first_task, first_child->id,
720  is_set(first_child->flags, pe_rsc_orphan) ? " (ORPHAN)" : "");
721  }
722  continue;
723  }
724 
725  /* We're only interested if 'then' is neither stopping nor being demoted */
726  if (then_action == NULL) {
727  if (is_not_set(then_child->flags, pe_rsc_orphan)
728  && crm_str_eq(then->task, RSC_STOP, TRUE) == FALSE
729  && crm_str_eq(then->task, RSC_DEMOTE, TRUE) == FALSE) {
730  crm_err("Internal error: No action found for %s in %s (then)",
731  then->task, then_child->id);
732 
733  } else {
734  crm_trace("No action found for %s in %s%s (then)",
735  then->task, then_child->id,
736  is_set(then_child->flags, pe_rsc_orphan) ? " (ORPHAN)" : "");
737  }
738  continue;
739  }
740 
741  if (order_actions(first_action, then_action, type)) {
742  crm_debug("Created constraint for %s (%d) -> %s (%d) %.6x",
743  first_action->uuid, is_set(first_action->flags, pe_action_optional),
744  then_action->uuid, is_set(then_action->flags, pe_action_optional), type);
746  }
747  if(first_action && then_action) {
748  changed |= then_child->cmds->update_actions(first_action,
749  then_action, node,
750  first_child->cmds->action_flags(first_action, node),
751  filter, type, data_set);
752  } else {
753  crm_err("Nothing found either for %s (%p) or %s (%p) %s",
754  first_child->id, first_action,
755  then_child->id, then_action, task2text(task));
756  }
757  }
758  }
759 
760  if(children != then->rsc->children) {
761  g_list_free(children);
762  }
763  return changed;
764 }
765 
766 static bool
767 can_interleave_actions(pe_action_t *first, pe_action_t *then)
768 {
769  bool interleave = FALSE;
770  resource_t *rsc = NULL;
771  const char *interleave_s = NULL;
772 
773  if(first->rsc == NULL || then->rsc == NULL) {
774  crm_trace("Not interleaving %s with %s (both must be resources)", first->uuid, then->uuid);
775  return FALSE;
776  } else if(first->rsc == then->rsc) {
777  crm_trace("Not interleaving %s with %s (must belong to different resources)", first->uuid, then->uuid);
778  return FALSE;
779  } else if(first->rsc->variant < pe_clone || then->rsc->variant < pe_clone) {
780  crm_trace("Not interleaving %s with %s (both sides must be clones or bundles)", first->uuid, then->uuid);
781  return FALSE;
782  }
783 
784  if (crm_ends_with(then->uuid, "_stop_0") || crm_ends_with(then->uuid, "_demote_0")) {
785  rsc = first->rsc;
786  } else {
787  rsc = then->rsc;
788  }
789 
790  interleave_s = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERLEAVE);
791  interleave = crm_is_true(interleave_s);
792  crm_trace("Interleave %s -> %s: %s (based on %s)",
793  first->uuid, then->uuid, interleave ? "yes" : "no", rsc->id);
794 
795  return interleave;
796 }
797 
798 enum pe_graph_flags
800  pe_node_t *node, enum pe_action_flags flags,
801  enum pe_action_flags filter, enum pe_ordering type,
802  pe_working_set_t *data_set)
803 {
804  enum pe_graph_flags changed = pe_graph_none;
805 
806  crm_trace("%s -> %s", first->uuid, then->uuid);
807 
808  if(can_interleave_actions(first, then)) {
809  changed = multi_update_interleave_actions(first, then, node, flags,
810  filter, type, data_set);
811 
812  } else if(then->rsc) {
813  GListPtr gIter = NULL;
814  GListPtr children = NULL;
815 
816  // Handle the 'primitive' ordering case
817  changed |= native_update_actions(first, then, node, flags, filter,
818  type, data_set);
819 
820  // Now any children (or containers in the case of a bundle)
821  children = get_containers_or_children(then->rsc);
822  for (gIter = children; gIter != NULL; gIter = gIter->next) {
823  resource_t *then_child = (resource_t *) gIter->data;
824  enum pe_graph_flags then_child_changed = pe_graph_none;
825  action_t *then_child_action = find_first_action(then_child->actions, NULL, then->task, node);
826 
827  if (then_child_action) {
828  enum pe_action_flags then_child_flags = then_child->cmds->action_flags(then_child_action, node);
829 
830  if (is_set(then_child_flags, pe_action_runnable)) {
831  then_child_changed |= then_child->cmds->update_actions(first,
832  then_child_action, node, flags, filter, type, data_set);
833  }
834  changed |= then_child_changed;
835  if (then_child_changed & pe_graph_updated_then) {
836  for (GListPtr lpc = then_child_action->actions_after; lpc != NULL; lpc = lpc->next) {
837  action_wrapper_t *next = (action_wrapper_t *) lpc->data;
838  update_action(next->action, data_set);
839  }
840  }
841  }
842  }
843 
844  if(children != then->rsc->children) {
845  g_list_free(children);
846  }
847  }
848  return changed;
849 }
850 
851 void
853 {
854  pe__bundle_variant_data_t *bundle_data = NULL;
855  get_bundle_variant_data(bundle_data, rsc);
856 
857  pe_rsc_trace(rsc, "Processing location constraint %s for %s", constraint->id, rsc->id);
858 
859  native_rsc_location(rsc, constraint);
860 
861  for (GList *gIter = bundle_data->replicas; gIter != NULL;
862  gIter = gIter->next) {
863  pe__bundle_replica_t *replica = gIter->data;
864 
865  if (replica->container) {
866  replica->container->cmds->rsc_location(replica->container,
867  constraint);
868  }
869  if (replica->ip) {
870  replica->ip->cmds->rsc_location(replica->ip, constraint);
871  }
872  }
873 
874  if (bundle_data->child
875  && ((constraint->role_filter == RSC_ROLE_SLAVE)
876  || (constraint->role_filter == RSC_ROLE_MASTER))) {
877  bundle_data->child->cmds->rsc_location(bundle_data->child, constraint);
878  bundle_data->child->rsc_location = g_list_prepend(bundle_data->child->rsc_location,
879  constraint);
880  }
881 }
882 
883 void
885 {
886  pe__bundle_variant_data_t *bundle_data = NULL;
887 
888  CRM_CHECK(rsc != NULL, return);
889 
890  get_bundle_variant_data(bundle_data, rsc);
891 
892  if (bundle_data->child) {
893  bundle_data->child->cmds->expand(bundle_data->child, data_set);
894  }
895 
896  for (GList *gIter = bundle_data->replicas; gIter != NULL;
897  gIter = gIter->next) {
898  pe__bundle_replica_t *replica = gIter->data;
899 
900  CRM_ASSERT(replica);
901  if (replica->remote && replica->container
902  && pe__bundle_needs_remote_name(replica->remote)) {
903 
904  /* REMOTE_CONTAINER_HACK: Allow remote nodes to run containers that
905  * run pacemaker-remoted inside, without needing a separate IP for
906  * the container. This is done by configuring the inner remote's
907  * connection host as the magic string "#uname", then
908  * replacing it with the underlying host when needed.
909  */
910  xmlNode *nvpair = get_xpath_object("//nvpair[@name='" XML_RSC_ATTR_REMOTE_RA_ADDR "']",
911  replica->remote->xml, LOG_ERR);
912  const char *calculated_addr = NULL;
913 
914  calculated_addr = pe__add_bundle_remote_name(replica->remote,
915  nvpair, "value");
916  if (calculated_addr) {
917  crm_trace("Set address for bundle connection %s to bundle host %s",
918  replica->remote->id, calculated_addr);
919  g_hash_table_replace(replica->remote->parameters,
921  strdup(calculated_addr));
922  } else {
923  /* The only way to get here is if the remote connection is
924  * neither currently running nor scheduled to run. That means we
925  * won't be doing any operations that require addr (only start
926  * requires it; we additionally use it to compare digests when
927  * unpacking status, promote, and migrate_from history, but
928  * that's already happened by this point).
929  */
930  crm_info("Unable to determine address for bundle %s remote connection",
931  rsc->id);
932  }
933  }
934  if (replica->ip) {
935  replica->ip->cmds->expand(replica->ip, data_set);
936  }
937  if (replica->container) {
938  replica->container->cmds->expand(replica->container, data_set);
939  }
940  if (replica->remote) {
941  replica->remote->cmds->expand(replica->remote, data_set);
942  }
943  }
944 }
945 
946 gboolean
948  pe_action_t *complete, gboolean force,
949  pe_working_set_t * data_set)
950 {
951  bool any_created = FALSE;
952  pe__bundle_variant_data_t *bundle_data = NULL;
953 
954  CRM_CHECK(rsc != NULL, return FALSE);
955 
956  get_bundle_variant_data(bundle_data, rsc);
957  for (GList *gIter = bundle_data->replicas; gIter != NULL;
958  gIter = gIter->next) {
959  pe__bundle_replica_t *replica = gIter->data;
960 
961  CRM_ASSERT(replica);
962  if (replica->ip) {
963  any_created |= replica->ip->cmds->create_probe(replica->ip, node,
964  complete, force,
965  data_set);
966  }
967  if (replica->child && (node->details == replica->node->details)) {
968  any_created |= replica->child->cmds->create_probe(replica->child,
969  node, complete,
970  force, data_set);
971  }
972  if (replica->container) {
973  bool created = replica->container->cmds->create_probe(replica->container,
974  node, complete,
975  force, data_set);
976 
977  if(created) {
978  any_created = TRUE;
979  /* If we're limited to one replica per host (due to
980  * the lack of an IP range probably), then we don't
981  * want any of our peer containers starting until
982  * we've established that no other copies are already
983  * running.
984  *
985  * Partly this is to ensure that nreplicas_per_host is
986  * observed, but also to ensure that the containers
987  * don't fail to start because the necessary port
988  * mappings (which won't include an IP for uniqueness)
989  * are already taken
990  */
991 
992  for (GList *tIter = bundle_data->replicas;
993  tIter && (bundle_data->nreplicas_per_host == 1);
994  tIter = tIter->next) {
995  pe__bundle_replica_t *other = tIter->data;
996 
997  if ((other != replica) && (other != NULL)
998  && (other->container != NULL)) {
999 
1000  custom_action_order(replica->container,
1001  generate_op_key(replica->container->id, RSC_STATUS, 0),
1002  NULL, other->container,
1003  generate_op_key(other->container->id, RSC_START, 0),
1004  NULL,
1006  data_set);
1007  }
1008  }
1009  }
1010  }
1011  if (replica->container && replica->remote
1012  && replica->remote->cmds->create_probe(replica->remote, node,
1013  complete, force,
1014  data_set)) {
1015 
1016  /* Do not probe the remote resource until we know where the
1017  * container is running. This is required for REMOTE_CONTAINER_HACK
1018  * to correctly probe remote resources.
1019  */
1020  char *probe_uuid = generate_op_key(replica->remote->id, RSC_STATUS,
1021  0);
1022  action_t *probe = find_first_action(replica->remote->actions,
1023  probe_uuid, NULL, node);
1024 
1025  free(probe_uuid);
1026  if (probe) {
1027  any_created = TRUE;
1028  crm_trace("Ordering %s probe on %s",
1029  replica->remote->id, node->details->uname);
1030  custom_action_order(replica->container,
1031  generate_op_key(replica->container->id, RSC_START, 0),
1032  NULL, replica->remote, NULL, probe,
1033  pe_order_probe, data_set);
1034  }
1035  }
1036  }
1037  return any_created;
1038 }
1039 
1040 void
1042 {
1043 }
1044 
1045 GHashTable *
1047  GHashTable *nodes, const char *attr,
1048  float factor, enum pe_weights flags)
1049 {
1050  return rsc_merge_weights(rsc, rhs, nodes, attr, factor, flags);
1051 }
1052 
1053 void
1055  gboolean terminal)
1056 {
1057  pe__bundle_variant_data_t *bundle_data = NULL;
1058 
1059  CRM_CHECK(rsc != NULL, return);
1060 
1061  get_bundle_variant_data(bundle_data, rsc);
1062  for (GList *gIter = bundle_data->replicas; gIter != NULL;
1063  gIter = gIter->next) {
1064  pe__bundle_replica_t *replica = gIter->data;
1065 
1066  CRM_ASSERT(replica);
1067  if (replica->ip) {
1068  LogActions(replica->ip, data_set, terminal);
1069  }
1070  if (replica->container) {
1071  LogActions(replica->container, data_set, terminal);
1072  }
1073  if (replica->remote) {
1074  LogActions(replica->remote, data_set, terminal);
1075  }
1076  if (replica->child) {
1077  LogActions(replica->child, data_set, terminal);
1078  }
1079  }
1080 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:156
enum rsc_role_e role_filter
Definition: internal.h:30
const char * task2text(enum action_tasks task)
Definition: common.c:276
pe_node_t * pcmk__bundle_color(pe_resource_t *rsc, pe_node_t *preferred, pe_working_set_t *data_set)
#define RSC_STOP
Definition: crm.h:177
enum pe_action_flags(* action_flags)(action_t *, node_t *)
GHashTable * pcmk__bundle_merge_weights(pe_resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
#define crm_notice(fmt, args...)
Definition: logging.h:242
gboolean is_child_compatible(resource_t *child_rsc, node_t *local_node, enum rsc_role_e filter, gboolean current)
bool assign_node(resource_t *rsc, node_t *node, gboolean force)
enum pe_action_flags pcmk__bundle_action_flags(pe_action_t *action, pe_node_t *node)
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:17
#define INFINITY
Definition: crm.h:73
GList * sort_nodes_by_weight(GList *nodes, pe_node_t *active_node, pe_working_set_t *data_set)
int priority
Definition: pe_types.h:363
pe_resource_t * container
Definition: pe_types.h:343
void distribute_children(resource_t *rsc, GListPtr children, GListPtr nodes, int max, int per_host_max, pe_working_set_t *data_set)
int copies_per_node(resource_t *rsc)
enum action_tasks clone_child_action(action_t *action)
resource_alloc_functions_t * cmds
Definition: pe_types.h:296
enum action_tasks get_complex_task(resource_t *rsc, const char *name, gboolean allow_non_atomic)
Definition: utils.c:1374
pe_resource_t * rsc
Definition: pe_types.h:365
gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
pe_resource_t * remote_rsc
Definition: pe_types.h:200
GHashTable * meta
Definition: pe_types.h:336
void pcmk__bundle_log_actions(pe_resource_t *rsc, pe_working_set_t *data_set, gboolean terminal)
void(* rsc_colocation_lh)(pe_resource_t *, pe_resource_t *, rsc_colocation_t *, pe_working_set_t *)
resource_object_functions_t * fns
Definition: pe_types.h:295
gboolean pe__is_guest_or_remote_node(pe_node_t *node)
Definition: remote.c:58
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:110
void pcmk__bundle_rsc_colocation_rh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
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)
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)
#define clear_bit(word, bit)
Definition: crm_internal.h:168
void native_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
gboolean show_scores
#define RSC_START
Definition: crm.h:174
int migration_threshold
Definition: pe_types.h:307
pe_action_t * action
Definition: pe_types.h:483
bool pe__bundle_needs_remote_name(pe_resource_t *rsc)
Definition: bundle.c:955
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:220
#define XML_RSC_ATTR_REMOTE_RA_ADDR
Definition: msg_xml.h:211
void promote_demote_constraints(resource_t *rsc, pe_working_set_t *data_set)
#define pe_rsc_provisional
Definition: pe_types.h:227
gboolean rsc_colocation_new(const char *id, const char *node_attr, int score, resource_t *rsc_lh, resource_t *rsc_rh, const char *state_lh, const char *state_rh, pe_working_set_t *data_set)
int weight
Definition: pe_types.h:210
#define crm_warn(fmt, args...)
Definition: logging.h:241
#define set_bit(word, bit)
Definition: crm_internal.h:167
pe_action_flags
Definition: pe_types.h:258
#define order_stop_stop(rsc1, rsc2, type)
#define crm_debug(fmt, args...)
Definition: logging.h:245
void clone_create_pseudo_actions(resource_t *rsc, GListPtr children, notify_data_t **start_notify, notify_data_t **stop_notify, pe_working_set_t *data_set)
char * task
Definition: pe_types.h:369
const char * pe__add_bundle_remote_name(pe_resource_t *rsc, xmlNode *xml, const char *field)
Definition: bundle.c:985
gboolean update_action(pe_action_t *action, pe_working_set_t *data_set)
#define crm_trace(fmt, args...)
Definition: logging.h:246
action_t * find_first_action(GListPtr input, const char *uuid, const char *task, node_t *on_node)
Definition: utils.c:1398
struct pe_node_shared_s * details
Definition: pe_types.h:213
resource_t * find_compatible_child_by_node(resource_t *local_child, node_t *local_node, resource_t *rsc, enum rsc_role_e filter, gboolean current)
GHashTable * rsc_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
unsigned long long flags
Definition: pe_types.h:311
const char * uname
Definition: pe_types.h:179
#define pe_rsc_promotable
Definition: pe_types.h:225
void LogActions(resource_t *rsc, pe_working_set_t *data_set, gboolean terminal)
pe_graph_flags
Definition: pe_types.h:250
#define XML_RSC_ATTR_INCARNATION_NODEMAX
Definition: msg_xml.h:189
char * uuid
Definition: pe_types.h:370
#define pe_rsc_allocating
Definition: pe_types.h:228
enum pe_obj_types variant
Definition: pe_types.h:293
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:220
enum pe_action_flags summary_action_flags(action_t *action, GListPtr children, node_t *node)
#define RSC_DEMOTED
Definition: crm.h:183
GListPtr actions
Definition: pe_types.h:322
gboolean crm_ends_with(const char *s, const char *match)
Definition: strings.c:309
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)
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)
int scores_log_level
pe_action_t * create_pseudo_resource_op(resource_t *rsc, const char *task, bool optional, bool runnable, pe_working_set_t *data_set)
#define RSC_STARTED
Definition: crm.h:175
resource_t * rsc_lh
GListPtr children
Definition: pe_types.h:340
void pcmk__bundle_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
#define crm_err(fmt, args...)
Definition: logging.h:240
#define CRM_ASSERT(expr)
Definition: results.h:42
#define RSC_STATUS
Definition: crm.h:188
void node_list_exclude(GHashTable *list, GListPtr list2, gboolean merge_scores)
Definition: utils.c:139
#define RSC_PROMOTE
Definition: crm.h:180
pe_weights
char data[0]
Definition: internal.h:92
void pcmk__bundle_expand(pe_resource_t *rsc, pe_working_set_t *data_set)
int pe_get_failcount(node_t *node, resource_t *rsc, time_t *last_failure, uint32_t flags, xmlNode *xml_op, pe_working_set_t *data_set)
Definition: failcounts.c:251
rsc_role_e
Definition: common.h:86
#define pe_rsc_block
Definition: pe_types.h:219
enum pe_action_flags flags
Definition: pe_types.h:374
#define pe_rsc_failure_ignored
Definition: pe_types.h:242
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition: pe_types.h:52
#define order_start_start(rsc1, rsc2, type)
#define RSC_STOPPED
Definition: crm.h:178
const char * id
#define RSC_PROMOTED
Definition: crm.h:181
int custom_action_order(resource_t *lh_rsc, char *lh_task, action_t *lh_action, resource_t *rh_rsc, char *rh_task, action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set)
gboolean crm_is_true(const char *s)
Definition: strings.c:172
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:18
#define pe_err(fmt...)
Definition: internal.h:20
#define dump_node_scores(level, rsc, text, nodes)
Definition: internal.h:186
#define XML_RSC_ATTR_INTERLEAVE
Definition: msg_xml.h:185
gboolean order_actions(action_t *lh_action, action_t *rh_action, enum pe_ordering order)
Definition: utils.c:1776
GList * GListPtr
Definition: crm.h:192
bool is_set_recursive(resource_t *rsc, long long flag, bool any)
Definition: clone.c:336
void pcmk__bundle_create_actions(pe_resource_t *rsc, pe_working_set_t *data_set)
#define crm_info(fmt, args...)
Definition: logging.h:243
#define pe_rsc_orphan
Definition: pe_types.h:217
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)
void pcmk__bundle_internal_constraints(pe_resource_t *rsc, pe_working_set_t *data_set)
char * generate_op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key.
Definition: operations.c:39
void pcmk__bundle_append_meta(pe_resource_t *rsc, xmlNode *xml)
pe_ordering
Definition: pe_types.h:437
uint64_t flags
Definition: remote.c:148
action_tasks
Definition: common.h:57
enum crm_ais_msg_types type
Definition: internal.h:85
#define RSC_DEMOTE
Definition: crm.h:182
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:16
void pcmk__bundle_rsc_colocation_lh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
char * id
Definition: pe_types.h:284
GHashTable * allowed_nodes
Definition: pe_types.h:331
int new_rsc_order(resource_t *lh_rsc, const char *lh_task, resource_t *rh_rsc, const char *rh_task, enum pe_ordering type, pe_working_set_t *data_set)