pacemaker  1.1.15-e174ec8
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  (*rsc)->cluster = data_set;
412 
413  if (expanded_xml) {
414  crm_log_xml_trace(expanded_xml, "Expanded resource...");
415  (*rsc)->xml = expanded_xml;
416  (*rsc)->orig_xml = xml_obj;
417 
418  } else {
419  (*rsc)->xml = xml_obj;
420  (*rsc)->orig_xml = NULL;
421  }
422 
423  /* Do not use xml_obj from here on, use (*rsc)->xml in case templates are involved */
424  rclass = crm_element_value((*rsc)->xml, XML_AGENT_ATTR_CLASS);
425  (*rsc)->parent = parent;
426 
427  ops = find_xml_node((*rsc)->xml, "operations", FALSE);
428  (*rsc)->ops_xml = expand_idref(ops, data_set->input);
429 
430  (*rsc)->variant = get_resource_type(crm_element_name((*rsc)->xml));
431  if ((*rsc)->variant == pe_unknown) {
432  pe_err("Unknown resource type: %s", crm_element_name((*rsc)->xml));
433  free(*rsc);
434  return FALSE;
435  }
436 
437  (*rsc)->parameters =
438  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
439 
440  (*rsc)->meta =
441  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
442 
443  (*rsc)->allowed_nodes =
444  g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
445 
446  (*rsc)->known_on = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
447 
448  value = crm_element_value((*rsc)->xml, XML_RSC_ATTR_INCARNATION);
449  if (value) {
450  (*rsc)->id = crm_concat(id, value, ':');
451  add_hash_param((*rsc)->meta, XML_RSC_ATTR_INCARNATION, value);
452 
453  } else {
454  (*rsc)->id = strdup(id);
455  }
456 
457  (*rsc)->fns = &resource_class_functions[(*rsc)->variant];
458  pe_rsc_trace((*rsc), "Unpacking resource...");
459 
460  get_meta_attributes((*rsc)->meta, *rsc, NULL, data_set);
461  get_rsc_attributes((*rsc)->parameters, *rsc, NULL, data_set);
462 
463  (*rsc)->flags = 0;
464  set_bit((*rsc)->flags, pe_rsc_runnable);
465  set_bit((*rsc)->flags, pe_rsc_provisional);
466 
467  if (is_set(data_set->flags, pe_flag_is_managed_default)) {
468  set_bit((*rsc)->flags, pe_rsc_managed);
469  }
470 
471  (*rsc)->rsc_cons = NULL;
472  (*rsc)->rsc_tickets = NULL;
473  (*rsc)->actions = NULL;
474  (*rsc)->role = RSC_ROLE_STOPPED;
475  (*rsc)->next_role = RSC_ROLE_UNKNOWN;
476 
477  (*rsc)->recovery_type = recovery_stop_start;
478  (*rsc)->stickiness = data_set->default_resource_stickiness;
479  (*rsc)->migration_threshold = INFINITY;
480  (*rsc)->failure_timeout = 0;
481 
482  value = g_hash_table_lookup((*rsc)->meta, XML_CIB_ATTR_PRIORITY);
483  (*rsc)->priority = crm_parse_int(value, "0");
484  (*rsc)->effective_priority = (*rsc)->priority;
485 
486  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_NOTIFY);
487  if (crm_is_true(value)) {
488  set_bit((*rsc)->flags, pe_rsc_notify);
489  }
490 
491  if (xml_contains_remote_node((*rsc)->xml)) {
492  if (g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_CONTAINER)) {
493  container_remote_node = 1;
494  } else {
495  baremetal_remote_node = 1;
496  }
497  }
498 
499  value = g_hash_table_lookup((*rsc)->meta, XML_OP_ATTR_ALLOW_MIGRATE);
500  if (crm_is_true(value)) {
501  set_bit((*rsc)->flags, pe_rsc_allow_migrate);
502  } else if (value == NULL && baremetal_remote_node) {
503  /* by default, we want baremetal remote-nodes to be able
504  * to float around the cluster without having to stop all the
505  * resources within the remote-node before moving. Allowing
506  * migration support enables this feature. If this ever causes
507  * problems, migration support can be explicitly turned off with
508  * allow-migrate=false. */
509  set_bit((*rsc)->flags, pe_rsc_allow_migrate);
510  }
511 
512  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MANAGED);
513  if (value != NULL && safe_str_neq("default", value)) {
514  gboolean bool_value = TRUE;
515 
516  crm_str_to_boolean(value, &bool_value);
517  if (bool_value == FALSE) {
518  clear_bit((*rsc)->flags, pe_rsc_managed);
519  } else {
520  set_bit((*rsc)->flags, pe_rsc_managed);
521  }
522  }
523 
524  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MAINTENANCE);
525  if (value != NULL && safe_str_neq("default", value)) {
526  gboolean bool_value = FALSE;
527 
528  crm_str_to_boolean(value, &bool_value);
529  if (bool_value == TRUE) {
530  clear_bit((*rsc)->flags, pe_rsc_managed);
531  set_bit((*rsc)->flags, pe_rsc_maintenance);
532  }
533 
534  } else if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
535  clear_bit((*rsc)->flags, pe_rsc_managed);
536  set_bit((*rsc)->flags, pe_rsc_maintenance);
537  }
538 
539  pe_rsc_trace((*rsc), "Options for %s", (*rsc)->id);
540 
541  handle_rsc_isolation(*rsc);
542 
543  top = uber_parent(*rsc);
544  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_UNIQUE);
545  if (crm_is_true(value) || top->variant < pe_clone) {
546  set_bit((*rsc)->flags, pe_rsc_unique);
547  }
548 
549  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_RESTART);
550  if (safe_str_eq(value, "restart")) {
551  (*rsc)->restart_type = pe_restart_restart;
552  pe_rsc_trace((*rsc), "\tDependency restart handling: restart");
553 
554  } else {
555  (*rsc)->restart_type = pe_restart_ignore;
556  pe_rsc_trace((*rsc), "\tDependency restart handling: ignore");
557  }
558 
559  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MULTIPLE);
560  if (safe_str_eq(value, "stop_only")) {
561  (*rsc)->recovery_type = recovery_stop_only;
562  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop only");
563 
564  } else if (safe_str_eq(value, "block")) {
565  (*rsc)->recovery_type = recovery_block;
566  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: block");
567 
568  } else {
569  (*rsc)->recovery_type = recovery_stop_start;
570  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop/start");
571  }
572 
573  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_STICKINESS);
574  if (value != NULL && safe_str_neq("default", value)) {
575  (*rsc)->stickiness = char2score(value);
576  }
577 
578  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_STICKINESS);
579  if (value != NULL && safe_str_neq("default", value)) {
580  (*rsc)->migration_threshold = char2score(value);
581 
582  } else if (value == NULL) {
583  /* Make a best-effort guess at a migration threshold for people with 0.6 configs
584  * try with underscores and hyphens, from both the resource and global defaults section
585  */
586 
587  value = g_hash_table_lookup((*rsc)->meta, "resource-failure-stickiness");
588  if (value == NULL) {
589  value = g_hash_table_lookup((*rsc)->meta, "resource_failure_stickiness");
590  }
591  if (value == NULL) {
592  value =
593  g_hash_table_lookup(data_set->config_hash, "default-resource-failure-stickiness");
594  }
595  if (value == NULL) {
596  value =
597  g_hash_table_lookup(data_set->config_hash, "default_resource_failure_stickiness");
598  }
599 
600  if (value) {
601  int fail_sticky = char2score(value);
602 
603  if (fail_sticky == -INFINITY) {
604  (*rsc)->migration_threshold = 1;
605  pe_rsc_info((*rsc),
606  "Set a migration threshold of %d for %s based on a failure-stickiness of %s",
607  (*rsc)->migration_threshold, (*rsc)->id, value);
608 
609  } else if ((*rsc)->stickiness != 0 && fail_sticky != 0) {
610  (*rsc)->migration_threshold = (*rsc)->stickiness / fail_sticky;
611  if ((*rsc)->migration_threshold < 0) {
612  /* Make sure it's positive */
613  (*rsc)->migration_threshold = 0 - (*rsc)->migration_threshold;
614  }
615  (*rsc)->migration_threshold += 1;
616  pe_rsc_info((*rsc),
617  "Calculated a migration threshold for %s of %d based on a stickiness of %d/%s",
618  (*rsc)->id, (*rsc)->migration_threshold, (*rsc)->stickiness, value);
619  }
620  }
621  }
622 
623  if (safe_str_eq(rclass, "stonith")) {
625  set_bit((*rsc)->flags, pe_rsc_fence_device);
626  }
627 
628  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_REQUIRES);
629 
630  handle_requires_pref:
631  if (safe_str_eq(value, "nothing")) {
632 
633  } else if (safe_str_eq(value, "quorum")) {
634  set_bit((*rsc)->flags, pe_rsc_needs_quorum);
635 
636  } else if (safe_str_eq(value, "unfencing")) {
637  if (is_set((*rsc)->flags, pe_rsc_fence_device)) {
638  crm_config_warn("%s is a fencing device but requires (un)fencing", (*rsc)->id);
639  value = "quorum";
640  isdefault = TRUE;
641  goto handle_requires_pref;
642 
643  } else if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
644  crm_config_warn("%s requires (un)fencing but fencing is disabled", (*rsc)->id);
645  value = "quorum";
646  isdefault = TRUE;
647  goto handle_requires_pref;
648 
649  } else {
650  set_bit((*rsc)->flags, pe_rsc_needs_fencing);
651  set_bit((*rsc)->flags, pe_rsc_needs_unfencing);
652  }
653 
654  } else if (safe_str_eq(value, "fencing")) {
655  set_bit((*rsc)->flags, pe_rsc_needs_fencing);
656  if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
657  crm_config_warn("%s requires fencing but fencing is disabled", (*rsc)->id);
658  }
659 
660  } else {
661  if (value) {
662  crm_config_err("Invalid value for %s->requires: %s%s",
663  (*rsc)->id, value,
664  is_set(data_set->flags, pe_flag_stonith_enabled) ? "" : " (stonith-enabled=false)");
665  }
666 
667  isdefault = TRUE;
668  if(is_set((*rsc)->flags, pe_rsc_fence_device)) {
669  value = "quorum";
670 
671  } else if (is_set(data_set->flags, pe_flag_enable_unfencing)) {
672  value = "unfencing";
673 
674  } else if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
675  value = "fencing";
676 
677  } else if (data_set->no_quorum_policy == no_quorum_ignore) {
678  value = "nothing";
679 
680  } else {
681  value = "quorum";
682  }
683  goto handle_requires_pref;
684  }
685 
686  pe_rsc_trace((*rsc), "\tRequired to start: %s%s", value, isdefault?" (default)":"");
687  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_TIMEOUT);
688  if (value != NULL) {
689  /* call crm_get_msec() and convert back to seconds */
690  (*rsc)->failure_timeout = (crm_get_msec(value) / 1000);
691  }
692 
693  if (baremetal_remote_node) {
694  value = g_hash_table_lookup((*rsc)->parameters, XML_REMOTE_ATTR_RECONNECT_INTERVAL);
695  if (value) {
696  /* reconnect delay works by setting failure_timeout and preventing the
697  * connection from starting until the failure is cleared. */
698  (*rsc)->remote_reconnect_interval = (crm_get_msec(value) / 1000);
699  /* we want to override any default failure_timeout in use when remote
700  * reconnect_interval is in use. */
701  (*rsc)->failure_timeout = (*rsc)->remote_reconnect_interval;
702  }
703  }
704 
705  get_target_role(*rsc, &((*rsc)->next_role));
706  pe_rsc_trace((*rsc), "\tDesired next state: %s",
707  (*rsc)->next_role != RSC_ROLE_UNKNOWN ? role2text((*rsc)->next_role) : "default");
708 
709  if ((*rsc)->fns->unpack(*rsc, data_set) == FALSE) {
710  return FALSE;
711  }
712 
713  if (is_set(data_set->flags, pe_flag_symmetric_cluster)) {
714  resource_location(*rsc, NULL, 0, "symmetric_default", data_set);
715  } else if (container_remote_node) {
716  /* remote resources tied to a container resource must always be allowed
717  * to opt-in to the cluster. Whether the connection resource is actually
718  * allowed to be placed on a node is dependent on the container resource */
719  resource_location(*rsc, NULL, 0, "remote_connection_default", data_set);
720  }
721 
722  pe_rsc_trace((*rsc), "\tAction notification: %s",
723  is_set((*rsc)->flags, pe_rsc_notify) ? "required" : "not required");
724 
725  (*rsc)->utilization =
726  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
727 
728  unpack_instance_attributes(data_set->input, (*rsc)->xml, XML_TAG_UTILIZATION, NULL,
729  (*rsc)->utilization, NULL, FALSE, data_set->now);
730 
731 /* data_set->resources = g_list_append(data_set->resources, (*rsc)); */
732 
733  if (expanded_xml) {
734  if (add_template_rsc(xml_obj, data_set) == FALSE) {
735  return FALSE;
736  }
737  }
738  return TRUE;
739 }
740 
741 void
742 common_update_score(resource_t * rsc, const char *id, int score)
743 {
744  node_t *node = NULL;
745 
746  node = pe_hash_table_lookup(rsc->allowed_nodes, id);
747  if (node != NULL) {
748  pe_rsc_trace(rsc, "Updating score for %s on %s: %d + %d", rsc->id, id, node->weight, score);
749  node->weight = merge_weights(node->weight, score);
750  }
751 
752  if (rsc->children) {
753  GListPtr gIter = rsc->children;
754 
755  for (; gIter != NULL; gIter = gIter->next) {
756  resource_t *child_rsc = (resource_t *) gIter->data;
757 
758  common_update_score(child_rsc, id, score);
759  }
760  }
761 }
762 
763 gboolean
765 {
766  resource_t *parent = child;
767 
768  if (parent == NULL || rsc == NULL) {
769  return FALSE;
770  }
771  while (parent->parent != NULL) {
772  if (parent->parent == rsc) {
773  return TRUE;
774  }
775  parent = parent->parent;
776  }
777  return FALSE;
778 }
779 
780 resource_t *
782 {
783  resource_t *parent = rsc;
784 
785  if (parent == NULL) {
786  return NULL;
787  }
788  while (parent->parent != NULL) {
789  parent = parent->parent;
790  }
791  return parent;
792 }
793 
794 void
796 {
797  if (rsc == NULL) {
798  return;
799  }
800 
801  pe_rsc_trace(rsc, "Freeing %s %d", rsc->id, rsc->variant);
802 
803  g_list_free(rsc->rsc_cons);
804  g_list_free(rsc->rsc_cons_lhs);
805  g_list_free(rsc->rsc_tickets);
806  g_list_free(rsc->dangling_migrations);
807 
808  if (rsc->parameters != NULL) {
809  g_hash_table_destroy(rsc->parameters);
810  }
811  if (rsc->meta != NULL) {
812  g_hash_table_destroy(rsc->meta);
813  }
814  if (rsc->utilization != NULL) {
815  g_hash_table_destroy(rsc->utilization);
816  }
817 
818  if (rsc->parent == NULL && is_set(rsc->flags, pe_rsc_orphan)) {
819  free_xml(rsc->xml);
820  rsc->xml = NULL;
821  free_xml(rsc->orig_xml);
822  rsc->orig_xml = NULL;
823 
824  /* if rsc->orig_xml, then rsc->xml is an expanded xml from a template */
825  } else if (rsc->orig_xml) {
826  free_xml(rsc->xml);
827  rsc->xml = NULL;
828  }
829  if (rsc->running_on) {
830  g_list_free(rsc->running_on);
831  rsc->running_on = NULL;
832  }
833  if (rsc->known_on) {
834  g_hash_table_destroy(rsc->known_on);
835  rsc->known_on = NULL;
836  }
837  if (rsc->actions) {
838  g_list_free(rsc->actions);
839  rsc->actions = NULL;
840  }
841  if (rsc->allowed_nodes) {
842  g_hash_table_destroy(rsc->allowed_nodes);
843  rsc->allowed_nodes = NULL;
844  }
845  g_list_free(rsc->fillers);
846  g_list_free(rsc->rsc_location);
847  pe_rsc_trace(rsc, "Resource freed");
848  free(rsc->id);
849  free(rsc->clone_name);
850  free(rsc->allocated_to);
851  free(rsc->variant_opaque);
852  free(rsc->pending_task);
853  free(rsc);
854 }
#define LOG_TRACE
Definition: logging.h:29
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:2443
void clone_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: clone.c:390
xmlNode * xml
Definition: status.h:246
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:696
#define INFINITY
Definition: crm.h:77
#define pe_rsc_needs_unfencing
Definition: status.h:208
GHashTable * utilization
Definition: status.h:286
gboolean get_target_role(resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:1727
#define pe_flag_enable_unfencing
Definition: status.h:64
int default_resource_stickiness
Definition: status.h:94
#define pe_rsc_maintenance
Definition: status.h:204
int weight
Definition: status.h:166
#define XML_TAG_UTILIZATION
Definition: msg_xml.h:181
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:270
#define pe_rsc_needs_quorum
Definition: status.h:206
#define XML_RSC_ATTR_INCARNATION
Definition: msg_xml.h:198
void common_free(resource_t *rsc)
Definition: complex.c:795
#define pe_rsc_orphan
Definition: status.h:175
GListPtr rsc_location
Definition: status.h:272
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:253
long long crm_get_msec(const char *input)
Definition: utils.c:776
#define pe_rsc_provisional
Definition: status.h:184
xmlNode * find_entity(xmlNode *parent, const char *node_name, const char *id)
Definition: xml.c:2476
enum pe_obj_types variant
Definition: status.h:252
int crm_parse_int(const char *text, const char *default_text)
Definition: utils.c:671
#define XML_CIB_TAG_RSC_TEMPLATE
Definition: msg_xml.h:189
void g_hash_destroy_str(gpointer data)
Definition: utils.c:615
no_quorum_policy_t no_quorum_policy
Definition: status.h:95
#define XML_RSC_ATTR_STICKINESS
Definition: msg_xml.h:209
char * clone_name
Definition: status.h:245
xmlNode * orig_xml
Definition: status.h:247
#define clear_bit(word, bit)
Definition: crm_internal.h:200
#define pe_rsc_allow_migrate
Definition: status.h:200
void native_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:436
GListPtr children
Definition: status.h:288
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:592
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:2744
char * id
Definition: status.h:244
GHashTable * parameters
Definition: status.h:285
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:245
const char * isolation_wrapper
Definition: status.h:299
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:2897
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:176
#define XML_CIB_TAG_RESOURCES
Definition: msg_xml.h:157
const char * role2text(enum rsc_role_e role)
Definition: common.c:340
struct node_shared_s * details
Definition: status.h:169
#define set_bit(word, bit)
Definition: crm_internal.h:199
#define XML_RSC_ATTR_REQUIRES
Definition: msg_xml.h:214
GListPtr rsc_cons_lhs
Definition: status.h:270
resource_object_functions_t resource_class_functions[]
Definition: complex.c:27
resource_t * uber_parent(resource_t *rsc)
Definition: complex.c:781
#define XML_RSC_ATTR_CONTAINER
Definition: msg_xml.h:216
#define XML_ATTR_ID
Definition: msg_xml.h:100
char * pending_task
Definition: status.h:297
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:184
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:115
#define XML_RSC_ATTR_ISOLATION
Definition: msg_xml.h:194
xmlNode * rsc_defaults
Definition: status.h:111
pe_obj_types
Definition: complex.h:30
GHashTable * allowed_nodes
Definition: status.h:279
void * variant_opaque
Definition: status.h:251
GListPtr rsc_cons
Definition: status.h:271
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:2613
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
Definition: xml.c:5802
#define pe_rsc_runnable
Definition: status.h:194
#define XML_TAG_META_SETS
Definition: msg_xml.h:177
GHashTable * config_hash
Definition: status.h:97
gboolean add_tag_ref(GHashTable *tags, const char *tag_name, const char *obj_ref)
Definition: utils.c:2117
#define XML_RSC_ATTR_MANAGED
Definition: msg_xml.h:205
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5842
unsigned long long flags
Definition: status.h:268
enum rsc_role_e native_resource_state(const resource_t *rsc, gboolean current)
Definition: native.c:697
#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:250
gboolean native_active(resource_t *rsc, gboolean all)
Definition: native.c:274
GListPtr dangling_migrations
Definition: status.h:289
void free_xml(xmlNode *child)
Definition: xml.c:2851
node_t * native_location(resource_t *rsc, GListPtr *list, gboolean current)
Definition: native.c:709
xmlNode * input
Definition: status.h:82
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: utils.c:1441
GListPtr fillers
Definition: status.h:295
GListPtr rsc_tickets
Definition: status.h:274
#define XML_REMOTE_ATTR_RECONNECT_INTERVAL
Definition: msg_xml.h:221
#define XML_RSC_ATTR_NOTIFY
Definition: msg_xml.h:208
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:210
enum rsc_role_e clone_resource_state(const resource_t *rsc, gboolean current)
Definition: clone.c:627
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:764
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:207
#define crm_config_warn(fmt...)
Definition: crm_internal.h:271
GListPtr actions
Definition: status.h:273
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Definition: xml.c:2698
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:722
#define pe_rsc_unique
Definition: status.h:181
gboolean clone_active(resource_t *rsc, gboolean all)
Definition: clone.c:270
GHashTable * meta
Definition: status.h:284
gboolean xml_contains_remote_node(xmlNode *xml)
Definition: remote.c:91
#define XML_CIB_TAG_INCARNATION
Definition: msg_xml.h:186
#define XML_RSC_ATTR_MAINTENANCE
Definition: msg_xml.h:218
#define XML_RSC_ATTR_FAIL_TIMEOUT
Definition: msg_xml.h:211
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:416
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1282
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:151
#define RSC_ROLE_SLAVE_S
Definition: common.h:94
int compare_version(const char *version1, const char *version2)
Definition: utils.c:536
int merge_weights(int w1, int w2)
Definition: common.c:379
#define pe_rsc_managed
Definition: status.h:176
#define XML_RSC_ATTR_MULTIPLE
Definition: msg_xml.h:212
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:83
node_t * allocated_to
Definition: status.h:276
void common_update_score(resource_t *rsc, const char *id, int score)
Definition: complex.c:742
GHashTable * known_on
Definition: status.h:278
#define XML_RSC_ATTR_RESTART
Definition: msg_xml.h:195
#define XML_CIB_TAG_MASTER
Definition: msg_xml.h:187
void native_free(resource_t *rsc)
Definition: native.c:690
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:165
gboolean crm_is_true(const char *s)
Definition: utils.c:711
#define XML_CIB_TAG_GROUP
Definition: msg_xml.h:185
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:25
#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:431
unsigned long long flags
Definition: status.h:91
#define ID(x)
Definition: msg_xml.h:419
#define pe_err(fmt...)
Definition: internal.h:27
#define pe_rsc_needs_fencing
Definition: status.h:207
#define safe_str_eq(a, b)
Definition: util.h:74
#define crm_str_hash
Definition: crm.h:198
gboolean group_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: group.c:31
#define pe_rsc_fence_device
Definition: status.h:182
GList * GListPtr
Definition: crm.h:192
#define pe_rsc_notify
Definition: status.h:180
crm_time_t * now
Definition: status.h:83
GHashTable * template_rsc_sets
Definition: status.h:122
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:225
#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:23
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:236
gboolean master_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: clone.c:137
GListPtr running_on
Definition: status.h:277