pacemaker  1.1.14-70404b0
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
complex.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <crm_internal.h>
20 
21 #include <crm/pengine/rules.h>
22 #include <crm/pengine/internal.h>
23 #include <crm/msg_xml.h>
24 
25 void populate_hash(xmlNode * nvpair_list, GHashTable * hash, const char **attrs, int attrs_length);
26 
28  {
36  native_free},
37  {
45  group_free},
46  {
54  clone_free},
55  {
63  clone_free}
64 };
65 
66 enum pe_obj_types
67 get_resource_type(const char *name)
68 {
69  if (safe_str_eq(name, XML_CIB_TAG_RESOURCE)) {
70  return pe_native;
71 
72  } else if (safe_str_eq(name, XML_CIB_TAG_GROUP)) {
73  return pe_group;
74 
75  } else if (safe_str_eq(name, XML_CIB_TAG_INCARNATION)) {
76  return pe_clone;
77 
78  } else if (safe_str_eq(name, XML_CIB_TAG_MASTER)) {
79  return pe_master;
80  }
81 
82  return pe_unknown;
83 }
84 
85 const char *
87 {
88  switch (type) {
89  case pe_native:
90  return XML_CIB_TAG_RESOURCE;
91  case pe_group:
92  return XML_CIB_TAG_GROUP;
93  case pe_clone:
95  case pe_master:
96  return XML_CIB_TAG_MASTER;
97  case pe_unknown:
98  return "unknown";
99  }
100  return "<unknown>";
101 }
102 
103 static void
104 dup_attr(gpointer key, gpointer value, gpointer user_data)
105 {
106  add_hash_param(user_data, key, value);
107 }
108 
109 void
110 get_meta_attributes(GHashTable * meta_hash, resource_t * rsc,
111  node_t * node, pe_working_set_t * data_set)
112 {
113  GHashTable *node_hash = NULL;
114  const char *version = crm_element_value(data_set->input, XML_ATTR_CRM_VERSION);
115 
116  if (node) {
117  node_hash = node->details->attrs;
118  }
119 
120  if (rsc->xml) {
121  xmlAttrPtr xIter = NULL;
122 
123  for (xIter = rsc->xml->properties; xIter; xIter = xIter->next) {
124  const char *prop_name = (const char *)xIter->name;
125  const char *prop_value = crm_element_value(rsc->xml, prop_name);
126 
127  add_hash_param(meta_hash, prop_name, prop_value);
128  }
129  }
130 
131  unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_META_SETS, node_hash,
132  meta_hash, NULL, FALSE, data_set->now);
133 
134  if(version == NULL || compare_version(version, "3.0.9") < 0) {
135  /* populate from the regular attributes until the GUI can create
136  * meta attributes
137  */
138  unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash,
139  meta_hash, NULL, FALSE, data_set->now);
140  }
141 
142  /* set anything else based on the parent */
143  if (rsc->parent != NULL) {
144  g_hash_table_foreach(rsc->parent->meta, dup_attr, meta_hash);
145  }
146 
147  /* and finally check the defaults */
149  node_hash, meta_hash, NULL, FALSE, data_set->now);
150 }
151 
152 void
153 get_rsc_attributes(GHashTable * meta_hash, resource_t * rsc,
154  node_t * node, pe_working_set_t * data_set)
155 {
156  GHashTable *node_hash = NULL;
157 
158  if (node) {
159  node_hash = node->details->attrs;
160  }
161 
162  unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash,
163  meta_hash, NULL, FALSE, data_set->now);
164 
165  /* set anything else based on the parent */
166  if (rsc->parent != NULL) {
167  get_rsc_attributes(meta_hash, rsc->parent, node, data_set);
168 
169  } else {
170  /* and finally check the defaults */
172  node_hash, meta_hash, NULL, FALSE, data_set->now);
173  }
174 }
175 
176 static char *
177 template_op_key(xmlNode * op)
178 {
179  const char *name = crm_element_value(op, "name");
180  const char *role = crm_element_value(op, "role");
181  char *key = NULL;
182 
183  if (role == NULL || crm_str_eq(role, RSC_ROLE_STARTED_S, TRUE)
184  || crm_str_eq(role, RSC_ROLE_SLAVE_S, TRUE)) {
185  role = RSC_ROLE_UNKNOWN_S;
186  }
187 
188  key = crm_concat(name, role, '-');
189  return key;
190 }
191 
192 static gboolean
193 unpack_template(xmlNode * xml_obj, xmlNode ** expanded_xml, pe_working_set_t * data_set)
194 {
195  xmlNode *cib_resources = NULL;
196  xmlNode *template = NULL;
197  xmlNode *new_xml = NULL;
198  xmlNode *child_xml = NULL;
199  xmlNode *rsc_ops = NULL;
200  xmlNode *template_ops = NULL;
201  const char *template_ref = NULL;
202  const char *clone = NULL;
203  const char *id = NULL;
204 
205  if (xml_obj == NULL) {
206  pe_err("No resource object for template unpacking");
207  return FALSE;
208  }
209 
210  template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE);
211  if (template_ref == NULL) {
212  return TRUE;
213  }
214 
215  id = ID(xml_obj);
216  if (id == NULL) {
217  pe_err("'%s' object must have a id", crm_element_name(xml_obj));
218  return FALSE;
219  }
220 
221  if (crm_str_eq(template_ref, id, TRUE)) {
222  pe_err("The resource object '%s' should not reference itself", id);
223  return FALSE;
224  }
225 
226  cib_resources = get_xpath_object("//"XML_CIB_TAG_RESOURCES, data_set->input, LOG_TRACE);
227  if (cib_resources == NULL) {
228  pe_err("No resources configured");
229  return FALSE;
230  }
231 
232  template = find_entity(cib_resources, XML_CIB_TAG_RSC_TEMPLATE, template_ref);
233  if (template == NULL) {
234  pe_err("No template named '%s'", template_ref);
235  return FALSE;
236  }
237 
238  new_xml = copy_xml(template);
239  xmlNodeSetName(new_xml, xml_obj->name);
240  crm_xml_replace(new_xml, XML_ATTR_ID, id);
241 
243  if(clone) {
244  crm_xml_add(new_xml, XML_RSC_ATTR_INCARNATION, clone);
245  }
246 
247  template_ops = find_xml_node(new_xml, "operations", FALSE);
248 
249  for (child_xml = __xml_first_child(xml_obj); child_xml != NULL;
250  child_xml = __xml_next_element(child_xml)) {
251  xmlNode *new_child = NULL;
252 
253  new_child = add_node_copy(new_xml, child_xml);
254 
255  if (crm_str_eq((const char *)new_child->name, "operations", TRUE)) {
256  rsc_ops = new_child;
257  }
258  }
259 
260  if (template_ops && rsc_ops) {
261  xmlNode *op = NULL;
262  GHashTable *rsc_ops_hash =
263  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, NULL);
264 
265  for (op = __xml_first_child(rsc_ops); op != NULL; op = __xml_next_element(op)) {
266  char *key = template_op_key(op);
267 
268  g_hash_table_insert(rsc_ops_hash, key, op);
269  }
270 
271  for (op = __xml_first_child(template_ops); op != NULL; op = __xml_next_element(op)) {
272  char *key = template_op_key(op);
273 
274  if (g_hash_table_lookup(rsc_ops_hash, key) == NULL) {
275  add_node_copy(rsc_ops, op);
276  }
277 
278  free(key);
279  }
280 
281  if (rsc_ops_hash) {
282  g_hash_table_destroy(rsc_ops_hash);
283  }
284 
285  free_xml(template_ops);
286  }
287 
288  /*free_xml(*expanded_xml); */
289  *expanded_xml = new_xml;
290 
291  /* Disable multi-level templates for now */
292  /*if(unpack_template(new_xml, expanded_xml, data_set) == FALSE) {
293  free_xml(*expanded_xml);
294  *expanded_xml = NULL;
295 
296  return FALSE;
297  } */
298 
299  return TRUE;
300 }
301 
302 static gboolean
303 add_template_rsc(xmlNode * xml_obj, pe_working_set_t * data_set)
304 {
305  const char *template_ref = NULL;
306  const char *id = NULL;
307 
308  if (xml_obj == NULL) {
309  pe_err("No resource object for processing resource list of template");
310  return FALSE;
311  }
312 
313  template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE);
314  if (template_ref == NULL) {
315  return TRUE;
316  }
317 
318  id = ID(xml_obj);
319  if (id == NULL) {
320  pe_err("'%s' object must have a id", crm_element_name(xml_obj));
321  return FALSE;
322  }
323 
324  if (crm_str_eq(template_ref, id, TRUE)) {
325  pe_err("The resource object '%s' should not reference itself", id);
326  return FALSE;
327  }
328 
329  if (add_tag_ref(data_set->template_rsc_sets, template_ref, id) == FALSE) {
330  return FALSE;
331  }
332 
333  return TRUE;
334 }
335 
336 static void
337 handle_rsc_isolation(resource_t *rsc)
338 {
339  resource_t *top = uber_parent(rsc);
340  resource_t *iso = rsc;
341  const char *wrapper = NULL;
342  const char *value;
343 
344  /* check for isolation wrapper mapping if the parent doesn't have one set
345  * isolation mapping is enabled by default. For safety, we are allowing isolation
346  * to be disabled by setting the meta attr, isolation=false. */
347  value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ISOLATION);
348  if (top->isolation_wrapper == NULL && (value == NULL || crm_is_true(value))) {
349  if (g_hash_table_lookup(rsc->parameters, "pcmk_docker_image")) {
350  wrapper = "docker-wrapper";
351  }
352  /* add more isolation technologies here as we expand */
353  } else if (top->isolation_wrapper) {
354  goto set_rsc_opts;
355  }
356 
357  if (wrapper == NULL) {
358  return;
359  }
360 
361  /* if this is a cloned primitive/group, go head and set the isolation wrapper at
362  * at the clone level. this is really the only sane thing to do in this situation.
363  * This allows someone to clone an isolated resource without having to shuffle
364  * around the isolation attributes to the clone parent */
365  if (top == rsc->parent && top->variant >= pe_clone) {
366  iso = top;
367  }
368 
369  iso->isolation_wrapper = wrapper;
370  set_bit(top->flags, pe_rsc_unique);
371 
372 set_rsc_opts:
374  set_bit(rsc->flags, pe_rsc_unique);
375  if (top->variant >= pe_clone) {
377  }
378 }
379 
380 gboolean
381 common_unpack(xmlNode * xml_obj, resource_t ** rsc,
382  resource_t * parent, pe_working_set_t * data_set)
383 {
384  bool isdefault = FALSE;
385  xmlNode *expanded_xml = NULL;
386  xmlNode *ops = NULL;
387  resource_t *top = NULL;
388  const char *value = NULL;
389  const char *rclass = NULL; /* Look for this after any templates have been expanded */
390  const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
391  int container_remote_node = 0;
392  int baremetal_remote_node = 0;
393 
394  crm_log_xml_trace(xml_obj, "Processing resource input...");
395 
396  if (id == NULL) {
397  pe_err("Must specify id tag in <resource>");
398  return FALSE;
399 
400  } else if (rsc == NULL) {
401  pe_err("Nowhere to unpack resource into");
402  return FALSE;
403 
404  }
405 
406  if (unpack_template(xml_obj, &expanded_xml, data_set) == FALSE) {
407  return FALSE;
408  }
409 
410  *rsc = calloc(1, sizeof(resource_t));
411 
412  if (expanded_xml) {
413  crm_log_xml_trace(expanded_xml, "Expanded resource...");
414  (*rsc)->xml = expanded_xml;
415  (*rsc)->orig_xml = xml_obj;
416 
417  } else {
418  (*rsc)->xml = xml_obj;
419  (*rsc)->orig_xml = NULL;
420  }
421 
422  /* Do not use xml_obj from here on, use (*rsc)->xml in case templates are involved */
423  rclass = crm_element_value((*rsc)->xml, XML_AGENT_ATTR_CLASS);
424  (*rsc)->parent = parent;
425 
426  ops = find_xml_node((*rsc)->xml, "operations", FALSE);
427  (*rsc)->ops_xml = expand_idref(ops, data_set->input);
428 
429  (*rsc)->variant = get_resource_type(crm_element_name((*rsc)->xml));
430  if ((*rsc)->variant == pe_unknown) {
431  pe_err("Unknown resource type: %s", crm_element_name((*rsc)->xml));
432  free(*rsc);
433  return FALSE;
434  }
435 
436  (*rsc)->parameters =
437  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
438 
439  (*rsc)->meta =
440  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
441 
442  (*rsc)->allowed_nodes =
443  g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
444 
445  (*rsc)->known_on = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
446 
447  value = crm_element_value((*rsc)->xml, XML_RSC_ATTR_INCARNATION);
448  if (value) {
449  (*rsc)->id = crm_concat(id, value, ':');
450  add_hash_param((*rsc)->meta, XML_RSC_ATTR_INCARNATION, value);
451 
452  } else {
453  (*rsc)->id = strdup(id);
454  }
455 
456  (*rsc)->fns = &resource_class_functions[(*rsc)->variant];
457  pe_rsc_trace((*rsc), "Unpacking resource...");
458 
459  get_meta_attributes((*rsc)->meta, *rsc, NULL, data_set);
460  get_rsc_attributes((*rsc)->parameters, *rsc, NULL, data_set);
461 
462  (*rsc)->flags = 0;
463  set_bit((*rsc)->flags, pe_rsc_runnable);
464  set_bit((*rsc)->flags, pe_rsc_provisional);
465 
466  if (is_set(data_set->flags, pe_flag_is_managed_default)) {
467  set_bit((*rsc)->flags, pe_rsc_managed);
468  }
469 
470  (*rsc)->rsc_cons = NULL;
471  (*rsc)->rsc_tickets = NULL;
472  (*rsc)->actions = NULL;
473  (*rsc)->role = RSC_ROLE_STOPPED;
474  (*rsc)->next_role = RSC_ROLE_UNKNOWN;
475 
476  (*rsc)->recovery_type = recovery_stop_start;
477  (*rsc)->stickiness = data_set->default_resource_stickiness;
478  (*rsc)->migration_threshold = INFINITY;
479  (*rsc)->failure_timeout = 0;
480 
481  value = g_hash_table_lookup((*rsc)->meta, XML_CIB_ATTR_PRIORITY);
482  (*rsc)->priority = crm_parse_int(value, "0");
483  (*rsc)->effective_priority = (*rsc)->priority;
484 
485  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_NOTIFY);
486  if (crm_is_true(value)) {
487  set_bit((*rsc)->flags, pe_rsc_notify);
488  }
489 
490  if (xml_contains_remote_node((*rsc)->xml)) {
491  if (g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_CONTAINER)) {
492  container_remote_node = 1;
493  } else {
494  baremetal_remote_node = 1;
495  }
496  }
497 
498  value = g_hash_table_lookup((*rsc)->meta, XML_OP_ATTR_ALLOW_MIGRATE);
499  if (crm_is_true(value)) {
500  set_bit((*rsc)->flags, pe_rsc_allow_migrate);
501  } else if (value == NULL && baremetal_remote_node) {
502  /* by default, we want baremetal remote-nodes to be able
503  * to float around the cluster without having to stop all the
504  * resources within the remote-node before moving. Allowing
505  * migration support enables this feature. If this ever causes
506  * problems, migration support can be explicitly turned off with
507  * allow-migrate=false. */
508  set_bit((*rsc)->flags, pe_rsc_allow_migrate);
509  }
510 
511  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MANAGED);
512  if (value != NULL && safe_str_neq("default", value)) {
513  gboolean bool_value = TRUE;
514 
515  crm_str_to_boolean(value, &bool_value);
516  if (bool_value == FALSE) {
517  clear_bit((*rsc)->flags, pe_rsc_managed);
518  } else {
519  set_bit((*rsc)->flags, pe_rsc_managed);
520  }
521  }
522 
523  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MAINTENANCE);
524  if (value != NULL && safe_str_neq("default", value)) {
525  gboolean bool_value = FALSE;
526 
527  crm_str_to_boolean(value, &bool_value);
528  if (bool_value == TRUE) {
529  clear_bit((*rsc)->flags, pe_rsc_managed);
530  set_bit((*rsc)->flags, pe_rsc_maintenance);
531  }
532 
533  } else if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
534  clear_bit((*rsc)->flags, pe_rsc_managed);
535  set_bit((*rsc)->flags, pe_rsc_maintenance);
536  }
537 
538  pe_rsc_trace((*rsc), "Options for %s", (*rsc)->id);
539 
540  handle_rsc_isolation(*rsc);
541 
542  top = uber_parent(*rsc);
543  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_UNIQUE);
544  if (crm_is_true(value) || top->variant < pe_clone) {
545  set_bit((*rsc)->flags, pe_rsc_unique);
546  }
547 
548  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_RESTART);
549  if (safe_str_eq(value, "restart")) {
550  (*rsc)->restart_type = pe_restart_restart;
551  pe_rsc_trace((*rsc), "\tDependency restart handling: restart");
552 
553  } else {
554  (*rsc)->restart_type = pe_restart_ignore;
555  pe_rsc_trace((*rsc), "\tDependency restart handling: ignore");
556  }
557 
558  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MULTIPLE);
559  if (safe_str_eq(value, "stop_only")) {
560  (*rsc)->recovery_type = recovery_stop_only;
561  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop only");
562 
563  } else if (safe_str_eq(value, "block")) {
564  (*rsc)->recovery_type = recovery_block;
565  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: block");
566 
567  } else {
568  (*rsc)->recovery_type = recovery_stop_start;
569  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop/start");
570  }
571 
572  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_STICKINESS);
573  if (value != NULL && safe_str_neq("default", value)) {
574  (*rsc)->stickiness = char2score(value);
575  }
576 
577  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_STICKINESS);
578  if (value != NULL && safe_str_neq("default", value)) {
579  (*rsc)->migration_threshold = char2score(value);
580 
581  } else if (value == NULL) {
582  /* Make a best-effort guess at a migration threshold for people with 0.6 configs
583  * try with underscores and hyphens, from both the resource and global defaults section
584  */
585 
586  value = g_hash_table_lookup((*rsc)->meta, "resource-failure-stickiness");
587  if (value == NULL) {
588  value = g_hash_table_lookup((*rsc)->meta, "resource_failure_stickiness");
589  }
590  if (value == NULL) {
591  value =
592  g_hash_table_lookup(data_set->config_hash, "default-resource-failure-stickiness");
593  }
594  if (value == NULL) {
595  value =
596  g_hash_table_lookup(data_set->config_hash, "default_resource_failure_stickiness");
597  }
598 
599  if (value) {
600  int fail_sticky = char2score(value);
601 
602  if (fail_sticky == -INFINITY) {
603  (*rsc)->migration_threshold = 1;
604  pe_rsc_info((*rsc),
605  "Set a migration threshold of %d for %s based on a failure-stickiness of %s",
606  (*rsc)->migration_threshold, (*rsc)->id, value);
607 
608  } else if ((*rsc)->stickiness != 0 && fail_sticky != 0) {
609  (*rsc)->migration_threshold = (*rsc)->stickiness / fail_sticky;
610  if ((*rsc)->migration_threshold < 0) {
611  /* Make sure it's positive */
612  (*rsc)->migration_threshold = 0 - (*rsc)->migration_threshold;
613  }
614  (*rsc)->migration_threshold += 1;
615  pe_rsc_info((*rsc),
616  "Calculated a migration threshold for %s of %d based on a stickiness of %d/%s",
617  (*rsc)->id, (*rsc)->migration_threshold, (*rsc)->stickiness, value);
618  }
619  }
620  }
621 
622  if (safe_str_eq(rclass, "stonith")) {
624  set_bit((*rsc)->flags, pe_rsc_fence_device);
625  }
626 
627  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_REQUIRES);
628 
629  handle_requires_pref:
630  if (safe_str_eq(value, "nothing")) {
631 
632  } else if (safe_str_eq(value, "quorum")) {
633  set_bit((*rsc)->flags, pe_rsc_needs_quorum);
634 
635  } else if (safe_str_eq(value, "unfencing")) {
636  if (is_set((*rsc)->flags, pe_rsc_fence_device)) {
637  crm_config_warn("%s is a fencing device but requires (un)fencing", (*rsc)->id);
638  value = "quorum";
639  isdefault = TRUE;
640  goto handle_requires_pref;
641 
642  } else if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
643  crm_config_warn("%s requires (un)fencing but fencing is disabled", (*rsc)->id);
644  value = "quorum";
645  isdefault = TRUE;
646  goto handle_requires_pref;
647 
648  } else {
649  set_bit((*rsc)->flags, pe_rsc_needs_fencing);
650  set_bit((*rsc)->flags, pe_rsc_needs_unfencing);
651  }
652 
653  } else if (safe_str_eq(value, "fencing")) {
654  set_bit((*rsc)->flags, pe_rsc_needs_fencing);
655  if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
656  crm_config_warn("%s requires fencing but fencing is disabled", (*rsc)->id);
657  }
658 
659  } else {
660  if (value) {
661  crm_config_err("Invalid value for %s->requires: %s%s",
662  (*rsc)->id, value,
663  is_set(data_set->flags, pe_flag_stonith_enabled) ? "" : " (stonith-enabled=false)");
664  }
665 
666  isdefault = TRUE;
667  if(is_set((*rsc)->flags, pe_rsc_fence_device)) {
668  value = "quorum";
669 
670  } else if (is_set(data_set->flags, pe_flag_enable_unfencing)) {
671  value = "unfencing";
672 
673  } else if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
674  value = "fencing";
675 
676  } else if (data_set->no_quorum_policy == no_quorum_ignore) {
677  value = "nothing";
678 
679  } else {
680  value = "quorum";
681  }
682  goto handle_requires_pref;
683  }
684 
685  pe_rsc_trace((*rsc), "\tRequired to start: %s%s", value, isdefault?" (default)":"");
686  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_TIMEOUT);
687  if (value != NULL) {
688  /* call crm_get_msec() and convert back to seconds */
689  (*rsc)->failure_timeout = (crm_get_msec(value) / 1000);
690  }
691 
692  if (baremetal_remote_node) {
693  value = g_hash_table_lookup((*rsc)->parameters, XML_REMOTE_ATTR_RECONNECT_INTERVAL);
694  if (value) {
695  /* reconnect delay works by setting failure_timeout and preventing the
696  * connection from starting until the failure is cleared. */
697  (*rsc)->remote_reconnect_interval = (crm_get_msec(value) / 1000);
698  /* we want to override any default failure_timeout in use when remote
699  * reconnect_interval is in use. */
700  (*rsc)->failure_timeout = (*rsc)->remote_reconnect_interval;
701  }
702  }
703 
704  get_target_role(*rsc, &((*rsc)->next_role));
705  pe_rsc_trace((*rsc), "\tDesired next state: %s",
706  (*rsc)->next_role != RSC_ROLE_UNKNOWN ? role2text((*rsc)->next_role) : "default");
707 
708  if ((*rsc)->fns->unpack(*rsc, data_set) == FALSE) {
709  return FALSE;
710  }
711 
712  if (is_set(data_set->flags, pe_flag_symmetric_cluster)) {
713  resource_location(*rsc, NULL, 0, "symmetric_default", data_set);
714  } else if (container_remote_node) {
715  /* remote resources tied to a container resource must always be allowed
716  * to opt-in to the cluster. Whether the connection resource is actually
717  * allowed to be placed on a node is dependent on the container resource */
718  resource_location(*rsc, NULL, 0, "remote_connection_default", data_set);
719  }
720 
721  pe_rsc_trace((*rsc), "\tAction notification: %s",
722  is_set((*rsc)->flags, pe_rsc_notify) ? "required" : "not required");
723 
724  (*rsc)->utilization =
725  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
726 
727  unpack_instance_attributes(data_set->input, (*rsc)->xml, XML_TAG_UTILIZATION, NULL,
728  (*rsc)->utilization, NULL, FALSE, data_set->now);
729 
730 /* data_set->resources = g_list_append(data_set->resources, (*rsc)); */
731 
732  if (expanded_xml) {
733  if (add_template_rsc(xml_obj, data_set) == FALSE) {
734  return FALSE;
735  }
736  }
737  return TRUE;
738 }
739 
740 void
741 common_update_score(resource_t * rsc, const char *id, int score)
742 {
743  node_t *node = NULL;
744 
745  node = pe_hash_table_lookup(rsc->allowed_nodes, id);
746  if (node != NULL) {
747  pe_rsc_trace(rsc, "Updating score for %s on %s: %d + %d", rsc->id, id, node->weight, score);
748  node->weight = merge_weights(node->weight, score);
749  }
750 
751  if (rsc->children) {
752  GListPtr gIter = rsc->children;
753 
754  for (; gIter != NULL; gIter = gIter->next) {
755  resource_t *child_rsc = (resource_t *) gIter->data;
756 
757  common_update_score(child_rsc, id, score);
758  }
759  }
760 }
761 
762 gboolean
764 {
765  resource_t *parent = child;
766 
767  if (parent == NULL || rsc == NULL) {
768  return FALSE;
769  }
770  while (parent->parent != NULL) {
771  if (parent->parent == rsc) {
772  return TRUE;
773  }
774  parent = parent->parent;
775  }
776  return FALSE;
777 }
778 
779 resource_t *
781 {
782  resource_t *parent = rsc;
783 
784  if (parent == NULL) {
785  return NULL;
786  }
787  while (parent->parent != NULL) {
788  parent = parent->parent;
789  }
790  return parent;
791 }
792 
793 void
795 {
796  if (rsc == NULL) {
797  return;
798  }
799 
800  pe_rsc_trace(rsc, "Freeing %s %d", rsc->id, rsc->variant);
801 
802  g_list_free(rsc->rsc_cons);
803  g_list_free(rsc->rsc_cons_lhs);
804  g_list_free(rsc->rsc_tickets);
805  g_list_free(rsc->dangling_migrations);
806 
807  if (rsc->parameters != NULL) {
808  g_hash_table_destroy(rsc->parameters);
809  }
810  if (rsc->meta != NULL) {
811  g_hash_table_destroy(rsc->meta);
812  }
813  if (rsc->utilization != NULL) {
814  g_hash_table_destroy(rsc->utilization);
815  }
816 
817  if (rsc->parent == NULL && is_set(rsc->flags, pe_rsc_orphan)) {
818  free_xml(rsc->xml);
819  rsc->xml = NULL;
820  free_xml(rsc->orig_xml);
821  rsc->orig_xml = NULL;
822 
823  /* if rsc->orig_xml, then rsc->xml is an expanded xml from a template */
824  } else if (rsc->orig_xml) {
825  free_xml(rsc->xml);
826  rsc->xml = NULL;
827  }
828  if (rsc->running_on) {
829  g_list_free(rsc->running_on);
830  rsc->running_on = NULL;
831  }
832  if (rsc->known_on) {
833  g_hash_table_destroy(rsc->known_on);
834  rsc->known_on = NULL;
835  }
836  if (rsc->actions) {
837  g_list_free(rsc->actions);
838  rsc->actions = NULL;
839  }
840  if (rsc->allowed_nodes) {
841  g_hash_table_destroy(rsc->allowed_nodes);
842  rsc->allowed_nodes = NULL;
843  }
844  g_list_free(rsc->fillers);
845  g_list_free(rsc->rsc_location);
846  pe_rsc_trace(rsc, "Resource freed");
847  free(rsc->id);
848  free(rsc->clone_name);
849  free(rsc->allocated_to);
850  free(rsc->variant_opaque);
851  free(rsc->pending_task);
852  free(rsc);
853 }
#define LOG_TRACE
Definition: logging.h:29
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:2440
void clone_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: clone.c:371
xmlNode * xml
Definition: status.h:242
void group_free(resource_t *rsc)
Definition: group.c:195
#define pe_flag_have_stonith_resource
Definition: status.h:63
gboolean safe_str_neq(const char *a, const char *b)
Definition: utils.c:668
#define INFINITY
Definition: crm.h:77
#define pe_rsc_needs_unfencing
Definition: status.h:204
GHashTable * utilization
Definition: status.h:282
gboolean get_target_role(resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:1729
#define pe_flag_enable_unfencing
Definition: status.h:64
int default_resource_stickiness
Definition: status.h:93
#define pe_rsc_maintenance
Definition: status.h:200
int weight
Definition: status.h:162
#define XML_TAG_UTILIZATION
Definition: msg_xml.h:178
enum pe_obj_types get_resource_type(const char *name)
Definition: complex.c:67
#define RSC_ROLE_STARTED_S
Definition: common.h:93
#define crm_config_err(fmt...)
Definition: crm_internal.h:269
#define pe_rsc_needs_quorum
Definition: status.h:202
#define XML_RSC_ATTR_INCARNATION
Definition: msg_xml.h:195
void common_free(resource_t *rsc)
Definition: complex.c:794
#define pe_rsc_orphan
Definition: status.h:171
GListPtr rsc_location
Definition: status.h:268
char * native_parameter(resource_t *rsc, node_t *node, gboolean create, const char *name, pe_working_set_t *data_set)
Definition: native.c:230
int char2score(const char *score)
Definition: utils.c:225
long long crm_get_msec(const char *input)
Definition: utils.c:748
#define pe_rsc_provisional
Definition: status.h:180
xmlNode * find_entity(xmlNode *parent, const char *node_name, const char *id)
Definition: xml.c:2473
enum pe_obj_types variant
Definition: status.h:248
int crm_parse_int(const char *text, const char *default_text)
Definition: utils.c:643
#define XML_CIB_TAG_RSC_TEMPLATE
Definition: msg_xml.h:186
void g_hash_destroy_str(gpointer data)
Definition: utils.c:587
no_quorum_policy_t no_quorum_policy
Definition: status.h:94
#define XML_RSC_ATTR_STICKINESS
Definition: msg_xml.h:206
char * clone_name
Definition: status.h:241
xmlNode * orig_xml
Definition: status.h:243
#define clear_bit(word, bit)
Definition: crm_internal.h:199
#define pe_rsc_allow_migrate
Definition: status.h:196
void native_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:436
GListPtr children
Definition: status.h:284
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:225
void clone_free(resource_t *rsc)
Definition: clone.c:555
enum rsc_role_e group_resource_state(const resource_t *rsc, gboolean current)
Definition: group.c:218
char version[256]
Definition: plugin.c:84
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
Definition: xml.c:2741
char * id
Definition: status.h:240
GHashTable * parameters
Definition: status.h:281
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:242
const char * isolation_wrapper
Definition: status.h:295
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:2894
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:173
#define XML_CIB_TAG_RESOURCES
Definition: msg_xml.h:157
const char * role2text(enum rsc_role_e role)
Definition: common.c:338
struct node_shared_s * details
Definition: status.h:165
#define set_bit(word, bit)
Definition: crm_internal.h:198
#define XML_RSC_ATTR_REQUIRES
Definition: msg_xml.h:211
GListPtr rsc_cons_lhs
Definition: status.h:266
resource_object_functions_t resource_class_functions[]
Definition: complex.c:27
resource_t * uber_parent(resource_t *rsc)
Definition: complex.c:780
#define XML_RSC_ATTR_CONTAINER
Definition: msg_xml.h:213
#define XML_ATTR_ID
Definition: msg_xml.h:100
char * pending_task
Definition: status.h:293
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:181
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:115
#define XML_RSC_ATTR_ISOLATION
Definition: msg_xml.h:191
xmlNode * rsc_defaults
Definition: status.h:110
pe_obj_types
Definition: complex.h:30
GHashTable * allowed_nodes
Definition: status.h:275
void * variant_opaque
Definition: status.h:247
GListPtr rsc_cons
Definition: status.h:267
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:2610
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
Definition: xml.c:5799
#define pe_rsc_runnable
Definition: status.h:190
#define XML_TAG_META_SETS
Definition: msg_xml.h:174
GHashTable * config_hash
Definition: status.h:96
gboolean xml_contains_remote_node(xmlNode *xml)
Definition: utils.c:2090
gboolean add_tag_ref(GHashTable *tags, const char *tag_name, const char *obj_ref)
Definition: utils.c:2198
#define XML_RSC_ATTR_MANAGED
Definition: msg_xml.h:202
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5839
unsigned long long flags
Definition: status.h:264
enum rsc_role_e native_resource_state(const resource_t *rsc, gboolean current)
Definition: native.c:682
#define pe_flag_maintenance_mode
Definition: status.h:60
void group_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: group.c:146
resource_t * parent
Definition: status.h:246
gboolean native_active(resource_t *rsc, gboolean all)
Definition: native.c:274
GListPtr dangling_migrations
Definition: status.h:285
void free_xml(xmlNode *child)
Definition: xml.c:2848
node_t * native_location(resource_t *rsc, GListPtr *list, gboolean current)
Definition: native.c:694
xmlNode * input
Definition: status.h:81
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: utils.c:1415
GListPtr fillers
Definition: status.h:291
GListPtr rsc_tickets
Definition: status.h:270
#define XML_REMOTE_ATTR_RECONNECT_INTERVAL
Definition: msg_xml.h:218
#define XML_RSC_ATTR_NOTIFY
Definition: msg_xml.h:205
void get_rsc_attributes(GHashTable *meta_hash, resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: complex.c:153
#define XML_RSC_ATTR_FAIL_STICKINESS
Definition: msg_xml.h:207
enum rsc_role_e clone_resource_state(const resource_t *rsc, gboolean current)
Definition: clone.c:590
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:763
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:204
#define crm_config_warn(fmt...)
Definition: crm_internal.h:270
GListPtr actions
Definition: status.h:269
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Definition: xml.c:2695
void get_meta_attributes(GHashTable *meta_hash, resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: complex.c:110
int crm_str_to_boolean(const char *s, int *ret)
Definition: utils.c:694
#define pe_rsc_unique
Definition: status.h:177
gboolean clone_active(resource_t *rsc, gboolean all)
Definition: clone.c:270
GHashTable * meta
Definition: status.h:280
#define XML_CIB_TAG_INCARNATION
Definition: msg_xml.h:183
#define XML_RSC_ATTR_MAINTENANCE
Definition: msg_xml.h:215
#define XML_RSC_ATTR_FAIL_TIMEOUT
Definition: msg_xml.h:208
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:414
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1284
gboolean group_active(resource_t *rsc, gboolean all)
Definition: group.c:101
const char * get_resource_typename(enum pe_obj_types type)
Definition: complex.c:86
GHashTable * attrs
Definition: status.h:147
#define RSC_ROLE_SLAVE_S
Definition: common.h:94
int compare_version(const char *version1, const char *version2)
Definition: utils.c:508
int merge_weights(int w1, int w2)
Definition: common.c:377
#define pe_rsc_managed
Definition: status.h:172
#define XML_RSC_ATTR_MULTIPLE
Definition: msg_xml.h:209
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:83
node_t * allocated_to
Definition: status.h:272
void common_update_score(resource_t *rsc, const char *id, int score)
Definition: complex.c:741
GHashTable * known_on
Definition: status.h:274
#define XML_RSC_ATTR_RESTART
Definition: msg_xml.h:192
#define XML_CIB_TAG_MASTER
Definition: msg_xml.h:184
void native_free(resource_t *rsc)
Definition: native.c:675
gboolean native_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: native.c:126
#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:686
#define pe_flag_is_managed_default
Definition: status.h:59
#define crm_log_xml_trace(xml, text)
Definition: logging.h:262
Definition: status.h:161
gboolean crm_is_true(const char *s)
Definition: utils.c:683
#define XML_CIB_TAG_GROUP
Definition: msg_xml.h:182
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:24
#define pe_flag_symmetric_cluster
Definition: status.h:58
gboolean common_unpack(xmlNode *xml_obj, resource_t **rsc, resource_t *parent, pe_working_set_t *data_set)
Definition: complex.c:381
char * crm_concat(const char *prefix, const char *suffix, char join)
Definition: utils.c:403
unsigned long long flags
Definition: status.h:90
#define ID(x)
Definition: msg_xml.h:408
#define pe_err(fmt...)
Definition: internal.h:26
#define pe_rsc_needs_fencing
Definition: status.h:203
#define safe_str_eq(a, b)
Definition: util.h:74
#define crm_str_hash
Definition: crm.h:196
gboolean group_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: group.c:31
#define pe_rsc_fence_device
Definition: status.h:178
GList * GListPtr
Definition: crm.h:190
#define pe_rsc_notify
Definition: status.h:176
crm_time_t * now
Definition: status.h:82
GHashTable * template_rsc_sets
Definition: status.h:121
resource_t * native_find_rsc(resource_t *rsc, const char *id, node_t *node, int flags)
Definition: native.c:161
#define XML_OP_ATTR_ALLOW_MIGRATE
Definition: msg_xml.h:222
#define pe_flag_stonith_enabled
Definition: status.h:62
enum crm_ais_msg_types type
Definition: internal.h:51
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:22
gboolean clone_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: clone.c:155
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:233
gboolean master_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: clone.c:137
GListPtr running_on
Definition: status.h:273