pacemaker  1.1.19-c3c624ea3d
Scalable High-Availability cluster resource manager
complex.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #include <crm/pengine/rules.h>
11 #include <crm/pengine/internal.h>
12 #include <crm/msg_xml.h>
13 
14 #include <unpack.h>
15 
16 void populate_hash(xmlNode * nvpair_list, GHashTable * hash, const char **attrs, int attrs_length);
17 
19  {
28  },
29  {
38  },
39  {
48  },
49  {
57  clone_free
58  },
59  {
68  }
69 };
70 
71 enum pe_obj_types
72 get_resource_type(const char *name)
73 {
74  if (safe_str_eq(name, XML_CIB_TAG_RESOURCE)) {
75  return pe_native;
76 
77  } else if (safe_str_eq(name, XML_CIB_TAG_GROUP)) {
78  return pe_group;
79 
80  } else if (safe_str_eq(name, XML_CIB_TAG_INCARNATION)) {
81  return pe_clone;
82 
83  } else if (safe_str_eq(name, XML_CIB_TAG_MASTER)) {
84  return pe_master;
85 
86  } else if (safe_str_eq(name, XML_CIB_TAG_CONTAINER)) {
87  return pe_container;
88  }
89 
90  return pe_unknown;
91 }
92 
93 const char *
95 {
96  switch (type) {
97  case pe_native:
98  return XML_CIB_TAG_RESOURCE;
99  case pe_group:
100  return XML_CIB_TAG_GROUP;
101  case pe_clone:
103  case pe_master:
104  return XML_CIB_TAG_MASTER;
105  case pe_container:
106  return XML_CIB_TAG_CONTAINER;
107  case pe_unknown:
108  return "unknown";
109  }
110  return "<unknown>";
111 }
112 
113 static void
114 dup_attr(gpointer key, gpointer value, gpointer user_data)
115 {
116  add_hash_param(user_data, key, value);
117 }
118 
119 void
120 get_meta_attributes(GHashTable * meta_hash, resource_t * rsc,
121  node_t * node, pe_working_set_t * data_set)
122 {
123  GHashTable *node_hash = NULL;
124  const char *version = crm_element_value(data_set->input, XML_ATTR_CRM_VERSION);
125 
126  if (node) {
127  node_hash = node->details->attrs;
128  }
129 
130  if (rsc->xml) {
131  xmlAttrPtr xIter = NULL;
132 
133  for (xIter = rsc->xml->properties; xIter; xIter = xIter->next) {
134  const char *prop_name = (const char *)xIter->name;
135  const char *prop_value = crm_element_value(rsc->xml, prop_name);
136 
137  add_hash_param(meta_hash, prop_name, prop_value);
138  }
139  }
140 
141  unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_META_SETS, node_hash,
142  meta_hash, NULL, FALSE, data_set->now);
143 
144  if(version == NULL || compare_version(version, "3.0.9") < 0) {
145  /* populate from the regular attributes until the GUI can create
146  * meta attributes
147  */
148  unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash,
149  meta_hash, NULL, FALSE, data_set->now);
150  }
151 
152  /* set anything else based on the parent */
153  if (rsc->parent != NULL) {
154  g_hash_table_foreach(rsc->parent->meta, dup_attr, meta_hash);
155  }
156 
157  /* and finally check the defaults */
159  node_hash, meta_hash, NULL, FALSE, data_set->now);
160 }
161 
162 void
163 get_rsc_attributes(GHashTable * meta_hash, resource_t * rsc,
164  node_t * node, pe_working_set_t * data_set)
165 {
166  GHashTable *node_hash = NULL;
167 
168  if (node) {
169  node_hash = node->details->attrs;
170  }
171 
172  unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash,
173  meta_hash, NULL, FALSE, data_set->now);
174 
175  /* set anything else based on the parent */
176  if (rsc->parent != NULL) {
177  get_rsc_attributes(meta_hash, rsc->parent, node, data_set);
178 
179  } else {
180  /* and finally check the defaults */
182  node_hash, meta_hash, NULL, FALSE, data_set->now);
183  }
184 }
185 
186 #if ENABLE_VERSIONED_ATTRS
187 void
188 pe_get_versioned_attributes(xmlNode * meta_hash, resource_t * rsc,
189  node_t * node, pe_working_set_t * data_set)
190 {
191  GHashTable *node_hash = NULL;
192 
193  if (node) {
194  node_hash = node->details->attrs;
195  }
196 
197  pe_unpack_versioned_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash,
198  meta_hash, data_set->now);
199 
200  /* set anything else based on the parent */
201  if (rsc->parent != NULL) {
202  pe_get_versioned_attributes(meta_hash, rsc->parent, node, data_set);
203 
204  } else {
205  /* and finally check the defaults */
206  pe_unpack_versioned_attributes(data_set->input, data_set->rsc_defaults, XML_TAG_ATTR_SETS,
207  node_hash, meta_hash, data_set->now);
208  }
209 }
210 #endif
211 
212 static char *
213 template_op_key(xmlNode * op)
214 {
215  const char *name = crm_element_value(op, "name");
216  const char *role = crm_element_value(op, "role");
217  char *key = NULL;
218 
219  if (role == NULL || crm_str_eq(role, RSC_ROLE_STARTED_S, TRUE)
220  || crm_str_eq(role, RSC_ROLE_SLAVE_S, TRUE)) {
221  role = RSC_ROLE_UNKNOWN_S;
222  }
223 
224  key = crm_concat(name, role, '-');
225  return key;
226 }
227 
228 static gboolean
229 unpack_template(xmlNode * xml_obj, xmlNode ** expanded_xml, pe_working_set_t * data_set)
230 {
231  xmlNode *cib_resources = NULL;
232  xmlNode *template = NULL;
233  xmlNode *new_xml = NULL;
234  xmlNode *child_xml = NULL;
235  xmlNode *rsc_ops = NULL;
236  xmlNode *template_ops = NULL;
237  const char *template_ref = NULL;
238  const char *clone = NULL;
239  const char *id = NULL;
240 
241  if (xml_obj == NULL) {
242  pe_err("No resource object for template unpacking");
243  return FALSE;
244  }
245 
246  template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE);
247  if (template_ref == NULL) {
248  return TRUE;
249  }
250 
251  id = ID(xml_obj);
252  if (id == NULL) {
253  pe_err("'%s' object must have a id", crm_element_name(xml_obj));
254  return FALSE;
255  }
256 
257  if (crm_str_eq(template_ref, id, TRUE)) {
258  pe_err("The resource object '%s' should not reference itself", id);
259  return FALSE;
260  }
261 
262  cib_resources = get_xpath_object("//"XML_CIB_TAG_RESOURCES, data_set->input, LOG_TRACE);
263  if (cib_resources == NULL) {
264  pe_err("No resources configured");
265  return FALSE;
266  }
267 
268  template = find_entity(cib_resources, XML_CIB_TAG_RSC_TEMPLATE, template_ref);
269  if (template == NULL) {
270  pe_err("No template named '%s'", template_ref);
271  return FALSE;
272  }
273 
274  new_xml = copy_xml(template);
275  xmlNodeSetName(new_xml, xml_obj->name);
276  crm_xml_replace(new_xml, XML_ATTR_ID, id);
277 
279  if(clone) {
280  crm_xml_add(new_xml, XML_RSC_ATTR_INCARNATION, clone);
281  }
282 
283  template_ops = find_xml_node(new_xml, "operations", FALSE);
284 
285  for (child_xml = __xml_first_child(xml_obj); child_xml != NULL;
286  child_xml = __xml_next_element(child_xml)) {
287  xmlNode *new_child = NULL;
288 
289  new_child = add_node_copy(new_xml, child_xml);
290 
291  if (crm_str_eq((const char *)new_child->name, "operations", TRUE)) {
292  rsc_ops = new_child;
293  }
294  }
295 
296  if (template_ops && rsc_ops) {
297  xmlNode *op = NULL;
298  GHashTable *rsc_ops_hash =
299  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, NULL);
300 
301  for (op = __xml_first_child(rsc_ops); op != NULL; op = __xml_next_element(op)) {
302  char *key = template_op_key(op);
303 
304  g_hash_table_insert(rsc_ops_hash, key, op);
305  }
306 
307  for (op = __xml_first_child(template_ops); op != NULL; op = __xml_next_element(op)) {
308  char *key = template_op_key(op);
309 
310  if (g_hash_table_lookup(rsc_ops_hash, key) == NULL) {
311  add_node_copy(rsc_ops, op);
312  }
313 
314  free(key);
315  }
316 
317  if (rsc_ops_hash) {
318  g_hash_table_destroy(rsc_ops_hash);
319  }
320 
321  free_xml(template_ops);
322  }
323 
324  /*free_xml(*expanded_xml); */
325  *expanded_xml = new_xml;
326 
327  /* Disable multi-level templates for now */
328  /*if(unpack_template(new_xml, expanded_xml, data_set) == FALSE) {
329  free_xml(*expanded_xml);
330  *expanded_xml = NULL;
331 
332  return FALSE;
333  } */
334 
335  return TRUE;
336 }
337 
338 static gboolean
339 add_template_rsc(xmlNode * xml_obj, pe_working_set_t * data_set)
340 {
341  const char *template_ref = NULL;
342  const char *id = NULL;
343 
344  if (xml_obj == NULL) {
345  pe_err("No resource object for processing resource list of template");
346  return FALSE;
347  }
348 
349  template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE);
350  if (template_ref == NULL) {
351  return TRUE;
352  }
353 
354  id = ID(xml_obj);
355  if (id == NULL) {
356  pe_err("'%s' object must have a id", crm_element_name(xml_obj));
357  return FALSE;
358  }
359 
360  if (crm_str_eq(template_ref, id, TRUE)) {
361  pe_err("The resource object '%s' should not reference itself", id);
362  return FALSE;
363  }
364 
365  if (add_tag_ref(data_set->template_rsc_sets, template_ref, id) == FALSE) {
366  return FALSE;
367  }
368 
369  return TRUE;
370 }
371 
372 static void
373 handle_rsc_isolation(resource_t *rsc)
374 {
375  resource_t *top = uber_parent(rsc);
376  resource_t *iso = rsc;
377  const char *wrapper = NULL;
378  const char *value;
379 
380  /* check for isolation wrapper mapping if the parent doesn't have one set
381  * isolation mapping is enabled by default. For safety, we are allowing isolation
382  * to be disabled by setting the meta attr, isolation=false. */
383  value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ISOLATION);
384  if (top->isolation_wrapper == NULL && (value == NULL || crm_is_true(value))) {
385  if (g_hash_table_lookup(rsc->parameters, "pcmk_docker_image")) {
386  wrapper = "docker-wrapper";
387  }
388  /* add more isolation technologies here as we expand */
389  } else if (top->isolation_wrapper) {
390  goto set_rsc_opts;
391  }
392 
393  if (wrapper == NULL) {
394  return;
395  }
396 
397  /* if this is a cloned primitive/group, go head and set the isolation wrapper at
398  * at the clone level. this is really the only sane thing to do in this situation.
399  * This allows someone to clone an isolated resource without having to shuffle
400  * around the isolation attributes to the clone parent */
401  if (top == rsc->parent && pe_rsc_is_clone(top)) {
402  iso = top;
403  }
404 
405  iso->isolation_wrapper = wrapper;
406  set_bit(top->flags, pe_rsc_unique);
407 
408 set_rsc_opts:
409  pe_warn_once(pe_wo_isolation, "Support for 'isolation' resource meta-attribute"
410  " is deprecated and will be removed in a future release"
411  " (use bundle syntax instead)");
412 
414  set_bit(rsc->flags, pe_rsc_unique);
415  if (pe_rsc_is_clone(top)) {
417  }
418 }
419 
420 static void
421 check_deprecated_stonith(resource_t *rsc)
422 {
423  GHashTableIter iter;
424  char *key;
425 
426  g_hash_table_iter_init(&iter, rsc->parameters);
427  while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) {
428  if (crm_starts_with(key, "pcmk_")) {
429  char *cmp = key + 5; // the part after "pcmk_"
430 
431  if (!strcmp(cmp, "poweroff_action")) {
433  "Support for the 'pcmk_poweroff_action' stonith resource parameter"
434  " is deprecated and will be removed in a future version"
435  " (use 'pcmk_off_action' instead)");
436 
437  } else if (!strcmp(cmp, "arg_map")) {
439  "Support for the 'pcmk_arg_map' stonith resource parameter"
440  " is deprecated and will be removed in a future version"
441  " (use 'pcmk_host_argument' instead)");
442 
443  } else if (crm_ends_with(cmp, "_cmd")) {
445  "Support for the 'pcmk_*_cmd' stonith resource parameters"
446  " is deprecated and will be removed in a future version"
447  " (use 'pcmk_*_action' instead)");
448  }
449  }
450  }
451 }
452 
453 gboolean
454 common_unpack(xmlNode * xml_obj, resource_t ** rsc,
455  resource_t * parent, pe_working_set_t * data_set)
456 {
457  bool isdefault = FALSE;
458  xmlNode *expanded_xml = NULL;
459  xmlNode *ops = NULL;
460  resource_t *top = NULL;
461  const char *value = NULL;
462  const char *rclass = NULL; /* Look for this after any templates have been expanded */
463  const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
464  int container_remote_node = 0;
465  int baremetal_remote_node = 0;
466  bool has_versioned_params = FALSE;
467 
468  crm_log_xml_trace(xml_obj, "Processing resource input...");
469 
470  if (id == NULL) {
471  pe_err("Must specify id tag in <resource>");
472  return FALSE;
473 
474  } else if (rsc == NULL) {
475  pe_err("Nowhere to unpack resource into");
476  return FALSE;
477 
478  }
479 
480  if (unpack_template(xml_obj, &expanded_xml, data_set) == FALSE) {
481  return FALSE;
482  }
483 
484  *rsc = calloc(1, sizeof(resource_t));
485  (*rsc)->cluster = data_set;
486 
487  if (expanded_xml) {
488  crm_log_xml_trace(expanded_xml, "Expanded resource...");
489  (*rsc)->xml = expanded_xml;
490  (*rsc)->orig_xml = xml_obj;
491 
492  } else {
493  (*rsc)->xml = xml_obj;
494  (*rsc)->orig_xml = NULL;
495  }
496 
497  /* Do not use xml_obj from here on, use (*rsc)->xml in case templates are involved */
498  rclass = crm_element_value((*rsc)->xml, XML_AGENT_ATTR_CLASS);
499  (*rsc)->parent = parent;
500 
501  ops = find_xml_node((*rsc)->xml, "operations", FALSE);
502  (*rsc)->ops_xml = expand_idref(ops, data_set->input);
503 
504  (*rsc)->variant = get_resource_type(crm_element_name((*rsc)->xml));
505  if ((*rsc)->variant == pe_unknown) {
506  pe_err("Unknown resource type: %s", crm_element_name((*rsc)->xml));
507  free(*rsc);
508  return FALSE;
509  }
510 
511  (*rsc)->parameters = crm_str_table_new();
512 
513 #if ENABLE_VERSIONED_ATTRS
514  (*rsc)->versioned_parameters = create_xml_node(NULL, XML_TAG_RSC_VER_ATTRS);
515 #endif
516 
517  (*rsc)->meta = crm_str_table_new();
518 
519  (*rsc)->allowed_nodes =
520  g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
521 
522  (*rsc)->known_on = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
523 
524  value = crm_element_value((*rsc)->xml, XML_RSC_ATTR_INCARNATION);
525  if (value) {
526  (*rsc)->id = crm_concat(id, value, ':');
527  add_hash_param((*rsc)->meta, XML_RSC_ATTR_INCARNATION, value);
528 
529  } else {
530  (*rsc)->id = strdup(id);
531  }
532 
533  (*rsc)->fns = &resource_class_functions[(*rsc)->variant];
534  pe_rsc_trace((*rsc), "Unpacking resource...");
535 
536  get_meta_attributes((*rsc)->meta, *rsc, NULL, data_set);
537  get_rsc_attributes((*rsc)->parameters, *rsc, NULL, data_set);
538 #if ENABLE_VERSIONED_ATTRS
539  pe_get_versioned_attributes((*rsc)->versioned_parameters, *rsc, NULL, data_set);
540 #endif
541 
542  (*rsc)->flags = 0;
543  set_bit((*rsc)->flags, pe_rsc_runnable);
544  set_bit((*rsc)->flags, pe_rsc_provisional);
545 
546  if (is_set(data_set->flags, pe_flag_is_managed_default)) {
547  set_bit((*rsc)->flags, pe_rsc_managed);
548  }
549 
550  (*rsc)->rsc_cons = NULL;
551  (*rsc)->rsc_tickets = NULL;
552  (*rsc)->actions = NULL;
553  (*rsc)->role = RSC_ROLE_STOPPED;
554  (*rsc)->next_role = RSC_ROLE_UNKNOWN;
555 
556  (*rsc)->recovery_type = recovery_stop_start;
557  (*rsc)->stickiness = data_set->default_resource_stickiness;
558  (*rsc)->migration_threshold = INFINITY;
559  (*rsc)->failure_timeout = 0;
560 
561  value = g_hash_table_lookup((*rsc)->meta, XML_CIB_ATTR_PRIORITY);
562  (*rsc)->priority = crm_parse_int(value, "0");
563  (*rsc)->effective_priority = (*rsc)->priority;
564 
565  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_NOTIFY);
566  if (crm_is_true(value)) {
567  set_bit((*rsc)->flags, pe_rsc_notify);
568  }
569 
570  if (xml_contains_remote_node((*rsc)->xml)) {
571  (*rsc)->is_remote_node = TRUE;
572  if (g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_CONTAINER)) {
573  container_remote_node = 1;
574  } else {
575  baremetal_remote_node = 1;
576  }
577  }
578 
579  value = g_hash_table_lookup((*rsc)->meta, XML_OP_ATTR_ALLOW_MIGRATE);
580 #if ENABLE_VERSIONED_ATTRS
581  has_versioned_params = xml_has_children((*rsc)->versioned_parameters);
582 #endif
583  if (crm_is_true(value) && has_versioned_params) {
584  pe_rsc_trace((*rsc), "Migration is disabled for resources with versioned parameters");
585  } else if (crm_is_true(value)) {
586  set_bit((*rsc)->flags, pe_rsc_allow_migrate);
587  } else if ((value == NULL) && baremetal_remote_node && !has_versioned_params) {
588  /* by default, we want baremetal remote-nodes to be able
589  * to float around the cluster without having to stop all the
590  * resources within the remote-node before moving. Allowing
591  * migration support enables this feature. If this ever causes
592  * problems, migration support can be explicitly turned off with
593  * allow-migrate=false.
594  * We don't support migration for versioned resources, though. */
595  set_bit((*rsc)->flags, pe_rsc_allow_migrate);
596  }
597 
598  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MANAGED);
599  if (value != NULL && safe_str_neq("default", value)) {
600  gboolean bool_value = TRUE;
601 
602  crm_str_to_boolean(value, &bool_value);
603  if (bool_value == FALSE) {
604  clear_bit((*rsc)->flags, pe_rsc_managed);
605  } else {
606  set_bit((*rsc)->flags, pe_rsc_managed);
607  }
608  }
609 
610  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MAINTENANCE);
611  if (value != NULL && safe_str_neq("default", value)) {
612  gboolean bool_value = FALSE;
613 
614  crm_str_to_boolean(value, &bool_value);
615  if (bool_value == TRUE) {
616  clear_bit((*rsc)->flags, pe_rsc_managed);
617  set_bit((*rsc)->flags, pe_rsc_maintenance);
618  }
619 
620  } else if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
621  clear_bit((*rsc)->flags, pe_rsc_managed);
622  set_bit((*rsc)->flags, pe_rsc_maintenance);
623  }
624 
625  pe_rsc_trace((*rsc), "Options for %s", (*rsc)->id);
626 
627  handle_rsc_isolation(*rsc);
628 
629  top = uber_parent(*rsc);
630  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_UNIQUE);
631  if (crm_is_true(value) || pe_rsc_is_clone(top) == FALSE) {
632  set_bit((*rsc)->flags, pe_rsc_unique);
633  }
634 
635  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_RESTART);
636  if (safe_str_eq(value, "restart")) {
637  (*rsc)->restart_type = pe_restart_restart;
638  pe_rsc_trace((*rsc), "\tDependency restart handling: restart");
639 
640  } else {
641  (*rsc)->restart_type = pe_restart_ignore;
642  pe_rsc_trace((*rsc), "\tDependency restart handling: ignore");
643  }
644 
645  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MULTIPLE);
646  if (safe_str_eq(value, "stop_only")) {
647  (*rsc)->recovery_type = recovery_stop_only;
648  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop only");
649 
650  } else if (safe_str_eq(value, "block")) {
651  (*rsc)->recovery_type = recovery_block;
652  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: block");
653 
654  } else {
655  (*rsc)->recovery_type = recovery_stop_start;
656  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop/start");
657  }
658 
659  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_STICKINESS);
660  if (value != NULL && safe_str_neq("default", value)) {
661  (*rsc)->stickiness = char2score(value);
662  }
663 
664  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_STICKINESS);
665  if (value != NULL && safe_str_neq("default", value)) {
666  (*rsc)->migration_threshold = char2score(value);
667 
668  } else if (value == NULL) {
669  /* Make a best-effort guess at a migration threshold for people with 0.6 configs
670  * try with underscores and hyphens, from both the resource and global defaults section
671  */
672  const char *legacy = NULL;
673 
674  legacy = g_hash_table_lookup((*rsc)->meta,
675  "resource-failure-stickiness");
676  if (legacy == NULL) {
677  legacy = g_hash_table_lookup((*rsc)->meta,
678  "resource_failure_stickiness");
679  }
680  if (legacy) {
681  value = legacy;
683  "Support for 'resource-failure-stickiness' resource meta-attribute"
684  " is deprecated and will be removed in a future release"
685  " (use 'migration-threshold' resource meta-attribute instead)");
686  }
687 
688  legacy = g_hash_table_lookup(data_set->config_hash,
689  "default-resource-failure-stickiness");
690  if (legacy == NULL) {
691  legacy = g_hash_table_lookup(data_set->config_hash,
692  "default_resource_failure_stickiness");
693  }
694  if (legacy) {
695  if (value == NULL) {
696  value = legacy;
697  }
699  "Support for 'default-resource-failure-stickiness' cluster option"
700  " is deprecated and will be removed in a future release"
701  " (use 'migration-threshold' in rsc_defaults instead)");
702  }
703 
704  if (value) {
705  int fail_sticky = char2score(value);
706 
707  if (fail_sticky == -INFINITY) {
708  (*rsc)->migration_threshold = 1;
709  pe_rsc_info((*rsc),
710  "Set a migration threshold of %d for %s based on a failure-stickiness of %s",
711  (*rsc)->migration_threshold, (*rsc)->id, value);
712 
713  } else if ((*rsc)->stickiness != 0 && fail_sticky != 0) {
714  (*rsc)->migration_threshold = (*rsc)->stickiness / fail_sticky;
715  if ((*rsc)->migration_threshold < 0) {
716  /* Make sure it's positive */
717  (*rsc)->migration_threshold = 0 - (*rsc)->migration_threshold;
718  }
719  (*rsc)->migration_threshold += 1;
720  pe_rsc_info((*rsc),
721  "Calculated a migration threshold for %s of %d based on a stickiness of %d/%s",
722  (*rsc)->id, (*rsc)->migration_threshold, (*rsc)->stickiness, value);
723  }
724  }
725  }
726 
729  set_bit((*rsc)->flags, pe_rsc_fence_device);
730  check_deprecated_stonith(*rsc);
731  }
732 
733  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_REQUIRES);
734 
735  handle_requires_pref:
736  if (safe_str_eq(value, "nothing")) {
737 
738  } else if (safe_str_eq(value, "quorum")) {
739  set_bit((*rsc)->flags, pe_rsc_needs_quorum);
740 
741  } else if (safe_str_eq(value, "unfencing")) {
742  if (is_set((*rsc)->flags, pe_rsc_fence_device)) {
743  crm_config_warn("%s is a fencing device but requires (un)fencing", (*rsc)->id);
744  value = "quorum";
745  isdefault = TRUE;
746  goto handle_requires_pref;
747 
748  } else if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
749  crm_config_warn("%s requires (un)fencing but fencing is disabled", (*rsc)->id);
750  value = "quorum";
751  isdefault = TRUE;
752  goto handle_requires_pref;
753 
754  } else {
755  set_bit((*rsc)->flags, pe_rsc_needs_fencing);
756  set_bit((*rsc)->flags, pe_rsc_needs_unfencing);
757  }
758 
759  } else if (safe_str_eq(value, "fencing")) {
760  set_bit((*rsc)->flags, pe_rsc_needs_fencing);
761  if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
762  crm_config_warn("%s requires fencing but fencing is disabled", (*rsc)->id);
763  }
764 
765  } else {
766  if (value) {
767  crm_config_err("Invalid value for %s->requires: %s%s",
768  (*rsc)->id, value,
769  is_set(data_set->flags, pe_flag_stonith_enabled) ? "" : " (stonith-enabled=false)");
770  }
771 
772  isdefault = TRUE;
773  if(is_set((*rsc)->flags, pe_rsc_fence_device)) {
774  value = "quorum";
775 
776  } else if (((*rsc)->variant == pe_native)
779  && safe_str_eq(crm_element_value((*rsc)->xml, XML_AGENT_ATTR_PROVIDER), "pacemaker")
780  && safe_str_eq(crm_element_value((*rsc)->xml, XML_ATTR_TYPE), "remote")
781  ) {
782  value = "quorum";
783 
784  } else if (is_set(data_set->flags, pe_flag_enable_unfencing)) {
785  value = "unfencing";
786 
787  } else if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
788  value = "fencing";
789 
790  } else if (data_set->no_quorum_policy == no_quorum_ignore) {
791  value = "nothing";
792 
793  } else {
794  value = "quorum";
795  }
796  goto handle_requires_pref;
797  }
798 
799  pe_rsc_trace((*rsc), "\tRequired to start: %s%s", value, isdefault?" (default)":"");
800  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_TIMEOUT);
801  if (value != NULL) {
802  /* call crm_get_msec() and convert back to seconds */
803  (*rsc)->failure_timeout = (crm_get_msec(value) / 1000);
804  }
805 
806  if (baremetal_remote_node) {
807  value = g_hash_table_lookup((*rsc)->parameters, XML_REMOTE_ATTR_RECONNECT_INTERVAL);
808  if (value) {
809  /* reconnect delay works by setting failure_timeout and preventing the
810  * connection from starting until the failure is cleared. */
811  (*rsc)->remote_reconnect_interval = (crm_get_msec(value) / 1000);
812  /* we want to override any default failure_timeout in use when remote
813  * reconnect_interval is in use. */
814  (*rsc)->failure_timeout = (*rsc)->remote_reconnect_interval;
815  }
816  }
817 
818  get_target_role(*rsc, &((*rsc)->next_role));
819  pe_rsc_trace((*rsc), "\tDesired next state: %s",
820  (*rsc)->next_role != RSC_ROLE_UNKNOWN ? role2text((*rsc)->next_role) : "default");
821 
822  if ((*rsc)->fns->unpack(*rsc, data_set) == FALSE) {
823  return FALSE;
824  }
825 
826  if (is_set(data_set->flags, pe_flag_symmetric_cluster)) {
827  // This tag must stay exactly the same because it is tested elsewhere
828  resource_location(*rsc, NULL, 0, "symmetric_default", data_set);
829  } else if (container_remote_node) {
830  /* remote resources tied to a container resource must always be allowed
831  * to opt-in to the cluster. Whether the connection resource is actually
832  * allowed to be placed on a node is dependent on the container resource */
833  resource_location(*rsc, NULL, 0, "remote_connection_default", data_set);
834  }
835 
836  pe_rsc_trace((*rsc), "\tAction notification: %s",
837  is_set((*rsc)->flags, pe_rsc_notify) ? "required" : "not required");
838 
839  (*rsc)->utilization = crm_str_table_new();
840 
841  unpack_instance_attributes(data_set->input, (*rsc)->xml, XML_TAG_UTILIZATION, NULL,
842  (*rsc)->utilization, NULL, FALSE, data_set->now);
843 
844 /* data_set->resources = g_list_append(data_set->resources, (*rsc)); */
845 
846  if (expanded_xml) {
847  if (add_template_rsc(xml_obj, data_set) == FALSE) {
848  return FALSE;
849  }
850  }
851  return TRUE;
852 }
853 
854 void
855 common_update_score(resource_t * rsc, const char *id, int score)
856 {
857  node_t *node = NULL;
858 
859  node = pe_hash_table_lookup(rsc->allowed_nodes, id);
860  if (node != NULL) {
861  pe_rsc_trace(rsc, "Updating score for %s on %s: %d + %d", rsc->id, id, node->weight, score);
862  node->weight = merge_weights(node->weight, score);
863  }
864 
865  if (rsc->children) {
866  GListPtr gIter = rsc->children;
867 
868  for (; gIter != NULL; gIter = gIter->next) {
869  resource_t *child_rsc = (resource_t *) gIter->data;
870 
871  common_update_score(child_rsc, id, score);
872  }
873  }
874 }
875 
876 gboolean
878 {
879  resource_t *parent = child;
880 
881  if (parent == NULL || rsc == NULL) {
882  return FALSE;
883  }
884  while (parent->parent != NULL) {
885  if (parent->parent == rsc) {
886  return TRUE;
887  }
888  parent = parent->parent;
889  }
890  return FALSE;
891 }
892 
893 resource_t *
895 {
896  resource_t *parent = rsc;
897 
898  if (parent == NULL) {
899  return NULL;
900  }
901  while (parent->parent != NULL && parent->parent->variant != pe_container) {
902  parent = parent->parent;
903  }
904  return parent;
905 }
906 
907 void
909 {
910  if (rsc == NULL) {
911  return;
912  }
913 
914  pe_rsc_trace(rsc, "Freeing %s %d", rsc->id, rsc->variant);
915 
916  g_list_free(rsc->rsc_cons);
917  g_list_free(rsc->rsc_cons_lhs);
918  g_list_free(rsc->rsc_tickets);
919  g_list_free(rsc->dangling_migrations);
920 
921  if (rsc->parameters != NULL) {
922  g_hash_table_destroy(rsc->parameters);
923  }
924 #if ENABLE_VERSIONED_ATTRS
925  if (rsc->versioned_parameters != NULL) {
926  free_xml(rsc->versioned_parameters);
927  }
928 #endif
929  if (rsc->meta != NULL) {
930  g_hash_table_destroy(rsc->meta);
931  }
932  if (rsc->utilization != NULL) {
933  g_hash_table_destroy(rsc->utilization);
934  }
935 
936  if (rsc->parent == NULL && is_set(rsc->flags, pe_rsc_orphan)) {
937  free_xml(rsc->xml);
938  rsc->xml = NULL;
939  free_xml(rsc->orig_xml);
940  rsc->orig_xml = NULL;
941 
942  /* if rsc->orig_xml, then rsc->xml is an expanded xml from a template */
943  } else if (rsc->orig_xml) {
944  free_xml(rsc->xml);
945  rsc->xml = NULL;
946  }
947  if (rsc->running_on) {
948  g_list_free(rsc->running_on);
949  rsc->running_on = NULL;
950  }
951  if (rsc->known_on) {
952  g_hash_table_destroy(rsc->known_on);
953  rsc->known_on = NULL;
954  }
955  if (rsc->actions) {
956  g_list_free(rsc->actions);
957  rsc->actions = NULL;
958  }
959  if (rsc->allowed_nodes) {
960  g_hash_table_destroy(rsc->allowed_nodes);
961  rsc->allowed_nodes = NULL;
962  }
963  g_list_free(rsc->fillers);
964  g_list_free(rsc->rsc_location);
965  pe_rsc_trace(rsc, "Resource freed");
966  free(rsc->id);
967  free(rsc->clone_name);
968  free(rsc->allocated_to);
969  free(rsc->variant_opaque);
970  free(rsc->pending_task);
971  free(rsc);
972 }
973 
989 pe_node_t *
990 pe__find_active_on(const resource_t *rsc, unsigned int *count_all,
991  unsigned int *count_clean)
992 {
993  pe_node_t *active = NULL;
994  pe_node_t *node = NULL;
995  bool keep_looking = FALSE;
996  bool is_happy = FALSE;
997 
998  if (count_all) {
999  *count_all = 0;
1000  }
1001  if (count_clean) {
1002  *count_clean = 0;
1003  }
1004  if (rsc == NULL) {
1005  return NULL;
1006  }
1007 
1008  for (GList *node_iter = rsc->running_on; node_iter != NULL;
1009  node_iter = node_iter->next) {
1010 
1011  node = node_iter->data;
1012  keep_looking = FALSE;
1013 
1014  is_happy = node->details->online && !node->details->unclean;
1015 
1016  if (count_all) {
1017  ++*count_all;
1018  }
1019  if (count_clean && is_happy) {
1020  ++*count_clean;
1021  }
1022  if (count_all || count_clean) {
1023  // If we're counting, we need to go through entire list
1024  keep_looking = TRUE;
1025  }
1026 
1027  if (rsc->partial_migration_source != NULL) {
1028  if (node->details == rsc->partial_migration_source->details) {
1029  // This is the migration source
1030  active = node;
1031  } else {
1032  keep_looking = TRUE;
1033  }
1034  } else if (is_not_set(rsc->flags, pe_rsc_needs_fencing)) {
1035  if (is_happy && (!active || !active->details->online
1036  || active->details->unclean)) {
1037  // This is the first clean node
1038  active = node;
1039  } else {
1040  keep_looking = TRUE;
1041  }
1042  }
1043  if (active == NULL) {
1044  // This is first node in list
1045  active = node;
1046  }
1047 
1048  if (keep_looking == FALSE) {
1049  // Don't waste time iterating if we don't have to
1050  break;
1051  }
1052  }
1053  return active;
1054 }
1055 
1069 pe_node_t *
1070 pe__find_active_requires(const resource_t *rsc, unsigned int *count)
1071 {
1072  if (rsc && is_not_set(rsc->flags, pe_rsc_needs_fencing)) {
1073  return pe__find_active_on(rsc, NULL, count);
1074  }
1075  return pe__find_active_on(rsc, count, NULL);
1076 }
#define LOG_TRACE
Definition: logging.h:29
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:2248
void container_free(resource_t *rsc)
Definition: container.c:1397
void clone_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: clone.c:372
xmlNode * xml
Definition: status.h:263
void group_free(resource_t *rsc)
Definition: group.c:184
#define pe_flag_have_stonith_resource
Definition: status.h:69
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:150
#define INFINITY
Definition: crm.h:73
#define pe_rsc_needs_unfencing
Definition: status.h:223
GHashTable * utilization
Definition: status.h:303
gboolean get_target_role(resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:1745
#define XML_CIB_TAG_CONTAINER
Definition: msg_xml.h:200
#define pe_flag_enable_unfencing
Definition: status.h:70
int default_resource_stickiness
Definition: status.h:102
#define pe_rsc_maintenance
Definition: status.h:218
int weight
Definition: status.h:179
#define XML_ATTR_TYPE
Definition: msg_xml.h:105
#define XML_TAG_UTILIZATION
Definition: msg_xml.h:193
enum pe_obj_types get_resource_type(const char *name)
Definition: complex.c:72
#define RSC_ROLE_STARTED_S
Definition: common.h:93
#define crm_config_err(fmt...)
Definition: crm_internal.h:256
#define pe_rsc_needs_quorum
Definition: status.h:221
#define XML_RSC_ATTR_INCARNATION
Definition: msg_xml.h:212
void common_free(resource_t *rsc)
Definition: complex.c:908
#define pe_rsc_orphan
Definition: status.h:188
GListPtr rsc_location
Definition: status.h:289
char * native_parameter(resource_t *rsc, node_t *node, gboolean create, const char *name, pe_working_set_t *data_set)
Definition: native.c:248
int char2score(const char *score)
Definition: utils.c:230
long long crm_get_msec(const char *input)
Definition: utils.c:598
#define pe_rsc_provisional
Definition: status.h:197
xmlNode * find_entity(xmlNode *parent, const char *node_name, const char *id)
Definition: xml.c:2313
enum pe_obj_types variant
Definition: status.h:269
node_t * partial_migration_source
Definition: status.h:309
int crm_parse_int(const char *text, const char *default_text)
Definition: strings.c:125
#define XML_CIB_TAG_RSC_TEMPLATE
Definition: msg_xml.h:202
no_quorum_policy_t no_quorum_policy
Definition: status.h:103
#define XML_RSC_ATTR_STICKINESS
Definition: msg_xml.h:223
char * clone_name
Definition: status.h:262
xmlNode * orig_xml
Definition: status.h:264
#define clear_bit(word, bit)
Definition: crm_internal.h:191
#define pe_rsc_allow_migrate
Definition: status.h:214
void native_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:735
GListPtr children
Definition: status.h:305
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:224
bool crm_starts_with(const char *str, const char *prefix)
Check whether a string starts with a certain sequence.
Definition: strings.c:252
void clone_free(resource_t *rsc)
Definition: clone.c:574
enum rsc_role_e group_resource_state(const resource_t *rsc, gboolean current)
Definition: group.c:205
char version[256]
Definition: plugin.c:84
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
Definition: xml.c:2569
char * id
Definition: status.h:261
GHashTable * parameters
Definition: status.h:302
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:265
const char * isolation_wrapper
Definition: status.h:316
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:2745
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:185
#define XML_CIB_TAG_RESOURCES
Definition: msg_xml.h:160
gboolean container_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: container.c:831
const char * role2text(enum rsc_role_e role)
Definition: common.c:346
struct node_shared_s * details
Definition: status.h:182
#define set_bit(word, bit)
Definition: crm_internal.h:190
#define XML_RSC_ATTR_REQUIRES
Definition: msg_xml.h:228
#define PCMK_RESOURCE_CLASS_OCF
Definition: services.h:57
GListPtr rsc_cons_lhs
Definition: status.h:287
gboolean unclean
Definition: status.h:150
resource_object_functions_t resource_class_functions[]
Definition: complex.c:18
resource_t * uber_parent(resource_t *rsc)
Definition: complex.c:894
#define XML_RSC_ATTR_CONTAINER
Definition: msg_xml.h:230
#define XML_ATTR_ID
Definition: msg_xml.h:102
char * pending_task
Definition: status.h:314
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:196
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:117
#define XML_RSC_ATTR_ISOLATION
Definition: msg_xml.h:208
xmlNode * rsc_defaults
Definition: status.h:121
pe_obj_types
Definition: complex.h:30
GHashTable * allowed_nodes
Definition: status.h:296
void * variant_opaque
Definition: status.h:268
GListPtr rsc_cons
Definition: status.h:288
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:2438
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
Definition: xml.c:5184
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:255
#define pe_rsc_runnable
Definition: status.h:208
#define XML_TAG_META_SETS
Definition: msg_xml.h:186
GHashTable * config_hash
Definition: status.h:105
gboolean add_tag_ref(GHashTable *tags, const char *tag_name, const char *obj_ref)
Definition: utils.c:2310
#define XML_RSC_ATTR_MANAGED
Definition: msg_xml.h:219
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:2621
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5224
unsigned long long flags
Definition: status.h:285
enum rsc_role_e native_resource_state(const resource_t *rsc, gboolean current)
Definition: native.c:757
#define pe_flag_maintenance_mode
Definition: status.h:66
void group_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: group.c:135
resource_t * parent
Definition: status.h:267
gboolean native_active(resource_t *rsc, gboolean all)
Definition: native.c:293
GListPtr dangling_migrations
Definition: status.h:306
#define XML_TAG_RSC_VER_ATTRS
Definition: msg_xml.h:188
void free_xml(xmlNode *child)
Definition: xml.c:2739
node_t * native_location(resource_t *rsc, GListPtr *list, gboolean current)
Definition: native.c:769
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:3868
xmlNode * input
Definition: status.h:90
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:213
pe_node_t * pe__find_active_on(const resource_t *rsc, unsigned int *count_all, unsigned int *count_clean)
Definition: complex.c:990
GListPtr fillers
Definition: status.h:312
GListPtr rsc_tickets
Definition: status.h:291
#define XML_REMOTE_ATTR_RECONNECT_INTERVAL
Definition: msg_xml.h:237
#define XML_RSC_ATTR_NOTIFY
Definition: msg_xml.h:222
void get_rsc_attributes(GHashTable *meta_hash, resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: complex.c:163
#define XML_RSC_ATTR_FAIL_STICKINESS
Definition: msg_xml.h:224
gboolean crm_ends_with(const char *s, const char *match)
Definition: strings.c:302
enum rsc_role_e clone_resource_state(const resource_t *rsc, gboolean current)
Definition: clone.c:608
void populate_hash(xmlNode *nvpair_list, GHashTable *hash, const char **attrs, int attrs_length)
gboolean is_parent(resource_t *child, resource_t *rsc)
Definition: complex.c:877
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:221
#define crm_config_warn(fmt...)
Definition: crm_internal.h:257
GListPtr actions
Definition: status.h:290
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Definition: xml.c:2523
#define PCMK_RESOURCE_CLASS_STONITH
Definition: services.h:64
void get_meta_attributes(GHashTable *meta_hash, resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: complex.c:120
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:176
#define pe_rsc_unique
Definition: status.h:194
gboolean clone_active(resource_t *rsc, gboolean all)
Definition: clone.c:239
GHashTable * meta
Definition: status.h:301
gboolean xml_contains_remote_node(xmlNode *xml)
Definition: remote.c:91
#define XML_CIB_TAG_INCARNATION
Definition: msg_xml.h:198
#define XML_RSC_ATTR_MAINTENANCE
Definition: msg_xml.h:232
#define XML_RSC_ATTR_FAIL_TIMEOUT
Definition: msg_xml.h:225
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:423
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1571
gboolean group_active(resource_t *rsc, gboolean all)
Definition: group.c:90
pe_node_t * pe__find_active_requires(const resource_t *rsc, unsigned int *count)
Definition: complex.c:1070
const char * get_resource_typename(enum pe_obj_types type)
Definition: complex.c:94
enum rsc_role_e container_resource_state(const resource_t *rsc, gboolean current)
Definition: container.c:1430
GHashTable * attrs
Definition: status.h:162
gboolean online
Definition: status.h:146
#define RSC_ROLE_SLAVE_S
Definition: common.h:94
int compare_version(const char *version1, const char *version2)
Definition: utils.c:486
int merge_weights(int w1, int w2)
Definition: common.c:386
#define pe_rsc_managed
Definition: status.h:189
#define crm_str_hash
Definition: util.h:73
#define XML_RSC_ATTR_MULTIPLE
Definition: msg_xml.h:226
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:84
void container_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: container.c:1297
node_t * allocated_to
Definition: status.h:293
void common_update_score(resource_t *rsc, const char *id, int score)
Definition: complex.c:855
gboolean container_active(resource_t *rsc, gboolean all)
Definition: container.c:1131
GHashTable * known_on
Definition: status.h:295
#define XML_RSC_ATTR_RESTART
Definition: msg_xml.h:209
#define XML_CIB_TAG_MASTER
Definition: msg_xml.h:199
void native_free(resource_t *rsc)
Definition: native.c:750
gboolean native_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: native.c:133
#define RSC_ROLE_UNKNOWN_S
Definition: common.h:91
void unpack_instance_attributes(xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now)
Definition: rules.c:919
#define pe_flag_is_managed_default
Definition: status.h:65
#define crm_log_xml_trace(xml, text)
Definition: logging.h:262
Definition: status.h:178
gboolean crm_is_true(const char *s)
Definition: strings.c:165
#define XML_CIB_TAG_GROUP
Definition: msg_xml.h:197
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:16
#define pe_flag_symmetric_cluster
Definition: status.h:64
char * crm_concat(const char *prefix, const char *suffix, char join)
Definition: strings.c:32
gboolean common_unpack(xmlNode *xml_obj, resource_t **rsc, resource_t *parent, pe_working_set_t *data_set)
Definition: complex.c:454
unsigned long long flags
Definition: status.h:99
#define ID(x)
Definition: msg_xml.h:447
#define pe_err(fmt...)
Definition: internal.h:18
#define pe_rsc_needs_fencing
Definition: status.h:222
#define safe_str_eq(a, b)
Definition: util.h:72
gboolean group_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: group.c:20
#define pe_rsc_fence_device
Definition: status.h:195
GList * GListPtr
Definition: crm.h:210
#define pe_rsc_notify
Definition: status.h:193
crm_time_t * now
Definition: status.h:91
void g_hash_destroy_str(gpointer data)
Definition: strings.c:74
GHashTable * template_rsc_sets
Definition: status.h:132
resource_t * native_find_rsc(resource_t *rsc, const char *id, node_t *node, int flags)
Definition: native.c:194
#define XML_OP_ATTR_ALLOW_MIGRATE
Definition: msg_xml.h:241
#define pe_flag_stonith_enabled
Definition: status.h:68
enum crm_ais_msg_types type
Definition: internal.h:51
#define pe_warn_once(pe_wo_bit, fmt...)
Definition: unpack.h:116
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:14
gboolean clone_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: clone.c:142
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:254
gboolean master_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: clone.c:124
GListPtr running_on
Definition: status.h:294