pacemaker  2.0.3-4b1f869f0f
Scalable High-Availability cluster resource manager
pcmk_sched_allocate.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 <sys/param.h>
13 
14 #include <crm/crm.h>
15 #include <crm/cib.h>
16 #include <crm/msg_xml.h>
17 #include <crm/common/xml.h>
18 
19 #include <glib.h>
20 
21 #include <crm/pengine/status.h>
22 #include <pacemaker-internal.h>
23 
24 CRM_TRACE_INIT_DATA(pe_allocate);
25 
26 void set_alloc_actions(pe_working_set_t * data_set);
27 extern void ReloadRsc(resource_t * rsc, node_t *node, pe_working_set_t * data_set);
28 extern gboolean DeleteRsc(resource_t * rsc, node_t * node, gboolean optional, pe_working_set_t * data_set);
29 static void apply_remote_node_ordering(pe_working_set_t *data_set);
30 static enum remote_connection_state get_remote_node_state(pe_node_t *node);
31 
38 };
39 
40 static const char *
41 state2text(enum remote_connection_state state)
42 {
43  switch (state) {
45  return "unknown";
46  case remote_state_alive:
47  return "alive";
49  return "resting";
51  return "failed";
53  return "stopped";
54  }
55 
56  return "impossible";
57 }
58 
60  {
73  },
74  {
87  },
88  {
101  },
102  {
115  }
116 };
117 
118 gboolean
119 update_action_flags(action_t * action, enum pe_action_flags flags, const char *source, int line)
120 {
121  static unsigned long calls = 0;
122  gboolean changed = FALSE;
123  gboolean clear = is_set(flags, pe_action_clear);
124  enum pe_action_flags last = action->flags;
125 
126  if (clear) {
127  action->flags = crm_clear_bit(source, line, action->uuid, action->flags, flags);
128  } else {
129  action->flags = crm_set_bit(source, line, action->uuid, action->flags, flags);
130  }
131 
132  if (last != action->flags) {
133  calls++;
134  changed = TRUE;
135  /* Useful for tracking down _who_ changed a specific flag */
136  /* CRM_ASSERT(calls != 534); */
138  crm_trace("%s on %s: %sset flags 0x%.6x (was 0x%.6x, now 0x%.6x, %lu, %s)",
139  action->uuid, action->node ? action->node->details->uname : "[none]",
140  clear ? "un-" : "", flags, last, action->flags, calls, source);
141  }
142 
143  return changed;
144 }
145 
146 static gboolean
147 check_rsc_parameters(resource_t * rsc, node_t * node, xmlNode * rsc_entry,
148  gboolean active_here, pe_working_set_t * data_set)
149 {
150  int attr_lpc = 0;
151  gboolean force_restart = FALSE;
152  gboolean delete_resource = FALSE;
153  gboolean changed = FALSE;
154 
155  const char *value = NULL;
156  const char *old_value = NULL;
157 
158  const char *attr_list[] = {
162  };
163 
164  for (; attr_lpc < DIMOF(attr_list); attr_lpc++) {
165  value = crm_element_value(rsc->xml, attr_list[attr_lpc]);
166  old_value = crm_element_value(rsc_entry, attr_list[attr_lpc]);
167  if (value == old_value /* i.e. NULL */
168  || crm_str_eq(value, old_value, TRUE)) {
169  continue;
170  }
171 
172  changed = TRUE;
173  trigger_unfencing(rsc, node, "Device definition changed", NULL, data_set);
174  if (active_here) {
175  force_restart = TRUE;
176  crm_notice("Forcing restart of %s on %s, %s changed: %s -> %s",
177  rsc->id, node->details->uname, attr_list[attr_lpc],
178  crm_str(old_value), crm_str(value));
179  }
180  }
181  if (force_restart) {
182  /* make sure the restart happens */
183  stop_action(rsc, node, FALSE);
185  delete_resource = TRUE;
186 
187  } else if (changed) {
188  delete_resource = TRUE;
189  }
190  return delete_resource;
191 }
192 
193 static void
194 CancelXmlOp(resource_t * rsc, xmlNode * xml_op, node_t * active_node,
195  const char *reason, pe_working_set_t * data_set)
196 {
197  guint interval_ms = 0;
198  action_t *cancel = NULL;
199 
200  const char *task = NULL;
201  const char *call_id = NULL;
202  const char *interval_ms_s = NULL;
203 
204  CRM_CHECK(xml_op != NULL, return);
205  CRM_CHECK(active_node != NULL, return);
206 
207  task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
208  call_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
209  interval_ms_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL_MS);
210 
211  interval_ms = crm_parse_ms(interval_ms_s);
212 
213  crm_info("Action " CRM_OP_FMT " on %s will be stopped: %s",
214  rsc->id, task, interval_ms,
215  active_node->details->uname, (reason? reason : "unknown"));
216 
217  cancel = pe_cancel_op(rsc, task, interval_ms, active_node, data_set);
218  add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id);
219  custom_action_order(rsc, stop_key(rsc), NULL, rsc, NULL, cancel, pe_order_optional, data_set);
220 }
221 
222 static gboolean
223 check_action_definition(resource_t * rsc, node_t * active_node, xmlNode * xml_op,
224  pe_working_set_t * data_set)
225 {
226  char *key = NULL;
227  guint interval_ms = 0;
228  const char *interval_ms_s = NULL;
229  const op_digest_cache_t *digest_data = NULL;
230  gboolean did_change = FALSE;
231 
232  const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
233  const char *digest_secure = NULL;
234 
235  CRM_CHECK(active_node != NULL, return FALSE);
236 
237  interval_ms_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL_MS);
238  interval_ms = crm_parse_ms(interval_ms_s);
239 
240  if (interval_ms > 0) {
241  xmlNode *op_match = NULL;
242 
243  /* we need to reconstruct the key because of the way we used to construct resource IDs */
244  key = generate_op_key(rsc->id, task, interval_ms);
245 
246  pe_rsc_trace(rsc, "Checking parameters for %s", key);
247  op_match = find_rsc_op_entry(rsc, key);
248 
249  if (op_match == NULL && is_set(data_set->flags, pe_flag_stop_action_orphans)) {
250  CancelXmlOp(rsc, xml_op, active_node, "orphan", data_set);
251  free(key);
252  return TRUE;
253 
254  } else if (op_match == NULL) {
255  pe_rsc_debug(rsc, "Orphan action detected: %s on %s", key, active_node->details->uname);
256  free(key);
257  return TRUE;
258  }
259  free(key);
260  key = NULL;
261  }
262 
263  crm_trace("Testing " CRM_OP_FMT " on %s",
264  rsc->id, task, interval_ms, active_node->details->uname);
265  if ((interval_ms == 0) && safe_str_eq(task, RSC_STATUS)) {
266  /* Reload based on the start action not a probe */
267  task = RSC_START;
268 
269  } else if ((interval_ms == 0) && safe_str_eq(task, RSC_MIGRATED)) {
270  /* Reload based on the start action not a migrate */
271  task = RSC_START;
272  } else if ((interval_ms == 0) && safe_str_eq(task, RSC_PROMOTE)) {
273  /* Reload based on the start action not a promote */
274  task = RSC_START;
275  }
276 
277  digest_data = rsc_action_digest_cmp(rsc, xml_op, active_node, data_set);
278 
279  if(is_set(data_set->flags, pe_flag_sanitized)) {
280  digest_secure = crm_element_value(xml_op, XML_LRM_ATTR_SECURE_DIGEST);
281  }
282 
283  if(digest_data->rc != RSC_DIGEST_MATCH
284  && digest_secure
285  && digest_data->digest_secure_calc
286  && strcmp(digest_data->digest_secure_calc, digest_secure) == 0) {
287  if (is_set(data_set->flags, pe_flag_stdout)) {
288  printf("Only 'private' parameters to " CRM_OP_FMT " on %s changed: %s\n",
289  rsc->id, task, interval_ms, active_node->details->uname,
291  }
292 
293  } else if (digest_data->rc == RSC_DIGEST_RESTART) {
294  /* Changes that force a restart */
295  pe_action_t *required = NULL;
296 
297  did_change = TRUE;
298  key = generate_op_key(rsc->id, task, interval_ms);
299  crm_log_xml_info(digest_data->params_restart, "params:restart");
300  required = custom_action(rsc, key, task, NULL, TRUE, TRUE, data_set);
301  pe_action_set_flag_reason(__FUNCTION__, __LINE__, required, NULL,
302  "resource definition change", pe_action_optional, TRUE);
303 
304  trigger_unfencing(rsc, active_node, "Device parameters changed", NULL, data_set);
305 
306  } else if ((digest_data->rc == RSC_DIGEST_ALL) || (digest_data->rc == RSC_DIGEST_UNKNOWN)) {
307  /* Changes that can potentially be handled by a reload */
308  const char *digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
309 
310  did_change = TRUE;
311  trigger_unfencing(rsc, active_node, "Device parameters changed (reload)", NULL, data_set);
312  crm_log_xml_info(digest_data->params_all, "params:reload");
313  key = generate_op_key(rsc->id, task, interval_ms);
314 
315  if (interval_ms > 0) {
316  action_t *op = NULL;
317 
318 #if 0
319  /* Always reload/restart the entire resource */
320  ReloadRsc(rsc, active_node, data_set);
321 #else
322  /* Re-sending the recurring op is sufficient - the old one will be cancelled automatically */
323  op = custom_action(rsc, key, task, active_node, TRUE, TRUE, data_set);
325 #endif
326 
327  } else if (digest_restart) {
328  pe_rsc_trace(rsc, "Reloading '%s' action for resource %s", task, rsc->id);
329 
330  /* Reload this resource */
331  ReloadRsc(rsc, active_node, data_set);
332  free(key);
333 
334  } else {
335  pe_action_t *required = NULL;
336  pe_rsc_trace(rsc, "Resource %s doesn't know how to reload", rsc->id);
337 
338  /* Re-send the start/demote/promote op
339  * Recurring ops will be detected independently
340  */
341  required = custom_action(rsc, key, task, NULL, TRUE, TRUE, data_set);
342  pe_action_set_flag_reason(__FUNCTION__, __LINE__, required, NULL,
343  "resource definition change", pe_action_optional, TRUE);
344  }
345  }
346 
347  return did_change;
348 }
349 
356 static void
357 check_params(pe_resource_t *rsc, pe_node_t *node, xmlNode *rsc_op,
358  enum pe_check_parameters check, pe_working_set_t *data_set)
359 {
360  const char *reason = NULL;
361  op_digest_cache_t *digest_data = NULL;
362 
363  switch (check) {
364  case pe_check_active:
365  if (check_action_definition(rsc, node, rsc_op, data_set)
366  && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
367  data_set)) {
368 
369  reason = "action definition changed";
370  }
371  break;
372 
374  digest_data = rsc_action_digest_cmp(rsc, rsc_op, node, data_set);
375  switch (digest_data->rc) {
376  case RSC_DIGEST_UNKNOWN:
377  crm_trace("Resource %s history entry %s on %s has no digest to compare",
378  rsc->id, ID(rsc_op), node->details->id);
379  break;
380  case RSC_DIGEST_MATCH:
381  break;
382  default:
383  reason = "resource parameters have changed";
384  break;
385  }
386  break;
387  }
388 
389  if (reason) {
390  pe__clear_failcount(rsc, node, reason, data_set);
391  }
392 }
393 
394 static void
395 check_actions_for(xmlNode * rsc_entry, resource_t * rsc, node_t * node, pe_working_set_t * data_set)
396 {
397  GListPtr gIter = NULL;
398  int offset = -1;
399  guint interval_ms = 0;
400  int stop_index = 0;
401  int start_index = 0;
402 
403  const char *task = NULL;
404  const char *interval_ms_s = NULL;
405 
406  xmlNode *rsc_op = NULL;
407  GListPtr op_list = NULL;
408  GListPtr sorted_op_list = NULL;
409 
410  CRM_CHECK(node != NULL, return);
411 
412  if (is_set(rsc->flags, pe_rsc_orphan)) {
413  resource_t *parent = uber_parent(rsc);
414  if(parent == NULL
415  || pe_rsc_is_clone(parent) == FALSE
416  || is_set(parent->flags, pe_rsc_unique)) {
417  pe_rsc_trace(rsc, "Skipping param check for %s and deleting: orphan", rsc->id);
418  DeleteRsc(rsc, node, FALSE, data_set);
419  } else {
420  pe_rsc_trace(rsc, "Skipping param check for %s (orphan clone)", rsc->id);
421  }
422  return;
423 
424  } else if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
425  if (check_rsc_parameters(rsc, node, rsc_entry, FALSE, data_set)) {
426  DeleteRsc(rsc, node, FALSE, data_set);
427  }
428  pe_rsc_trace(rsc, "Skipping param check for %s: no longer active on %s",
429  rsc->id, node->details->uname);
430  return;
431  }
432 
433  pe_rsc_trace(rsc, "Processing %s on %s", rsc->id, node->details->uname);
434 
435  if (check_rsc_parameters(rsc, node, rsc_entry, TRUE, data_set)) {
436  DeleteRsc(rsc, node, FALSE, data_set);
437  }
438 
439  for (rsc_op = __xml_first_child_element(rsc_entry); rsc_op != NULL;
440  rsc_op = __xml_next_element(rsc_op)) {
441 
442  if (crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) {
443  op_list = g_list_prepend(op_list, rsc_op);
444  }
445  }
446 
447  sorted_op_list = g_list_sort(op_list, sort_op_by_callid);
448  calculate_active_ops(sorted_op_list, &start_index, &stop_index);
449 
450  for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
451  xmlNode *rsc_op = (xmlNode *) gIter->data;
452 
453  offset++;
454 
455  if (start_index < stop_index) {
456  /* stopped */
457  continue;
458  } else if (offset < start_index) {
459  /* action occurred prior to a start */
460  continue;
461  }
462 
463  task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
464 
465  interval_ms_s = crm_element_value(rsc_op, XML_LRM_ATTR_INTERVAL_MS);
466  interval_ms = crm_parse_ms(interval_ms_s);
467 
468  if ((interval_ms > 0) &&
469  (is_set(rsc->flags, pe_rsc_maintenance) || node->details->maintenance)) {
470  // Maintenance mode cancels recurring operations
471  CancelXmlOp(rsc, rsc_op, node, "maintenance mode", data_set);
472 
473  } else if ((interval_ms > 0)
474  || safe_str_eq(task, RSC_STATUS)
475  || safe_str_eq(task, RSC_START)
476  || safe_str_eq(task, RSC_PROMOTE)
477  || safe_str_eq(task, RSC_MIGRATED)) {
478 
479  /* If a resource operation failed, and the operation's definition
480  * has changed, clear any fail count so they can be retried fresh.
481  */
482 
483  if (pe__bundle_needs_remote_name(rsc)) {
484  /* We haven't allocated resources to nodes yet, so if the
485  * REMOTE_CONTAINER_HACK is used, we may calculate the digest
486  * based on the literal "#uname" value rather than the properly
487  * substituted value. That would mistakenly make the action
488  * definition appear to have been changed. Defer the check until
489  * later in this case.
490  */
491  pe__add_param_check(rsc_op, rsc, node, pe_check_active,
492  data_set);
493 
494  } else if (check_action_definition(rsc, node, rsc_op, data_set)
495  && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
496  data_set)) {
497  pe__clear_failcount(rsc, node, "action definition changed",
498  data_set);
499  }
500  }
501  }
502  g_list_free(sorted_op_list);
503 }
504 
505 static GListPtr
506 find_rsc_list(GListPtr result, resource_t * rsc, const char *id, gboolean renamed_clones,
507  gboolean partial, pe_working_set_t * data_set)
508 {
509  GListPtr gIter = NULL;
510  gboolean match = FALSE;
511 
512  if (id == NULL) {
513  return NULL;
514  }
515 
516  if (rsc == NULL) {
517  if (data_set == NULL) {
518  return NULL;
519  }
520  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
521  pe_resource_t *child = (pe_resource_t *) gIter->data;
522 
523  result = find_rsc_list(result, child, id, renamed_clones, partial,
524  NULL);
525  }
526  return result;
527  }
528 
529  if (partial) {
530  if (strstr(rsc->id, id)) {
531  match = TRUE;
532 
533  } else if (renamed_clones && rsc->clone_name && strstr(rsc->clone_name, id)) {
534  match = TRUE;
535  }
536 
537  } else {
538  if (strcmp(rsc->id, id) == 0) {
539  match = TRUE;
540 
541  } else if (renamed_clones && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
542  match = TRUE;
543  }
544  }
545 
546  if (match) {
547  result = g_list_prepend(result, rsc);
548  }
549 
550  if (rsc->children) {
551  gIter = rsc->children;
552  for (; gIter != NULL; gIter = gIter->next) {
553  resource_t *child = (resource_t *) gIter->data;
554 
555  result = find_rsc_list(result, child, id, renamed_clones, partial, NULL);
556  }
557  }
558 
559  return result;
560 }
561 
562 static void
563 check_actions(pe_working_set_t * data_set)
564 {
565  const char *id = NULL;
566  node_t *node = NULL;
567  xmlNode *lrm_rscs = NULL;
568  xmlNode *status = get_object_root(XML_CIB_TAG_STATUS, data_set->input);
569 
570  xmlNode *node_state = NULL;
571 
572  for (node_state = __xml_first_child_element(status); node_state != NULL;
573  node_state = __xml_next_element(node_state)) {
574  if (crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE)) {
575  id = crm_element_value(node_state, XML_ATTR_ID);
576  lrm_rscs = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
577  lrm_rscs = find_xml_node(lrm_rscs, XML_LRM_TAG_RESOURCES, FALSE);
578 
579  node = pe_find_node_id(data_set->nodes, id);
580 
581  if (node == NULL) {
582  continue;
583 
584  /* Still need to check actions for a maintenance node to cancel existing monitor operations */
585  } else if (can_run_resources(node) == FALSE && node->details->maintenance == FALSE) {
586  crm_trace("Skipping param check for %s: can't run resources",
587  node->details->uname);
588  continue;
589  }
590 
591  crm_trace("Processing node %s", node->details->uname);
592  if (node->details->online || is_set(data_set->flags, pe_flag_stonith_enabled)) {
593  xmlNode *rsc_entry = NULL;
594 
595  for (rsc_entry = __xml_first_child_element(lrm_rscs);
596  rsc_entry != NULL;
597  rsc_entry = __xml_next_element(rsc_entry)) {
598 
599  if (crm_str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, TRUE)) {
600 
601  if (xml_has_children(rsc_entry)) {
602  GListPtr gIter = NULL;
603  GListPtr result = NULL;
604  const char *rsc_id = ID(rsc_entry);
605 
606  CRM_CHECK(rsc_id != NULL, return);
607 
608  result = find_rsc_list(NULL, NULL, rsc_id, TRUE, FALSE, data_set);
609  for (gIter = result; gIter != NULL; gIter = gIter->next) {
610  resource_t *rsc = (resource_t *) gIter->data;
611 
612  if (rsc->variant != pe_native) {
613  continue;
614  }
615  check_actions_for(rsc_entry, rsc, node, data_set);
616  }
617  g_list_free(result);
618  }
619  }
620  }
621  }
622  }
623  }
624 }
625 
626 static gboolean
627 apply_placement_constraints(pe_working_set_t * data_set)
628 {
629  GListPtr gIter = NULL;
630 
631  crm_trace("Applying constraints...");
632 
633  for (gIter = data_set->placement_constraints; gIter != NULL; gIter = gIter->next) {
634  pe__location_t *cons = gIter->data;
635 
636  cons->rsc_lh->cmds->rsc_location(cons->rsc_lh, cons);
637  }
638 
639  return TRUE;
640 
641 }
642 
643 static gboolean
644 failcount_clear_action_exists(node_t * node, resource_t * rsc)
645 {
646  gboolean rc = FALSE;
647  GList *list = pe__resource_actions(rsc, node, CRM_OP_CLEAR_FAILCOUNT, TRUE);
648 
649  if (list) {
650  rc = TRUE;
651  }
652  g_list_free(list);
653  return rc;
654 }
655 
664 static void
665 check_migration_threshold(resource_t *rsc, node_t *node,
666  pe_working_set_t *data_set)
667 {
668  int fail_count, countdown;
669  resource_t *failed;
670 
671  /* Migration threshold of 0 means never force away */
672  if (rsc->migration_threshold == 0) {
673  return;
674  }
675 
676  // If we're ignoring failures, also ignore the migration threshold
677  if (is_set(rsc->flags, pe_rsc_failure_ignored)) {
678  return;
679  }
680 
681  /* If there are no failures, there's no need to force away */
682  fail_count = pe_get_failcount(node, rsc, NULL,
684  data_set);
685  if (fail_count <= 0) {
686  return;
687  }
688 
689  /* How many more times recovery will be tried on this node */
690  countdown = QB_MAX(rsc->migration_threshold - fail_count, 0);
691 
692  /* If failed resource has a parent, we'll force the parent away */
693  failed = rsc;
694  if (is_not_set(rsc->flags, pe_rsc_unique)) {
695  failed = uber_parent(rsc);
696  }
697 
698  if (countdown == 0) {
699  resource_location(failed, node, -INFINITY, "__fail_limit__", data_set);
700  crm_warn("Forcing %s away from %s after %d failures (max=%d)",
701  failed->id, node->details->uname, fail_count,
702  rsc->migration_threshold);
703  } else {
704  crm_info("%s can fail %d more times on %s before being forced off",
705  failed->id, countdown, node->details->uname);
706  }
707 }
708 
709 static void
710 common_apply_stickiness(resource_t * rsc, node_t * node, pe_working_set_t * data_set)
711 {
712  if (rsc->children) {
713  GListPtr gIter = rsc->children;
714 
715  for (; gIter != NULL; gIter = gIter->next) {
716  resource_t *child_rsc = (resource_t *) gIter->data;
717 
718  common_apply_stickiness(child_rsc, node, data_set);
719  }
720  return;
721  }
722 
723  if (is_set(rsc->flags, pe_rsc_managed)
724  && rsc->stickiness != 0 && g_list_length(rsc->running_on) == 1) {
725  node_t *current = pe_find_node_id(rsc->running_on, node->details->id);
726  node_t *match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
727 
728  if (current == NULL) {
729 
730  } else if (match != NULL || is_set(data_set->flags, pe_flag_symmetric_cluster)) {
731  resource_t *sticky_rsc = rsc;
732 
733  resource_location(sticky_rsc, node, rsc->stickiness, "stickiness", data_set);
734  pe_rsc_debug(sticky_rsc, "Resource %s: preferring current location"
735  " (node=%s, weight=%d)", sticky_rsc->id,
736  node->details->uname, rsc->stickiness);
737  } else {
738  GHashTableIter iter;
739  node_t *nIter = NULL;
740 
741  pe_rsc_debug(rsc, "Ignoring stickiness for %s: the cluster is asymmetric"
742  " and node %s is not explicitly allowed", rsc->id, node->details->uname);
743  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
744  while (g_hash_table_iter_next(&iter, NULL, (void **)&nIter)) {
745  crm_err("%s[%s] = %d", rsc->id, nIter->details->uname, nIter->weight);
746  }
747  }
748  }
749 
750  /* Check the migration threshold only if a failcount clear action
751  * has not already been placed for this resource on the node.
752  * There is no sense in potentially forcing the resource from this
753  * node if the failcount is being reset anyway.
754  *
755  * @TODO A clear_failcount operation can be scheduled in stage4() via
756  * check_actions_for(), or in stage5() via check_params(). This runs in
757  * stage2(), so it cannot detect those, meaning we might check the migration
758  * threshold when we shouldn't -- worst case, we stop or move the resource,
759  * then move it back next transition.
760  */
761  if (failcount_clear_action_exists(node, rsc) == FALSE) {
762  check_migration_threshold(rsc, node, data_set);
763  }
764 }
765 
766 void
768 {
769  GListPtr gIter = rsc->children;
770 
772 
773  for (; gIter != NULL; gIter = gIter->next) {
774  resource_t *child_rsc = (resource_t *) gIter->data;
775 
776  complex_set_cmds(child_rsc);
777  }
778 }
779 
780 void
782 {
783 
784  GListPtr gIter = data_set->resources;
785 
786  for (; gIter != NULL; gIter = gIter->next) {
787  resource_t *rsc = (resource_t *) gIter->data;
788 
789  complex_set_cmds(rsc);
790  }
791 }
792 
793 static void
794 calculate_system_health(gpointer gKey, gpointer gValue, gpointer user_data)
795 {
796  const char *key = (const char *)gKey;
797  const char *value = (const char *)gValue;
798  int *system_health = (int *)user_data;
799 
800  if (!gKey || !gValue || !user_data) {
801  return;
802  }
803 
804  if (crm_starts_with(key, "#health")) {
805  int score;
806 
807  /* Convert the value into an integer */
808  score = char2score(value);
809 
810  /* Add it to the running total */
811  *system_health = merge_weights(score, *system_health);
812  }
813 }
814 
815 static gboolean
816 apply_system_health(pe_working_set_t * data_set)
817 {
818  GListPtr gIter = NULL;
819  const char *health_strategy = pe_pref(data_set->config_hash, "node-health-strategy");
820  int base_health = 0;
821 
822  if (health_strategy == NULL || safe_str_eq(health_strategy, "none")) {
823  /* Prevent any accidental health -> score translation */
824  node_score_red = 0;
825  node_score_yellow = 0;
826  node_score_green = 0;
827  return TRUE;
828 
829  } else if (safe_str_eq(health_strategy, "migrate-on-red")) {
830 
831  /* Resources on nodes which have health values of red are
832  * weighted away from that node.
833  */
835  node_score_yellow = 0;
836  node_score_green = 0;
837 
838  } else if (safe_str_eq(health_strategy, "only-green")) {
839 
840  /* Resources on nodes which have health values of red or yellow
841  * are forced away from that node.
842  */
845  node_score_green = 0;
846 
847  } else if (safe_str_eq(health_strategy, "progressive")) {
848  /* Same as the above, but use the r/y/g scores provided by the user
849  * Defaults are provided by the pe_prefs table
850  * Also, custom health "base score" can be used
851  */
852  base_health = crm_parse_int(pe_pref(data_set->config_hash, "node-health-base"), "0");
853 
854  } else if (safe_str_eq(health_strategy, "custom")) {
855 
856  /* Requires the admin to configure the rsc_location constaints for
857  * processing the stored health scores
858  */
859  /* TODO: Check for the existence of appropriate node health constraints */
860  return TRUE;
861 
862  } else {
863  crm_err("Unknown node health strategy: %s", health_strategy);
864  return FALSE;
865  }
866 
867  crm_info("Applying automated node health strategy: %s", health_strategy);
868 
869  for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
870  int system_health = base_health;
871  node_t *node = (node_t *) gIter->data;
872 
873  /* Search through the node hash table for system health entries. */
874  g_hash_table_foreach(node->details->attrs, calculate_system_health, &system_health);
875 
876  crm_info(" Node %s has an combined system health of %d",
877  node->details->uname, system_health);
878 
879  /* If the health is non-zero, then create a new rsc2node so that the
880  * weight will be added later on.
881  */
882  if (system_health != 0) {
883 
884  GListPtr gIter2 = data_set->resources;
885 
886  for (; gIter2 != NULL; gIter2 = gIter2->next) {
887  resource_t *rsc = (resource_t *) gIter2->data;
888 
889  rsc2node_new(health_strategy, rsc, system_health, NULL, node, data_set);
890  }
891  }
892  }
893 
894  return TRUE;
895 }
896 
897 gboolean
899 {
900  xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input);
901 
902  if (data_set->input == NULL) {
903  return FALSE;
904  }
905 
906  if (is_set(data_set->flags, pe_flag_have_status) == FALSE) {
907  crm_trace("Calculating status");
908  cluster_status(data_set);
909  }
910 
911  set_alloc_actions(data_set);
912  apply_system_health(data_set);
913  unpack_constraints(cib_constraints, data_set);
914 
915  return TRUE;
916 }
917 
918 /*
919  * Check nodes for resources started outside of the LRM
920  */
921 gboolean
923 {
924  action_t *probe_node_complete = NULL;
925 
926  for (GListPtr gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
927  node_t *node = (node_t *) gIter->data;
928  const char *probed = pe_node_attribute_raw(node, CRM_OP_PROBED);
929 
930  if (node->details->online == FALSE) {
931 
932  if (pe__is_remote_node(node) && node->details->remote_rsc
933  && (get_remote_node_state(node) == remote_state_failed)) {
934 
935  pe_fence_node(data_set, node, "the connection is unrecoverable");
936  }
937  continue;
938 
939  } else if (node->details->unclean) {
940  continue;
941 
942  } else if (node->details->rsc_discovery_enabled == FALSE) {
943  /* resource discovery is disabled for this node */
944  continue;
945  }
946 
947  if (probed != NULL && crm_is_true(probed) == FALSE) {
948  action_t *probe_op = custom_action(NULL, crm_strdup_printf("%s-%s", CRM_OP_REPROBE, node->details->uname),
949  CRM_OP_REPROBE, node, FALSE, TRUE, data_set);
950 
952  continue;
953  }
954 
955  for (GListPtr gIter2 = data_set->resources; gIter2 != NULL; gIter2 = gIter2->next) {
956  resource_t *rsc = (resource_t *) gIter2->data;
957 
958  rsc->cmds->create_probe(rsc, node, probe_node_complete, FALSE, data_set);
959  }
960  }
961  return TRUE;
962 }
963 
964 static void
965 rsc_discover_filter(resource_t *rsc, node_t *node)
966 {
967  GListPtr gIter = rsc->children;
968  resource_t *top = uber_parent(rsc);
969  node_t *match;
970 
971  if (rsc->exclusive_discover == FALSE && top->exclusive_discover == FALSE) {
972  return;
973  }
974 
975  for (; gIter != NULL; gIter = gIter->next) {
976  resource_t *child_rsc = (resource_t *) gIter->data;
977  rsc_discover_filter(child_rsc, node);
978  }
979 
980  match = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
981  if (match && match->rsc_discover_mode != pe_discover_exclusive) {
982  match->weight = -INFINITY;
983  }
984 }
985 
986 /*
987  * Count how many valid nodes we have (so we know the maximum number of
988  * colors we can resolve).
989  *
990  * Apply node constraints (i.e. filter the "allowed_nodes" part of resources)
991  */
992 gboolean
994 {
995  GListPtr gIter = NULL;
996 
997  crm_trace("Applying placement constraints");
998 
999  gIter = data_set->nodes;
1000  for (; gIter != NULL; gIter = gIter->next) {
1001  node_t *node = (node_t *) gIter->data;
1002 
1003  if (node == NULL) {
1004  /* error */
1005 
1006  } else if (node->weight >= 0.0 /* global weight */
1007  && node->details->online && node->details->type != node_ping) {
1008  data_set->max_valid_nodes++;
1009  }
1010  }
1011 
1012  apply_placement_constraints(data_set);
1013 
1014  gIter = data_set->nodes;
1015  for (; gIter != NULL; gIter = gIter->next) {
1016  GListPtr gIter2 = NULL;
1017  node_t *node = (node_t *) gIter->data;
1018 
1019  gIter2 = data_set->resources;
1020  for (; gIter2 != NULL; gIter2 = gIter2->next) {
1021  resource_t *rsc = (resource_t *) gIter2->data;
1022 
1023  common_apply_stickiness(rsc, node, data_set);
1024  rsc_discover_filter(rsc, node);
1025  }
1026  }
1027 
1028  return TRUE;
1029 }
1030 
1031 /*
1032  * Create internal resource constraints before allocation
1033  */
1034 gboolean
1036 {
1037 
1038  GListPtr gIter = data_set->resources;
1039 
1040  for (; gIter != NULL; gIter = gIter->next) {
1041  resource_t *rsc = (resource_t *) gIter->data;
1042 
1043  rsc->cmds->internal_constraints(rsc, data_set);
1044  }
1045 
1046  return TRUE;
1047 }
1048 
1049 /*
1050  * Check for orphaned or redefined actions
1051  */
1052 gboolean
1054 {
1055  check_actions(data_set);
1056  return TRUE;
1057 }
1058 
1059 static void *
1060 convert_const_pointer(const void *ptr)
1061 {
1062  /* Worst function ever */
1063  return (void *)ptr;
1064 }
1065 
1066 static gint
1067 sort_rsc_process_order(gconstpointer a, gconstpointer b, gpointer data)
1068 {
1069  int rc = 0;
1070  int r1_weight = -INFINITY;
1071  int r2_weight = -INFINITY;
1072 
1073  const char *reason = "existence";
1074 
1075  const GListPtr nodes = (GListPtr) data;
1076  const resource_t *resource1 = a;
1077  const resource_t *resource2 = b;
1078 
1079  node_t *r1_node = NULL;
1080  node_t *r2_node = NULL;
1081  GListPtr gIter = NULL;
1082  GHashTable *r1_nodes = NULL;
1083  GHashTable *r2_nodes = NULL;
1084 
1085  if (a == NULL && b == NULL) {
1086  goto done;
1087  }
1088  if (a == NULL) {
1089  return 1;
1090  }
1091  if (b == NULL) {
1092  return -1;
1093  }
1094 
1095  reason = "priority";
1096  r1_weight = resource1->priority;
1097  r2_weight = resource2->priority;
1098 
1099  if (r1_weight > r2_weight) {
1100  rc = -1;
1101  goto done;
1102  }
1103 
1104  if (r1_weight < r2_weight) {
1105  rc = 1;
1106  goto done;
1107  }
1108 
1109  reason = "no node list";
1110  if (nodes == NULL) {
1111  goto done;
1112  }
1113 
1114  r1_nodes = rsc_merge_weights(convert_const_pointer(resource1),
1115  resource1->id, NULL, NULL, 1,
1117  dump_node_scores(LOG_TRACE, NULL, resource1->id, r1_nodes);
1118 
1119  r2_nodes = rsc_merge_weights(convert_const_pointer(resource2),
1120  resource2->id, NULL, NULL, 1,
1122  dump_node_scores(LOG_TRACE, NULL, resource2->id, r2_nodes);
1123 
1124  /* Current location score */
1125  reason = "current location";
1126  r1_weight = -INFINITY;
1127  r2_weight = -INFINITY;
1128 
1129  if (resource1->running_on) {
1130  r1_node = pe__current_node(resource1);
1131  r1_node = g_hash_table_lookup(r1_nodes, r1_node->details->id);
1132  if (r1_node != NULL) {
1133  r1_weight = r1_node->weight;
1134  }
1135  }
1136  if (resource2->running_on) {
1137  r2_node = pe__current_node(resource2);
1138  r2_node = g_hash_table_lookup(r2_nodes, r2_node->details->id);
1139  if (r2_node != NULL) {
1140  r2_weight = r2_node->weight;
1141  }
1142  }
1143 
1144  if (r1_weight > r2_weight) {
1145  rc = -1;
1146  goto done;
1147  }
1148 
1149  if (r1_weight < r2_weight) {
1150  rc = 1;
1151  goto done;
1152  }
1153 
1154  reason = "score";
1155  for (gIter = nodes; gIter != NULL; gIter = gIter->next) {
1156  node_t *node = (node_t *) gIter->data;
1157 
1158  r1_node = NULL;
1159  r2_node = NULL;
1160 
1161  r1_weight = -INFINITY;
1162  if (r1_nodes) {
1163  r1_node = g_hash_table_lookup(r1_nodes, node->details->id);
1164  }
1165  if (r1_node) {
1166  r1_weight = r1_node->weight;
1167  }
1168 
1169  r2_weight = -INFINITY;
1170  if (r2_nodes) {
1171  r2_node = g_hash_table_lookup(r2_nodes, node->details->id);
1172  }
1173  if (r2_node) {
1174  r2_weight = r2_node->weight;
1175  }
1176 
1177  if (r1_weight > r2_weight) {
1178  rc = -1;
1179  goto done;
1180  }
1181 
1182  if (r1_weight < r2_weight) {
1183  rc = 1;
1184  goto done;
1185  }
1186  }
1187 
1188  done:
1189  crm_trace("%s (%d) on %s %c %s (%d) on %s: %s",
1190  resource1->id, r1_weight, r1_node ? r1_node->details->id : "n/a",
1191  rc < 0 ? '>' : rc > 0 ? '<' : '=',
1192  resource2->id, r2_weight, r2_node ? r2_node->details->id : "n/a", reason);
1193 
1194  if (r1_nodes) {
1195  g_hash_table_destroy(r1_nodes);
1196  }
1197  if (r2_nodes) {
1198  g_hash_table_destroy(r2_nodes);
1199  }
1200 
1201  return rc;
1202 }
1203 
1204 static void
1205 allocate_resources(pe_working_set_t * data_set)
1206 {
1207  GListPtr gIter = NULL;
1208 
1209  if (is_set(data_set->flags, pe_flag_have_remote_nodes)) {
1210  /* Force remote connection resources to be allocated first. This
1211  * also forces any colocation dependencies to be allocated as well */
1212  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1213  resource_t *rsc = (resource_t *) gIter->data;
1214  if (rsc->is_remote_node == FALSE) {
1215  continue;
1216  }
1217  pe_rsc_trace(rsc, "Allocating: %s", rsc->id);
1218  /* For remote node connection resources, always prefer the partial
1219  * migration target during resource allocation, if the rsc is in the
1220  * middle of a migration.
1221  */
1222  rsc->cmds->allocate(rsc, rsc->partial_migration_target, data_set);
1223  }
1224  }
1225 
1226  /* now do the rest of the resources */
1227  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1228  resource_t *rsc = (resource_t *) gIter->data;
1229  if (rsc->is_remote_node == TRUE) {
1230  continue;
1231  }
1232  pe_rsc_trace(rsc, "Allocating: %s", rsc->id);
1233  rsc->cmds->allocate(rsc, NULL, data_set);
1234  }
1235 }
1236 
1237 /* We always use pe_order_preserve with these convenience functions to exempt
1238  * internally generated constraints from the prohibition of user constraints
1239  * involving remote connection resources.
1240  *
1241  * The start ordering additionally uses pe_order_runnable_left so that the
1242  * specified action is not runnable if the start is not runnable.
1243  */
1244 
1245 static inline void
1246 order_start_then_action(resource_t *lh_rsc, action_t *rh_action,
1247  enum pe_ordering extra, pe_working_set_t *data_set)
1248 {
1249  if (lh_rsc && rh_action && data_set) {
1250  custom_action_order(lh_rsc, start_key(lh_rsc), NULL,
1251  rh_action->rsc, NULL, rh_action,
1252  pe_order_preserve | pe_order_runnable_left | extra,
1253  data_set);
1254  }
1255 }
1256 
1257 static inline void
1258 order_action_then_stop(action_t *lh_action, resource_t *rh_rsc,
1259  enum pe_ordering extra, pe_working_set_t *data_set)
1260 {
1261  if (lh_action && rh_rsc && data_set) {
1262  custom_action_order(lh_action->rsc, NULL, lh_action,
1263  rh_rsc, stop_key(rh_rsc), NULL,
1264  pe_order_preserve | extra, data_set);
1265  }
1266 }
1267 
1268 // Clear fail counts for orphaned rsc on all online nodes
1269 static void
1270 cleanup_orphans(resource_t * rsc, pe_working_set_t * data_set)
1271 {
1272  GListPtr gIter = NULL;
1273 
1274  for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1275  node_t *node = (node_t *) gIter->data;
1276 
1277  if (node->details->online
1278  && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
1279  data_set)) {
1280 
1281  pe_action_t *clear_op = NULL;
1282 
1283  clear_op = pe__clear_failcount(rsc, node, "it is orphaned",
1284  data_set);
1285 
1286  /* We can't use order_action_then_stop() here because its
1287  * pe_order_preserve breaks things
1288  */
1289  custom_action_order(clear_op->rsc, NULL, clear_op,
1290  rsc, stop_key(rsc), NULL,
1291  pe_order_optional, data_set);
1292  }
1293  }
1294 }
1295 
1296 gboolean
1298 {
1299  GListPtr gIter = NULL;
1300 
1301  if (safe_str_neq(data_set->placement_strategy, "default")) {
1302  GListPtr nodes = g_list_copy(data_set->nodes);
1303 
1304  nodes = sort_nodes_by_weight(nodes, NULL, data_set);
1305  data_set->resources =
1306  g_list_sort_with_data(data_set->resources, sort_rsc_process_order, nodes);
1307 
1308  g_list_free(nodes);
1309  }
1310 
1311  gIter = data_set->nodes;
1312  for (; gIter != NULL; gIter = gIter->next) {
1313  node_t *node = (node_t *) gIter->data;
1314 
1316  }
1317 
1318  crm_trace("Allocating services");
1319  /* Take (next) highest resource, assign it and create its actions */
1320 
1321  allocate_resources(data_set);
1322 
1323  gIter = data_set->nodes;
1324  for (; gIter != NULL; gIter = gIter->next) {
1325  node_t *node = (node_t *) gIter->data;
1326 
1327  dump_node_capacity(show_utilization ? 0 : utilization_log_level, "Remaining", node);
1328  }
1329 
1330  // Process deferred action checks
1331  pe__foreach_param_check(data_set, check_params);
1332  pe__free_param_checks(data_set);
1333 
1334  if (is_set(data_set->flags, pe_flag_startup_probes)) {
1335  crm_trace("Calculating needed probes");
1336  /* This code probably needs optimization
1337  * ptest -x with 100 nodes, 100 clones and clone-max=100:
1338 
1339  With probes:
1340 
1341  ptest[14781]: 2010/09/27_17:56:46 notice: TRACE: do_calculations: pengine.c:258 Calculate cluster status
1342  ptest[14781]: 2010/09/27_17:56:46 notice: TRACE: do_calculations: pengine.c:278 Applying placement constraints
1343  ptest[14781]: 2010/09/27_17:56:47 notice: TRACE: do_calculations: pengine.c:285 Create internal constraints
1344  ptest[14781]: 2010/09/27_17:56:47 notice: TRACE: do_calculations: pengine.c:292 Check actions
1345  ptest[14781]: 2010/09/27_17:56:48 notice: TRACE: do_calculations: pengine.c:299 Allocate resources
1346  ptest[14781]: 2010/09/27_17:56:48 notice: TRACE: stage5: allocate.c:881 Allocating services
1347  ptest[14781]: 2010/09/27_17:56:49 notice: TRACE: stage5: allocate.c:894 Calculating needed probes
1348  ptest[14781]: 2010/09/27_17:56:51 notice: TRACE: stage5: allocate.c:899 Creating actions
1349  ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: stage5: allocate.c:905 Creating done
1350  ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: do_calculations: pengine.c:306 Processing fencing and shutdown cases
1351  ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: do_calculations: pengine.c:313 Applying ordering constraints
1352  36s
1353  ptest[14781]: 2010/09/27_17:57:28 notice: TRACE: do_calculations: pengine.c:320 Create transition graph
1354 
1355  Without probes:
1356 
1357  ptest[14637]: 2010/09/27_17:56:21 notice: TRACE: do_calculations: pengine.c:258 Calculate cluster status
1358  ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:278 Applying placement constraints
1359  ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:285 Create internal constraints
1360  ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:292 Check actions
1361  ptest[14637]: 2010/09/27_17:56:23 notice: TRACE: do_calculations: pengine.c:299 Allocate resources
1362  ptest[14637]: 2010/09/27_17:56:23 notice: TRACE: stage5: allocate.c:881 Allocating services
1363  ptest[14637]: 2010/09/27_17:56:24 notice: TRACE: stage5: allocate.c:899 Creating actions
1364  ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: stage5: allocate.c:905 Creating done
1365  ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:306 Processing fencing and shutdown cases
1366  ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:313 Applying ordering constraints
1367  ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:320 Create transition graph
1368  */
1369 
1370  probe_resources(data_set);
1371  }
1372 
1373  crm_trace("Handle orphans");
1374  if (is_set(data_set->flags, pe_flag_stop_rsc_orphans)) {
1375  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1376  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1377 
1378  /* There's no need to recurse into rsc->children because those
1379  * should just be unallocated clone instances.
1380  */
1381  if (is_set(rsc->flags, pe_rsc_orphan)) {
1382  cleanup_orphans(rsc, data_set);
1383  }
1384  }
1385  }
1386 
1387  crm_trace("Creating actions");
1388 
1389  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1390  resource_t *rsc = (resource_t *) gIter->data;
1391 
1392  rsc->cmds->create_actions(rsc, data_set);
1393  }
1394 
1395  crm_trace("Creating done");
1396  return TRUE;
1397 }
1398 
1399 static gboolean
1400 is_managed(const resource_t * rsc)
1401 {
1402  GListPtr gIter = rsc->children;
1403 
1404  if (is_set(rsc->flags, pe_rsc_managed)) {
1405  return TRUE;
1406  }
1407 
1408  for (; gIter != NULL; gIter = gIter->next) {
1409  resource_t *child_rsc = (resource_t *) gIter->data;
1410 
1411  if (is_managed(child_rsc)) {
1412  return TRUE;
1413  }
1414  }
1415 
1416  return FALSE;
1417 }
1418 
1419 static gboolean
1420 any_managed_resources(pe_working_set_t * data_set)
1421 {
1422 
1423  GListPtr gIter = data_set->resources;
1424 
1425  for (; gIter != NULL; gIter = gIter->next) {
1426  resource_t *rsc = (resource_t *) gIter->data;
1427 
1428  if (is_managed(rsc)) {
1429  return TRUE;
1430  }
1431  }
1432  return FALSE;
1433 }
1434 
1442 static void
1443 fence_guest(pe_node_t *node, pe_working_set_t *data_set)
1444 {
1445  resource_t *container = node->details->remote_rsc->container;
1446  pe_action_t *stop = NULL;
1447  pe_action_t *stonith_op = NULL;
1448 
1449  /* The fence action is just a label; we don't do anything differently for
1450  * off vs. reboot. We specify it explicitly, rather than let it default to
1451  * cluster's default action, because we are not _initiating_ fencing -- we
1452  * are creating a pseudo-event to describe fencing that is already occurring
1453  * by other means (container recovery).
1454  */
1455  const char *fence_action = "off";
1456 
1457  /* Check whether guest's container resource has any explicit stop or
1458  * start (the stop may be implied by fencing of the guest's host).
1459  */
1460  if (container) {
1461  stop = find_first_action(container->actions, NULL, CRMD_ACTION_STOP, NULL);
1462 
1463  if (find_first_action(container->actions, NULL, CRMD_ACTION_START, NULL)) {
1464  fence_action = "reboot";
1465  }
1466  }
1467 
1468  /* Create a fence pseudo-event, so we have an event to order actions
1469  * against, and the controller can always detect it.
1470  */
1471  stonith_op = pe_fence_op(node, fence_action, FALSE, "guest is unclean", data_set);
1473  __FUNCTION__, __LINE__);
1474 
1475  /* We want to imply stops/demotes after the guest is stopped, not wait until
1476  * it is restarted, so we always order pseudo-fencing after stop, not start
1477  * (even though start might be closer to what is done for a real reboot).
1478  */
1479  if(stop && is_set(stop->flags, pe_action_pseudo)) {
1480  pe_action_t *parent_stonith_op = pe_fence_op(stop->node, NULL, FALSE, NULL, data_set);
1481  crm_info("Implying guest node %s is down (action %d) after %s fencing",
1482  node->details->uname, stonith_op->id, stop->node->details->uname);
1483  order_actions(parent_stonith_op, stonith_op,
1485 
1486  } else if (stop) {
1487  order_actions(stop, stonith_op,
1489  crm_info("Implying guest node %s is down (action %d) "
1490  "after container %s is stopped (action %d)",
1491  node->details->uname, stonith_op->id,
1492  container->id, stop->id);
1493  } else {
1494  /* If we're fencing the guest node but there's no stop for the guest
1495  * resource, we must think the guest is already stopped. However, we may
1496  * think so because its resource history was just cleaned. To avoid
1497  * unnecessarily considering the guest node down if it's really up,
1498  * order the pseudo-fencing after any stop of the connection resource,
1499  * which will be ordered after any container (re-)probe.
1500  */
1501  stop = find_first_action(node->details->remote_rsc->actions, NULL,
1502  RSC_STOP, NULL);
1503 
1504  if (stop) {
1505  order_actions(stop, stonith_op, pe_order_optional);
1506  crm_info("Implying guest node %s is down (action %d) "
1507  "after connection is stopped (action %d)",
1508  node->details->uname, stonith_op->id, stop->id);
1509  } else {
1510  /* Not sure why we're fencing, but everything must already be
1511  * cleanly stopped.
1512  */
1513  crm_info("Implying guest node %s is down (action %d) ",
1514  node->details->uname, stonith_op->id);
1515  }
1516  }
1517 
1518  /* Order/imply other actions relative to pseudo-fence as with real fence */
1519  stonith_constraints(node, stonith_op, data_set);
1520 }
1521 
1522 /*
1523  * Create dependencies for stonith and shutdown operations
1524  */
1525 gboolean
1527 {
1528  action_t *dc_down = NULL;
1529  action_t *stonith_op = NULL;
1530  gboolean integrity_lost = FALSE;
1531  gboolean need_stonith = TRUE;
1532  GListPtr gIter;
1533  GListPtr stonith_ops = NULL;
1534  GList *shutdown_ops = NULL;
1535 
1536  /* Remote ordering constraints need to happen prior to calculating fencing
1537  * because it is one more place we will mark the node as dirty.
1538  *
1539  * A nice side effect of doing them early is that apply_*_ordering() can be
1540  * simpler because pe_fence_node() has already done some of the work.
1541  */
1542  crm_trace("Creating remote ordering constraints");
1543  apply_remote_node_ordering(data_set);
1544 
1545  crm_trace("Processing fencing and shutdown cases");
1546  if (any_managed_resources(data_set) == FALSE) {
1547  crm_notice("Delaying fencing operations until there are resources to manage");
1548  need_stonith = FALSE;
1549  }
1550 
1551  /* Check each node for stonith/shutdown */
1552  for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1553  node_t *node = (node_t *) gIter->data;
1554 
1555  /* Guest nodes are "fenced" by recovering their container resource,
1556  * so handle them separately.
1557  */
1558  if (pe__is_guest_node(node)) {
1559  if (node->details->remote_requires_reset && need_stonith
1560  && pe_can_fence(data_set, node)) {
1561  fence_guest(node, data_set);
1562  }
1563  continue;
1564  }
1565 
1566  stonith_op = NULL;
1567 
1568  if (node->details->unclean
1569  && need_stonith && pe_can_fence(data_set, node)) {
1570 
1571  stonith_op = pe_fence_op(node, NULL, FALSE, "node is unclean", data_set);
1572  pe_warn("Scheduling Node %s for STONITH", node->details->uname);
1573 
1574  stonith_constraints(node, stonith_op, data_set);
1575 
1576  if (node->details->is_dc) {
1577  // Remember if the DC is being fenced
1578  dc_down = stonith_op;
1579 
1580  } else {
1581 
1582  if (is_not_set(data_set->flags, pe_flag_concurrent_fencing)
1583  && (stonith_ops != NULL)) {
1584  /* Concurrent fencing is disabled, so order each non-DC
1585  * fencing in a chain. If there is any DC fencing or
1586  * shutdown, it will be ordered after the last action in the
1587  * chain later.
1588  */
1589  order_actions((pe_action_t *) stonith_ops->data,
1590  stonith_op, pe_order_optional);
1591  }
1592 
1593  // Remember all non-DC fencing actions in a separate list
1594  stonith_ops = g_list_prepend(stonith_ops, stonith_op);
1595  }
1596 
1597  } else if (node->details->online && node->details->shutdown &&
1598  /* TODO define what a shutdown op means for a remote node.
1599  * For now we do not send shutdown operations for remote nodes, but
1600  * if we can come up with a good use for this in the future, we will. */
1601  pe__is_guest_or_remote_node(node) == FALSE) {
1602 
1603  action_t *down_op = sched_shutdown_op(node, data_set);
1604 
1605  if (node->details->is_dc) {
1606  // Remember if the DC is being shut down
1607  dc_down = down_op;
1608  } else {
1609  // Remember non-DC shutdowns for later ordering
1610  shutdown_ops = g_list_prepend(shutdown_ops, down_op);
1611  }
1612  }
1613 
1614  if (node->details->unclean && stonith_op == NULL) {
1615  integrity_lost = TRUE;
1616  pe_warn("Node %s is unclean!", node->details->uname);
1617  }
1618  }
1619 
1620  if (integrity_lost) {
1621  if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) {
1622  pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
1623  pe_err("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
1624 
1625  } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE) {
1626  crm_notice("Cannot fence unclean nodes until quorum is"
1627  " attained (or no-quorum-policy is set to ignore)");
1628  }
1629  }
1630 
1631  if (dc_down != NULL) {
1632  /* Order any non-DC shutdowns before any DC shutdown, to avoid repeated
1633  * DC elections. However, we don't want to order non-DC shutdowns before
1634  * a DC *fencing*, because even though we don't want a node that's
1635  * shutting down to become DC, the DC fencing could be ordered before a
1636  * clone stop that's also ordered before the shutdowns, thus leading to
1637  * a graph loop.
1638  */
1639  if (safe_str_eq(dc_down->task, CRM_OP_SHUTDOWN)) {
1640  for (gIter = shutdown_ops; gIter != NULL; gIter = gIter->next) {
1641  action_t *node_stop = (action_t *) gIter->data;
1642 
1643  crm_debug("Ordering shutdown on %s before %s on DC %s",
1644  node_stop->node->details->uname,
1645  dc_down->task, dc_down->node->details->uname);
1646 
1647  order_actions(node_stop, dc_down, pe_order_optional);
1648  }
1649  }
1650 
1651  // Order any non-DC fencing before any DC fencing or shutdown
1652 
1653  if (is_set(data_set->flags, pe_flag_concurrent_fencing)) {
1654  /* With concurrent fencing, order each non-DC fencing action
1655  * separately before any DC fencing or shutdown.
1656  */
1657  for (gIter = stonith_ops; gIter != NULL; gIter = gIter->next) {
1658  order_actions((pe_action_t *) gIter->data, dc_down,
1660  }
1661  } else if (stonith_ops) {
1662  /* Without concurrent fencing, the non-DC fencing actions are
1663  * already ordered relative to each other, so we just need to order
1664  * the DC fencing after the last action in the chain (which is the
1665  * first item in the list).
1666  */
1667  order_actions((pe_action_t *) stonith_ops->data, dc_down,
1669  }
1670  }
1671  g_list_free(stonith_ops);
1672  g_list_free(shutdown_ops);
1673  return TRUE;
1674 }
1675 
1676 /*
1677  * Determine the sets of independent actions and the correct order for the
1678  * actions in each set.
1679  *
1680  * Mark dependencies of un-runnable actions un-runnable
1681  *
1682  */
1683 static GListPtr
1684 find_actions_by_task(GListPtr actions, resource_t * rsc, const char *original_key)
1685 {
1686  GListPtr list = NULL;
1687 
1688  list = find_actions(actions, original_key, NULL);
1689  if (list == NULL) {
1690  /* we're potentially searching a child of the original resource */
1691  char *key = NULL;
1692  char *task = NULL;
1693  guint interval_ms = 0;
1694 
1695  if (parse_op_key(original_key, NULL, &task, &interval_ms)) {
1696  key = generate_op_key(rsc->id, task, interval_ms);
1697  list = find_actions(actions, key, NULL);
1698 
1699  } else {
1700  crm_err("search key: %s", original_key);
1701  }
1702 
1703  free(key);
1704  free(task);
1705  }
1706 
1707  return list;
1708 }
1709 
1710 static void
1711 rsc_order_then(pe_action_t *lh_action, pe_resource_t *rsc,
1712  pe__ordering_t *order)
1713 {
1714  GListPtr gIter = NULL;
1715  GListPtr rh_actions = NULL;
1716  action_t *rh_action = NULL;
1717  enum pe_ordering type;
1718 
1719  CRM_CHECK(rsc != NULL, return);
1720  CRM_CHECK(order != NULL, return);
1721 
1722  type = order->type;
1723  rh_action = order->rh_action;
1724  crm_trace("Processing RH of ordering constraint %d", order->id);
1725 
1726  if (rh_action != NULL) {
1727  rh_actions = g_list_prepend(NULL, rh_action);
1728 
1729  } else if (rsc != NULL) {
1730  rh_actions = find_actions_by_task(rsc->actions, rsc, order->rh_action_task);
1731  }
1732 
1733  if (rh_actions == NULL) {
1734  pe_rsc_trace(rsc, "No RH-Side (%s/%s) found for constraint..."
1735  " ignoring", rsc->id, order->rh_action_task);
1736  if (lh_action) {
1737  pe_rsc_trace(rsc, "LH-Side was: %s", lh_action->uuid);
1738  }
1739  return;
1740  }
1741 
1742  if (lh_action && lh_action->rsc == rsc && is_set(lh_action->flags, pe_action_dangle)) {
1743  pe_rsc_trace(rsc, "Detected dangling operation %s -> %s", lh_action->uuid,
1744  order->rh_action_task);
1746  }
1747 
1748  gIter = rh_actions;
1749  for (; gIter != NULL; gIter = gIter->next) {
1750  action_t *rh_action_iter = (action_t *) gIter->data;
1751 
1752  if (lh_action) {
1753  order_actions(lh_action, rh_action_iter, type);
1754 
1755  } else if (type & pe_order_implies_then) {
1756  update_action_flags(rh_action_iter, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
1757  crm_warn("Unrunnable %s 0x%.6x", rh_action_iter->uuid, type);
1758  } else {
1759  crm_warn("neither %s 0x%.6x", rh_action_iter->uuid, type);
1760  }
1761  }
1762 
1763  g_list_free(rh_actions);
1764 }
1765 
1766 static void
1767 rsc_order_first(pe_resource_t *lh_rsc, pe__ordering_t *order,
1768  pe_working_set_t *data_set)
1769 {
1770  GListPtr gIter = NULL;
1771  GListPtr lh_actions = NULL;
1772  action_t *lh_action = order->lh_action;
1773  resource_t *rh_rsc = order->rh_rsc;
1774 
1775  crm_trace("Processing LH of ordering constraint %d", order->id);
1776  CRM_ASSERT(lh_rsc != NULL);
1777 
1778  if (lh_action != NULL) {
1779  lh_actions = g_list_prepend(NULL, lh_action);
1780 
1781  } else {
1782  lh_actions = find_actions_by_task(lh_rsc->actions, lh_rsc, order->lh_action_task);
1783  }
1784 
1785  if (lh_actions == NULL && lh_rsc != rh_rsc) {
1786  char *key = NULL;
1787  char *op_type = NULL;
1788  guint interval_ms = 0;
1789 
1790  parse_op_key(order->lh_action_task, NULL, &op_type, &interval_ms);
1791  key = generate_op_key(lh_rsc->id, op_type, interval_ms);
1792 
1793  if (lh_rsc->fns->state(lh_rsc, TRUE) == RSC_ROLE_STOPPED && safe_str_eq(op_type, RSC_STOP)) {
1794  free(key);
1795  pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - ignoring",
1796  lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1797 
1798  } else if (lh_rsc->fns->state(lh_rsc, TRUE) == RSC_ROLE_SLAVE && safe_str_eq(op_type, RSC_DEMOTE)) {
1799  free(key);
1800  pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - ignoring",
1801  lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1802 
1803  } else {
1804  pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - creating",
1805  lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1806  lh_action = custom_action(lh_rsc, key, op_type, NULL, TRUE, TRUE, data_set);
1807  lh_actions = g_list_prepend(NULL, lh_action);
1808  }
1809 
1810  free(op_type);
1811  }
1812 
1813  gIter = lh_actions;
1814  for (; gIter != NULL; gIter = gIter->next) {
1815  action_t *lh_action_iter = (action_t *) gIter->data;
1816 
1817  if (rh_rsc == NULL && order->rh_action) {
1818  rh_rsc = order->rh_action->rsc;
1819  }
1820  if (rh_rsc) {
1821  rsc_order_then(lh_action_iter, rh_rsc, order);
1822 
1823  } else if (order->rh_action) {
1824  order_actions(lh_action_iter, order->rh_action, order->type);
1825  }
1826  }
1827 
1828  g_list_free(lh_actions);
1829 }
1830 
1831 extern void update_colo_start_chain(pe_action_t *action,
1832  pe_working_set_t *data_set);
1833 
1834 static int
1835 is_recurring_action(action_t *action)
1836 {
1837  const char *interval_ms_s = g_hash_table_lookup(action->meta,
1839  guint interval_ms = crm_parse_ms(interval_ms_s);
1840 
1841  return (interval_ms > 0);
1842 }
1843 
1844 static void
1845 apply_container_ordering(action_t *action, pe_working_set_t *data_set)
1846 {
1847  /* VMs are also classified as containers for these purposes... in
1848  * that they both involve a 'thing' running on a real or remote
1849  * cluster node.
1850  *
1851  * This allows us to be smarter about the type and extent of
1852  * recovery actions required in various scenarios
1853  */
1854  resource_t *remote_rsc = NULL;
1855  resource_t *container = NULL;
1856  enum action_tasks task = text2task(action->task);
1857 
1858  CRM_ASSERT(action->rsc);
1859  CRM_ASSERT(action->node);
1861 
1862  remote_rsc = action->node->details->remote_rsc;
1863  CRM_ASSERT(remote_rsc);
1864 
1865  container = remote_rsc->container;
1866  CRM_ASSERT(container);
1867 
1868  if(is_set(container->flags, pe_rsc_failed)) {
1869  pe_fence_node(data_set, action->node, "container failed");
1870  }
1871 
1872  crm_trace("Order %s action %s relative to %s%s for %s%s",
1873  action->task, action->uuid,
1874  is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
1875  remote_rsc->id,
1876  is_set(container->flags, pe_rsc_failed)? "failed " : "",
1877  container->id);
1878 
1879  if (safe_str_eq(action->task, CRMD_ACTION_MIGRATE)
1880  || safe_str_eq(action->task, CRMD_ACTION_MIGRATED)) {
1881  /* Migration ops map to "no_action", but we need to apply the same
1882  * ordering as for stop or demote (see get_router_node()).
1883  */
1884  task = stop_rsc;
1885  }
1886 
1887  switch (task) {
1888  case start_rsc:
1889  case action_promote:
1890  /* Force resource recovery if the container is recovered */
1891  order_start_then_action(container, action, pe_order_implies_then,
1892  data_set);
1893 
1894  /* Wait for the connection resource to be up too */
1895  order_start_then_action(remote_rsc, action, pe_order_none,
1896  data_set);
1897  break;
1898 
1899  case stop_rsc:
1900  case action_demote:
1901  if (is_set(container->flags, pe_rsc_failed)) {
1902  /* When the container representing a guest node fails, any stop
1903  * or demote actions for resources running on the guest node
1904  * are implied by the container stopping. This is similar to
1905  * how fencing operations work for cluster nodes and remote
1906  * nodes.
1907  */
1908  } else {
1909  /* Ensure the operation happens before the connection is brought
1910  * down.
1911  *
1912  * If we really wanted to, we could order these after the
1913  * connection start, IFF the container's current role was
1914  * stopped (otherwise we re-introduce an ordering loop when the
1915  * connection is restarting).
1916  */
1917  order_action_then_stop(action, remote_rsc, pe_order_none,
1918  data_set);
1919  }
1920  break;
1921 
1922  default:
1923  /* Wait for the connection resource to be up */
1924  if (is_recurring_action(action)) {
1925  /* In case we ever get the recovery logic wrong, force
1926  * recurring monitors to be restarted, even if just
1927  * the connection was re-established
1928  */
1929  if(task != no_action) {
1930  order_start_then_action(remote_rsc, action,
1931  pe_order_implies_then, data_set);
1932  }
1933  } else {
1934  order_start_then_action(remote_rsc, action, pe_order_none,
1935  data_set);
1936  }
1937  break;
1938  }
1939 }
1940 
1941 static enum remote_connection_state
1942 get_remote_node_state(pe_node_t *node)
1943 {
1944  resource_t *remote_rsc = NULL;
1945  node_t *cluster_node = NULL;
1946 
1947  CRM_ASSERT(node);
1948 
1949  remote_rsc = node->details->remote_rsc;
1950  CRM_ASSERT(remote_rsc);
1951 
1952  cluster_node = pe__current_node(remote_rsc);
1953 
1954  /* If the cluster node the remote connection resource resides on
1955  * is unclean or went offline, we can't process any operations
1956  * on that remote node until after it starts elsewhere.
1957  */
1958  if(remote_rsc->next_role == RSC_ROLE_STOPPED || remote_rsc->allocated_to == NULL) {
1959  /* The connection resource is not going to run anywhere */
1960 
1961  if (cluster_node && cluster_node->details->unclean) {
1962  /* The remote connection is failed because its resource is on a
1963  * failed node and can't be recovered elsewhere, so we must fence.
1964  */
1965  return remote_state_failed;
1966  }
1967 
1968  if (is_not_set(remote_rsc->flags, pe_rsc_failed)) {
1969  /* Connection resource is cleanly stopped */
1970  return remote_state_stopped;
1971  }
1972 
1973  /* Connection resource is failed */
1974 
1975  if ((remote_rsc->next_role == RSC_ROLE_STOPPED)
1976  && remote_rsc->remote_reconnect_ms
1977  && node->details->remote_was_fenced
1978  && !pe__shutdown_requested(node)) {
1979 
1980  /* We won't know whether the connection is recoverable until the
1981  * reconnect interval expires and we reattempt connection.
1982  */
1983  return remote_state_unknown;
1984  }
1985 
1986  /* The remote connection is in a failed state. If there are any
1987  * resources known to be active on it (stop) or in an unknown state
1988  * (probe), we must assume the worst and fence it.
1989  */
1990  return remote_state_failed;
1991 
1992  } else if (cluster_node == NULL) {
1993  /* Connection is recoverable but not currently running anywhere, see if we can recover it first */
1994  return remote_state_unknown;
1995 
1996  } else if(cluster_node->details->unclean == TRUE
1997  || cluster_node->details->online == FALSE) {
1998  /* Connection is running on a dead node, see if we can recover it first */
1999  return remote_state_resting;
2000 
2001  } else if (g_list_length(remote_rsc->running_on) > 1
2002  && remote_rsc->partial_migration_source
2003  && remote_rsc->partial_migration_target) {
2004  /* We're in the middle of migrating a connection resource,
2005  * wait until after the resource migrates before performing
2006  * any actions.
2007  */
2008  return remote_state_resting;
2009 
2010  }
2011  return remote_state_alive;
2012 }
2013 
2018 static void
2019 apply_remote_ordering(action_t *action, pe_working_set_t *data_set)
2020 {
2021  resource_t *remote_rsc = NULL;
2022  enum action_tasks task = text2task(action->task);
2023  enum remote_connection_state state = get_remote_node_state(action->node);
2024 
2025  enum pe_ordering order_opts = pe_order_none;
2026 
2027  if (action->rsc == NULL) {
2028  return;
2029  }
2030 
2031  CRM_ASSERT(action->node);
2033 
2034  remote_rsc = action->node->details->remote_rsc;
2035  CRM_ASSERT(remote_rsc);
2036 
2037  crm_trace("Order %s action %s relative to %s%s (state: %s)",
2038  action->task, action->uuid,
2039  is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
2040  remote_rsc->id, state2text(state));
2041 
2042  if (safe_str_eq(action->task, CRMD_ACTION_MIGRATE)
2043  || safe_str_eq(action->task, CRMD_ACTION_MIGRATED)) {
2044  /* Migration ops map to "no_action", but we need to apply the same
2045  * ordering as for stop or demote (see get_router_node()).
2046  */
2047  task = stop_rsc;
2048  }
2049 
2050  switch (task) {
2051  case start_rsc:
2052  case action_promote:
2053  order_opts = pe_order_none;
2054 
2055  if (state == remote_state_failed) {
2056  /* Force recovery, by making this action required */
2057  order_opts |= pe_order_implies_then;
2058  }
2059 
2060  /* Ensure connection is up before running this action */
2061  order_start_then_action(remote_rsc, action, order_opts, data_set);
2062  break;
2063 
2064  case stop_rsc:
2065  if(state == remote_state_alive) {
2066  order_action_then_stop(action, remote_rsc,
2067  pe_order_implies_first, data_set);
2068 
2069  } else if(state == remote_state_failed) {
2070  /* The resource is active on the node, but since we don't have a
2071  * valid connection, the only way to stop the resource is by
2072  * fencing the node. There is no need to order the stop relative
2073  * to the remote connection, since the stop will become implied
2074  * by the fencing.
2075  */
2076  pe_fence_node(data_set, action->node, "resources are active and the connection is unrecoverable");
2077 
2078  } else if(remote_rsc->next_role == RSC_ROLE_STOPPED) {
2079  /* State must be remote_state_unknown or remote_state_stopped.
2080  * Since the connection is not coming back up in this
2081  * transition, stop this resource first.
2082  */
2083  order_action_then_stop(action, remote_rsc,
2084  pe_order_implies_first, data_set);
2085 
2086  } else {
2087  /* The connection is going to be started somewhere else, so
2088  * stop this resource after that completes.
2089  */
2090  order_start_then_action(remote_rsc, action, pe_order_none, data_set);
2091  }
2092  break;
2093 
2094  case action_demote:
2095  /* Only order this demote relative to the connection start if the
2096  * connection isn't being torn down. Otherwise, the demote would be
2097  * blocked because the connection start would not be allowed.
2098  */
2099  if(state == remote_state_resting || state == remote_state_unknown) {
2100  order_start_then_action(remote_rsc, action, pe_order_none,
2101  data_set);
2102  } /* Otherwise we can rely on the stop ordering */
2103  break;
2104 
2105  default:
2106  /* Wait for the connection resource to be up */
2107  if (is_recurring_action(action)) {
2108  /* In case we ever get the recovery logic wrong, force
2109  * recurring monitors to be restarted, even if just
2110  * the connection was re-established
2111  */
2112  order_start_then_action(remote_rsc, action,
2113  pe_order_implies_then, data_set);
2114 
2115  } else {
2116  node_t *cluster_node = pe__current_node(remote_rsc);
2117 
2118  if(task == monitor_rsc && state == remote_state_failed) {
2119  /* We would only be here if we do not know the
2120  * state of the resource on the remote node.
2121  * Since we have no way to find out, it is
2122  * necessary to fence the node.
2123  */
2124  pe_fence_node(data_set, action->node, "resources are in an unknown state and the connection is unrecoverable");
2125  }
2126 
2127  if(cluster_node && state == remote_state_stopped) {
2128  /* The connection is currently up, but is going
2129  * down permanently.
2130  *
2131  * Make sure we check services are actually
2132  * stopped _before_ we let the connection get
2133  * closed
2134  */
2135  order_action_then_stop(action, remote_rsc,
2136  pe_order_runnable_left, data_set);
2137 
2138  } else {
2139  order_start_then_action(remote_rsc, action, pe_order_none,
2140  data_set);
2141  }
2142  }
2143  break;
2144  }
2145 }
2146 
2147 static void
2148 apply_remote_node_ordering(pe_working_set_t *data_set)
2149 {
2150  if (is_set(data_set->flags, pe_flag_have_remote_nodes) == FALSE) {
2151  return;
2152  }
2153 
2154  for (GListPtr gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2155  action_t *action = (action_t *) gIter->data;
2156  resource_t *remote = NULL;
2157 
2158  // We are only interested in resource actions
2159  if (action->rsc == NULL) {
2160  continue;
2161  }
2162 
2163  /* Special case: If we are clearing the failcount of an actual
2164  * remote connection resource, then make sure this happens before
2165  * any start of the resource in this transition.
2166  */
2167  if (action->rsc->is_remote_node &&
2169 
2170  custom_action_order(action->rsc,
2171  NULL,
2172  action,
2173  action->rsc,
2174  generate_op_key(action->rsc->id, RSC_START, 0),
2175  NULL,
2177  data_set);
2178 
2179  continue;
2180  }
2181 
2182  // We are only interested in actions allocated to a node
2183  if (action->node == NULL) {
2184  continue;
2185  }
2186 
2187  if (!pe__is_guest_or_remote_node(action->node)) {
2188  continue;
2189  }
2190 
2191  /* We are only interested in real actions.
2192  *
2193  * @TODO This is probably wrong; pseudo-actions might be converted to
2194  * real actions and vice versa later in update_actions() at the end of
2195  * stage7().
2196  */
2197  if (is_set(action->flags, pe_action_pseudo)) {
2198  continue;
2199  }
2200 
2201  remote = action->node->details->remote_rsc;
2202  if (remote == NULL) {
2203  // Orphaned
2204  continue;
2205  }
2206 
2207  /* Another special case: if a resource is moving to a Pacemaker Remote
2208  * node, order the stop on the original node after any start of the
2209  * remote connection. This ensures that if the connection fails to
2210  * start, we leave the resource running on the original node.
2211  */
2212  if (safe_str_eq(action->task, RSC_START)) {
2213  for (GList *item = action->rsc->actions; item != NULL;
2214  item = item->next) {
2215  pe_action_t *rsc_action = item->data;
2216 
2217  if ((rsc_action->node->details != action->node->details)
2218  && safe_str_eq(rsc_action->task, RSC_STOP)) {
2219  custom_action_order(remote, start_key(remote), NULL,
2220  action->rsc, NULL, rsc_action,
2221  pe_order_optional, data_set);
2222  }
2223  }
2224  }
2225 
2226  /* The action occurs across a remote connection, so create
2227  * ordering constraints that guarantee the action occurs while the node
2228  * is active (after start, before stop ... things like that).
2229  *
2230  * This is somewhat brittle in that we need to make sure the results of
2231  * this ordering are compatible with the result of get_router_node().
2232  * It would probably be better to add XML_LRM_ATTR_ROUTER_NODE as part
2233  * of this logic rather than action2xml().
2234  */
2235  if (remote->container) {
2236  crm_trace("Container ordering for %s", action->uuid);
2237  apply_container_ordering(action, data_set);
2238 
2239  } else {
2240  crm_trace("Remote ordering for %s", action->uuid);
2241  apply_remote_ordering(action, data_set);
2242  }
2243  }
2244 }
2245 
2246 static gboolean
2247 order_first_probe_unneeded(pe_action_t * probe, pe_action_t * rh_action)
2248 {
2249  /* No need to probe the resource on the node that is being
2250  * unfenced. Otherwise it might introduce transition loop
2251  * since probe will be performed after the node is
2252  * unfenced.
2253  */
2254  if (safe_str_eq(rh_action->task, CRM_OP_FENCE)
2255  && probe->node && rh_action->node
2256  && probe->node->details == rh_action->node->details) {
2257  const char *op = g_hash_table_lookup(rh_action->meta, "stonith_action");
2258 
2259  if (safe_str_eq(op, "on")) {
2260  return TRUE;
2261  }
2262  }
2263 
2264  // Shutdown waits for probe to complete only if it's on the same node
2265  if ((safe_str_eq(rh_action->task, CRM_OP_SHUTDOWN))
2266  && probe->node && rh_action->node
2267  && probe->node->details != rh_action->node->details) {
2268  return TRUE;
2269  }
2270  return FALSE;
2271 }
2272 
2273 static void
2274 order_first_probes_imply_stops(pe_working_set_t * data_set)
2275 {
2276  GListPtr gIter = NULL;
2277 
2278  for (gIter = data_set->ordering_constraints; gIter != NULL; gIter = gIter->next) {
2279  pe__ordering_t *order = gIter->data;
2280  enum pe_ordering order_type = pe_order_optional;
2281 
2282  pe_resource_t *lh_rsc = order->lh_rsc;
2283  pe_resource_t *rh_rsc = order->rh_rsc;
2284  pe_action_t *lh_action = order->lh_action;
2285  pe_action_t *rh_action = order->rh_action;
2286  const char *lh_action_task = order->lh_action_task;
2287  const char *rh_action_task = order->rh_action_task;
2288 
2289  GListPtr probes = NULL;
2290  GListPtr rh_actions = NULL;
2291 
2292  GListPtr pIter = NULL;
2293 
2294  if (lh_rsc == NULL) {
2295  continue;
2296 
2297  } else if (rh_rsc && lh_rsc == rh_rsc) {
2298  continue;
2299  }
2300 
2301  if (lh_action == NULL && lh_action_task == NULL) {
2302  continue;
2303  }
2304 
2305  if (rh_action == NULL && rh_action_task == NULL) {
2306  continue;
2307  }
2308 
2309  /* Technically probe is expected to return "not running", which could be
2310  * the alternative of stop action if the status of the resource is
2311  * unknown yet.
2312  */
2313  if (lh_action && safe_str_neq(lh_action->task, RSC_STOP)) {
2314  continue;
2315 
2316  } else if (lh_action == NULL
2317  && lh_action_task
2318  && crm_ends_with(lh_action_task, "_" RSC_STOP "_0") == FALSE) {
2319  continue;
2320  }
2321 
2322  /* Do not probe the resource inside of a stopping container. Otherwise
2323  * it might introduce transition loop since probe will be performed
2324  * after the container starts again.
2325  */
2326  if (rh_rsc && lh_rsc->container == rh_rsc) {
2327  if (rh_action && safe_str_eq(rh_action->task, RSC_STOP)) {
2328  continue;
2329 
2330  } else if (rh_action == NULL && rh_action_task
2331  && crm_ends_with(rh_action_task,"_" RSC_STOP "_0")) {
2332  continue;
2333  }
2334  }
2335 
2336  if (order->type == pe_order_none) {
2337  continue;
2338  }
2339 
2340  // Preserve the order options for future filtering
2341  if (is_set(order->type, pe_order_apply_first_non_migratable)) {
2343  }
2344 
2345  if (is_set(order->type, pe_order_same_node)) {
2346  set_bit(order_type, pe_order_same_node);
2347  }
2348 
2349  // Keep the order types for future filtering
2350  if (order->type == pe_order_anti_colocation
2351  || order->type == pe_order_load) {
2352  order_type = order->type;
2353  }
2354 
2355  probes = pe__resource_actions(lh_rsc, NULL, RSC_STATUS, FALSE);
2356  if (probes == NULL) {
2357  continue;
2358  }
2359 
2360  if (rh_action) {
2361  rh_actions = g_list_prepend(rh_actions, rh_action);
2362 
2363  } else if (rh_rsc && rh_action_task) {
2364  rh_actions = find_actions(rh_rsc->actions, rh_action_task, NULL);
2365  }
2366 
2367  if (rh_actions == NULL) {
2368  g_list_free(probes);
2369  continue;
2370  }
2371 
2372  crm_trace("Processing for LH probe based on ordering constraint %s -> %s"
2373  " (id=%d, type=%.6x)",
2374  lh_action ? lh_action->uuid : lh_action_task,
2375  rh_action ? rh_action->uuid : rh_action_task,
2376  order->id, order->type);
2377 
2378  for (pIter = probes; pIter != NULL; pIter = pIter->next) {
2379  pe_action_t *probe = (pe_action_t *) pIter->data;
2380  GListPtr rIter = NULL;
2381 
2382  for (rIter = rh_actions; rIter != NULL; rIter = rIter->next) {
2383  pe_action_t *rh_action_iter = (pe_action_t *) rIter->data;
2384 
2385  if (order_first_probe_unneeded(probe, rh_action_iter)) {
2386  continue;
2387  }
2388  order_actions(probe, rh_action_iter, order_type);
2389  }
2390  }
2391 
2392  g_list_free(rh_actions);
2393  g_list_free(probes);
2394  }
2395 }
2396 
2397 static void
2398 order_first_probe_then_restart_repromote(pe_action_t * probe,
2399  pe_action_t * after,
2400  pe_working_set_t * data_set)
2401 {
2402  GListPtr gIter = NULL;
2403  bool interleave = FALSE;
2404  pe_resource_t *compatible_rsc = NULL;
2405 
2406  if (probe == NULL
2407  || probe->rsc == NULL
2408  || probe->rsc->variant != pe_native) {
2409  return;
2410  }
2411 
2412  if (after == NULL
2413  // Avoid running into any possible loop
2414  || is_set(after->flags, pe_action_tracking)) {
2415  return;
2416  }
2417 
2418  if (safe_str_neq(probe->task, RSC_STATUS)) {
2419  return;
2420  }
2421 
2423 
2424  crm_trace("Processing based on %s %s -> %s %s",
2425  probe->uuid,
2426  probe->node ? probe->node->details->uname: "",
2427  after->uuid,
2428  after->node ? after->node->details->uname : "");
2429 
2430  if (after->rsc
2431  /* Better not build a dependency directly with a clone/group.
2432  * We are going to proceed through the ordering chain and build
2433  * dependencies with its children.
2434  */
2435  && after->rsc->variant == pe_native
2436  && probe->rsc != after->rsc) {
2437 
2438  GListPtr then_actions = NULL;
2439  enum pe_ordering probe_order_type = pe_order_optional;
2440 
2441  if (safe_str_eq(after->task, RSC_START)) {
2442  then_actions = pe__resource_actions(after->rsc, NULL, RSC_STOP, FALSE);
2443 
2444  } else if (safe_str_eq(after->task, RSC_PROMOTE)) {
2445  then_actions = pe__resource_actions(after->rsc, NULL, RSC_DEMOTE, FALSE);
2446  }
2447 
2448  for (gIter = then_actions; gIter != NULL; gIter = gIter->next) {
2449  pe_action_t *then = (pe_action_t *) gIter->data;
2450 
2451  // Skip any pseudo action which for example is implied by fencing
2452  if (is_set(then->flags, pe_action_pseudo)) {
2453  continue;
2454  }
2455 
2456  order_actions(probe, then, probe_order_type);
2457  }
2458  g_list_free(then_actions);
2459  }
2460 
2461  if (after->rsc
2462  && after->rsc->variant > pe_group) {
2463  const char *interleave_s = g_hash_table_lookup(after->rsc->meta,
2465 
2466  interleave = crm_is_true(interleave_s);
2467 
2468  if (interleave) {
2469  /* For an interleaved clone, we should build a dependency only
2470  * with the relevant clone child.
2471  */
2472  compatible_rsc = find_compatible_child(probe->rsc,
2473  after->rsc,
2475  FALSE, data_set);
2476  }
2477  }
2478 
2479  for (gIter = after->actions_after; gIter != NULL; gIter = gIter->next) {
2480  pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) gIter->data;
2481  /* pe_order_implies_then is the reason why a required A.start
2482  * implies/enforces B.start to be required too, which is the cause of
2483  * B.restart/re-promote.
2484  *
2485  * Not sure about pe_order_implies_then_on_node though. It's now only
2486  * used for unfencing case, which tends to introduce transition
2487  * loops...
2488  */
2489 
2490  if (is_not_set(after_wrapper->type, pe_order_implies_then)) {
2491  /* The order type between a group/clone and its child such as
2492  * B.start-> B_child.start is:
2493  * pe_order_implies_first_printed | pe_order_runnable_left
2494  *
2495  * Proceed through the ordering chain and build dependencies with
2496  * its children.
2497  */
2498  if (after->rsc == NULL
2499  || after->rsc->variant < pe_group
2500  || probe->rsc->parent == after->rsc
2501  || after_wrapper->action->rsc == NULL
2502  || after_wrapper->action->rsc->variant > pe_group
2503  || after->rsc != after_wrapper->action->rsc->parent) {
2504  continue;
2505  }
2506 
2507  /* Proceed to the children of a group or a non-interleaved clone.
2508  * For an interleaved clone, proceed only to the relevant child.
2509  */
2510  if (after->rsc->variant > pe_group
2511  && interleave == TRUE
2512  && (compatible_rsc == NULL
2513  || compatible_rsc != after_wrapper->action->rsc)) {
2514  continue;
2515  }
2516  }
2517 
2518  crm_trace("Proceeding through %s %s -> %s %s (type=0x%.6x)",
2519  after->uuid,
2520  after->node ? after->node->details->uname: "",
2521  after_wrapper->action->uuid,
2522  after_wrapper->action->node ? after_wrapper->action->node->details->uname : "",
2523  after_wrapper->type);
2524 
2525  order_first_probe_then_restart_repromote(probe, after_wrapper->action, data_set);
2526  }
2527 }
2528 
2529 static void clear_actions_tracking_flag(pe_working_set_t * data_set)
2530 {
2531  GListPtr gIter = NULL;
2532 
2533  for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2534  pe_action_t *action = (pe_action_t *) gIter->data;
2535 
2536  if (is_set(action->flags, pe_action_tracking)) {
2538  }
2539  }
2540 }
2541 
2542 static void
2543 order_first_rsc_probes(pe_resource_t * rsc, pe_working_set_t * data_set)
2544 {
2545  GListPtr gIter = NULL;
2546  GListPtr probes = NULL;
2547 
2548  for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
2549  pe_resource_t * child = (pe_resource_t *) gIter->data;
2550 
2551  order_first_rsc_probes(child, data_set);
2552  }
2553 
2554  if (rsc->variant != pe_native) {
2555  return;
2556  }
2557 
2558  probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
2559 
2560  for (gIter = probes; gIter != NULL; gIter= gIter->next) {
2561  pe_action_t *probe = (pe_action_t *) gIter->data;
2562  GListPtr aIter = NULL;
2563 
2564  for (aIter = probe->actions_after; aIter != NULL; aIter = aIter->next) {
2565  pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) aIter->data;
2566 
2567  order_first_probe_then_restart_repromote(probe, after_wrapper->action, data_set);
2568  clear_actions_tracking_flag(data_set);
2569  }
2570  }
2571 
2572  g_list_free(probes);
2573 }
2574 
2575 static void
2576 order_first_probes(pe_working_set_t * data_set)
2577 {
2578  GListPtr gIter = NULL;
2579 
2580  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2581  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2582 
2583  order_first_rsc_probes(rsc, data_set);
2584  }
2585 
2586  order_first_probes_imply_stops(data_set);
2587 }
2588 
2589 static void
2590 order_then_probes(pe_working_set_t * data_set)
2591 {
2592 #if 0
2593  GListPtr gIter = NULL;
2594 
2595  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2596  resource_t *rsc = (resource_t *) gIter->data;
2597 
2598  /* Given "A then B", we would prefer to wait for A to be
2599  * started before probing B.
2600  *
2601  * If A was a filesystem on which the binaries and data for B
2602  * lived, it would have been useful if the author of B's agent
2603  * could assume that A is running before B.monitor will be
2604  * called.
2605  *
2606  * However we can't _only_ probe once A is running, otherwise
2607  * we'd not detect the state of B if A could not be started
2608  * for some reason.
2609  *
2610  * In practice however, we cannot even do an opportunistic
2611  * version of this because B may be moving:
2612  *
2613  * B.probe -> B.start
2614  * B.probe -> B.stop
2615  * B.stop -> B.start
2616  * A.stop -> A.start
2617  * A.start -> B.probe
2618  *
2619  * So far so good, but if we add the result of this code:
2620  *
2621  * B.stop -> A.stop
2622  *
2623  * Then we get a loop:
2624  *
2625  * B.probe -> B.stop -> A.stop -> A.start -> B.probe
2626  *
2627  * We could kill the 'B.probe -> B.stop' dependency, but that
2628  * could mean stopping B "too" soon, because B.start must wait
2629  * for the probes to complete.
2630  *
2631  * Another option is to allow it only if A is a non-unique
2632  * clone with clone-max == node-max (since we'll never be
2633  * moving it). However, we could still be stopping one
2634  * instance at the same time as starting another.
2635 
2636  * The complexity of checking for allowed conditions combined
2637  * with the ever narrowing usecase suggests that this code
2638  * should remain disabled until someone gets smarter.
2639  */
2640  action_t *start = NULL;
2641  GListPtr actions = NULL;
2642  GListPtr probes = NULL;
2643 
2644  actions = pe__resource_actions(rsc, NULL, RSC_START, FALSE);
2645 
2646  if (actions) {
2647  start = actions->data;
2648  g_list_free(actions);
2649  }
2650 
2651  if(start == NULL) {
2652  crm_err("No start action for %s", rsc->id);
2653  continue;
2654  }
2655 
2656  probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
2657 
2658  for (actions = start->actions_before; actions != NULL; actions = actions->next) {
2659  action_wrapper_t *before = (action_wrapper_t *) actions->data;
2660 
2661  GListPtr pIter = NULL;
2662  action_t *first = before->action;
2663  resource_t *first_rsc = first->rsc;
2664 
2665  if(first->required_runnable_before) {
2666  GListPtr clone_actions = NULL;
2667  for (clone_actions = first->actions_before; clone_actions != NULL; clone_actions = clone_actions->next) {
2668  before = (action_wrapper_t *) clone_actions->data;
2669 
2670  crm_trace("Testing %s -> %s (%p) for %s", first->uuid, before->action->uuid, before->action->rsc, start->uuid);
2671 
2672  CRM_ASSERT(before->action->rsc);
2673  first_rsc = before->action->rsc;
2674  break;
2675  }
2676 
2677  } else if(safe_str_neq(first->task, RSC_START)) {
2678  crm_trace("Not a start op %s for %s", first->uuid, start->uuid);
2679  }
2680 
2681  if(first_rsc == NULL) {
2682  continue;
2683 
2684  } else if(uber_parent(first_rsc) == uber_parent(start->rsc)) {
2685  crm_trace("Same parent %s for %s", first_rsc->id, start->uuid);
2686  continue;
2687 
2688  } else if(FALSE && pe_rsc_is_clone(uber_parent(first_rsc)) == FALSE) {
2689  crm_trace("Not a clone %s for %s", first_rsc->id, start->uuid);
2690  continue;
2691  }
2692 
2693  crm_err("Applying %s before %s %d", first->uuid, start->uuid, uber_parent(first_rsc)->variant);
2694 
2695  for (pIter = probes; pIter != NULL; pIter = pIter->next) {
2696  action_t *probe = (action_t *) pIter->data;
2697 
2698  crm_err("Ordering %s before %s", first->uuid, probe->uuid);
2699  order_actions(first, probe, pe_order_optional);
2700  }
2701  }
2702  }
2703 #endif
2704 }
2705 
2706 static void
2707 order_probes(pe_working_set_t * data_set)
2708 {
2709  order_first_probes(data_set);
2710  order_then_probes(data_set);
2711 }
2712 
2713 gboolean
2715 {
2716  GList *gIter = NULL;
2717 
2718  crm_trace("Applying ordering constraints");
2719 
2720  /* Don't ask me why, but apparently they need to be processed in
2721  * the order they were created in... go figure
2722  *
2723  * Also g_list_append() has horrendous performance characteristics
2724  * So we need to use g_list_prepend() and then reverse the list here
2725  */
2726  data_set->ordering_constraints = g_list_reverse(data_set->ordering_constraints);
2727 
2728  for (gIter = data_set->ordering_constraints; gIter != NULL; gIter = gIter->next) {
2729  pe__ordering_t *order = gIter->data;
2730  resource_t *rsc = order->lh_rsc;
2731 
2732  crm_trace("Applying ordering constraint: %d", order->id);
2733 
2734  if (rsc != NULL) {
2735  crm_trace("rsc_action-to-*");
2736  rsc_order_first(rsc, order, data_set);
2737  continue;
2738  }
2739 
2740  rsc = order->rh_rsc;
2741  if (rsc != NULL) {
2742  crm_trace("action-to-rsc_action");
2743  rsc_order_then(order->lh_action, rsc, order);
2744 
2745  } else {
2746  crm_trace("action-to-action");
2747  order_actions(order->lh_action, order->rh_action, order->type);
2748  }
2749  }
2750 
2751  for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2752  action_t *action = (action_t *) gIter->data;
2753 
2754  update_colo_start_chain(action, data_set);
2755  }
2756 
2757  crm_trace("Ordering probes");
2758  order_probes(data_set);
2759 
2760  crm_trace("Updating %d actions", g_list_length(data_set->actions));
2761  for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2762  action_t *action = (action_t *) gIter->data;
2763 
2764  update_action(action, data_set);
2765  }
2766 
2767  // Check for invalid orderings
2768  for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2769  pe_action_t *action = (pe_action_t *) gIter->data;
2770  pe_action_wrapper_t *input = NULL;
2771 
2772  for (GList *input_iter = action->actions_before;
2773  input_iter != NULL; input_iter = input_iter->next) {
2774 
2775  input = (pe_action_wrapper_t *) input_iter->data;
2776  if (pcmk__ordering_is_invalid(action, input)) {
2777  input->type = pe_order_none;
2778  }
2779  }
2780  }
2781 
2782  LogNodeActions(data_set, FALSE);
2783  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2784  resource_t *rsc = (resource_t *) gIter->data;
2785 
2786  LogActions(rsc, data_set, FALSE);
2787  }
2788  return TRUE;
2789 }
2790 
2791 static int transition_id = -1;
2792 
2799 void
2800 pcmk__log_transition_summary(const char *filename)
2801 {
2802  if (was_processing_error) {
2803  crm_err("Calculated transition %d (with errors), saving inputs in %s",
2804  transition_id, filename);
2805 
2806  } else if (was_processing_warning) {
2807  crm_warn("Calculated transition %d (with warnings), saving inputs in %s",
2808  transition_id, filename);
2809 
2810  } else {
2811  crm_notice("Calculated transition %d, saving inputs in %s",
2812  transition_id, filename);
2813  }
2814  if (crm_config_error) {
2815  crm_notice("Configuration errors found during scheduler processing,"
2816  " please run \"crm_verify -L\" to identify issues");
2817  }
2818 }
2819 
2820 /*
2821  * Create a dependency graph to send to the transitioner (via the controller)
2822  */
2823 gboolean
2825 {
2826  GListPtr gIter = NULL;
2827  const char *value = NULL;
2828 
2829  transition_id++;
2830  crm_trace("Creating transition graph %d.", transition_id);
2831 
2832  data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH);
2833 
2834  value = pe_pref(data_set->config_hash, "cluster-delay");
2835  crm_xml_add(data_set->graph, "cluster-delay", value);
2836 
2837  value = pe_pref(data_set->config_hash, "stonith-timeout");
2838  crm_xml_add(data_set->graph, "stonith-timeout", value);
2839 
2840  crm_xml_add(data_set->graph, "failed-stop-offset", "INFINITY");
2841 
2842  if (is_set(data_set->flags, pe_flag_start_failure_fatal)) {
2843  crm_xml_add(data_set->graph, "failed-start-offset", "INFINITY");
2844  } else {
2845  crm_xml_add(data_set->graph, "failed-start-offset", "1");
2846  }
2847 
2848  value = pe_pref(data_set->config_hash, "batch-limit");
2849  crm_xml_add(data_set->graph, "batch-limit", value);
2850 
2851  crm_xml_add_int(data_set->graph, "transition_id", transition_id);
2852 
2853  value = pe_pref(data_set->config_hash, "migration-limit");
2854  if (crm_int_helper(value, NULL) > 0) {
2855  crm_xml_add(data_set->graph, "migration-limit", value);
2856  }
2857 
2858  if (data_set->recheck_by > 0) {
2859  char *recheck_epoch = NULL;
2860 
2861  recheck_epoch = crm_strdup_printf("%llu",
2862  (long long) data_set->recheck_by);
2863  crm_xml_add(data_set->graph, "recheck-by", recheck_epoch);
2864  free(recheck_epoch);
2865  }
2866 
2867 /* errors...
2868  slist_iter(action, action_t, action_list, lpc,
2869  if(action->optional == FALSE && action->runnable == FALSE) {
2870  print_action("Ignoring", action, TRUE);
2871  }
2872  );
2873 */
2874 
2875  /* The following code will de-duplicate action inputs, so nothing past this
2876  * should rely on the action input type flags retaining their original
2877  * values.
2878  */
2879 
2880  gIter = data_set->resources;
2881  for (; gIter != NULL; gIter = gIter->next) {
2882  resource_t *rsc = (resource_t *) gIter->data;
2883 
2884  pe_rsc_trace(rsc, "processing actions for rsc=%s", rsc->id);
2885  rsc->cmds->expand(rsc, data_set);
2886  }
2887 
2888  crm_log_xml_trace(data_set->graph, "created resource-driven action list");
2889 
2890  /* pseudo action to distribute list of nodes with maintenance state update */
2891  add_maintenance_update(data_set);
2892 
2893  /* catch any non-resource specific actions */
2894  crm_trace("processing non-resource actions");
2895 
2896  gIter = data_set->actions;
2897  for (; gIter != NULL; gIter = gIter->next) {
2898  action_t *action = (action_t *) gIter->data;
2899 
2900  if (action->rsc
2901  && action->node
2902  && action->node->details->shutdown
2903  && is_not_set(action->rsc->flags, pe_rsc_maintenance)
2904  && is_not_set(action->flags, pe_action_optional)
2905  && is_not_set(action->flags, pe_action_runnable)
2906  && crm_str_eq(action->task, RSC_STOP, TRUE)
2907  ) {
2908  /* Eventually we should just ignore the 'fence' case
2909  * But for now it's the best way to detect (in CTS) when
2910  * CIB resource updates are being lost
2911  */
2912  if (is_set(data_set->flags, pe_flag_have_quorum)
2913  || data_set->no_quorum_policy == no_quorum_ignore) {
2914  crm_crit("Cannot %s node '%s' because of %s:%s%s (%s)",
2915  action->node->details->unclean ? "fence" : "shut down",
2916  action->node->details->uname, action->rsc->id,
2917  is_not_set(action->rsc->flags, pe_rsc_managed) ? " unmanaged" : " blocked",
2918  is_set(action->rsc->flags, pe_rsc_failed) ? " failed" : "",
2919  action->uuid);
2920  }
2921  }
2922 
2923  graph_element_from_action(action, data_set);
2924  }
2925 
2926  crm_log_xml_trace(data_set->graph, "created generic action list");
2927  crm_trace("Created transition graph %d.", transition_id);
2928 
2929  return TRUE;
2930 }
2931 
2932 void
2933 LogNodeActions(pe_working_set_t * data_set, gboolean terminal)
2934 {
2935  GListPtr gIter = NULL;
2936 
2937  for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2938  char *node_name = NULL;
2939  char *task = NULL;
2940  action_t *action = (action_t *) gIter->data;
2941 
2942  if (action->rsc != NULL) {
2943  continue;
2944  } else if (is_set(action->flags, pe_action_optional)) {
2945  continue;
2946  }
2947 
2948  if (pe__is_guest_node(action->node)) {
2949  node_name = crm_strdup_printf("%s (resource: %s)", action->node->details->uname, action->node->details->remote_rsc->container->id);
2950  } else if(action->node) {
2951  node_name = crm_strdup_printf("%s", action->node->details->uname);
2952  }
2953 
2954 
2955  if (safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
2956  task = strdup("Shutdown");
2957  } else if (safe_str_eq(action->task, CRM_OP_FENCE)) {
2958  const char *op = g_hash_table_lookup(action->meta, "stonith_action");
2959  task = crm_strdup_printf("Fence (%s)", op);
2960  }
2961 
2962  if(task == NULL) {
2963  /* Nothing to report */
2964  } else if(terminal && action->reason) {
2965  printf(" * %s %s '%s'\n", task, node_name, action->reason);
2966  } else if(terminal) {
2967  printf(" * %s %s\n", task, node_name);
2968  } else if(action->reason) {
2969  crm_notice(" * %s %s '%s'\n", task, node_name, action->reason);
2970  } else {
2971  crm_notice(" * %s %s\n", task, node_name);
2972  }
2973 
2974  free(node_name);
2975  free(task);
2976  }
2977 }
pe_action_flags
pe_action_flags
Definition: pe_types.h:265
pe_resource_s::priority
int priority
Definition: pe_types.h:311
pe_rsc_orphan
#define pe_rsc_orphan
Definition: pe_types.h:224
pe_native
Definition: pe_types.h:37
RSC_DIGEST_RESTART
Definition: internal.h:320
start_key
#define start_key(rsc)
Definition: internal.h:235
pe_resource_s::stickiness
int stickiness
Definition: pe_types.h:312
clone_rsc_location
void clone_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
Definition: pcmk_sched_clone.c:1214
clone_rsc_colocation_rh
void clone_rsc_colocation_rh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
Definition: pcmk_sched_clone.c:1029
resource_class_alloc_functions
resource_alloc_functions_t resource_class_alloc_functions[]
Definition: pcmk_sched_allocate.c:59
GListPtr
GList * GListPtr
Definition: crm.h:214
pe_working_set_s::input
xmlNode * input
Definition: pe_types.h:118
INFINITY
#define INFINITY
Definition: crm.h:95
CRM_TRACE_INIT_DATA
CRM_TRACE_INIT_DATA(pe_allocate)
order_actions
gboolean order_actions(action_t *lh_action, action_t *rh_action, enum pe_ordering order)
Definition: utils.c:1778
group_create_actions
void group_create_actions(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_group.c:79
resource_alloc_functions_s::rsc_location
void(* rsc_location)(pe_resource_t *, pe__location_t *)
Definition: pcmki_sched_allocate.h:33
group_merge_weights
GHashTable * group_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
Definition: pcmk_sched_group.c:483
stage3
gboolean stage3(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:1035
native_expand
void native_expand(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:2216
sort_nodes_by_weight
GList * sort_nodes_by_weight(GList *nodes, pe_node_t *active_node, pe_working_set_t *data_set)
Definition: pcmk_sched_utils.c:185
pe_resource_s::exclusive_discover
gboolean exclusive_discover
Definition: pe_types.h:323
pe_cancel_op
pe_action_t * pe_cancel_op(pe_resource_t *rsc, const char *name, guint interval_ms, pe_node_t *node, pe_working_set_t *data_set)
Definition: pcmk_sched_utils.c:421
crm_str_eq
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:224
pcmk__bundle_action_flags
enum pe_action_flags pcmk__bundle_action_flags(pe_action_t *action, pe_node_t *node)
Definition: pcmk_sched_bundle.c:542
pe_resource_s::variant
enum pe_obj_types variant
Definition: pe_types.h:301
XML_LRM_TAG_RESOURCE
#define XML_LRM_TAG_RESOURCE
Definition: msg_xml.h:227
remote_state_failed
Definition: pcmk_sched_allocate.c:36
RSC_PROMOTE
#define RSC_PROMOTE
Definition: crm.h:202
group_action_flags
enum pe_action_flags group_action_flags(action_t *action, node_t *node)
Definition: pcmk_sched_group.c:372
find_rsc_op_entry
xmlNode * find_rsc_op_entry(resource_t *rsc, const char *key)
Definition: utils.c:1261
remote_state_unknown
Definition: pcmk_sched_allocate.c:33
CRM_OP_CLEAR_FAILCOUNT
#define CRM_OP_CLEAR_FAILCOUNT
Definition: crm.h:151
pe_node_shared_s::rsc_discovery_enabled
gboolean rsc_discovery_enabled
Definition: pe_types.h:200
RSC_DEMOTE
#define RSC_DEMOTE
Definition: crm.h:204
pe__location_constraint_s::rsc_lh
pe_resource_t * rsc_lh
Definition: internal.h:30
pe_working_set_s::resources
GListPtr resources
Definition: pe_types.h:139
pe_action_s::actions_before
GListPtr actions_before
Definition: pe_types.h:410
op_digest_cache_s::rc
enum rsc_digest_cmp_val rc
Definition: internal.h:329
pe_resource_s::actions
GListPtr actions
Definition: pe_types.h:330
pe_action_tracking
Definition: pe_types.h:286
XML_CIB_TAG_CONSTRAINTS
#define XML_CIB_TAG_CONSTRAINTS
Definition: msg_xml.h:143
pacemaker-internal.h
pe_working_set_s::max_valid_nodes
int max_valid_nodes
Definition: pe_types.h:152
pe_resource_s::next_role
enum rsc_role_e next_role
Definition: pe_types.h:342
op_digest_cache_s::digest_secure_calc
char * digest_secure_calc
Definition: internal.h:334
flags
uint64_t flags
Definition: remote.c:148
pe_working_set_s::nodes
GListPtr nodes
Definition: pe_types.h:138
msg_xml.h
RSC_ROLE_STOPPED
Definition: common.h:88
node_score_yellow
int node_score_yellow
Definition: utils.c:65
dump_node_capacity
void dump_node_capacity(int level, const char *comment, node_t *node)
Definition: utils.c:367
pe_working_set_s::recheck_by
time_t recheck_by
Definition: pe_types.h:168
action_demote
Definition: common.h:68
stage7
gboolean stage7(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:2714
data
char data[0]
Definition: internal.h:90
pe_node_shared_s::remote_rsc
pe_resource_t * remote_rsc
Definition: pe_types.h:207
LOG_TRACE
#define LOG_TRACE
Definition: logging.h:26
pe_rsc_debug
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:18
sched_shutdown_op
pe_action_t * sched_shutdown_op(pe_node_t *node, pe_working_set_t *data_set)
Definition: pcmk_sched_utils.c:456
stage5
gboolean stage5(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:1297
pe_order_runnable_left
Definition: pe_types.h:458
create_xml_node
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1970
pe_resource_s::children
GListPtr children
Definition: pe_types.h:348
pe_resource_s::id
char * id
Definition: pe_types.h:292
pe_resource_s::allocated_to
pe_node_t * allocated_to
Definition: pe_types.h:334
resource_alloc_functions_s::create_actions
void(* create_actions)(resource_t *, pe_working_set_t *)
Definition: pcmki_sched_allocate.h:24
stop_action
#define stop_action(rsc, node, optional)
Definition: internal.h:230
stonith_constraints
gboolean stonith_constraints(node_t *node, action_t *stonith_op, pe_working_set_t *data_set)
Definition: pcmk_sched_graph.c:762
pe_fc_fillers
Definition: internal.h:150
pe_flag_sanitized
#define pe_flag_sanitized
Definition: pe_types.h:111
crm_crit
#define crm_crit(fmt, args...)
Definition: logging.h:240
stop_rsc
Definition: common.h:60
pe__order_constraint_s::lh_action
action_t * lh_action
Definition: internal.h:42
pe_fc_effective
Definition: internal.h:149
XML_CIB_TAG_STATE
#define XML_CIB_TAG_STATE
Definition: msg_xml.h:158
pe_weights_init
Definition: pcmki_scheduler.h:34
was_processing_warning
gboolean was_processing_warning
Definition: common.c:19
crm_config_error
gboolean crm_config_error
Definition: utils.c:59
RSC_MIGRATED
#define RSC_MIGRATED
Definition: crm.h:194
CRM_CHECK
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:157
pe_flag_have_status
#define pe_flag_have_status
Definition: pe_types.h:107
dump_node_scores
#define dump_node_scores(level, rsc, text, nodes)
Definition: internal.h:206
pe_node_s::weight
int weight
Definition: pe_types.h:217
crm_parse_ms
guint crm_parse_ms(const char *text)
Definition: strings.c:147
pe_action_pseudo
Definition: pe_types.h:266
clear_bit
#define clear_bit(word, bit)
Definition: crm_internal.h:168
pe_pref
const char * pe_pref(GHashTable *options, const char *name)
Definition: common.c:187
XML_CIB_TAG_LRM
#define XML_CIB_TAG_LRM
Definition: msg_xml.h:225
graph_element_from_action
void graph_element_from_action(action_t *action, pe_working_set_t *data_set)
Definition: pcmk_sched_graph.c:1754
pe_node_s::details
struct pe_node_shared_s * details
Definition: pe_types.h:220
custom_action
action_t * custom_action(resource_t *rsc, char *key, const char *task, node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Definition: utils.c:455
crm_notice
#define crm_notice(fmt, args...)
Definition: logging.h:243
stage4
gboolean stage4(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:1053
pcmk__bundle_internal_constraints
void pcmk__bundle_internal_constraints(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_bundle.c:244
pe_node_shared_s::id
const char * id
Definition: pe_types.h:185
pe_action_s::actions_after
GListPtr actions_after
Definition: pe_types.h:411
clone_create_actions
void clone_create_actions(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_clone.c:805
clone_create_probe
gboolean clone_create_probe(resource_t *rsc, node_t *node, action_t *complete, gboolean force, pe_working_set_t *data_set)
Definition: pcmk_sched_clone.c:1383
type
enum crm_ais_msg_types type
Definition: internal.h:83
crm_err
#define crm_err(fmt, args...)
Definition: logging.h:241
pe_weights_forward
Definition: pcmki_scheduler.h:35
pe_can_fence
bool pe_can_fence(pe_working_set_t *data_set, node_t *node)
Definition: utils.c:89
pcmk__log_transition_summary
void pcmk__log_transition_summary(const char *filename)
Definition: pcmk_sched_allocate.c:2800
complex_set_cmds
void complex_set_cmds(resource_t *rsc)
Definition: pcmk_sched_allocate.c:767
RSC_DIGEST_MATCH
Definition: internal.h:318
clone_action_flags
enum pe_action_flags clone_action_flags(action_t *action, node_t *node)
Definition: pcmk_sched_clone.c:1208
pe_flag_stop_action_orphans
#define pe_flag_stop_action_orphans
Definition: pe_types.h:99
crm_trace
#define crm_trace(fmt, args...)
Definition: logging.h:247
pe_resource_s::meta
GHashTable * meta
Definition: pe_types.h:344
CRM_OP_PROBED
#define CRM_OP_PROBED
Definition: crm.h:149
safe_str_eq
#define safe_str_eq(a, b)
Definition: util.h:61
pe_warn
#define pe_warn(fmt...)
Definition: internal.h:22
text2task
enum action_tasks text2task(const char *task)
Definition: common.c:230
uber_parent
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:764
pe__is_guest_or_remote_node
gboolean pe__is_guest_or_remote_node(pe_node_t *node)
Definition: remote.c:58
crm_warn
#define crm_warn(fmt, args...)
Definition: logging.h:242
pe__order_constraint_s::rh_action
action_t * rh_action
Definition: internal.h:47
native_rsc_location
void native_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
Definition: pcmk_sched_native.c:2151
trigger_unfencing
void trigger_unfencing(resource_t *rsc, node_t *node, const char *reason, action_t *dependency, pe_working_set_t *data_set)
Definition: utils.c:2371
pe_action_set_flag_reason
void pe_action_set_flag_reason(const char *function, long line, pe_action_t *action, pe_action_t *reason, const char *text, enum pe_action_flags flags, bool overwrite)
Definition: utils.c:2441
pe_action_s::flags
enum pe_action_flags flags
Definition: pe_types.h:382
op_digest_cache_s::params_all
xmlNode * params_all
Definition: internal.h:330
pe_group
Definition: pe_types.h:38
group_color
node_t * group_color(resource_t *rsc, node_t *preferred, pe_working_set_t *data_set)
Definition: pcmk_sched_group.c:18
pe_resource_s::running_on
GListPtr running_on
Definition: pe_types.h:337
pe_resource_s::partial_migration_target
pe_node_t * partial_migration_target
Definition: pe_types.h:335
group_internal_constraints
void group_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_group.c:162
remote_connection_state
remote_connection_state
Definition: pcmk_sched_allocate.c:32
pe_action_wrapper_s
Definition: pe_types.h:489
pe_get_failcount
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
xml.h
Wrappers for and extensions to libxml2.
pe_node_shared_s::is_dc
gboolean is_dc
Definition: pe_types.h:198
crm_is_true
gboolean crm_is_true(const char *s)
Definition: strings.c:176
CRM_OP_SHUTDOWN
#define CRM_OP_SHUTDOWN
Definition: crm.h:140
pe_working_set_s::placement_strategy
const char * placement_strategy
Definition: pe_types.h:125
xml_has_children
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:3316
XML_CIB_TAG_STATUS
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:139
pcmk__bundle_create_actions
void pcmk__bundle_create_actions(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_bundle.c:195
pe_node_shared_s::remote_requires_reset
gboolean remote_requires_reset
Definition: pe_types.h:201
set_bit
#define set_bit(word, bit)
Definition: crm_internal.h:167
native_merge_weights
GHashTable * native_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
Definition: pcmk_sched_native.c:297
native_rsc_colocation_lh
void native_rsc_colocation_lh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:1575
native_update_actions
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)
Definition: pcmk_sched_native.c:1996
clone_color
node_t * clone_color(resource_t *rsc, node_t *preferred, pe_working_set_t *data_set)
Definition: pcmk_sched_clone.c:591
pcmk__bundle_color
pe_node_t * pcmk__bundle_color(pe_resource_t *rsc, pe_node_t *preferred, pe_working_set_t *data_set)
Definition: pcmk_sched_bundle.c:101
custom_action_order
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)
Definition: pcmk_sched_constraints.c:1564
pcmk__bundle_merge_weights
GHashTable * pcmk__bundle_merge_weights(pe_resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
Definition: pcmk_sched_bundle.c:1046
XML_ATTR_ID
#define XML_ATTR_ID
Definition: msg_xml.h:96
pe_action_s::uuid
char * uuid
Definition: pe_types.h:378
get_object_root
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
Definition: cib_utils.c:144
CRM_OP_REPROBE
#define CRM_OP_REPROBE
Definition: crm.h:150
ID
#define ID(x)
Definition: msg_xml.h:415
pe_order_same_node
Definition: pe_types.h:473
RSC_START
#define RSC_START
Definition: crm.h:196
pcmk__bundle_append_meta
void pcmk__bundle_append_meta(pe_resource_t *rsc, xmlNode *xml)
Definition: pcmk_sched_bundle.c:1041
parse_op_key
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: operations.c:47
pe_order_load
Definition: pe_types.h:479
pe_fence_node
void pe_fence_node(pe_working_set_t *data_set, node_t *node, const char *reason)
Schedule a fence action for a node.
Definition: unpack.c:78
pe_err
#define pe_err(fmt...)
Definition: internal.h:21
RSC_ROLE_SLAVE
Definition: common.h:90
pe_action_s
Definition: pe_types.h:369
rsc2node_new
pe__location_t * rsc2node_new(const char *id, pe_resource_t *rsc, int weight, const char *discovery_mode, pe_node_t *node, pe_working_set_t *data_set)
Definition: pcmk_sched_utils.c:14
pe_node_shared_s::shutdown
gboolean shutdown
Definition: pe_types.h:196
rsc_action_digest_cmp
op_digest_cache_t * rsc_action_digest_cmp(resource_t *rsc, xmlNode *xml_op, node_t *node, pe_working_set_t *data_set)
Definition: utils.c:2050
pe_resource_s::xml
xmlNode * xml
Definition: pe_types.h:294
pe_check_last_failure
Definition: pe_types.h:176
crm_info
#define crm_info(fmt, args...)
Definition: logging.h:244
resource_alloc_functions_s::create_probe
gboolean(* create_probe)(resource_t *, node_t *, action_t *, gboolean, pe_working_set_t *)
Definition: pcmki_sched_allocate.h:25
pe__order_constraint_s::id
int id
Definition: internal.h:37
pe_order_anti_colocation
Definition: pe_types.h:481
pe__order_constraint_s::rh_action_task
char * rh_action_task
Definition: internal.h:48
clone_expand
void clone_expand(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_clone.c:1230
remote_state_alive
Definition: pcmk_sched_allocate.c:34
stage6
gboolean stage6(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:1526
pe__is_remote_node
gboolean pe__is_remote_node(pe_node_t *node)
Definition: remote.c:36
CRMD_ACTION_MIGRATED
#define CRMD_ACTION_MIGRATED
Definition: crm.h:169
XML_AGENT_ATTR_CLASS
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:229
CRM_OP_FMT
#define CRM_OP_FMT
Definition: crm_internal.h:133
pe__order_constraint_s::rh_rsc
resource_t * rh_rsc
Definition: internal.h:46
XML_LRM_ATTR_TASK
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:260
op_digest_cache_s::params_restart
xmlNode * params_restart
Definition: internal.h:332
DeleteRsc
gboolean DeleteRsc(resource_t *rsc, node_t *node, gboolean optional, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:2731
pe_working_set_s::config_hash
GHashTable * config_hash
Definition: pe_types.h:132
cluster_status
gboolean cluster_status(pe_working_set_t *data_set)
Definition: status.c:68
crm_strdup_printf
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
remote_state_stopped
Definition: pcmk_sched_allocate.c:37
CRMD_ACTION_START
#define CRMD_ACTION_START
Definition: crm.h:171
RSC_ROLE_UNKNOWN
Definition: common.h:87
DIMOF
#define DIMOF(a)
Definition: crm.h:57
crm_debug
#define crm_debug(fmt, args...)
Definition: logging.h:246
CRMD_ACTION_MIGRATE
#define CRMD_ACTION_MIGRATE
Definition: crm.h:168
group_append_meta
void group_append_meta(resource_t *rsc, xmlNode *xml)
Definition: pcmk_sched_group.c:515
pe_flag_stdout
#define pe_flag_stdout
Definition: pe_types.h:112
pe_action_s::node
pe_node_t * node
Definition: pe_types.h:374
show_utilization
gboolean show_utilization
Definition: pcmk_sched_messages.c:27
resource_object_functions_s::state
enum rsc_role_e(* state)(const pe_resource_t *, gboolean)
Definition: pe_types.h:52
pe__foreach_param_check
void pe__foreach_param_check(pe_working_set_t *data_set, void(*cb)(pe_resource_t *, pe_node_t *, xmlNode *, enum pe_check_parameters, pe_working_set_t *))
Definition: remote.c:241
ReloadRsc
void ReloadRsc(resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:3252
CRMD_ACTION_STOP
#define CRMD_ACTION_STOP
Definition: crm.h:174
pe_order_optional
Definition: pe_types.h:448
remote_state_resting
Definition: pcmk_sched_allocate.c:35
native_create_actions
void native_create_actions(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:1119
stage2
gboolean stage2(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:993
sort_op_by_callid
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
Definition: utils.c:1610
pe__order_constraint_s::lh_action_task
char * lh_action_task
Definition: internal.h:43
pe_node_s::rsc_discover_mode
int rsc_discover_mode
Definition: pe_types.h:221
pe_action_optional
Definition: pe_types.h:268
stage0
gboolean stage0(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:898
pe_resource_s::partial_migration_source
pe_node_t * partial_migration_source
Definition: pe_types.h:336
pe_order_implies_first
Definition: pe_types.h:451
resource_alloc_functions_s::expand
void(* expand)(resource_t *, pe_working_set_t *)
Definition: pcmki_sched_allocate.h:42
native_rsc_colocation_rh
void native_rsc_colocation_rh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:1785
pe_working_set_s::ordering_constraints
GListPtr ordering_constraints
Definition: pe_types.h:141
RSC_STOP
#define RSC_STOP
Definition: crm.h:199
crm_log_xml_trace
#define crm_log_xml_trace(xml, text)
Definition: logging.h:255
crm_xml_add
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:313
XML_LRM_TAG_RESOURCES
#define XML_LRM_TAG_RESOURCES
Definition: msg_xml.h:226
XML_ATTR_TE_NOWAIT
#define XML_ATTR_TE_NOWAIT
Definition: msg_xml.h:360
pe_working_set_s
Definition: pe_types.h:117
XML_LRM_TAG_RSC_OP
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:228
pe__shutdown_requested
bool pe__shutdown_requested(pe_node_t *node)
Definition: utils.c:2529
crm_element_value
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:519
pe_action_clear
Definition: pe_types.h:277
RSC_DIGEST_ALL
Definition: internal.h:322
pe_action_s::reason
char * reason
Definition: pe_types.h:380
no_quorum_ignore
Definition: pe_types.h:63
crm_log_xml_info
#define crm_log_xml_info(xml, text)
Definition: logging.h:253
pe_set_action_bit
#define pe_set_action_bit(action, bit)
Definition: internal.h:25
resource_alloc_functions_s
Definition: pcmki_sched_allocate.h:20
update_colo_start_chain
void update_colo_start_chain(pe_action_t *action, pe_working_set_t *data_set)
Definition: pcmk_sched_graph.c:472
pcmk__multi_update_actions
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)
Definition: pcmk_sched_bundle.c:799
pe_working_set_s::placement_constraints
GListPtr placement_constraints
Definition: pe_types.h:140
pe_action_s::id
int id
Definition: pe_types.h:370
update_action_flags
gboolean update_action_flags(action_t *action, enum pe_action_flags flags, const char *source, int line)
Definition: pcmk_sched_allocate.c:119
can_run_resources
gboolean can_run_resources(const node_t *node)
Definition: pcmk_sched_utils.c:62
utilization_log_level
int utilization_log_level
Definition: pcmk_sched_messages.c:28
group_rsc_colocation_lh
void group_rsc_colocation_lh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
Definition: pcmk_sched_group.c:282
add_hash_param
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:412
pe__order_constraint_s::lh_rsc
resource_t * lh_rsc
Definition: internal.h:41
pe_resource_s::container
pe_resource_t * container
Definition: pe_types.h:351
CRM_OP_FENCE
#define CRM_OP_FENCE
Definition: crm.h:141
pcmk__ordering_is_invalid
bool pcmk__ordering_is_invalid(pe_action_t *action, pe_action_wrapper_t *input)
Definition: pcmk_sched_graph.c:1669
pe_fence_op
action_t * pe_fence_op(node_t *node, const char *op, bool optional, const char *reason, pe_working_set_t *data_set)
Definition: utils.c:2289
pe_working_set_s::actions
GListPtr actions
Definition: pe_types.h:145
pe_rsc_unique
#define pe_rsc_unique
Definition: pe_types.h:230
crm_parse_int
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:114
pe_order_implies_then
Definition: pe_types.h:452
resource_location
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1566
cib.h
Cluster Configuration.
find_actions
GListPtr find_actions(GListPtr input, const char *key, const node_t *on_node)
Definition: utils.c:1429
RSC_STATUS
#define RSC_STATUS
Definition: crm.h:210
find_compatible_child
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)
Definition: pcmk_sched_clone.c:983
add_maintenance_update
void add_maintenance_update(pe_working_set_t *data_set)
Definition: pcmk_sched_graph.c:924
pe_action_reschedule
Definition: pe_types.h:285
pe_resource_s::clone_name
char * clone_name
Definition: pe_types.h:293
pe_clear_action_bit
#define pe_clear_action_bit(action, bit)
Definition: internal.h:26
safe_str_neq
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:161
pe_order_none
Definition: pe_types.h:447
pe_action_s::rsc
pe_resource_t * rsc
Definition: pe_types.h:373
pe_resource_s::parent
pe_resource_t * parent
Definition: pe_types.h:299
crm_str
#define crm_str(x)
Definition: logging.h:267
crm_xml_add_int
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:421
action_promote
Definition: common.h:66
char2score
int char2score(const char *score)
Definition: utils.c:199
pcmk__bundle_rsc_location
void pcmk__bundle_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
Definition: pcmk_sched_bundle.c:852
XML_LRM_ATTR_RESTART_DIGEST
#define XML_LRM_ATTR_RESTART_DIGEST
Definition: msg_xml.h:276
pe_flag_concurrent_fencing
#define pe_flag_concurrent_fencing
Definition: pe_types.h:96
clone_append_meta
void clone_append_meta(resource_t *rsc, xmlNode *xml)
Definition: pcmk_sched_clone.c:1423
native_internal_constraints
void native_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:1362
group_rsc_colocation_rh
void group_rsc_colocation_rh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
Definition: pcmk_sched_group.c:324
pe_resource_s::flags
unsigned long long flags
Definition: pe_types.h:319
pe__free_param_checks
void pe__free_param_checks(pe_working_set_t *data_set)
Definition: remote.c:256
pe_resource_s::remote_reconnect_ms
guint remote_reconnect_ms
Definition: pe_types.h:316
group_update_actions
enum pe_graph_flags group_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)
Definition: pcmk_sched_group.c:413
probe_resources
gboolean probe_resources(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:922
unpack_constraints
gboolean unpack_constraints(xmlNode *xml_constraints, pe_working_set_t *data_set)
Definition: pcmk_sched_constraints.c:71
pe_check_parameters
pe_check_parameters
Definition: pe_types.h:172
pe_rsc_trace
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:19
XML_LRM_ATTR_SECURE_DIGEST
#define XML_LRM_ATTR_SECURE_DIGEST
Definition: msg_xml.h:277
XML_AGENT_ATTR_PROVIDER
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:230
pe_working_set_s::graph
xmlNode * graph
Definition: pe_types.h:157
XML_ATTR_TRANSITION_MAGIC
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:357
pe_order_preserve
Definition: pe_types.h:483
pe_node_shared_s::remote_was_fenced
gboolean remote_was_fenced
Definition: pe_types.h:202
rsc_merge_weights
GHashTable * rsc_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
Definition: pcmk_sched_native.c:304
pe_flag_startup_probes
#define pe_flag_startup_probes
Definition: pe_types.h:106
crm_ends_with
gboolean crm_ends_with(const char *s, const char *match)
Definition: strings.c:313
pe__add_param_check
void pe__add_param_check(xmlNode *rsc_op, pe_resource_t *rsc, pe_node_t *node, enum pe_check_parameters, pe_working_set_t *data_set)
Definition: remote.c:215
resource_alloc_functions_s::internal_constraints
void(* internal_constraints)(resource_t *, pe_working_set_t *)
Definition: pcmki_sched_allocate.h:26
CRM_ASSERT
#define CRM_ASSERT(expr)
Definition: results.h:42
find_xml_node
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:1758
pe__bundle_needs_remote_name
bool pe__bundle_needs_remote_name(pe_resource_t *rsc)
Definition: bundle.c:955
pe_check_active
Definition: pe_types.h:181
pe__resource_actions
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
Definition: utils.c:1518
pe_rsc_start_pending
#define pe_rsc_start_pending
Definition: pe_types.h:243
native_action_flags
enum pe_action_flags native_action_flags(action_t *action, node_t *node)
Definition: pcmk_sched_native.c:1917
LogNodeActions
void LogNodeActions(pe_working_set_t *data_set, gboolean terminal)
Definition: pcmk_sched_allocate.c:2933
pe_action_runnable
Definition: pe_types.h:267
start_rsc
Definition: common.h:62
pe_order_apply_first_non_migratable
Definition: pe_types.h:449
XML_RSC_ATTR_INTERLEAVE
#define XML_RSC_ATTR_INTERLEAVE
Definition: msg_xml.h:185
pe_action_dangle
Definition: pe_types.h:278
pe_flag_start_failure_fatal
#define pe_flag_start_failure_fatal
Definition: pe_types.h:102
pe__clear_failcount
pe_action_t * pe__clear_failcount(pe_resource_t *rsc, pe_node_t *node, const char *reason, pe_working_set_t *data_set)
Schedule a controller operation to clear a fail count.
Definition: failcounts.c:360
pe_resource_s::migration_threshold
int migration_threshold
Definition: pe_types.h:315
group_expand
void group_expand(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_group.c:468
pe_rsc_managed
#define pe_rsc_managed
Definition: pe_types.h:225
pcmk__bundle_rsc_colocation_rh
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)
Definition: pcmk_sched_bundle.c:463
pe_action_wrapper_s::action
pe_action_t * action
Definition: pe_types.h:492
XML_LRM_ATTR_INTERVAL_MS
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:258
set_alloc_actions
void set_alloc_actions(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:781
group_rsc_location
void group_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
Definition: pcmk_sched_group.c:439
calculate_active_ops
void calculate_active_ops(GList *sorted_op_list, int *start_index, int *stop_index)
Definition: unpack.c:2143
node_score_red
int node_score_red
Definition: utils.c:63
clone_merge_weights
GHashTable * clone_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
Definition: pcmk_sched_clone.c:1469
clone_rsc_colocation_lh
void clone_rsc_colocation_lh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
Definition: pcmk_sched_clone.c:1017
pe_node_attribute_raw
const char * pe_node_attribute_raw(pe_node_t *node, const char *name)
Definition: common.c:468
XML_ATTR_TYPE
#define XML_ATTR_TYPE
Definition: msg_xml.h:99
RSC_DIGEST_UNKNOWN
Definition: internal.h:325
native_color
node_t * native_color(resource_t *rsc, node_t *preferred, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:437
pe_flag_stonith_enabled
#define pe_flag_stonith_enabled
Definition: pe_types.h:93
pe_node_shared_s::maintenance
gboolean maintenance
Definition: pe_types.h:199
merge_weights
int merge_weights(int w1, int w2)
Definition: common.c:375
pe__is_guest_node
gboolean pe__is_guest_node(pe_node_t *node)
Definition: remote.c:47
pe_resource_s
Definition: pe_types.h:291
stage8
gboolean stage8(pe_working_set_t *data_set)
Definition: pcmk_sched_allocate.c:2824
pe_resource_s::allowed_nodes
GHashTable * allowed_nodes
Definition: pe_types.h:339
pe_working_set_s::flags
unsigned long long flags
Definition: pe_types.h:127
pe_node_shared_s::unclean
gboolean unclean
Definition: pe_types.h:194
pe__location_constraint_s
Definition: internal.h:28
crm_starts_with
bool crm_starts_with(const char *str, const char *prefix)
Check whether a string starts with a certain sequence.
Definition: strings.c:263
was_processing_error
gboolean was_processing_error
Definition: common.c:18
native_create_probe
gboolean native_create_probe(resource_t *rsc, node_t *node, action_t *complete, gboolean force, pe_working_set_t *data_set)
Definition: pcmk_sched_native.c:2761
pe_working_set_s::no_quorum_policy
enum pe_quorum_policy no_quorum_policy
Definition: pe_types.h:130
pe_flag_symmetric_cluster
#define pe_flag_symmetric_cluster
Definition: pe_types.h:90
generate_op_key
char * generate_op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key.
Definition: operations.c:39
update_action
gboolean update_action(pe_action_t *action, pe_working_set_t *data_set)
Definition: pcmk_sched_graph.c:512
XML_LRM_ATTR_CALLID
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:272
pcmk__bundle_expand
void pcmk__bundle_expand(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_bundle.c:884
pe__order_constraint_s
Definition: internal.h:36
pe_node_shared_s::type
enum node_type type
Definition: pe_types.h:187
pe_node_shared_s::online
gboolean online
Definition: pe_types.h:190
pe_action_s::task
char * task
Definition: pe_types.h:377
pe_node_shared_s::uname
const char * uname
Definition: pe_types.h:186
LogActions
void LogActions(resource_t *rsc, pe_working_set_t *data_set, gboolean terminal)
Definition: pcmk_sched_native.c:2364
pe_resource_s::cmds
resource_alloc_functions_t * cmds
Definition: pe_types.h:304
pe_discover_exclusive
Definition: pe_types.h:442
native_append_meta
void native_append_meta(resource_t *rsc, xmlNode *xml)
Definition: pcmk_sched_native.c:3299
pe_flag_stop_rsc_orphans
#define pe_flag_stop_rsc_orphans
Definition: pe_types.h:98
pcmk__bundle_create_probe
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)
Definition: pcmk_sched_bundle.c:947
pe_resource_s::is_remote_node
gboolean is_remote_node
Definition: pe_types.h:322
crm_internal.h
action_tasks
action_tasks
Definition: common.h:57
stop_key
#define stop_key(rsc)
Definition: internal.h:229
pe_node_s
Definition: pe_types.h:216
pe__order_constraint_s::type
enum pe_ordering type
Definition: internal.h:38
monitor_rsc
Definition: common.h:59
pe_flag_have_quorum
#define pe_flag_have_quorum
Definition: pe_types.h:89
status.h
Cluster status and scheduling.
crm.h
A dumping ground.
pe_rsc_maintenance
#define pe_rsc_maintenance
Definition: pe_types.h:250
node_score_green
int node_score_green
Definition: utils.c:64
pe_find_node_id
pe_node_t * pe_find_node_id(GListPtr node_list, const char *id)
Definition: status.c:406
clone_internal_constraints
void clone_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
Definition: pcmk_sched_clone.c:880
pe_action_s::meta
GHashTable * meta
Definition: pe_types.h:387
no_action
Definition: common.h:58
crm_int_helper
long long crm_int_helper(const char *text, char **end_text)
Definition: strings.c:34
XML_BOOLEAN_TRUE
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:107
pe_rsc_failure_ignored
#define pe_rsc_failure_ignored
Definition: pe_types.h:249
pe_resource_s::fns
resource_object_functions_t * fns
Definition: pe_types.h:303
pe_flag_have_remote_nodes
#define pe_flag_have_remote_nodes
Definition: pe_types.h:108
find_first_action
action_t * find_first_action(GListPtr input, const char *uuid, const char *task, node_t *on_node)
Definition: utils.c:1399
pcmk__bundle_rsc_colocation_lh
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)
Definition: pcmk_sched_bundle.c:419
node_ping
Definition: pe_types.h:68
pe_node_shared_s::attrs
GHashTable * attrs
Definition: pe_types.h:211
op_digest_cache_s
Definition: internal.h:328
pe_rsc_failed
#define pe_rsc_failed
Definition: pe_types.h:241
pe_ordering
pe_ordering
Definition: pe_types.h:446
XML_TAG_GRAPH
#define XML_TAG_GRAPH
Definition: msg_xml.h:288
pe_action_wrapper_s::type
enum pe_ordering type
Definition: pe_types.h:490