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