pacemaker  2.0.5-ba59be712
Scalable High-Availability cluster resource manager
complex.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <crm/pengine/rules.h>
13 #include <crm/pengine/internal.h>
14 #include <crm/msg_xml.h>
16 
17 void populate_hash(xmlNode * nvpair_list, GHashTable * hash, const char **attrs, int attrs_length);
18 
20  {
31  },
32  {
40  group_free,
43  },
44  {
52  clone_free,
55  },
56  {
67  }
68 };
69 
70 static enum pe_obj_types
71 get_resource_type(const char *name)
72 {
73  if (pcmk__str_eq(name, XML_CIB_TAG_RESOURCE, pcmk__str_casei)) {
74  return pe_native;
75 
76  } else if (pcmk__str_eq(name, XML_CIB_TAG_GROUP, pcmk__str_casei)) {
77  return pe_group;
78 
79  } else if (pcmk__str_eq(name, XML_CIB_TAG_INCARNATION, pcmk__str_casei)) {
80  return pe_clone;
81 
82  } else if (pcmk__str_eq(name, XML_CIB_TAG_MASTER, pcmk__str_casei)) {
83  // @COMPAT deprecated since 2.0.0
84  return pe_clone;
85 
86  } else if (pcmk__str_eq(name, XML_CIB_TAG_CONTAINER, pcmk__str_casei)) {
87  return pe_container;
88  }
89 
90  return pe_unknown;
91 }
92 
93 static void
94 dup_attr(gpointer key, gpointer value, gpointer user_data)
95 {
96  add_hash_param(user_data, key, value);
97 }
98 
99 void
100 get_meta_attributes(GHashTable * meta_hash, pe_resource_t * rsc,
101  pe_node_t * node, pe_working_set_t * data_set)
102 {
103  pe_rsc_eval_data_t rsc_rule_data = {
105  .provider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER),
107  };
108 
109  pe_rule_eval_data_t rule_data = {
110  .node_hash = NULL,
111  .role = RSC_ROLE_UNKNOWN,
112  .now = data_set->now,
113  .match_data = NULL,
114  .rsc_data = &rsc_rule_data,
115  .op_data = NULL
116  };
117 
118  if (node) {
119  rule_data.node_hash = node->details->attrs;
120  }
121 
122  if (rsc->xml) {
123  xmlAttrPtr xIter = NULL;
124 
125  for (xIter = rsc->xml->properties; xIter; xIter = xIter->next) {
126  const char *prop_name = (const char *)xIter->name;
127  const char *prop_value = crm_element_value(rsc->xml, prop_name);
128 
129  add_hash_param(meta_hash, prop_name, prop_value);
130  }
131  }
132 
134  meta_hash, NULL, FALSE, data_set);
135 
136  /* set anything else based on the parent */
137  if (rsc->parent != NULL) {
138  g_hash_table_foreach(rsc->parent->meta, dup_attr, meta_hash);
139  }
140 
141  /* and finally check the defaults */
143  &rule_data, meta_hash, NULL, FALSE, data_set);
144 }
145 
146 void
147 get_rsc_attributes(GHashTable * meta_hash, pe_resource_t * rsc,
148  pe_node_t * node, pe_working_set_t * data_set)
149 {
150  pe_rule_eval_data_t rule_data = {
151  .node_hash = NULL,
152  .role = RSC_ROLE_UNKNOWN,
153  .now = data_set->now,
154  .match_data = NULL,
155  .rsc_data = NULL,
156  .op_data = NULL
157  };
158 
159  if (node) {
160  rule_data.node_hash = node->details->attrs;
161  }
162 
164  meta_hash, NULL, FALSE, data_set);
165 
166  /* set anything else based on the parent */
167  if (rsc->parent != NULL) {
168  get_rsc_attributes(meta_hash, rsc->parent, node, data_set);
169 
170  } else {
171  /* and finally check the defaults */
173  &rule_data, meta_hash, NULL, FALSE, data_set);
174  }
175 }
176 
177 #if ENABLE_VERSIONED_ATTRS
178 void
179 pe_get_versioned_attributes(xmlNode * meta_hash, pe_resource_t * rsc,
180  pe_node_t * node, pe_working_set_t * data_set)
181 {
182  pe_rule_eval_data_t rule_data = {
183  .node_hash = (node == NULL)? NULL : node->details->attrs,
184  .role = RSC_ROLE_UNKNOWN,
185  .now = data_set->now,
186  .match_data = NULL,
187  .rsc_data = NULL,
188  .op_data = NULL
189  };
190 
191  pe_eval_versioned_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS,
192  &rule_data, meta_hash, NULL);
193 
194  /* set anything else based on the parent */
195  if (rsc->parent != NULL) {
196  pe_get_versioned_attributes(meta_hash, rsc->parent, node, data_set);
197 
198  } else {
199  /* and finally check the defaults */
200  pe_eval_versioned_attributes(data_set->input, data_set->rsc_defaults,
201  XML_TAG_ATTR_SETS, &rule_data, meta_hash,
202  NULL);
203  }
204 }
205 #endif
206 
207 static char *
208 template_op_key(xmlNode * op)
209 {
210  const char *name = crm_element_value(op, "name");
211  const char *role = crm_element_value(op, "role");
212  char *key = NULL;
213 
214  if (pcmk__str_eq(role, RSC_ROLE_STARTED_S, pcmk__str_null_matches)
215  || pcmk__str_eq(role, RSC_ROLE_SLAVE_S, pcmk__str_none)) {
216  role = RSC_ROLE_UNKNOWN_S;
217  }
218 
219  key = crm_strdup_printf("%s-%s", name, role);
220  return key;
221 }
222 
223 static gboolean
224 unpack_template(xmlNode * xml_obj, xmlNode ** expanded_xml, pe_working_set_t * data_set)
225 {
226  xmlNode *cib_resources = NULL;
227  xmlNode *template = NULL;
228  xmlNode *new_xml = NULL;
229  xmlNode *child_xml = NULL;
230  xmlNode *rsc_ops = NULL;
231  xmlNode *template_ops = NULL;
232  const char *template_ref = NULL;
233  const char *clone = NULL;
234  const char *id = NULL;
235 
236  if (xml_obj == NULL) {
237  pe_err("No resource object for template unpacking");
238  return FALSE;
239  }
240 
241  template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE);
242  if (template_ref == NULL) {
243  return TRUE;
244  }
245 
246  id = ID(xml_obj);
247  if (id == NULL) {
248  pe_err("'%s' object must have a id", crm_element_name(xml_obj));
249  return FALSE;
250  }
251 
252  if (pcmk__str_eq(template_ref, id, pcmk__str_none)) {
253  pe_err("The resource object '%s' should not reference itself", id);
254  return FALSE;
255  }
256 
257  cib_resources = get_xpath_object("//"XML_CIB_TAG_RESOURCES, data_set->input, LOG_TRACE);
258  if (cib_resources == NULL) {
259  pe_err("No resources configured");
260  return FALSE;
261  }
262 
263  template = pcmk__xe_match(cib_resources, XML_CIB_TAG_RSC_TEMPLATE,
264  XML_ATTR_ID, template_ref);
265  if (template == NULL) {
266  pe_err("No template named '%s'", template_ref);
267  return FALSE;
268  }
269 
270  new_xml = copy_xml(template);
271  xmlNodeSetName(new_xml, xml_obj->name);
272  crm_xml_replace(new_xml, XML_ATTR_ID, id);
273 
275  if(clone) {
276  crm_xml_add(new_xml, XML_RSC_ATTR_INCARNATION, clone);
277  }
278 
279  template_ops = find_xml_node(new_xml, "operations", FALSE);
280 
281  for (child_xml = pcmk__xe_first_child(xml_obj); child_xml != NULL;
282  child_xml = pcmk__xe_next(child_xml)) {
283  xmlNode *new_child = NULL;
284 
285  new_child = add_node_copy(new_xml, child_xml);
286 
287  if (pcmk__str_eq((const char *)new_child->name, "operations", pcmk__str_none)) {
288  rsc_ops = new_child;
289  }
290  }
291 
292  if (template_ops && rsc_ops) {
293  xmlNode *op = NULL;
294  GHashTable *rsc_ops_hash = g_hash_table_new_full(crm_str_hash,
295  g_str_equal, free,
296  NULL);
297 
298  for (op = pcmk__xe_first_child(rsc_ops); op != NULL;
299  op = pcmk__xe_next(op)) {
300 
301  char *key = template_op_key(op);
302 
303  g_hash_table_insert(rsc_ops_hash, key, op);
304  }
305 
306  for (op = pcmk__xe_first_child(template_ops); op != NULL;
307  op = pcmk__xe_next(op)) {
308 
309  char *key = template_op_key(op);
310 
311  if (g_hash_table_lookup(rsc_ops_hash, key) == NULL) {
312  add_node_copy(rsc_ops, op);
313  }
314 
315  free(key);
316  }
317 
318  if (rsc_ops_hash) {
319  g_hash_table_destroy(rsc_ops_hash);
320  }
321 
322  free_xml(template_ops);
323  }
324 
325  /*free_xml(*expanded_xml); */
326  *expanded_xml = new_xml;
327 
328  /* Disable multi-level templates for now */
329  /*if(unpack_template(new_xml, expanded_xml, data_set) == FALSE) {
330  free_xml(*expanded_xml);
331  *expanded_xml = NULL;
332 
333  return FALSE;
334  } */
335 
336  return TRUE;
337 }
338 
339 static gboolean
340 add_template_rsc(xmlNode * xml_obj, pe_working_set_t * data_set)
341 {
342  const char *template_ref = NULL;
343  const char *id = NULL;
344 
345  if (xml_obj == NULL) {
346  pe_err("No resource object for processing resource list of template");
347  return FALSE;
348  }
349 
350  template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE);
351  if (template_ref == NULL) {
352  return TRUE;
353  }
354 
355  id = ID(xml_obj);
356  if (id == NULL) {
357  pe_err("'%s' object must have a id", crm_element_name(xml_obj));
358  return FALSE;
359  }
360 
361  if (pcmk__str_eq(template_ref, id, pcmk__str_none)) {
362  pe_err("The resource object '%s' should not reference itself", id);
363  return FALSE;
364  }
365 
366  if (add_tag_ref(data_set->template_rsc_sets, template_ref, id) == FALSE) {
367  return FALSE;
368  }
369 
370  return TRUE;
371 }
372 
373 static bool
374 detect_promotable(pe_resource_t *rsc)
375 {
376  const char *promotable = g_hash_table_lookup(rsc->meta,
378 
379  if (crm_is_true(promotable)) {
380  return TRUE;
381  }
382 
383  // @COMPAT deprecated since 2.0.0
384  if (pcmk__str_eq(crm_element_name(rsc->xml), XML_CIB_TAG_MASTER, pcmk__str_casei)) {
385  /* @TODO in some future version, pe_warn_once() here,
386  * then drop support in even later version
387  */
388  g_hash_table_insert(rsc->meta, strdup(XML_RSC_ATTR_PROMOTABLE),
389  strdup(XML_BOOLEAN_TRUE));
390  return TRUE;
391  }
392  return FALSE;
393 }
394 
395 gboolean
396 common_unpack(xmlNode * xml_obj, pe_resource_t ** rsc,
397  pe_resource_t * parent, pe_working_set_t * data_set)
398 {
399  bool isdefault = FALSE;
400  xmlNode *expanded_xml = NULL;
401  xmlNode *ops = NULL;
402  const char *value = NULL;
403  const char *rclass = NULL; /* Look for this after any templates have been expanded */
404  const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
405  bool guest_node = FALSE;
406  bool remote_node = FALSE;
407  bool has_versioned_params = FALSE;
408 
409  pe_rule_eval_data_t rule_data = {
410  .node_hash = NULL,
411  .role = RSC_ROLE_UNKNOWN,
412  .now = data_set->now,
413  .match_data = NULL,
414  .rsc_data = NULL,
415  .op_data = NULL
416  };
417 
418  crm_log_xml_trace(xml_obj, "Processing resource input...");
419 
420  if (id == NULL) {
421  pe_err("Must specify id tag in <resource>");
422  return FALSE;
423 
424  } else if (rsc == NULL) {
425  pe_err("Nowhere to unpack resource into");
426  return FALSE;
427 
428  }
429 
430  if (unpack_template(xml_obj, &expanded_xml, data_set) == FALSE) {
431  return FALSE;
432  }
433 
434  *rsc = calloc(1, sizeof(pe_resource_t));
435  (*rsc)->cluster = data_set;
436 
437  if (expanded_xml) {
438  crm_log_xml_trace(expanded_xml, "Expanded resource...");
439  (*rsc)->xml = expanded_xml;
440  (*rsc)->orig_xml = xml_obj;
441 
442  } else {
443  (*rsc)->xml = xml_obj;
444  (*rsc)->orig_xml = NULL;
445  }
446 
447  /* Do not use xml_obj from here on, use (*rsc)->xml in case templates are involved */
448  rclass = crm_element_value((*rsc)->xml, XML_AGENT_ATTR_CLASS);
449  (*rsc)->parent = parent;
450 
451  ops = find_xml_node((*rsc)->xml, "operations", FALSE);
452  (*rsc)->ops_xml = expand_idref(ops, data_set->input);
453 
454  (*rsc)->variant = get_resource_type(crm_element_name((*rsc)->xml));
455  if ((*rsc)->variant == pe_unknown) {
456  pe_err("Unknown resource type: %s", crm_element_name((*rsc)->xml));
457  free(*rsc);
458  return FALSE;
459  }
460 
461  (*rsc)->parameters = crm_str_table_new();
462 
463 #if ENABLE_VERSIONED_ATTRS
464  (*rsc)->versioned_parameters = create_xml_node(NULL, XML_TAG_RSC_VER_ATTRS);
465 #endif
466 
467  (*rsc)->meta = crm_str_table_new();
468 
469  (*rsc)->allowed_nodes =
470  g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free);
471 
472  (*rsc)->known_on = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL,
473  free);
474 
475  value = crm_element_value((*rsc)->xml, XML_RSC_ATTR_INCARNATION);
476  if (value) {
477  (*rsc)->id = crm_strdup_printf("%s:%s", id, value);
478  add_hash_param((*rsc)->meta, XML_RSC_ATTR_INCARNATION, value);
479 
480  } else {
481  (*rsc)->id = strdup(id);
482  }
483 
484  (*rsc)->fns = &resource_class_functions[(*rsc)->variant];
485  pe_rsc_trace((*rsc), "Unpacking resource...");
486 
487  get_meta_attributes((*rsc)->meta, *rsc, NULL, data_set);
488  get_rsc_attributes((*rsc)->parameters, *rsc, NULL, data_set);
489 #if ENABLE_VERSIONED_ATTRS
490  pe_get_versioned_attributes((*rsc)->versioned_parameters, *rsc, NULL, data_set);
491 #endif
492 
493  (*rsc)->flags = 0;
495 
496  if (!pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)) {
498  }
499 
500  (*rsc)->rsc_cons = NULL;
501  (*rsc)->rsc_tickets = NULL;
502  (*rsc)->actions = NULL;
503  (*rsc)->role = RSC_ROLE_STOPPED;
504  (*rsc)->next_role = RSC_ROLE_UNKNOWN;
505 
506  (*rsc)->recovery_type = recovery_stop_start;
507  (*rsc)->stickiness = 0;
508  (*rsc)->migration_threshold = INFINITY;
509  (*rsc)->failure_timeout = 0;
510 
511  value = g_hash_table_lookup((*rsc)->meta, XML_CIB_ATTR_PRIORITY);
512  (*rsc)->priority = crm_parse_int(value, "0");
513 
514  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_NOTIFY);
515  if (crm_is_true(value)) {
517  }
518 
519  if (xml_contains_remote_node((*rsc)->xml)) {
520  (*rsc)->is_remote_node = TRUE;
521  if (g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_CONTAINER)) {
522  guest_node = TRUE;
523  } else {
524  remote_node = TRUE;
525  }
526  }
527 
528  value = g_hash_table_lookup((*rsc)->meta, XML_OP_ATTR_ALLOW_MIGRATE);
529 #if ENABLE_VERSIONED_ATTRS
530  has_versioned_params = xml_has_children((*rsc)->versioned_parameters);
531 #endif
532  if (crm_is_true(value) && has_versioned_params) {
533  pe_rsc_trace((*rsc), "Migration is disabled for resources with versioned parameters");
534  } else if (crm_is_true(value)) {
536  } else if ((value == NULL) && remote_node && !has_versioned_params) {
537  /* By default, we want remote nodes to be able
538  * to float around the cluster without having to stop all the
539  * resources within the remote-node before moving. Allowing
540  * migration support enables this feature. If this ever causes
541  * problems, migration support can be explicitly turned off with
542  * allow-migrate=false.
543  * We don't support migration for versioned resources, though. */
545  }
546 
547  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MANAGED);
548  if (value != NULL && !pcmk__str_eq("default", value, pcmk__str_casei)) {
549  if (crm_is_true(value)) {
551  } else {
553  }
554  }
555 
556  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MAINTENANCE);
557  if (crm_is_true(value)) {
560  }
561  if (pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)) {
564  }
565 
566  if (pe_rsc_is_clone(uber_parent(*rsc))) {
567  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_UNIQUE);
568  if (crm_is_true(value)) {
570  }
571  if (detect_promotable(*rsc)) {
573  }
574  } else {
576  }
577 
578  pe_rsc_trace((*rsc), "Options for %s", (*rsc)->id);
579 
580  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_RESTART);
581  if (pcmk__str_eq(value, "restart", pcmk__str_casei)) {
582  (*rsc)->restart_type = pe_restart_restart;
583  pe_rsc_trace((*rsc), "\tDependency restart handling: restart");
585  "Support for restart-type is deprecated and will be removed in a future release");
586 
587  } else {
588  (*rsc)->restart_type = pe_restart_ignore;
589  pe_rsc_trace((*rsc), "\tDependency restart handling: ignore");
590  }
591 
592  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MULTIPLE);
593  if (pcmk__str_eq(value, "stop_only", pcmk__str_casei)) {
594  (*rsc)->recovery_type = recovery_stop_only;
595  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop only");
596 
597  } else if (pcmk__str_eq(value, "block", pcmk__str_casei)) {
598  (*rsc)->recovery_type = recovery_block;
599  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: block");
600 
601  } else {
602  (*rsc)->recovery_type = recovery_stop_start;
603  pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop/start");
604  }
605 
606  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_STICKINESS);
607  if (value != NULL && !pcmk__str_eq("default", value, pcmk__str_casei)) {
608  (*rsc)->stickiness = char2score(value);
609  }
610 
611  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_STICKINESS);
612  if (value != NULL && !pcmk__str_eq("default", value, pcmk__str_casei)) {
613  (*rsc)->migration_threshold = char2score(value);
614  if ((*rsc)->migration_threshold < 0) {
615  /* @TODO We use 1 here to preserve previous behavior, but this
616  * should probably use the default (INFINITY) or 0 (to disable)
617  * instead.
618  */
621  " must be non-negative, using 1 instead");
622  (*rsc)->migration_threshold = 1;
623  }
624  }
625 
626  if (pcmk__str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
629  }
630 
631  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_REQUIRES);
632 
633  handle_requires_pref:
634  if (pcmk__str_eq(value, "nothing", pcmk__str_casei)) {
635 
636  } else if (pcmk__str_eq(value, "quorum", pcmk__str_casei)) {
638 
639  } else if (pcmk__str_eq(value, "unfencing", pcmk__str_casei)) {
640  if (pcmk_is_set((*rsc)->flags, pe_rsc_fence_device)) {
641  pcmk__config_warn("Resetting '" XML_RSC_ATTR_REQUIRES "' for %s "
642  "to 'quorum' because fencing devices cannot "
643  "require unfencing", (*rsc)->id);
644  value = "quorum";
645  isdefault = TRUE;
646  goto handle_requires_pref;
647 
648  } else if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
649  pcmk__config_warn("Resetting '" XML_RSC_ATTR_REQUIRES "' for %s "
650  "to 'quorum' because fencing is disabled",
651  (*rsc)->id);
652  value = "quorum";
653  isdefault = TRUE;
654  goto handle_requires_pref;
655 
656  } else {
659  }
660 
661  } else if (pcmk__str_eq(value, "fencing", pcmk__str_casei)) {
663  if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
664  pcmk__config_warn("%s requires fencing but fencing is disabled",
665  (*rsc)->id);
666  }
667 
668  } else {
669  const char *orig_value = value;
670 
671  isdefault = TRUE;
672  if (pcmk_is_set((*rsc)->flags, pe_rsc_fence_device)) {
673  value = "quorum";
674 
675  } else if (((*rsc)->variant == pe_native)
677  && pcmk__str_eq(crm_element_value((*rsc)->xml, XML_AGENT_ATTR_PROVIDER), "pacemaker", pcmk__str_casei)
678  && pcmk__str_eq(crm_element_value((*rsc)->xml, XML_ATTR_TYPE), "remote", pcmk__str_casei)
679  ) {
680  value = "quorum";
681 
682  } else if (pcmk_is_set(data_set->flags, pe_flag_enable_unfencing)) {
683  value = "unfencing";
684 
685  } else if (pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
686  value = "fencing";
687 
688  } else if (data_set->no_quorum_policy == no_quorum_ignore) {
689  value = "nothing";
690 
691  } else {
692  value = "quorum";
693  }
694 
695  if (orig_value != NULL) {
696  pcmk__config_err("Resetting '" XML_RSC_ATTR_REQUIRES "' for %s "
697  "to '%s' because '%s' is not valid",
698  (*rsc)->id, value, orig_value);
699  }
700 
701  goto handle_requires_pref;
702  }
703 
704  pe_rsc_trace((*rsc), "\tRequired to start: %s%s", value, isdefault?" (default)":"");
705  value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_TIMEOUT);
706  if (value != NULL) {
707  // Stored as seconds
708  (*rsc)->failure_timeout = (int) (crm_parse_interval_spec(value) / 1000);
709  }
710 
711  if (remote_node) {
712  value = g_hash_table_lookup((*rsc)->parameters, XML_REMOTE_ATTR_RECONNECT_INTERVAL);
713  if (value) {
714  /* reconnect delay works by setting failure_timeout and preventing the
715  * connection from starting until the failure is cleared. */
716  (*rsc)->remote_reconnect_ms = crm_parse_interval_spec(value);
717  /* we want to override any default failure_timeout in use when remote
718  * reconnect_interval is in use. */
719  (*rsc)->failure_timeout = (*rsc)->remote_reconnect_ms / 1000;
720  }
721  }
722 
723  get_target_role(*rsc, &((*rsc)->next_role));
724  pe_rsc_trace((*rsc), "\tDesired next state: %s",
725  (*rsc)->next_role != RSC_ROLE_UNKNOWN ? role2text((*rsc)->next_role) : "default");
726 
727  if ((*rsc)->fns->unpack(*rsc, data_set) == FALSE) {
728  return FALSE;
729  }
730 
731  if (pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster)) {
732  // This tag must stay exactly the same because it is tested elsewhere
733  resource_location(*rsc, NULL, 0, "symmetric_default", data_set);
734  } else if (guest_node) {
735  /* remote resources tied to a container resource must always be allowed
736  * to opt-in to the cluster. Whether the connection resource is actually
737  * allowed to be placed on a node is dependent on the container resource */
738  resource_location(*rsc, NULL, 0, "remote_connection_default", data_set);
739  }
740 
741  pe_rsc_trace((*rsc), "\tAction notification: %s",
742  pcmk_is_set((*rsc)->flags, pe_rsc_notify)? "required" : "not required");
743 
744  (*rsc)->utilization = crm_str_table_new();
745 
746  pe__unpack_dataset_nvpairs((*rsc)->xml, XML_TAG_UTILIZATION, &rule_data,
747  (*rsc)->utilization, NULL, FALSE, data_set);
748 
749 /* data_set->resources = g_list_append(data_set->resources, (*rsc)); */
750 
751  if (expanded_xml) {
752  if (add_template_rsc(xml_obj, data_set) == FALSE) {
753  return FALSE;
754  }
755  }
756  return TRUE;
757 }
758 
759 void
760 common_update_score(pe_resource_t * rsc, const char *id, int score)
761 {
762  pe_node_t *node = NULL;
763 
764  node = pe_hash_table_lookup(rsc->allowed_nodes, id);
765  if (node != NULL) {
766  pe_rsc_trace(rsc, "Updating score for %s on %s: %d + %d", rsc->id, id, node->weight, score);
767  node->weight = pe__add_scores(node->weight, score);
768  }
769 
770  if (rsc->children) {
771  GListPtr gIter = rsc->children;
772 
773  for (; gIter != NULL; gIter = gIter->next) {
774  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
775 
776  common_update_score(child_rsc, id, score);
777  }
778  }
779 }
780 
781 gboolean
783 {
784  pe_resource_t *parent = child;
785 
786  if (parent == NULL || rsc == NULL) {
787  return FALSE;
788  }
789  while (parent->parent != NULL) {
790  if (parent->parent == rsc) {
791  return TRUE;
792  }
793  parent = parent->parent;
794  }
795  return FALSE;
796 }
797 
800 {
801  pe_resource_t *parent = rsc;
802 
803  if (parent == NULL) {
804  return NULL;
805  }
806  while (parent->parent != NULL && parent->parent->variant != pe_container) {
807  parent = parent->parent;
808  }
809  return parent;
810 }
811 
812 void
814 {
815  if (rsc == NULL) {
816  return;
817  }
818 
819  pe_rsc_trace(rsc, "Freeing %s %d", rsc->id, rsc->variant);
820 
821  g_list_free(rsc->rsc_cons);
822  g_list_free(rsc->rsc_cons_lhs);
823  g_list_free(rsc->rsc_tickets);
824  g_list_free(rsc->dangling_migrations);
825 
826  if (rsc->parameters != NULL) {
827  g_hash_table_destroy(rsc->parameters);
828  }
829 #if ENABLE_VERSIONED_ATTRS
830  if (rsc->versioned_parameters != NULL) {
831  free_xml(rsc->versioned_parameters);
832  }
833 #endif
834  if (rsc->meta != NULL) {
835  g_hash_table_destroy(rsc->meta);
836  }
837  if (rsc->utilization != NULL) {
838  g_hash_table_destroy(rsc->utilization);
839  }
840 
841  if ((rsc->parent == NULL) && pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
842  free_xml(rsc->xml);
843  rsc->xml = NULL;
844  free_xml(rsc->orig_xml);
845  rsc->orig_xml = NULL;
846 
847  /* if rsc->orig_xml, then rsc->xml is an expanded xml from a template */
848  } else if (rsc->orig_xml) {
849  free_xml(rsc->xml);
850  rsc->xml = NULL;
851  }
852  if (rsc->running_on) {
853  g_list_free(rsc->running_on);
854  rsc->running_on = NULL;
855  }
856  if (rsc->known_on) {
857  g_hash_table_destroy(rsc->known_on);
858  rsc->known_on = NULL;
859  }
860  if (rsc->actions) {
861  g_list_free(rsc->actions);
862  rsc->actions = NULL;
863  }
864  if (rsc->allowed_nodes) {
865  g_hash_table_destroy(rsc->allowed_nodes);
866  rsc->allowed_nodes = NULL;
867  }
868  g_list_free(rsc->fillers);
869  g_list_free(rsc->rsc_location);
870  pe_rsc_trace(rsc, "Resource freed");
871  free(rsc->id);
872  free(rsc->clone_name);
873  free(rsc->allocated_to);
874  free(rsc->variant_opaque);
875  free(rsc->pending_task);
876  free(rsc);
877 }
878 
894 pe_node_t *
895 pe__find_active_on(const pe_resource_t *rsc, unsigned int *count_all,
896  unsigned int *count_clean)
897 {
898  pe_node_t *active = NULL;
899  pe_node_t *node = NULL;
900  bool keep_looking = FALSE;
901  bool is_happy = FALSE;
902 
903  if (count_all) {
904  *count_all = 0;
905  }
906  if (count_clean) {
907  *count_clean = 0;
908  }
909  if (rsc == NULL) {
910  return NULL;
911  }
912 
913  for (GList *node_iter = rsc->running_on; node_iter != NULL;
914  node_iter = node_iter->next) {
915 
916  node = node_iter->data;
917  keep_looking = FALSE;
918 
919  is_happy = node->details->online && !node->details->unclean;
920 
921  if (count_all) {
922  ++*count_all;
923  }
924  if (count_clean && is_happy) {
925  ++*count_clean;
926  }
927  if (count_all || count_clean) {
928  // If we're counting, we need to go through entire list
929  keep_looking = TRUE;
930  }
931 
932  if (rsc->partial_migration_source != NULL) {
933  if (node->details == rsc->partial_migration_source->details) {
934  // This is the migration source
935  active = node;
936  } else {
937  keep_looking = TRUE;
938  }
939  } else if (!pcmk_is_set(rsc->flags, pe_rsc_needs_fencing)) {
940  if (is_happy && (!active || !active->details->online
941  || active->details->unclean)) {
942  // This is the first clean node
943  active = node;
944  } else {
945  keep_looking = TRUE;
946  }
947  }
948  if (active == NULL) {
949  // This is first node in list
950  active = node;
951  }
952 
953  if (keep_looking == FALSE) {
954  // Don't waste time iterating if we don't have to
955  break;
956  }
957  }
958  return active;
959 }
960 
974 pe_node_t *
975 pe__find_active_requires(const pe_resource_t *rsc, unsigned int *count)
976 {
977  if (rsc && !pcmk_is_set(rsc->flags, pe_rsc_needs_fencing)) {
978  return pe__find_active_on(rsc, NULL, count);
979  }
980  return pe__find_active_on(rsc, count, NULL);
981 }
982 
983 void
985 {
986  if (rsc->children != NULL) {
987  for (GList *item = rsc->children; item != NULL; item = item->next) {
988  ((pe_resource_t *) item->data)->fns->count(item->data);
989  }
990 
991  } else if (!pcmk_is_set(rsc->flags, pe_rsc_orphan)
992  || (rsc->role > RSC_ROLE_STOPPED)) {
993  rsc->cluster->ninstances++;
994  if (pe__resource_is_disabled(rsc)) {
995  rsc->cluster->disabled_resources++;
996  }
997  if (pcmk_is_set(rsc->flags, pe_rsc_block)) {
998  rsc->cluster->blocked_resources++;
999  }
1000  }
1001 }
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:799
#define LOG_TRACE
Definition: logging.h:36
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:447
xmlNode * orig_xml
Definition: pe_types.h:311
enum pe_quorum_policy no_quorum_policy
Definition: pe_types.h:140
void pe__count_common(pe_resource_t *rsc)
Definition: complex.c:984
GHashTable * known_on
Definition: pe_types.h:354
GHashTable * attrs
Definition: pe_types.h:223
void group_free(pe_resource_t *rsc)
Definition: group.c:345
#define INFINITY
Definition: crm.h:95
void group_print(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: group.c:135
gboolean pe__group_is_filtered(pe_resource_t *rsc, GListPtr only_rsc, gboolean check_parent)
Definition: group.c:385
GListPtr dangling_migrations
Definition: pe_types.h:365
#define XML_EXPR_ATTR_TYPE
Definition: msg_xml.h:312
#define XML_CIB_TAG_CONTAINER
Definition: msg_xml.h:185
pe_node_t * partial_migration_source
Definition: pe_types.h:352
#define XML_ATTR_TYPE
Definition: msg_xml.h:99
#define pe_rsc_runnable
Definition: pe_types.h:256
enum rsc_role_e role
Definition: pe_types.h:357
#define XML_TAG_UTILIZATION
Definition: msg_xml.h:178
#define RSC_ROLE_STARTED_S
Definition: common.h:103
void pe__free_bundle(pe_resource_t *rsc)
Definition: bundle.c:2004
#define pe_flag_symmetric_cluster
Definition: pe_types.h:94
enum rsc_role_e pe__bundle_resource_state(const pe_resource_t *rsc, gboolean current)
Definition: bundle.c:2038
#define pcmk__config_err(fmt...)
Definition: internal.h:107
GListPtr rsc_tickets
Definition: pe_types.h:347
xmlNode * xml
Definition: pe_types.h:310
#define XML_RSC_ATTR_INCARNATION
Definition: msg_xml.h:193
#define pe_flag_maintenance_mode
Definition: pe_types.h:95
gboolean group_active(pe_resource_t *rsc, gboolean all)
Definition: group.c:90
int char2score(const char *score)
Definition: utils.c:61
pe_node_t * native_location(const pe_resource_t *rsc, GList **list, int current)
Definition: native.c:1207
GHashTable * meta
Definition: pe_types.h:360
#define pe_rsc_unique
Definition: pe_types.h:243
#define pe_rsc_notify
Definition: pe_types.h:242
xmlNode * pcmk__xe_match(xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:497
GHashTable * parameters
Definition: pe_types.h:361
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:317
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:134
GListPtr fillers
Definition: pe_types.h:368
#define XML_CIB_TAG_RSC_TEMPLATE
Definition: msg_xml.h:187
#define XML_RSC_ATTR_STICKINESS
Definition: msg_xml.h:206
void resource_location(pe_resource_t *rsc, pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1669
guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition: utils.c:307
GListPtr rsc_cons
Definition: pe_types.h:344
pe_node_t * allocated_to
Definition: pe_types.h:350
void pe__print_bundle(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: bundle.c:1902
char * pending_task
Definition: pe_types.h:333
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:213
gboolean pe__unpack_bundle(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: bundle.c:1032
void native_free(pe_resource_t *rsc)
Definition: native.c:1178
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:47
void clone_free(pe_resource_t *rsc)
Definition: clone.c:1110
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:242
void pe__unpack_dataset_nvpairs(xmlNode *xml_obj, const char *set_name, pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, pe_working_set_t *data_set)
Definition: utils.c:2741
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:796
enum rsc_role_e group_resource_state(const pe_resource_t *rsc, gboolean current)
Definition: group.c:366
#define pe_rsc_provisional
Definition: pe_types.h:247
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:170
#define XML_CIB_TAG_RESOURCES
Definition: msg_xml.h:147
#define XML_RSC_ATTR_PROMOTABLE
Definition: msg_xml.h:197
const char * role2text(enum rsc_role_e role)
Definition: common.c:463
int weight
Definition: pe_types.h:230
enum rsc_role_e clone_resource_state(const pe_resource_t *rsc, gboolean current)
Definition: clone.c:1144
#define XML_RSC_ATTR_REQUIRES
Definition: msg_xml.h:210
#define PCMK_RESOURCE_CLASS_OCF
Definition: services.h:46
void get_rsc_attributes(GHashTable *meta_hash, pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Definition: complex.c:147
#define pe_rsc_allow_migrate
Definition: pe_types.h:261
resource_object_functions_t resource_class_functions[]
Definition: complex.c:19
#define XML_RSC_ATTR_CONTAINER
Definition: msg_xml.h:212
gboolean clone_active(pe_resource_t *rsc, gboolean all)
Definition: clone.c:237
#define XML_ATTR_ID
Definition: msg_xml.h:96
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:523
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:181
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:107
xmlNode * rsc_defaults
Definition: pe_types.h:158
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
Replace an XML attribute with specified name and (possibly NULL) value.
Definition: nvpair.c:374
#define pe_warn_once(pe_wo_bit, fmt...)
Definition: internal.h:153
char * native_parameter(pe_resource_t *rsc, pe_node_t *node, gboolean create, const char *name, pe_working_set_t *data_set)
Definition: native.c:316
bool xml_contains_remote_node(xmlNode *xml)
Definition: remote.c:84
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:196
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:641
int blocked_resources
Definition: pe_types.h:173
pe_node_t * pe__find_active_on(const pe_resource_t *rsc, unsigned int *count_all, unsigned int *count_clean)
Definition: complex.c:895
struct pe_node_shared_s * details
Definition: pe_types.h:233
GListPtr running_on
Definition: pe_types.h:353
gboolean get_target_role(pe_resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:1845
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
Definition: xml.c:2850
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:237
#define pe_rsc_needs_fencing
Definition: pe_types.h:268
unsigned long long flags
Definition: pe_types.h:335
#define pe_rsc_promotable
Definition: pe_types.h:245
#define XML_TAG_META_SETS
Definition: msg_xml.h:171
char * clone_name
Definition: pe_types.h:309
gboolean add_tag_ref(GHashTable *tags, const char *tag_name, const char *obj_ref)
Definition: utils.c:2584
#define XML_RSC_ATTR_MANAGED
Definition: msg_xml.h:202
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:663
#define pe_flag_stonith_enabled
Definition: pe_types.h:97
enum rsc_role_e native_resource_state(const pe_resource_t *rsc, gboolean current)
Definition: native.c:1185
void clone_print(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: clone.c:370
GHashTable * utilization
Definition: pe_types.h:362
void native_print(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:1030
GListPtr rsc_cons_lhs
Definition: pe_types.h:343
#define XML_TAG_RSC_VER_ATTRS
Definition: msg_xml.h:173
void free_xml(xmlNode *child)
Definition: xml.c:790
enum pe_obj_types variant
Definition: pe_types.h:317
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:2010
xmlNode * input
Definition: pe_types.h:128
#define XML_REMOTE_ATTR_RECONNECT_INTERVAL
Definition: msg_xml.h:222
#define XML_RSC_ATTR_NOTIFY
Definition: msg_xml.h:205
GListPtr actions
Definition: pe_types.h:346
#define XML_RSC_ATTR_FAIL_STICKINESS
Definition: msg_xml.h:207
GListPtr rsc_location
Definition: pe_types.h:345
gboolean native_active(pe_resource_t *rsc, gboolean all)
Definition: native.c:361
void populate_hash(xmlNode *nvpair_list, GHashTable *hash, const char **attrs, int attrs_length)
#define pe_rsc_fence_device
Definition: pe_types.h:244
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:204
#define PCMK_RESOURCE_CLASS_STONITH
Definition: services.h:52
gboolean pe__bundle_is_filtered(pe_resource_t *rsc, GListPtr only_rsc, gboolean check_parent)
Definition: bundle.c:2089
pe_resource_t * native_find_rsc(pe_resource_t *rsc, const char *id, const pe_node_t *node, int flags)
Definition: native.c:261
#define XML_CIB_TAG_INCARNATION
Definition: msg_xml.h:183
const char * standard
Definition: common.h:162
#define XML_RSC_ATTR_MAINTENANCE
Definition: msg_xml.h:214
#define XML_RSC_ATTR_FAIL_TIMEOUT
Definition: msg_xml.h:208
void get_meta_attributes(GHashTable *meta_hash, pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Definition: complex.c:100
GListPtr children
Definition: pe_types.h:364
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:573
void * variant_opaque
Definition: pe_types.h:318
int pe__add_scores(int score1, int score2)
Definition: common.c:510
gboolean clone_unpack(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: clone.c:112
GHashTable * node_hash
Definition: common.h:173
int disabled_resources
Definition: pe_types.h:174
gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc)
Definition: complex.c:782
#define RSC_ROLE_SLAVE_S
Definition: common.h:104
gboolean pe__clone_is_filtered(pe_resource_t *rsc, GListPtr only_rsc, gboolean check_parent)
Definition: clone.c:1185
#define pe_rsc_needs_unfencing
Definition: pe_types.h:269
#define crm_str_hash
Definition: util.h:62
#define XML_RSC_ATTR_MULTIPLE
Definition: msg_xml.h:209
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:53
#define pe__set_working_set_flags(working_set, flags_to_set)
Definition: internal.h:35
#define pe_rsc_block
Definition: pe_types.h:239
#define pe_rsc_maintenance
Definition: pe_types.h:264
#define XML_RSC_ATTR_RESTART
Definition: msg_xml.h:190
#define XML_CIB_TAG_MASTER
Definition: msg_xml.h:184
pe_working_set_t * cluster
Definition: pe_types.h:314
#define RSC_ROLE_UNKNOWN_S
Definition: common.h:101
void common_free(pe_resource_t *rsc)
Definition: complex.c:813
#define pe_rsc_needs_quorum
Definition: pe_types.h:267
#define crm_log_xml_trace(xml, text)
Definition: logging.h:361
gboolean crm_is_true(const char *s)
Definition: strings.c:392
#define pe_flag_have_stonith_resource
Definition: pe_types.h:98
#define XML_CIB_TAG_GROUP
Definition: msg_xml.h:182
#define pe_flag_enable_unfencing
Definition: pe_types.h:99
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:20
bool pe__resource_is_disabled(pe_resource_t *rsc)
Definition: utils.c:2759
void common_update_score(pe_resource_t *rsc, const char *id, int score)
Definition: complex.c:760
unsigned long long flags
Definition: pe_types.h:137
#define ID(x)
Definition: msg_xml.h:425
#define pe_err(fmt...)
Definition: internal.h:22
gboolean common_unpack(xmlNode *xml_obj, pe_resource_t **rsc, pe_resource_t *parent, pe_working_set_t *data_set)
Definition: complex.c:396
char * name
Definition: pcmk_fence.c:31
gboolean native_unpack(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: native.c:191
gboolean unclean
Definition: pe_types.h:206
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
GList * GListPtr
Definition: crm.h:214
crm_time_t * now
Definition: pe_types.h:129
pe_node_t * pe__find_active_requires(const pe_resource_t *rsc, unsigned int *count)
Definition: complex.c:975
#define pe_rsc_managed
Definition: pe_types.h:238
#define pe_rsc_orphan
Definition: pe_types.h:237
GHashTable * template_rsc_sets
Definition: pe_types.h:169
void pe__count_bundle(pe_resource_t *rsc)
Definition: bundle.c:2065
#define pcmk__config_warn(fmt...)
Definition: internal.h:119
gboolean online
Definition: pe_types.h:202
#define XML_OP_ATTR_ALLOW_MIGRATE
Definition: msg_xml.h:226
pe_resource_t * parent
Definition: pe_types.h:315
gboolean pe__native_is_filtered(pe_resource_t *rsc, GListPtr only_rsc, gboolean check_parent)
Definition: native.c:1492
pe_obj_types
Definition: pe_types.h:35
gboolean pe__bundle_active(pe_resource_t *rsc, gboolean all)
Definition: bundle.c:1369
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:236
char * id
Definition: pe_types.h:308
GHashTable * allowed_nodes
Definition: pe_types.h:355
gboolean group_unpack(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: group.c:23