pacemaker  1.1.17-b36b869ca8
Scalable High-Availability cluster resource manager
unpack.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 #include <crm_internal.h>
19 
20 #include <glib.h>
21 
22 #include <crm/crm.h>
23 #include <crm/services.h>
24 #include <crm/msg_xml.h>
25 #include <crm/common/xml.h>
26 
27 #include <crm/common/util.h>
28 #include <crm/pengine/rules.h>
29 #include <crm/pengine/internal.h>
30 #include <unpack.h>
31 
32 CRM_TRACE_INIT_DATA(pe_status);
33 
34 #define set_config_flag(data_set, option, flag) do { \
35  const char *tmp = pe_pref(data_set->config_hash, option); \
36  if(tmp) { \
37  if(crm_is_true(tmp)) { \
38  set_bit(data_set->flags, flag); \
39  } else { \
40  clear_bit(data_set->flags, flag); \
41  } \
42  } \
43  } while(0)
44 
45 gboolean unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, xmlNode ** last_failure,
46  enum action_fail_response *failed, pe_working_set_t * data_set);
47 static gboolean determine_remote_online_status(pe_working_set_t * data_set, node_t * this_node);
48 
49 static gboolean
50 is_dangling_container_remote_node(node_t *node)
51 {
52  /* we are looking for a remote-node that was supposed to be mapped to a
53  * container resource, but all traces of that container have disappeared
54  * from both the config and the status section. */
55  if (is_remote_node(node) &&
56  node->details->remote_rsc &&
57  node->details->remote_rsc->container == NULL &&
59  return TRUE;
60  }
61 
62  return FALSE;
63 }
64 
65 
73 void
74 pe_fence_node(pe_working_set_t * data_set, node_t * node, const char *reason)
75 {
76  CRM_CHECK(node, return);
77 
78  /* A guest node is fenced by marking its container as failed */
79  if (is_container_remote_node(node)) {
80  resource_t *rsc = node->details->remote_rsc->container;
81 
82  if (is_set(rsc->flags, pe_rsc_failed) == FALSE) {
83  if (!is_set(rsc->flags, pe_rsc_managed)) {
84  crm_notice("Not fencing guest node %s "
85  "(otherwise would because %s): "
86  "its guest resource %s is unmanaged",
87  node->details->uname, reason, rsc->id);
88  } else {
89  crm_warn("Guest node %s will be fenced "
90  "(by recovering its guest resource %s): %s",
91  node->details->uname, rsc->id, reason);
92 
93  /* We don't mark the node as unclean because that would prevent the
94  * node from running resources. We want to allow it to run resources
95  * in this transition if the recovery succeeds.
96  */
97  node->details->remote_requires_reset = TRUE;
99  }
100  }
101 
102  } else if (is_dangling_container_remote_node(node)) {
103  crm_info("Cleaning up dangling connection for guest node %s: "
104  "fencing was already done because %s, "
105  "and guest resource no longer exists",
106  node->details->uname, reason);
108 
109  } else if (is_baremetal_remote_node(node)) {
110  resource_t *rsc = node->details->remote_rsc;
111 
112  if (rsc && (!is_set(rsc->flags, pe_rsc_managed))) {
113  crm_notice("Not fencing remote node %s "
114  "(otherwise would because %s): connection is unmanaged",
115  node->details->uname, reason);
116  } else if(node->details->remote_requires_reset == FALSE) {
117  node->details->remote_requires_reset = TRUE;
118  crm_warn("Remote node %s %s: %s",
119  node->details->uname,
120  pe_can_fence(data_set, node)? "will be fenced" : "is unclean",
121  reason);
122  }
123  node->details->unclean = TRUE;
124 
125  } else if (node->details->unclean) {
126  crm_trace("Cluster node %s %s because %s",
127  node->details->uname,
128  pe_can_fence(data_set, node)? "would also be fenced" : "also is unclean",
129  reason);
130 
131  } else {
132  crm_warn("Cluster node %s %s: %s",
133  node->details->uname,
134  pe_can_fence(data_set, node)? "will be fenced" : "is unclean",
135  reason);
136  node->details->unclean = TRUE;
137  }
138 }
139 
140 gboolean
141 unpack_config(xmlNode * config, pe_working_set_t * data_set)
142 {
143  const char *value = NULL;
144  GHashTable *config_hash =
145  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
146 
147  xmlXPathObjectPtr xpathObj = NULL;
148 
149  if(is_not_set(data_set->flags, pe_flag_enable_unfencing)) {
150  xpathObj = xpath_search(data_set->input, "//nvpair[@name='provides' and @value='unfencing']");
151  if(xpathObj && numXpathResults(xpathObj) > 0) {
153  }
154  freeXpathObject(xpathObj);
155  }
156 
157  if(is_not_set(data_set->flags, pe_flag_enable_unfencing)) {
158  xpathObj = xpath_search(data_set->input, "//nvpair[@name='requires' and @value='unfencing']");
159  if(xpathObj && numXpathResults(xpathObj) > 0) {
161  }
162  freeXpathObject(xpathObj);
163  }
164 
165 
166 #ifdef REDHAT_COMPAT_6
167  if(is_not_set(data_set->flags, pe_flag_enable_unfencing)) {
168  xpathObj = xpath_search(data_set->input, "//primitive[@type='fence_scsi']");
169  if(xpathObj && numXpathResults(xpathObj) > 0) {
171  }
172  freeXpathObject(xpathObj);
173  }
174 #endif
175 
176  data_set->config_hash = config_hash;
177 
178  unpack_instance_attributes(data_set->input, config, XML_CIB_TAG_PROPSET, NULL, config_hash,
179  CIB_OPTIONS_FIRST, FALSE, data_set->now);
180 
181  verify_pe_options(data_set->config_hash);
182 
183  set_config_flag(data_set, "enable-startup-probes", pe_flag_startup_probes);
184  if(is_not_set(data_set->flags, pe_flag_startup_probes)) {
185  crm_info("Startup probes: disabled (dangerous)");
186  }
187 
188  value = pe_pref(data_set->config_hash, XML_ATTR_HAVE_WATCHDOG);
189  if (value && crm_is_true(value)) {
190  crm_notice("Watchdog will be used via SBD if fencing is required");
192  }
193 
194  value = pe_pref(data_set->config_hash, "stonith-timeout");
195  data_set->stonith_timeout = crm_get_msec(value);
196  crm_debug("STONITH timeout: %d", data_set->stonith_timeout);
197 
198  set_config_flag(data_set, "stonith-enabled", pe_flag_stonith_enabled);
199  crm_debug("STONITH of failed nodes is %s",
200  is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
201 
202  data_set->stonith_action = pe_pref(data_set->config_hash, "stonith-action");
203  crm_trace("STONITH will %s nodes", data_set->stonith_action);
204 
205  set_config_flag(data_set, "concurrent-fencing", pe_flag_concurrent_fencing);
206  crm_debug("Concurrent fencing is %s",
207  is_set(data_set->flags, pe_flag_concurrent_fencing) ? "enabled" : "disabled");
208 
209  set_config_flag(data_set, "stop-all-resources", pe_flag_stop_everything);
210  crm_debug("Stop all active resources: %s",
211  is_set(data_set->flags, pe_flag_stop_everything) ? "true" : "false");
212 
213  set_config_flag(data_set, "symmetric-cluster", pe_flag_symmetric_cluster);
214  if (is_set(data_set->flags, pe_flag_symmetric_cluster)) {
215  crm_debug("Cluster is symmetric" " - resources can run anywhere by default");
216  }
217 
218  value = pe_pref(data_set->config_hash, "default-resource-stickiness");
219  data_set->default_resource_stickiness = char2score(value);
220  crm_debug("Default stickiness: %d", data_set->default_resource_stickiness);
221 
222  value = pe_pref(data_set->config_hash, "no-quorum-policy");
223 
224  if (safe_str_eq(value, "ignore")) {
226 
227  } else if (safe_str_eq(value, "freeze")) {
229 
230  } else if (safe_str_eq(value, "suicide")) {
231  gboolean do_panic = FALSE;
232 
233  crm_element_value_int(data_set->input, XML_ATTR_QUORUM_PANIC, &do_panic);
234 
235  if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) {
237  ("Setting no-quorum-policy=suicide makes no sense if stonith-enabled=false");
238  }
239 
240  if (do_panic && is_set(data_set->flags, pe_flag_stonith_enabled)) {
242 
243  } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE && do_panic == FALSE) {
244  crm_notice("Resetting no-quorum-policy to 'stop': The cluster has never had quorum");
245  data_set->no_quorum_policy = no_quorum_stop;
246  }
247 
248  } else {
249  data_set->no_quorum_policy = no_quorum_stop;
250  }
251 
252  switch (data_set->no_quorum_policy) {
253  case no_quorum_freeze:
254  crm_debug("On loss of CCM Quorum: Freeze resources");
255  break;
256  case no_quorum_stop:
257  crm_debug("On loss of CCM Quorum: Stop ALL resources");
258  break;
259  case no_quorum_suicide:
260  crm_notice("On loss of CCM Quorum: Fence all remaining nodes");
261  break;
262  case no_quorum_ignore:
263  crm_notice("On loss of CCM Quorum: Ignore");
264  break;
265  }
266 
267  set_config_flag(data_set, "stop-orphan-resources", pe_flag_stop_rsc_orphans);
268  crm_trace("Orphan resources are %s",
269  is_set(data_set->flags, pe_flag_stop_rsc_orphans) ? "stopped" : "ignored");
270 
271  set_config_flag(data_set, "stop-orphan-actions", pe_flag_stop_action_orphans);
272  crm_trace("Orphan resource actions are %s",
273  is_set(data_set->flags, pe_flag_stop_action_orphans) ? "stopped" : "ignored");
274 
275  set_config_flag(data_set, "remove-after-stop", pe_flag_remove_after_stop);
276  crm_trace("Stopped resources are removed from the status section: %s",
277  is_set(data_set->flags, pe_flag_remove_after_stop) ? "true" : "false");
278 
279  set_config_flag(data_set, "maintenance-mode", pe_flag_maintenance_mode);
280  crm_trace("Maintenance mode: %s",
281  is_set(data_set->flags, pe_flag_maintenance_mode) ? "true" : "false");
282 
283  if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
285  } else {
286  set_config_flag(data_set, "is-managed-default", pe_flag_is_managed_default);
287  }
288  crm_trace("By default resources are %smanaged",
289  is_set(data_set->flags, pe_flag_is_managed_default) ? "" : "not ");
290 
291  set_config_flag(data_set, "start-failure-is-fatal", pe_flag_start_failure_fatal);
292  crm_trace("Start failures are %s",
293  is_set(data_set->flags,
294  pe_flag_start_failure_fatal) ? "always fatal" : "handled by failcount");
295 
296  node_score_red = char2score(pe_pref(data_set->config_hash, "node-health-red"));
297  node_score_green = char2score(pe_pref(data_set->config_hash, "node-health-green"));
298  node_score_yellow = char2score(pe_pref(data_set->config_hash, "node-health-yellow"));
299 
300  crm_debug("Node scores: 'red' = %s, 'yellow' = %s, 'green' = %s",
301  pe_pref(data_set->config_hash, "node-health-red"),
302  pe_pref(data_set->config_hash, "node-health-yellow"),
303  pe_pref(data_set->config_hash, "node-health-green"));
304 
305  data_set->placement_strategy = pe_pref(data_set->config_hash, "placement-strategy");
306  crm_trace("Placement strategy: %s", data_set->placement_strategy);
307 
308  return TRUE;
309 }
310 
311 static void
312 destroy_digest_cache(gpointer ptr)
313 {
314  op_digest_cache_t *data = ptr;
315 
316  free_xml(data->params_all);
317  free_xml(data->params_secure);
318  free_xml(data->params_restart);
319 
320  free(data->digest_all_calc);
321  free(data->digest_restart_calc);
322  free(data->digest_secure_calc);
323 
324  free(data);
325 }
326 
327 node_t *
328 pe_create_node(const char *id, const char *uname, const char *type,
329  const char *score, pe_working_set_t * data_set)
330 {
331  node_t *new_node = NULL;
332 
333  if (pe_find_node(data_set->nodes, uname) != NULL) {
334  crm_config_warn("Detected multiple node entries with uname=%s"
335  " - this is rarely intended", uname);
336  }
337 
338  new_node = calloc(1, sizeof(node_t));
339  if (new_node == NULL) {
340  return NULL;
341  }
342 
343  new_node->weight = char2score(score);
344  new_node->fixed = FALSE;
345  new_node->details = calloc(1, sizeof(struct node_shared_s));
346 
347  if (new_node->details == NULL) {
348  free(new_node);
349  return NULL;
350  }
351 
352  crm_trace("Creating node for entry %s/%s", uname, id);
353  new_node->details->id = id;
354  new_node->details->uname = uname;
355  new_node->details->online = FALSE;
356  new_node->details->shutdown = FALSE;
357  new_node->details->rsc_discovery_enabled = TRUE;
358  new_node->details->running_rsc = NULL;
359  new_node->details->type = node_ping;
360 
361  if (safe_str_eq(type, "remote")) {
362  new_node->details->type = node_remote;
364  } else if (type == NULL || safe_str_eq(type, "member")
365  || safe_str_eq(type, NORMALNODE)) {
366  new_node->details->type = node_member;
367  }
368 
369  new_node->details->attrs = g_hash_table_new_full(crm_str_hash, g_str_equal,
372 
373  if (is_remote_node(new_node)) {
374  g_hash_table_insert(new_node->details->attrs, strdup("#kind"), strdup("remote"));
375  } else {
376  g_hash_table_insert(new_node->details->attrs, strdup("#kind"), strdup("cluster"));
377  }
378 
379  new_node->details->utilization =
380  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str,
382 
383  new_node->details->digest_cache =
384  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str,
385  destroy_digest_cache);
386 
387  data_set->nodes = g_list_insert_sorted(data_set->nodes, new_node, sort_node_uname);
388  return new_node;
389 }
390 
391 bool
392 remote_id_conflict(const char *remote_name, pe_working_set_t *data)
393 {
394  bool match = FALSE;
395 #if 1
396  pe_find_resource(data->resources, remote_name);
397 #else
398  if (data->name_check == NULL) {
399  data->name_check = g_hash_table_new(crm_str_hash, g_str_equal);
400  for (xml_rsc = __xml_first_child(parent); xml_rsc != NULL; xml_rsc = __xml_next_element(xml_rsc)) {
401  const char *id = ID(xml_rsc);
402 
403  /* avoiding heap allocation here because we know the duration of this hashtable allows us to */
404  g_hash_table_insert(data->name_check, (char *) id, (char *) id);
405  }
406  }
407  if (g_hash_table_lookup(data->name_check, remote_name)) {
408  match = TRUE;
409  }
410 #endif
411  if (match) {
412  crm_err("Invalid remote-node name, a resource called '%s' already exists.", remote_name);
413  return NULL;
414  }
415 
416  return match;
417 }
418 
419 
420 static const char *
421 expand_remote_rsc_meta(xmlNode *xml_obj, xmlNode *parent, pe_working_set_t *data)
422 {
423  xmlNode *xml_rsc = NULL;
424  xmlNode *xml_tmp = NULL;
425  xmlNode *attr_set = NULL;
426  xmlNode *attr = NULL;
427 
428  const char *container_id = ID(xml_obj);
429  const char *remote_name = NULL;
430  const char *remote_server = NULL;
431  const char *remote_port = NULL;
432  const char *connect_timeout = "60s";
433  const char *remote_allow_migrate=NULL;
434  const char *container_managed = NULL;
435 
436  for (attr_set = __xml_first_child(xml_obj); attr_set != NULL; attr_set = __xml_next_element(attr_set)) {
437  if (safe_str_neq((const char *)attr_set->name, XML_TAG_META_SETS)) {
438  continue;
439  }
440 
441  for (attr = __xml_first_child(attr_set); attr != NULL; attr = __xml_next_element(attr)) {
442  const char *value = crm_element_value(attr, XML_NVPAIR_ATTR_VALUE);
443  const char *name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME);
444 
446  remote_name = value;
447  } else if (safe_str_eq(name, "remote-addr")) {
448  remote_server = value;
449  } else if (safe_str_eq(name, "remote-port")) {
450  remote_port = value;
451  } else if (safe_str_eq(name, "remote-connect-timeout")) {
452  connect_timeout = value;
453  } else if (safe_str_eq(name, "remote-allow-migrate")) {
454  remote_allow_migrate=value;
455  } else if (safe_str_eq(name, XML_RSC_ATTR_MANAGED)) {
456  container_managed = value;
457  }
458  }
459  }
460 
461  if (remote_name == NULL) {
462  return NULL;
463  }
464 
465  if (remote_id_conflict(remote_name, data)) {
466  return NULL;
467  }
468 
469  xml_rsc = create_xml_node(parent, XML_CIB_TAG_RESOURCE);
470 
471  crm_xml_add(xml_rsc, XML_ATTR_ID, remote_name);
473  crm_xml_add(xml_rsc, XML_AGENT_ATTR_PROVIDER, "pacemaker");
474  crm_xml_add(xml_rsc, XML_ATTR_TYPE, "remote");
475 
476  xml_tmp = create_xml_node(xml_rsc, XML_TAG_META_SETS);
477  crm_xml_set_id(xml_tmp, "%s_%s", remote_name, XML_TAG_META_SETS);
478 
479  attr = create_xml_node(xml_tmp, XML_CIB_TAG_NVPAIR);
480  crm_xml_set_id(attr, "%s_%s", remote_name, "meta-attributes-container");
482  crm_xml_add(attr, XML_NVPAIR_ATTR_VALUE, container_id);
483 
484  attr = create_xml_node(xml_tmp, XML_CIB_TAG_NVPAIR);
485  crm_xml_set_id(attr, "%s_%s", remote_name, "meta-attributes-internal");
487  crm_xml_add(attr, XML_NVPAIR_ATTR_VALUE, "true");
488 
489  if (remote_allow_migrate) {
490  attr = create_xml_node(xml_tmp, XML_CIB_TAG_NVPAIR);
491  crm_xml_set_id(attr, "%s_%s", remote_name, "meta-attributes-migrate");
493  crm_xml_add(attr, XML_NVPAIR_ATTR_VALUE, remote_allow_migrate);
494  }
495 
496  if (container_managed) {
497  attr = create_xml_node(xml_tmp, XML_CIB_TAG_NVPAIR);
498  crm_xml_set_id(attr, "%s_%s", remote_name, "meta-attributes-managed");
500  crm_xml_add(attr, XML_NVPAIR_ATTR_VALUE, container_managed);
501  }
502 
503  xml_tmp = create_xml_node(xml_rsc, "operations");
504  attr = create_xml_node(xml_tmp, XML_ATTR_OP);
505  crm_xml_set_id(attr, "%s_%s", remote_name, "monitor-interval-30s");
506  crm_xml_add(attr, XML_ATTR_TIMEOUT, "30s");
507  crm_xml_add(attr, XML_LRM_ATTR_INTERVAL, "30s");
508  crm_xml_add(attr, XML_NVPAIR_ATTR_NAME, "monitor");
509 
510  if (connect_timeout) {
511  attr = create_xml_node(xml_tmp, XML_ATTR_OP);
512  crm_xml_set_id(attr, "%s_%s", remote_name, "start-interval-0");
513  crm_xml_add(attr, XML_ATTR_TIMEOUT, connect_timeout);
515  crm_xml_add(attr, XML_NVPAIR_ATTR_NAME, "start");
516  }
517 
518  if (remote_port || remote_server) {
519  xml_tmp = create_xml_node(xml_rsc, XML_TAG_ATTR_SETS);
520  crm_xml_set_id(xml_tmp, "%s_%s", remote_name, XML_TAG_ATTR_SETS);
521 
522  if (remote_server) {
523  attr = create_xml_node(xml_tmp, XML_CIB_TAG_NVPAIR);
524  crm_xml_set_id(attr, "%s_%s", remote_name, "instance-attributes-addr");
525  crm_xml_add(attr, XML_NVPAIR_ATTR_NAME, "addr");
526  crm_xml_add(attr, XML_NVPAIR_ATTR_VALUE, remote_server);
527  }
528  if (remote_port) {
529  attr = create_xml_node(xml_tmp, XML_CIB_TAG_NVPAIR);
530  crm_xml_set_id(attr, "%s_%s", remote_name, "instance-attributes-port");
531  crm_xml_add(attr, XML_NVPAIR_ATTR_NAME, "port");
532  crm_xml_add(attr, XML_NVPAIR_ATTR_VALUE, remote_port);
533  }
534  }
535 
536  return remote_name;
537 }
538 
539 static void
540 handle_startup_fencing(pe_working_set_t *data_set, node_t *new_node)
541 {
542  static const char *blind_faith = NULL;
543  static gboolean unseen_are_unclean = TRUE;
544  static gboolean need_warning = TRUE;
545 
546  if ((new_node->details->type == node_remote) && (new_node->details->remote_rsc == NULL)) {
547  /* Ignore fencing for remote nodes that don't have a connection resource
548  * associated with them. This happens when remote node entries get left
549  * in the nodes section after the connection resource is removed.
550  */
551  return;
552  }
553 
554  blind_faith = pe_pref(data_set->config_hash, "startup-fencing");
555 
556  if (crm_is_true(blind_faith) == FALSE) {
557  unseen_are_unclean = FALSE;
558  if (need_warning) {
559  crm_warn("Blind faith: not fencing unseen nodes");
560 
561  /* Warn once per run, not per node and transition */
562  need_warning = FALSE;
563  }
564  }
565 
566  if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE
567  || unseen_are_unclean == FALSE) {
568  /* blind faith... */
569  new_node->details->unclean = FALSE;
570 
571  } else {
572  /* all nodes are unclean until we've seen their
573  * status entry
574  */
575  new_node->details->unclean = TRUE;
576  }
577 
578  /* We need to be able to determine if a node's status section
579  * exists or not separate from whether the node is unclean. */
580  new_node->details->unseen = TRUE;
581 }
582 
583 gboolean
584 unpack_nodes(xmlNode * xml_nodes, pe_working_set_t * data_set)
585 {
586  xmlNode *xml_obj = NULL;
587  node_t *new_node = NULL;
588  const char *id = NULL;
589  const char *uname = NULL;
590  const char *type = NULL;
591  const char *score = NULL;
592 
593  for (xml_obj = __xml_first_child(xml_nodes); xml_obj != NULL; xml_obj = __xml_next_element(xml_obj)) {
594  if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_NODE, TRUE)) {
595  new_node = NULL;
596 
597  id = crm_element_value(xml_obj, XML_ATTR_ID);
598  uname = crm_element_value(xml_obj, XML_ATTR_UNAME);
599  type = crm_element_value(xml_obj, XML_ATTR_TYPE);
600  score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE);
601  crm_trace("Processing node %s/%s", uname, id);
602 
603  if (id == NULL) {
604  crm_config_err("Must specify id tag in <node>");
605  continue;
606  }
607  new_node = pe_create_node(id, uname, type, score, data_set);
608 
609  if (new_node == NULL) {
610  return FALSE;
611  }
612 
613 /* if(data_set->have_quorum == FALSE */
614 /* && data_set->no_quorum_policy == no_quorum_stop) { */
615 /* /\* start shutting resources down *\/ */
616 /* new_node->weight = -INFINITY; */
617 /* } */
618 
619  handle_startup_fencing(data_set, new_node);
620 
621  add_node_attrs(xml_obj, new_node, FALSE, data_set);
622  unpack_instance_attributes(data_set->input, xml_obj, XML_TAG_UTILIZATION, NULL,
623  new_node->details->utilization, NULL, FALSE, data_set->now);
624 
625  crm_trace("Done with node %s", crm_element_value(xml_obj, XML_ATTR_UNAME));
626  }
627  }
628 
629  if (data_set->localhost && pe_find_node(data_set->nodes, data_set->localhost) == NULL) {
630  crm_info("Creating a fake local node");
631  pe_create_node(data_set->localhost, data_set->localhost, NULL, 0,
632  data_set);
633  }
634 
635  return TRUE;
636 }
637 
638 static void
639 setup_container(resource_t * rsc, pe_working_set_t * data_set)
640 {
641  const char *container_id = NULL;
642 
643  if (rsc->children) {
644  GListPtr gIter = rsc->children;
645 
646  for (; gIter != NULL; gIter = gIter->next) {
647  resource_t *child_rsc = (resource_t *) gIter->data;
648 
649  setup_container(child_rsc, data_set);
650  }
651  return;
652  }
653 
654  container_id = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_CONTAINER);
655  if (container_id && safe_str_neq(container_id, rsc->id)) {
656  resource_t *container = pe_find_resource(data_set->resources, container_id);
657 
658  if (container) {
659  rsc->container = container;
660  container->fillers = g_list_append(container->fillers, rsc);
661  pe_rsc_trace(rsc, "Resource %s's container is %s", rsc->id, container_id);
662  } else {
663  pe_err("Resource %s: Unknown resource container (%s)", rsc->id, container_id);
664  }
665  }
666 }
667 
668 gboolean
669 unpack_remote_nodes(xmlNode * xml_resources, pe_working_set_t * data_set)
670 {
671  xmlNode *xml_obj = NULL;
672 
673  /* generate remote nodes from resource config before unpacking resources */
674  for (xml_obj = __xml_first_child(xml_resources); xml_obj != NULL; xml_obj = __xml_next_element(xml_obj)) {
675  const char *new_node_id = NULL;
676 
677  /* first check if this is a bare metal remote node. Bare metal remote nodes
678  * are defined as a resource primitive only. */
679  if (xml_contains_remote_node(xml_obj)) {
680  new_node_id = ID(xml_obj);
681  /* The "pe_find_node" check is here to make sure we don't iterate over
682  * an expanded node that has already been added to the node list. */
683  if (new_node_id && pe_find_node(data_set->nodes, new_node_id) == NULL) {
684  crm_trace("Found baremetal remote node %s in container resource %s", new_node_id, ID(xml_obj));
685  pe_create_node(new_node_id, new_node_id, "remote", NULL,
686  data_set);
687  }
688  continue;
689  }
690 
691  /* Now check for guest remote nodes.
692  * guest remote nodes are defined within a resource primitive.
693  * Example1: a vm resource might be configured as a remote node.
694  * Example2: a vm resource might be configured within a group to be a remote node.
695  * Note: right now we only support guest remote nodes in as a standalone primitive
696  * or a primitive within a group. No cloned primitives can be a guest remote node
697  * right now */
698  if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_RESOURCE, TRUE)) {
699  /* expands a metadata defined remote resource into the xml config
700  * as an actual rsc primitive to be unpacked later. */
701  new_node_id = expand_remote_rsc_meta(xml_obj, xml_resources, data_set);
702 
703  if (new_node_id && pe_find_node(data_set->nodes, new_node_id) == NULL) {
704  crm_trace("Found guest remote node %s in container resource %s", new_node_id, ID(xml_obj));
705  pe_create_node(new_node_id, new_node_id, "remote", NULL,
706  data_set);
707  }
708  continue;
709 
710  } else if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_GROUP, TRUE)) {
711  xmlNode *xml_obj2 = NULL;
712  /* search through a group to see if any of the primitive contain a remote node. */
713  for (xml_obj2 = __xml_first_child(xml_obj); xml_obj2 != NULL; xml_obj2 = __xml_next_element(xml_obj2)) {
714 
715  new_node_id = expand_remote_rsc_meta(xml_obj2, xml_resources, data_set);
716 
717  if (new_node_id && pe_find_node(data_set->nodes, new_node_id) == NULL) {
718  crm_trace("Found guest remote node %s in container resource %s which is in group %s", new_node_id, ID(xml_obj2), ID(xml_obj));
719  pe_create_node(new_node_id, new_node_id, "remote", NULL,
720  data_set);
721  }
722  }
723  }
724  }
725  return TRUE;
726 }
727 
728 
729 /* Call this after all the nodes and resources have been
730  * unpacked, but before the status section is read.
731  *
732  * A remote node's online status is reflected by the state
733  * of the remote node's connection resource. We need to link
734  * the remote node to this connection resource so we can have
735  * easy access to the connection resource during the PE calculations.
736  */
737 static void
738 link_rsc2remotenode(pe_working_set_t *data_set, resource_t *new_rsc)
739 {
740  node_t *remote_node = NULL;
741 
742  if (new_rsc->is_remote_node == FALSE) {
743  return;
744  }
745 
746  if (is_set(data_set->flags, pe_flag_quick_location)) {
747  /* remote_nodes and remote_resources are not linked in quick location calculations */
748  return;
749  }
750 
751  print_resource(LOG_DEBUG_3, "Linking remote-node connection resource, ", new_rsc, FALSE);
752 
753  remote_node = pe_find_node(data_set->nodes, new_rsc->id);
754  CRM_CHECK(remote_node != NULL, return;);
755 
756  remote_node->details->remote_rsc = new_rsc;
757  /* If this is a baremetal remote-node (no container resource
758  * associated with it) then we need to handle startup fencing the same way
759  * as cluster nodes. */
760  if (new_rsc->container == NULL) {
761  handle_startup_fencing(data_set, remote_node);
762  } else {
763  /* At this point we know if the remote node is a container or baremetal
764  * remote node, update the #kind attribute if a container is involved */
765  g_hash_table_replace(remote_node->details->attrs, strdup("#kind"), strdup("container"));
766  }
767 }
768 
769 static void
770 destroy_tag(gpointer data)
771 {
772  tag_t *tag = data;
773 
774  if (tag) {
775  free(tag->id);
776  g_list_free_full(tag->refs, free);
777  free(tag);
778  }
779 }
780 
781 gboolean
782 unpack_resources(xmlNode * xml_resources, pe_working_set_t * data_set)
783 {
784  xmlNode *xml_obj = NULL;
785  GListPtr gIter = NULL;
786 
787  data_set->template_rsc_sets =
788  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str,
789  destroy_tag);
790 
791  for (xml_obj = __xml_first_child(xml_resources); xml_obj != NULL; xml_obj = __xml_next_element(xml_obj)) {
792  resource_t *new_rsc = NULL;
793 
794  if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_RSC_TEMPLATE, TRUE)) {
795  const char *template_id = ID(xml_obj);
796 
797  if (template_id && g_hash_table_lookup_extended(data_set->template_rsc_sets,
798  template_id, NULL, NULL) == FALSE) {
799  /* Record the template's ID for the knowledge of its existence anyway. */
800  g_hash_table_insert(data_set->template_rsc_sets, strdup(template_id), NULL);
801  }
802  continue;
803  }
804 
805  crm_trace("Beginning unpack... <%s id=%s... >", crm_element_name(xml_obj), ID(xml_obj));
806  if (common_unpack(xml_obj, &new_rsc, NULL, data_set)) {
807  data_set->resources = g_list_append(data_set->resources, new_rsc);
808  print_resource(LOG_DEBUG_3, "Added ", new_rsc, FALSE);
809 
810  } else {
811  crm_config_err("Failed unpacking %s %s",
812  crm_element_name(xml_obj), crm_element_value(xml_obj, XML_ATTR_ID));
813  if (new_rsc != NULL && new_rsc->fns != NULL) {
814  new_rsc->fns->free(new_rsc);
815  }
816  }
817  }
818 
819  for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
820  resource_t *rsc = (resource_t *) gIter->data;
821 
822  setup_container(rsc, data_set);
823  link_rsc2remotenode(data_set, rsc);
824  }
825 
826  data_set->resources = g_list_sort(data_set->resources, sort_rsc_priority);
827  if (is_set(data_set->flags, pe_flag_quick_location)) {
828  /* Ignore */
829 
830  } else if (is_set(data_set->flags, pe_flag_stonith_enabled)
831  && is_set(data_set->flags, pe_flag_have_stonith_resource) == FALSE) {
832 
833  crm_config_err("Resource start-up disabled since no STONITH resources have been defined");
834  crm_config_err("Either configure some or disable STONITH with the stonith-enabled option");
835  crm_config_err("NOTE: Clusters with shared data need STONITH to ensure data integrity");
836  }
837 
838  return TRUE;
839 }
840 
841 gboolean
842 unpack_tags(xmlNode * xml_tags, pe_working_set_t * data_set)
843 {
844  xmlNode *xml_tag = NULL;
845 
846  data_set->tags =
847  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_tag);
848 
849  for (xml_tag = __xml_first_child(xml_tags); xml_tag != NULL; xml_tag = __xml_next_element(xml_tag)) {
850  xmlNode *xml_obj_ref = NULL;
851  const char *tag_id = ID(xml_tag);
852 
853  if (crm_str_eq((const char *)xml_tag->name, XML_CIB_TAG_TAG, TRUE) == FALSE) {
854  continue;
855  }
856 
857  if (tag_id == NULL) {
858  crm_config_err("Failed unpacking %s: %s should be specified",
859  crm_element_name(xml_tag), XML_ATTR_ID);
860  continue;
861  }
862 
863  for (xml_obj_ref = __xml_first_child(xml_tag); xml_obj_ref != NULL; xml_obj_ref = __xml_next_element(xml_obj_ref)) {
864  const char *obj_ref = ID(xml_obj_ref);
865 
866  if (crm_str_eq((const char *)xml_obj_ref->name, XML_CIB_TAG_OBJ_REF, TRUE) == FALSE) {
867  continue;
868  }
869 
870  if (obj_ref == NULL) {
871  crm_config_err("Failed unpacking %s for tag %s: %s should be specified",
872  crm_element_name(xml_obj_ref), tag_id, XML_ATTR_ID);
873  continue;
874  }
875 
876  if (add_tag_ref(data_set->tags, tag_id, obj_ref) == FALSE) {
877  return FALSE;
878  }
879  }
880  }
881 
882  return TRUE;
883 }
884 
885 /* The ticket state section:
886  * "/cib/status/tickets/ticket_state" */
887 static gboolean
888 unpack_ticket_state(xmlNode * xml_ticket, pe_working_set_t * data_set)
889 {
890  const char *ticket_id = NULL;
891  const char *granted = NULL;
892  const char *last_granted = NULL;
893  const char *standby = NULL;
894  xmlAttrPtr xIter = NULL;
895 
896  ticket_t *ticket = NULL;
897 
898  ticket_id = ID(xml_ticket);
899  if (ticket_id == NULL || strlen(ticket_id) == 0) {
900  return FALSE;
901  }
902 
903  crm_trace("Processing ticket state for %s", ticket_id);
904 
905  ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
906  if (ticket == NULL) {
907  ticket = ticket_new(ticket_id, data_set);
908  if (ticket == NULL) {
909  return FALSE;
910  }
911  }
912 
913  for (xIter = xml_ticket->properties; xIter; xIter = xIter->next) {
914  const char *prop_name = (const char *)xIter->name;
915  const char *prop_value = crm_element_value(xml_ticket, prop_name);
916 
917  if (crm_str_eq(prop_name, XML_ATTR_ID, TRUE)) {
918  continue;
919  }
920  g_hash_table_replace(ticket->state, strdup(prop_name), strdup(prop_value));
921  }
922 
923  granted = g_hash_table_lookup(ticket->state, "granted");
924  if (granted && crm_is_true(granted)) {
925  ticket->granted = TRUE;
926  crm_info("We have ticket '%s'", ticket->id);
927  } else {
928  ticket->granted = FALSE;
929  crm_info("We do not have ticket '%s'", ticket->id);
930  }
931 
932  last_granted = g_hash_table_lookup(ticket->state, "last-granted");
933  if (last_granted) {
934  ticket->last_granted = crm_parse_int(last_granted, 0);
935  }
936 
937  standby = g_hash_table_lookup(ticket->state, "standby");
938  if (standby && crm_is_true(standby)) {
939  ticket->standby = TRUE;
940  if (ticket->granted) {
941  crm_info("Granted ticket '%s' is in standby-mode", ticket->id);
942  }
943  } else {
944  ticket->standby = FALSE;
945  }
946 
947  crm_trace("Done with ticket state for %s", ticket_id);
948 
949  return TRUE;
950 }
951 
952 static gboolean
953 unpack_tickets_state(xmlNode * xml_tickets, pe_working_set_t * data_set)
954 {
955  xmlNode *xml_obj = NULL;
956 
957  for (xml_obj = __xml_first_child(xml_tickets); xml_obj != NULL; xml_obj = __xml_next_element(xml_obj)) {
958  if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_TICKET_STATE, TRUE) == FALSE) {
959  continue;
960  }
961  unpack_ticket_state(xml_obj, data_set);
962  }
963 
964  return TRUE;
965 }
966 
967 /* Compatibility with the deprecated ticket state section:
968  * "/cib/status/tickets/instance_attributes" */
969 static void
970 get_ticket_state_legacy(gpointer key, gpointer value, gpointer user_data)
971 {
972  const char *long_key = key;
973  char *state_key = NULL;
974 
975  const char *granted_prefix = "granted-ticket-";
976  const char *last_granted_prefix = "last-granted-";
977  static int granted_prefix_strlen = 0;
978  static int last_granted_prefix_strlen = 0;
979 
980  const char *ticket_id = NULL;
981  const char *is_granted = NULL;
982  const char *last_granted = NULL;
983  const char *sep = NULL;
984 
985  ticket_t *ticket = NULL;
986  pe_working_set_t *data_set = user_data;
987 
988  if (granted_prefix_strlen == 0) {
989  granted_prefix_strlen = strlen(granted_prefix);
990  }
991 
992  if (last_granted_prefix_strlen == 0) {
993  last_granted_prefix_strlen = strlen(last_granted_prefix);
994  }
995 
996  if (strstr(long_key, granted_prefix) == long_key) {
997  ticket_id = long_key + granted_prefix_strlen;
998  if (strlen(ticket_id)) {
999  state_key = strdup("granted");
1000  is_granted = value;
1001  }
1002  } else if (strstr(long_key, last_granted_prefix) == long_key) {
1003  ticket_id = long_key + last_granted_prefix_strlen;
1004  if (strlen(ticket_id)) {
1005  state_key = strdup("last-granted");
1006  last_granted = value;
1007  }
1008  } else if ((sep = strrchr(long_key, '-'))) {
1009  ticket_id = sep + 1;
1010  state_key = strndup(long_key, strlen(long_key) - strlen(sep));
1011  }
1012 
1013  if (ticket_id == NULL || strlen(ticket_id) == 0) {
1014  free(state_key);
1015  return;
1016  }
1017 
1018  if (state_key == NULL || strlen(state_key) == 0) {
1019  free(state_key);
1020  return;
1021  }
1022 
1023  ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
1024  if (ticket == NULL) {
1025  ticket = ticket_new(ticket_id, data_set);
1026  if (ticket == NULL) {
1027  free(state_key);
1028  return;
1029  }
1030  }
1031 
1032  g_hash_table_replace(ticket->state, state_key, strdup(value));
1033 
1034  if (is_granted) {
1035  if (crm_is_true(is_granted)) {
1036  ticket->granted = TRUE;
1037  crm_info("We have ticket '%s'", ticket->id);
1038  } else {
1039  ticket->granted = FALSE;
1040  crm_info("We do not have ticket '%s'", ticket->id);
1041  }
1042 
1043  } else if (last_granted) {
1044  ticket->last_granted = crm_parse_int(last_granted, 0);
1045  }
1046 }
1047 
1048 static void
1049 unpack_handle_remote_attrs(node_t *this_node, xmlNode *state, pe_working_set_t * data_set)
1050 {
1051  const char *resource_discovery_enabled = NULL;
1052  xmlNode *attrs = NULL;
1053  resource_t *rsc = NULL;
1054  const char *shutdown = NULL;
1055 
1056  if (crm_str_eq((const char *)state->name, XML_CIB_TAG_STATE, TRUE) == FALSE) {
1057  return;
1058  }
1059 
1060  if ((this_node == NULL) || (is_remote_node(this_node) == FALSE)) {
1061  return;
1062  }
1063  crm_trace("Processing remote node id=%s, uname=%s", this_node->details->id, this_node->details->uname);
1064 
1065  this_node->details->remote_maintenance =
1067 
1068  rsc = this_node->details->remote_rsc;
1069  if (this_node->details->remote_requires_reset == FALSE) {
1070  this_node->details->unclean = FALSE;
1071  this_node->details->unseen = FALSE;
1072  }
1073  attrs = find_xml_node(state, XML_TAG_TRANSIENT_NODEATTRS, FALSE);
1074  add_node_attrs(attrs, this_node, TRUE, data_set);
1075 
1076  shutdown = g_hash_table_lookup(this_node->details->attrs, XML_CIB_ATTR_SHUTDOWN);
1077  if (shutdown != NULL && safe_str_neq("0", shutdown)) {
1078  crm_info("Node %s is shutting down", this_node->details->uname);
1079  this_node->details->shutdown = TRUE;
1080  if (rsc) {
1081  rsc->next_role = RSC_ROLE_STOPPED;
1082  }
1083  }
1084 
1085  if (crm_is_true(g_hash_table_lookup(this_node->details->attrs, "standby"))) {
1086  crm_info("Node %s is in standby-mode", this_node->details->uname);
1087  this_node->details->standby = TRUE;
1088  }
1089 
1090  if (crm_is_true(g_hash_table_lookup(this_node->details->attrs, "maintenance")) ||
1091  (rsc && !is_set(rsc->flags, pe_rsc_managed))) {
1092  crm_info("Node %s is in maintenance-mode", this_node->details->uname);
1093  this_node->details->maintenance = TRUE;
1094  }
1095 
1096  resource_discovery_enabled = g_hash_table_lookup(this_node->details->attrs, XML_NODE_ATTR_RSC_DISCOVERY);
1097  if (resource_discovery_enabled && !crm_is_true(resource_discovery_enabled)) {
1098  if (is_baremetal_remote_node(this_node) && is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
1099  crm_warn("ignoring %s attribute on baremetal remote node %s, disabling resource discovery requires stonith to be enabled.",
1101  } else {
1102  /* if we're here, this is either a baremetal node and fencing is enabled,
1103  * or this is a container node which we don't care if fencing is enabled
1104  * or not on. container nodes are 'fenced' by recovering the container resource
1105  * regardless of whether fencing is enabled. */
1106  crm_info("Node %s has resource discovery disabled", this_node->details->uname);
1107  this_node->details->rsc_discovery_enabled = FALSE;
1108  }
1109  }
1110 }
1111 
1112 static bool
1113 unpack_node_loop(xmlNode * status, bool fence, pe_working_set_t * data_set)
1114 {
1115  bool changed = false;
1116  xmlNode *lrm_rsc = NULL;
1117 
1118  for (xmlNode *state = __xml_first_child(status); state != NULL; state = __xml_next_element(state)) {
1119  const char *id = NULL;
1120  const char *uname = NULL;
1121  node_t *this_node = NULL;
1122  bool process = FALSE;
1123 
1124  if (crm_str_eq((const char *)state->name, XML_CIB_TAG_STATE, TRUE) == FALSE) {
1125  continue;
1126  }
1127 
1128  id = crm_element_value(state, XML_ATTR_ID);
1129  uname = crm_element_value(state, XML_ATTR_UNAME);
1130  this_node = pe_find_node_any(data_set->nodes, id, uname);
1131 
1132  if (this_node == NULL) {
1133  crm_info("Node %s is unknown", id);
1134  continue;
1135 
1136  } else if (this_node->details->unpacked) {
1137  crm_info("Node %s is already processed", id);
1138  continue;
1139 
1140  } else if (is_remote_node(this_node) == FALSE && is_set(data_set->flags, pe_flag_stonith_enabled)) {
1141  // A redundant test, but preserves the order for regression tests
1142  process = TRUE;
1143 
1144  } else if (is_remote_node(this_node)) {
1145  resource_t *rsc = this_node->details->remote_rsc;
1146 
1147  if (fence || (rsc && rsc->role == RSC_ROLE_STARTED)) {
1148  determine_remote_online_status(data_set, this_node);
1149  unpack_handle_remote_attrs(this_node, state, data_set);
1150  process = TRUE;
1151  }
1152 
1153  } else if (this_node->details->online) {
1154  process = TRUE;
1155 
1156  } else if (fence) {
1157  process = TRUE;
1158  }
1159 
1160  if(process) {
1161  crm_trace("Processing lrm resource entries on %shealthy%s node: %s",
1162  fence?"un":"", is_remote_node(this_node)?" remote":"",
1163  this_node->details->uname);
1164  changed = TRUE;
1165  this_node->details->unpacked = TRUE;
1166 
1167  lrm_rsc = find_xml_node(state, XML_CIB_TAG_LRM, FALSE);
1168  lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE);
1169  unpack_lrm_resources(this_node, lrm_rsc, data_set);
1170  }
1171  }
1172  return changed;
1173 }
1174 
1175 /* remove nodes that are down, stopping */
1176 /* create +ve rsc_to_node constraints between resources and the nodes they are running on */
1177 /* anything else? */
1178 gboolean
1179 unpack_status(xmlNode * status, pe_working_set_t * data_set)
1180 {
1181  const char *id = NULL;
1182  const char *uname = NULL;
1183 
1184  xmlNode *state = NULL;
1185  node_t *this_node = NULL;
1186 
1187  crm_trace("Beginning unpack");
1188 
1189  if (data_set->tickets == NULL) {
1190  data_set->tickets =
1191  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket);
1192  }
1193 
1194  for (state = __xml_first_child(status); state != NULL; state = __xml_next_element(state)) {
1195  if (crm_str_eq((const char *)state->name, XML_CIB_TAG_TICKETS, TRUE)) {
1196  xmlNode *xml_tickets = state;
1197  GHashTable *state_hash = NULL;
1198 
1199  /* Compatibility with the deprecated ticket state section:
1200  * Unpack the attributes in the deprecated "/cib/status/tickets/instance_attributes" if it exists. */
1201  state_hash =
1202  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str,
1204 
1205  unpack_instance_attributes(data_set->input, xml_tickets, XML_TAG_ATTR_SETS, NULL,
1206  state_hash, NULL, TRUE, data_set->now);
1207 
1208  g_hash_table_foreach(state_hash, get_ticket_state_legacy, data_set);
1209 
1210  if (state_hash) {
1211  g_hash_table_destroy(state_hash);
1212  }
1213 
1214  /* Unpack the new "/cib/status/tickets/ticket_state"s */
1215  unpack_tickets_state(xml_tickets, data_set);
1216  }
1217 
1218  if (crm_str_eq((const char *)state->name, XML_CIB_TAG_STATE, TRUE)) {
1219  xmlNode *attrs = NULL;
1220  const char *resource_discovery_enabled = NULL;
1221 
1222  id = crm_element_value(state, XML_ATTR_ID);
1223  uname = crm_element_value(state, XML_ATTR_UNAME);
1224  this_node = pe_find_node_any(data_set->nodes, id, uname);
1225 
1226  if (uname == NULL) {
1227  /* error */
1228  continue;
1229 
1230  } else if (this_node == NULL) {
1231  crm_config_warn("Node %s in status section no longer exists", uname);
1232  continue;
1233 
1234  } else if (is_remote_node(this_node)) {
1235  /* online state for remote nodes is determined by the
1236  * rsc state after all the unpacking is done. we do however
1237  * need to mark whether or not the node has been fenced as this plays
1238  * a role during unpacking cluster node resource state */
1239  this_node->details->remote_was_fenced =
1241  continue;
1242  }
1243 
1244  crm_trace("Processing node id=%s, uname=%s", id, uname);
1245 
1246  /* Mark the node as provisionally clean
1247  * - at least we have seen it in the current cluster's lifetime
1248  */
1249  this_node->details->unclean = FALSE;
1250  this_node->details->unseen = FALSE;
1251  attrs = find_xml_node(state, XML_TAG_TRANSIENT_NODEATTRS, FALSE);
1252  add_node_attrs(attrs, this_node, TRUE, data_set);
1253 
1254  if (crm_is_true(g_hash_table_lookup(this_node->details->attrs, "standby"))) {
1255  crm_info("Node %s is in standby-mode", this_node->details->uname);
1256  this_node->details->standby = TRUE;
1257  }
1258 
1259  if (crm_is_true(g_hash_table_lookup(this_node->details->attrs, "maintenance"))) {
1260  crm_info("Node %s is in maintenance-mode", this_node->details->uname);
1261  this_node->details->maintenance = TRUE;
1262  }
1263 
1264  resource_discovery_enabled = g_hash_table_lookup(this_node->details->attrs, XML_NODE_ATTR_RSC_DISCOVERY);
1265  if (resource_discovery_enabled && !crm_is_true(resource_discovery_enabled)) {
1266  crm_warn("ignoring %s attribute on node %s, disabling resource discovery is not allowed on cluster nodes",
1268  }
1269 
1270  crm_trace("determining node state");
1271  determine_online_status(state, this_node, data_set);
1272 
1273  if (this_node->details->online && data_set->no_quorum_policy == no_quorum_suicide) {
1274  /* Everything else should flow from this automatically
1275  * At least until the PE becomes able to migrate off healthy resources
1276  */
1277  pe_fence_node(data_set, this_node, "cluster does not have quorum");
1278  }
1279  }
1280  }
1281 
1282 
1283  while(unpack_node_loop(status, FALSE, data_set)) {
1284  crm_trace("Start another loop");
1285  }
1286 
1287  // Now catch any nodes we didnt see
1288  unpack_node_loop(status, is_set(data_set->flags, pe_flag_stonith_enabled), data_set);
1289 
1290  for (GListPtr gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1291  node_t *this_node = gIter->data;
1292 
1293  if (this_node == NULL) {
1294  continue;
1295  } else if(is_remote_node(this_node) == FALSE) {
1296  continue;
1297  } else if(this_node->details->unpacked) {
1298  continue;
1299  }
1300  determine_remote_online_status(data_set, this_node);
1301  }
1302 
1303  return TRUE;
1304 }
1305 
1306 static gboolean
1307 determine_online_status_no_fencing(pe_working_set_t * data_set, xmlNode * node_state,
1308  node_t * this_node)
1309 {
1310  gboolean online = FALSE;
1311  const char *join = crm_element_value(node_state, XML_NODE_JOIN_STATE);
1312  const char *is_peer = crm_element_value(node_state, XML_NODE_IS_PEER);
1313  const char *in_cluster = crm_element_value(node_state, XML_NODE_IN_CLUSTER);
1314  const char *exp_state = crm_element_value(node_state, XML_NODE_EXPECTED);
1315 
1316  if (!crm_is_true(in_cluster)) {
1317  crm_trace("Node is down: in_cluster=%s", crm_str(in_cluster));
1318 
1319  } else if (safe_str_eq(is_peer, ONLINESTATUS)) {
1320  if (safe_str_eq(join, CRMD_JOINSTATE_MEMBER)) {
1321  online = TRUE;
1322  } else {
1323  crm_debug("Node is not ready to run resources: %s", join);
1324  }
1325 
1326  } else if (this_node->details->expected_up == FALSE) {
1327  crm_trace("CRMd is down: in_cluster=%s", crm_str(in_cluster));
1328  crm_trace("\tis_peer=%s, join=%s, expected=%s",
1329  crm_str(is_peer), crm_str(join), crm_str(exp_state));
1330 
1331  } else {
1332  /* mark it unclean */
1333  pe_fence_node(data_set, this_node, "peer is unexpectedly down");
1334  crm_info("\tin_cluster=%s, is_peer=%s, join=%s, expected=%s",
1335  crm_str(in_cluster), crm_str(is_peer), crm_str(join), crm_str(exp_state));
1336  }
1337  return online;
1338 }
1339 
1340 static gboolean
1341 determine_online_status_fencing(pe_working_set_t * data_set, xmlNode * node_state,
1342  node_t * this_node)
1343 {
1344  gboolean online = FALSE;
1345  gboolean do_terminate = FALSE;
1346  const char *join = crm_element_value(node_state, XML_NODE_JOIN_STATE);
1347  const char *is_peer = crm_element_value(node_state, XML_NODE_IS_PEER);
1348  const char *in_cluster = crm_element_value(node_state, XML_NODE_IN_CLUSTER);
1349  const char *exp_state = crm_element_value(node_state, XML_NODE_EXPECTED);
1350  const char *terminate = g_hash_table_lookup(this_node->details->attrs, "terminate");
1351 
1352 /*
1353  - XML_NODE_IN_CLUSTER ::= true|false
1354  - XML_NODE_IS_PEER ::= true|false|online|offline
1355  - XML_NODE_JOIN_STATE ::= member|down|pending|banned
1356  - XML_NODE_EXPECTED ::= member|down
1357 */
1358 
1359  if (crm_is_true(terminate)) {
1360  do_terminate = TRUE;
1361 
1362  } else if (terminate != NULL && strlen(terminate) > 0) {
1363  /* could be a time() value */
1364  char t = terminate[0];
1365 
1366  if (t != '0' && isdigit(t)) {
1367  do_terminate = TRUE;
1368  }
1369  }
1370 
1371  crm_trace("%s: in_cluster=%s, is_peer=%s, join=%s, expected=%s, term=%d",
1372  this_node->details->uname, crm_str(in_cluster), crm_str(is_peer),
1373  crm_str(join), crm_str(exp_state), do_terminate);
1374 
1375  online = crm_is_true(in_cluster);
1376  if (safe_str_eq(is_peer, ONLINESTATUS)) {
1377  is_peer = XML_BOOLEAN_YES;
1378  }
1379  if (exp_state == NULL) {
1380  exp_state = CRMD_JOINSTATE_DOWN;
1381  }
1382 
1383  if (this_node->details->shutdown) {
1384  crm_debug("%s is shutting down", this_node->details->uname);
1385 
1386  /* Slightly different criteria since we can't shut down a dead peer */
1387  online = crm_is_true(is_peer);
1388 
1389  } else if (in_cluster == NULL) {
1390  pe_fence_node(data_set, this_node, "peer has not been seen by the cluster");
1391 
1392  } else if (safe_str_eq(join, CRMD_JOINSTATE_NACK)) {
1393  pe_fence_node(data_set, this_node, "peer failed the pacemaker membership criteria");
1394 
1395  } else if (do_terminate == FALSE && safe_str_eq(exp_state, CRMD_JOINSTATE_DOWN)) {
1396 
1397  if (crm_is_true(in_cluster) || crm_is_true(is_peer)) {
1398  crm_info("- Node %s is not ready to run resources", this_node->details->uname);
1399  this_node->details->standby = TRUE;
1400  this_node->details->pending = TRUE;
1401 
1402  } else {
1403  crm_trace("%s is down or still coming up", this_node->details->uname);
1404  }
1405 
1406  } else if (do_terminate && safe_str_eq(join, CRMD_JOINSTATE_DOWN)
1407  && crm_is_true(in_cluster) == FALSE && crm_is_true(is_peer) == FALSE) {
1408  crm_info("Node %s was just shot", this_node->details->uname);
1409  online = FALSE;
1410 
1411  } else if (crm_is_true(in_cluster) == FALSE) {
1412  pe_fence_node(data_set, this_node, "peer is no longer part of the cluster");
1413 
1414  } else if (crm_is_true(is_peer) == FALSE) {
1415  pe_fence_node(data_set, this_node, "peer process is no longer available");
1416 
1417  /* Everything is running at this point, now check join state */
1418  } else if (do_terminate) {
1419  pe_fence_node(data_set, this_node, "termination was requested");
1420 
1421  } else if (safe_str_eq(join, CRMD_JOINSTATE_MEMBER)) {
1422  crm_info("Node %s is active", this_node->details->uname);
1423 
1424  } else if (safe_str_eq(join, CRMD_JOINSTATE_PENDING)
1425  || safe_str_eq(join, CRMD_JOINSTATE_DOWN)) {
1426  crm_info("Node %s is not ready to run resources", this_node->details->uname);
1427  this_node->details->standby = TRUE;
1428  this_node->details->pending = TRUE;
1429 
1430  } else {
1431  pe_fence_node(data_set, this_node, "peer was in an unknown state");
1432  crm_warn("%s: in-cluster=%s, is-peer=%s, join=%s, expected=%s, term=%d, shutdown=%d",
1433  this_node->details->uname, crm_str(in_cluster), crm_str(is_peer),
1434  crm_str(join), crm_str(exp_state), do_terminate, this_node->details->shutdown);
1435  }
1436 
1437  return online;
1438 }
1439 
1440 static gboolean
1441 determine_remote_online_status(pe_working_set_t * data_set, node_t * this_node)
1442 {
1443  resource_t *rsc = this_node->details->remote_rsc;
1444  resource_t *container = NULL;
1445  pe_node_t *host = NULL;
1446 
1447  /* If there is a node state entry for a (former) Pacemaker Remote node
1448  * but no resource creating that node, the node's connection resource will
1449  * be NULL. Consider it an offline remote node in that case.
1450  */
1451  if (rsc == NULL) {
1452  this_node->details->online = FALSE;
1453  goto remote_online_done;
1454  }
1455 
1456  container = rsc->container;
1457 
1458  if (container && (g_list_length(rsc->running_on) == 1)) {
1459  host = rsc->running_on->data;
1460  }
1461 
1462  /* If the resource is currently started, mark it online. */
1463  if (rsc->role == RSC_ROLE_STARTED) {
1464  crm_trace("%s node %s presumed ONLINE because connection resource is started",
1465  (container? "Guest" : "Remote"), this_node->details->id);
1466  this_node->details->online = TRUE;
1467  }
1468 
1469  /* consider this node shutting down if transitioning start->stop */
1470  if (rsc->role == RSC_ROLE_STARTED && rsc->next_role == RSC_ROLE_STOPPED) {
1471  crm_trace("%s node %s shutting down because connection resource is stopping",
1472  (container? "Guest" : "Remote"), this_node->details->id);
1473  this_node->details->shutdown = TRUE;
1474  }
1475 
1476  /* Now check all the failure conditions. */
1477  if(container && is_set(container->flags, pe_rsc_failed)) {
1478  crm_trace("Guest node %s UNCLEAN because guest resource failed",
1479  this_node->details->id);
1480  this_node->details->online = FALSE;
1481  this_node->details->remote_requires_reset = TRUE;
1482 
1483  } else if(is_set(rsc->flags, pe_rsc_failed)) {
1484  crm_trace("%s node %s OFFLINE because connection resource failed",
1485  (container? "Guest" : "Remote"), this_node->details->id);
1486  this_node->details->online = FALSE;
1487 
1488  } else if (rsc->role == RSC_ROLE_STOPPED
1489  || (container && container->role == RSC_ROLE_STOPPED)) {
1490 
1491  crm_trace("%s node %s OFFLINE because its resource is stopped",
1492  (container? "Guest" : "Remote"), this_node->details->id);
1493  this_node->details->online = FALSE;
1494  this_node->details->remote_requires_reset = FALSE;
1495 
1496  } else if (host && (host->details->online == FALSE)
1497  && host->details->unclean) {
1498  crm_trace("Guest node %s UNCLEAN because host is unclean",
1499  this_node->details->id);
1500  this_node->details->online = FALSE;
1501  this_node->details->remote_requires_reset = TRUE;
1502  }
1503 
1504 remote_online_done:
1505  crm_trace("Remote node %s online=%s",
1506  this_node->details->id, this_node->details->online ? "TRUE" : "FALSE");
1507  return this_node->details->online;
1508 }
1509 
1510 gboolean
1511 determine_online_status(xmlNode * node_state, node_t * this_node, pe_working_set_t * data_set)
1512 {
1513  gboolean online = FALSE;
1514  const char *shutdown = NULL;
1515  const char *exp_state = crm_element_value(node_state, XML_NODE_EXPECTED);
1516 
1517  if (this_node == NULL) {
1518  crm_config_err("No node to check");
1519  return online;
1520  }
1521 
1522  this_node->details->shutdown = FALSE;
1523  this_node->details->expected_up = FALSE;
1524  shutdown = g_hash_table_lookup(this_node->details->attrs, XML_CIB_ATTR_SHUTDOWN);
1525 
1526  if (shutdown != NULL && safe_str_neq("0", shutdown)) {
1527  this_node->details->shutdown = TRUE;
1528 
1529  } else if (safe_str_eq(exp_state, CRMD_JOINSTATE_MEMBER)) {
1530  this_node->details->expected_up = TRUE;
1531  }
1532 
1533  if (this_node->details->type == node_ping) {
1534  this_node->details->unclean = FALSE;
1535  online = FALSE; /* As far as resource management is concerned,
1536  * the node is safely offline.
1537  * Anyone caught abusing this logic will be shot
1538  */
1539 
1540  } else if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) {
1541  online = determine_online_status_no_fencing(data_set, node_state, this_node);
1542 
1543  } else {
1544  online = determine_online_status_fencing(data_set, node_state, this_node);
1545  }
1546 
1547  if (online) {
1548  this_node->details->online = TRUE;
1549 
1550  } else {
1551  /* remove node from contention */
1552  this_node->fixed = TRUE;
1553  this_node->weight = -INFINITY;
1554  }
1555 
1556  if (online && this_node->details->shutdown) {
1557  /* don't run resources here */
1558  this_node->fixed = TRUE;
1559  this_node->weight = -INFINITY;
1560  }
1561 
1562  if (this_node->details->type == node_ping) {
1563  crm_info("Node %s is not a pacemaker node", this_node->details->uname);
1564 
1565  } else if (this_node->details->unclean) {
1566  pe_proc_warn("Node %s is unclean", this_node->details->uname);
1567 
1568  } else if (this_node->details->online) {
1569  crm_info("Node %s is %s", this_node->details->uname,
1570  this_node->details->shutdown ? "shutting down" :
1571  this_node->details->pending ? "pending" :
1572  this_node->details->standby ? "standby" :
1573  this_node->details->maintenance ? "maintenance" : "online");
1574 
1575  } else {
1576  crm_trace("Node %s is offline", this_node->details->uname);
1577  }
1578 
1579  return online;
1580 }
1581 
1582 char *
1583 clone_strip(const char *last_rsc_id)
1584 {
1585  int lpc = 0;
1586  char *zero = NULL;
1587 
1588  CRM_CHECK(last_rsc_id != NULL, return NULL);
1589  lpc = strlen(last_rsc_id);
1590  while (--lpc > 0) {
1591  switch (last_rsc_id[lpc]) {
1592  case 0:
1593  crm_err("Empty string: %s", last_rsc_id);
1594  return NULL;
1595  break;
1596  case '0':
1597  case '1':
1598  case '2':
1599  case '3':
1600  case '4':
1601  case '5':
1602  case '6':
1603  case '7':
1604  case '8':
1605  case '9':
1606  break;
1607  case ':':
1608  zero = calloc(1, lpc + 1);
1609  memcpy(zero, last_rsc_id, lpc);
1610  zero[lpc] = 0;
1611  return zero;
1612  default:
1613  goto done;
1614  }
1615  }
1616  done:
1617  zero = strdup(last_rsc_id);
1618  return zero;
1619 }
1620 
1621 char *
1622 clone_zero(const char *last_rsc_id)
1623 {
1624  int lpc = 0;
1625  char *zero = NULL;
1626 
1627  CRM_CHECK(last_rsc_id != NULL, return NULL);
1628  if (last_rsc_id != NULL) {
1629  lpc = strlen(last_rsc_id);
1630  }
1631 
1632  while (--lpc > 0) {
1633  switch (last_rsc_id[lpc]) {
1634  case 0:
1635  return NULL;
1636  break;
1637  case '0':
1638  case '1':
1639  case '2':
1640  case '3':
1641  case '4':
1642  case '5':
1643  case '6':
1644  case '7':
1645  case '8':
1646  case '9':
1647  break;
1648  case ':':
1649  zero = calloc(1, lpc + 3);
1650  memcpy(zero, last_rsc_id, lpc);
1651  zero[lpc] = ':';
1652  zero[lpc + 1] = '0';
1653  zero[lpc + 2] = 0;
1654  return zero;
1655  default:
1656  goto done;
1657  }
1658  }
1659  done:
1660  lpc = strlen(last_rsc_id);
1661  zero = calloc(1, lpc + 3);
1662  memcpy(zero, last_rsc_id, lpc);
1663  zero[lpc] = ':';
1664  zero[lpc + 1] = '0';
1665  zero[lpc + 2] = 0;
1666  crm_trace("%s -> %s", last_rsc_id, zero);
1667  return zero;
1668 }
1669 
1670 static resource_t *
1671 create_fake_resource(const char *rsc_id, xmlNode * rsc_entry, pe_working_set_t * data_set)
1672 {
1673  resource_t *rsc = NULL;
1674  xmlNode *xml_rsc = create_xml_node(NULL, XML_CIB_TAG_RESOURCE);
1675 
1676  copy_in_properties(xml_rsc, rsc_entry);
1677  crm_xml_add(xml_rsc, XML_ATTR_ID, rsc_id);
1678  crm_log_xml_debug(xml_rsc, "Orphan resource");
1679 
1680  if (!common_unpack(xml_rsc, &rsc, NULL, data_set)) {
1681  return NULL;
1682  }
1683 
1684  if (xml_contains_remote_node(xml_rsc)) {
1685  node_t *node;
1686 
1687  crm_debug("Detected orphaned remote node %s", rsc_id);
1688  node = pe_find_node(data_set->nodes, rsc_id);
1689  if (node == NULL) {
1690  node = pe_create_node(rsc_id, rsc_id, "remote", NULL, data_set);
1691  }
1692  link_rsc2remotenode(data_set, rsc);
1693 
1694  if (node) {
1695  crm_trace("Setting node %s as shutting down due to orphaned connection resource", rsc_id);
1696  node->details->shutdown = TRUE;
1697  }
1698  }
1699 
1700  if (crm_element_value(rsc_entry, XML_RSC_ATTR_CONTAINER)) {
1701  /* This orphaned rsc needs to be mapped to a container. */
1702  crm_trace("Detected orphaned container filler %s", rsc_id);
1704  }
1705  set_bit(rsc->flags, pe_rsc_orphan);
1706  data_set->resources = g_list_append(data_set->resources, rsc);
1707  return rsc;
1708 }
1709 
1710 extern resource_t *create_child_clone(resource_t * rsc, int sub_id, pe_working_set_t * data_set);
1711 
1712 static resource_t *
1713 find_anonymous_clone(pe_working_set_t * data_set, node_t * node, resource_t * parent,
1714  const char *rsc_id)
1715 {
1716  GListPtr rIter = NULL;
1717  resource_t *rsc = NULL;
1718  gboolean skip_inactive = FALSE;
1719 
1720  CRM_ASSERT(parent != NULL);
1721  CRM_ASSERT(pe_rsc_is_clone(parent));
1722  CRM_ASSERT(is_not_set(parent->flags, pe_rsc_unique));
1723 
1724  /* Find an instance active (or partially active for grouped clones) on the specified node */
1725  pe_rsc_trace(parent, "Looking for %s on %s in %s", rsc_id, node->details->uname, parent->id);
1726  for (rIter = parent->children; rsc == NULL && rIter; rIter = rIter->next) {
1727  GListPtr nIter = NULL;
1728  GListPtr locations = NULL;
1729  resource_t *child = rIter->data;
1730 
1731  child->fns->location(child, &locations, TRUE);
1732  if (locations == NULL) {
1733  pe_rsc_trace(child, "Resource %s, skip inactive", child->id);
1734  continue;
1735  }
1736 
1737  for (nIter = locations; nIter && rsc == NULL; nIter = nIter->next) {
1738  node_t *childnode = nIter->data;
1739 
1740  if (childnode->details == node->details) {
1741  /* ->find_rsc() because we might be a cloned group */
1742  rsc = parent->fns->find_rsc(child, rsc_id, NULL, pe_find_clone);
1743  if(rsc) {
1744  pe_rsc_trace(rsc, "Resource %s, active", rsc->id);
1745  }
1746  }
1747 
1748  /* Keep this block, it means we'll do the right thing if
1749  * anyone toggles the unique flag to 'off'
1750  */
1751  if (rsc && rsc->running_on) {
1752  crm_notice("/Anonymous/ clone %s is already running on %s",
1753  parent->id, node->details->uname);
1754  skip_inactive = TRUE;
1755  rsc = NULL;
1756  }
1757  }
1758 
1759  g_list_free(locations);
1760  }
1761 
1762  /* Find an inactive instance */
1763  if (skip_inactive == FALSE) {
1764  pe_rsc_trace(parent, "Looking for %s anywhere", rsc_id);
1765  for (rIter = parent->children; rsc == NULL && rIter; rIter = rIter->next) {
1766  GListPtr locations = NULL;
1767  resource_t *child = rIter->data;
1768 
1769  if (is_set(child->flags, pe_rsc_block)) {
1770  pe_rsc_trace(child, "Skip: blocked in stopped state");
1771  continue;
1772  }
1773 
1774  child->fns->location(child, &locations, TRUE);
1775  if (locations == NULL) {
1776  /* ->find_rsc() because we might be a cloned group */
1777  rsc = parent->fns->find_rsc(child, rsc_id, NULL, pe_find_clone);
1778  pe_rsc_trace(parent, "Resource %s, empty slot", rsc->id);
1779  }
1780  g_list_free(locations);
1781  }
1782  }
1783 
1784  if (rsc == NULL) {
1785  /* Create an extra orphan */
1786  resource_t *top = create_child_clone(parent, -1, data_set);
1787 
1788  /* ->find_rsc() because we might be a cloned group */
1789  rsc = top->fns->find_rsc(top, rsc_id, NULL, pe_find_clone);
1790  CRM_ASSERT(rsc != NULL);
1791 
1792  pe_rsc_debug(parent, "Created orphan %s for %s: %s on %s", top->id, parent->id, rsc_id,
1793  node->details->uname);
1794  }
1795 
1796  if (safe_str_neq(rsc_id, rsc->id)) {
1797  pe_rsc_debug(rsc, "Internally renamed %s on %s to %s%s",
1798  rsc_id, node->details->uname, rsc->id,
1799  is_set(rsc->flags, pe_rsc_orphan) ? " (ORPHAN)" : "");
1800  }
1801 
1802  return rsc;
1803 }
1804 
1805 static resource_t *
1806 unpack_find_resource(pe_working_set_t * data_set, node_t * node, const char *rsc_id,
1807  xmlNode * rsc_entry)
1808 {
1809  resource_t *rsc = NULL;
1810  resource_t *parent = NULL;
1811 
1812  crm_trace("looking for %s", rsc_id);
1813  rsc = pe_find_resource(data_set->resources, rsc_id);
1814 
1815  /* no match */
1816  if (rsc == NULL) {
1817  /* Even when clone-max=0, we still create a single :0 orphan to match against */
1818  char *tmp = clone_zero(rsc_id);
1819  resource_t *clone0 = pe_find_resource(data_set->resources, tmp);
1820 
1821  if (clone0 && is_not_set(clone0->flags, pe_rsc_unique)) {
1822  rsc = clone0;
1823  } else {
1824  crm_trace("%s is not known as %s either", rsc_id, tmp);
1825  }
1826 
1827  parent = uber_parent(clone0);
1828  free(tmp);
1829 
1830  crm_trace("%s not found: %s", rsc_id, parent ? parent->id : "orphan");
1831 
1832  } else if (rsc->variant > pe_native) {
1833  crm_trace("%s is no longer a primitive resource, the lrm_resource entry is obsolete",
1834  rsc_id);
1835  return NULL;
1836 
1837  } else {
1838  parent = uber_parent(rsc);
1839  }
1840 
1841  if(parent && parent->parent) {
1842  rsc = find_container_child(rsc_id, rsc, node);
1843 
1844  } else if (pe_rsc_is_clone(parent)) {
1845  if (is_not_set(parent->flags, pe_rsc_unique)) {
1846  char *base = clone_strip(rsc_id);
1847 
1848  rsc = find_anonymous_clone(data_set, node, parent, base);
1849  CRM_ASSERT(rsc != NULL);
1850  free(base);
1851  }
1852 
1853  if (rsc && safe_str_neq(rsc_id, rsc->id)) {
1854  free(rsc->clone_name);
1855  rsc->clone_name = strdup(rsc_id);
1856  }
1857  }
1858 
1859  return rsc;
1860 }
1861 
1862 static resource_t *
1863 process_orphan_resource(xmlNode * rsc_entry, node_t * node, pe_working_set_t * data_set)
1864 {
1865  resource_t *rsc = NULL;
1866  const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID);
1867 
1868  crm_debug("Detected orphan resource %s on %s", rsc_id, node->details->uname);
1869  rsc = create_fake_resource(rsc_id, rsc_entry, data_set);
1870 
1871  if (is_set(data_set->flags, pe_flag_stop_rsc_orphans) == FALSE) {
1873 
1874  } else {
1875  print_resource(LOG_DEBUG_3, "Added orphan", rsc, FALSE);
1876 
1877  CRM_CHECK(rsc != NULL, return NULL);
1878  resource_location(rsc, NULL, -INFINITY, "__orphan_dont_run__", data_set);
1879  }
1880  return rsc;
1881 }
1882 
1883 static void
1884 process_rsc_state(resource_t * rsc, node_t * node,
1885  enum action_fail_response on_fail,
1886  xmlNode * migrate_op, pe_working_set_t * data_set)
1887 {
1888  node_t *tmpnode = NULL;
1889  char *reason = NULL;
1890 
1891  CRM_ASSERT(rsc);
1892  pe_rsc_trace(rsc, "Resource %s is %s on %s: on_fail=%s",
1893  rsc->id, role2text(rsc->role), node->details->uname, fail2text(on_fail));
1894 
1895  /* process current state */
1896  if (rsc->role != RSC_ROLE_UNKNOWN) {
1897  resource_t *iter = rsc;
1898 
1899  while (iter) {
1900  if (g_hash_table_lookup(iter->known_on, node->details->id) == NULL) {
1901  node_t *n = node_copy(node);
1902 
1903  pe_rsc_trace(rsc, "%s (aka. %s) known on %s", rsc->id, rsc->clone_name,
1904  n->details->uname);
1905  g_hash_table_insert(iter->known_on, (gpointer) n->details->id, n);
1906  }
1907  if (is_set(iter->flags, pe_rsc_unique)) {
1908  break;
1909  }
1910  iter = iter->parent;
1911  }
1912  }
1913 
1914  /* If a managed resource is believed to be running, but node is down ... */
1915  if (rsc->role > RSC_ROLE_STOPPED
1916  && node->details->online == FALSE
1917  && node->details->maintenance == FALSE
1918  && is_set(rsc->flags, pe_rsc_managed)) {
1919 
1920  gboolean should_fence = FALSE;
1921 
1922  /* If this is a guest node, fence it (regardless of whether fencing is
1923  * enabled, because guest node fencing is done by recovery of the
1924  * container resource rather than by stonithd). Mark the resource
1925  * we're processing as failed. When the guest comes back up, its
1926  * operation history in the CIB will be cleared, freeing the affected
1927  * resource to run again once we are sure we know its state.
1928  */
1929  if (is_container_remote_node(node)) {
1930  set_bit(rsc->flags, pe_rsc_failed);
1931  should_fence = TRUE;
1932 
1933  } else if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
1934  if (is_baremetal_remote_node(node) && node->details->remote_rsc
1935  && is_not_set(node->details->remote_rsc->flags, pe_rsc_failed)) {
1936 
1937  /* setting unseen = true means that fencing of the remote node will
1938  * only occur if the connection resource is not going to start somewhere.
1939  * This allows connection resources on a failed cluster-node to move to
1940  * another node without requiring the baremetal remote nodes to be fenced
1941  * as well. */
1942  node->details->unseen = TRUE;
1943  reason = crm_strdup_printf("%s is active there (fencing will be"
1944  " revoked if remote connection can "
1945  "be re-established elsewhere)",
1946  rsc->id);
1947  }
1948  should_fence = TRUE;
1949  }
1950 
1951  if (should_fence) {
1952  if (reason == NULL) {
1953  reason = crm_strdup_printf("%s is thought to be active there", rsc->id);
1954  }
1955  pe_fence_node(data_set, node, reason);
1956  }
1957  free(reason);
1958  }
1959 
1960  if (node->details->unclean) {
1961  /* No extra processing needed
1962  * Also allows resources to be started again after a node is shot
1963  */
1964  on_fail = action_fail_ignore;
1965  }
1966 
1967  switch (on_fail) {
1968  case action_fail_ignore:
1969  /* nothing to do */
1970  break;
1971 
1972  case action_fail_fence:
1973  /* treat it as if it is still running
1974  * but also mark the node as unclean
1975  */
1976  reason = crm_strdup_printf("%s failed there", rsc->id);
1977  pe_fence_node(data_set, node, reason);
1978  free(reason);
1979  break;
1980 
1981  case action_fail_standby:
1982  node->details->standby = TRUE;
1983  node->details->standby_onfail = TRUE;
1984  break;
1985 
1986  case action_fail_block:
1987  /* is_managed == FALSE will prevent any
1988  * actions being sent for the resource
1989  */
1991  set_bit(rsc->flags, pe_rsc_block);
1992  break;
1993 
1994  case action_fail_migrate:
1995  /* make sure it comes up somewhere else
1996  * or not at all
1997  */
1998  resource_location(rsc, node, -INFINITY, "__action_migration_auto__", data_set);
1999  break;
2000 
2001  case action_fail_stop:
2002  rsc->next_role = RSC_ROLE_STOPPED;
2003  break;
2004 
2005  case action_fail_recover:
2006  if (rsc->role != RSC_ROLE_STOPPED && rsc->role != RSC_ROLE_UNKNOWN) {
2007  set_bit(rsc->flags, pe_rsc_failed);
2008  stop_action(rsc, node, FALSE);
2009  }
2010  break;
2011 
2013  set_bit(rsc->flags, pe_rsc_failed);
2014 
2015  if (rsc->container) {
2016  stop_action(rsc->container, node, FALSE);
2017  } else if (rsc->role != RSC_ROLE_STOPPED && rsc->role != RSC_ROLE_UNKNOWN) {
2018  stop_action(rsc, node, FALSE);
2019  }
2020  break;
2021 
2023  set_bit(rsc->flags, pe_rsc_failed);
2024  if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
2025  tmpnode = NULL;
2026  if (rsc->is_remote_node) {
2027  tmpnode = pe_find_node(data_set->nodes, rsc->id);
2028  }
2029  if (tmpnode &&
2030  is_baremetal_remote_node(tmpnode) &&
2031  tmpnode->details->remote_was_fenced == 0) {
2032 
2033  /* connection resource to baremetal resource failed in a way that
2034  * should result in fencing the remote-node. */
2035  pe_fence_node(data_set, tmpnode,
2036  "remote connection is unrecoverable");
2037  }
2038  }
2039 
2040  /* require the stop action regardless if fencing is occuring or not. */
2041  if (rsc->role > RSC_ROLE_STOPPED) {
2042  stop_action(rsc, node, FALSE);
2043  }
2044 
2045  /* if reconnect delay is in use, prevent the connection from exiting the
2046  * "STOPPED" role until the failure is cleared by the delay timeout. */
2047  if (rsc->remote_reconnect_interval) {
2048  rsc->next_role = RSC_ROLE_STOPPED;
2049  }
2050  break;
2051  }
2052 
2053  /* ensure a remote-node connection failure forces an unclean remote-node
2054  * to be fenced. By setting unseen = FALSE, the remote-node failure will
2055  * result in a fencing operation regardless if we're going to attempt to
2056  * reconnect to the remote-node in this transition or not. */
2057  if (is_set(rsc->flags, pe_rsc_failed) && rsc->is_remote_node) {
2058  tmpnode = pe_find_node(data_set->nodes, rsc->id);
2059  if (tmpnode && tmpnode->details->unclean) {
2060  tmpnode->details->unseen = FALSE;
2061  }
2062  }
2063 
2064  if (rsc->role != RSC_ROLE_STOPPED && rsc->role != RSC_ROLE_UNKNOWN) {
2065  if (is_set(rsc->flags, pe_rsc_orphan)) {
2066  if (is_set(rsc->flags, pe_rsc_managed)) {
2067  crm_config_warn("Detected active orphan %s running on %s",
2068  rsc->id, node->details->uname);
2069  } else {
2070  crm_config_warn("Cluster configured not to stop active orphans."
2071  " %s must be stopped manually on %s",
2072  rsc->id, node->details->uname);
2073  }
2074  }
2075 
2076  native_add_running(rsc, node, data_set);
2077  if (on_fail != action_fail_ignore) {
2078  set_bit(rsc->flags, pe_rsc_failed);
2079  }
2080 
2081  } else if (rsc->clone_name && strchr(rsc->clone_name, ':') != NULL) {
2082  /* Only do this for older status sections that included instance numbers
2083  * Otherwise stopped instances will appear as orphans
2084  */
2085  pe_rsc_trace(rsc, "Resetting clone_name %s for %s (stopped)", rsc->clone_name, rsc->id);
2086  free(rsc->clone_name);
2087  rsc->clone_name = NULL;
2088 
2089  } else {
2090  char *key = stop_key(rsc);
2091  GListPtr possible_matches = find_actions(rsc->actions, key, node);
2092  GListPtr gIter = possible_matches;
2093 
2094  for (; gIter != NULL; gIter = gIter->next) {
2095  action_t *stop = (action_t *) gIter->data;
2096 
2097  stop->flags |= pe_action_optional;
2098  }
2099 
2100  g_list_free(possible_matches);
2101  free(key);
2102  }
2103 }
2104 
2105 /* create active recurring operations as optional */
2106 static void
2107 process_recurring(node_t * node, resource_t * rsc,
2108  int start_index, int stop_index,
2109  GListPtr sorted_op_list, pe_working_set_t * data_set)
2110 {
2111  int counter = -1;
2112  const char *task = NULL;
2113  const char *status = NULL;
2114  GListPtr gIter = sorted_op_list;
2115 
2116  CRM_ASSERT(rsc);
2117  pe_rsc_trace(rsc, "%s: Start index %d, stop index = %d", rsc->id, start_index, stop_index);
2118 
2119  for (; gIter != NULL; gIter = gIter->next) {
2120  xmlNode *rsc_op = (xmlNode *) gIter->data;
2121 
2122  int interval = 0;
2123  char *key = NULL;
2124  const char *id = ID(rsc_op);
2125  const char *interval_s = NULL;
2126 
2127  counter++;
2128 
2129  if (node->details->online == FALSE) {
2130  pe_rsc_trace(rsc, "Skipping %s/%s: node is offline", rsc->id, node->details->uname);
2131  break;
2132 
2133  /* Need to check if there's a monitor for role="Stopped" */
2134  } else if (start_index < stop_index && counter <= stop_index) {
2135  pe_rsc_trace(rsc, "Skipping %s/%s: resource is not active", id, node->details->uname);
2136  continue;
2137 
2138  } else if (counter < start_index) {
2139  pe_rsc_trace(rsc, "Skipping %s/%s: old %d", id, node->details->uname, counter);
2140  continue;
2141  }
2142 
2143  interval_s = crm_element_value(rsc_op, XML_LRM_ATTR_INTERVAL);
2144  interval = crm_parse_int(interval_s, "0");
2145  if (interval == 0) {
2146  pe_rsc_trace(rsc, "Skipping %s/%s: non-recurring", id, node->details->uname);
2147  continue;
2148  }
2149 
2150  status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS);
2151  if (safe_str_eq(status, "-1")) {
2152  pe_rsc_trace(rsc, "Skipping %s/%s: status", id, node->details->uname);
2153  continue;
2154  }
2155  task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
2156  /* create the action */
2157  key = generate_op_key(rsc->id, task, interval);
2158  pe_rsc_trace(rsc, "Creating %s/%s", key, node->details->uname);
2159  custom_action(rsc, key, task, node, TRUE, TRUE, data_set);
2160  }
2161 }
2162 
2163 void
2164 calculate_active_ops(GListPtr sorted_op_list, int *start_index, int *stop_index)
2165 {
2166  int counter = -1;
2167  int implied_monitor_start = -1;
2168  int implied_master_start = -1;
2169  const char *task = NULL;
2170  const char *status = NULL;
2171  GListPtr gIter = sorted_op_list;
2172 
2173  *stop_index = -1;
2174  *start_index = -1;
2175 
2176  for (; gIter != NULL; gIter = gIter->next) {
2177  xmlNode *rsc_op = (xmlNode *) gIter->data;
2178 
2179  counter++;
2180 
2181  task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
2182  status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS);
2183 
2184  if (safe_str_eq(task, CRMD_ACTION_STOP)
2185  && safe_str_eq(status, "0")) {
2186  *stop_index = counter;
2187 
2188  } else if (safe_str_eq(task, CRMD_ACTION_START) || safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
2189  *start_index = counter;
2190 
2191  } else if ((implied_monitor_start <= *stop_index) && safe_str_eq(task, CRMD_ACTION_STATUS)) {
2192  const char *rc = crm_element_value(rsc_op, XML_LRM_ATTR_RC);
2193 
2194  if (safe_str_eq(rc, "0") || safe_str_eq(rc, "8")) {
2195  implied_monitor_start = counter;
2196  }
2197  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE) || safe_str_eq(task, CRMD_ACTION_DEMOTE)) {
2198  implied_master_start = counter;
2199  }
2200  }
2201 
2202  if (*start_index == -1) {
2203  if (implied_master_start != -1) {
2204  *start_index = implied_master_start;
2205  } else if (implied_monitor_start != -1) {
2206  *start_index = implied_monitor_start;
2207  }
2208  }
2209 }
2210 
2211 static resource_t *
2212 unpack_lrm_rsc_state(node_t * node, xmlNode * rsc_entry, pe_working_set_t * data_set)
2213 {
2214  GListPtr gIter = NULL;
2215  int stop_index = -1;
2216  int start_index = -1;
2217  enum rsc_role_e req_role = RSC_ROLE_UNKNOWN;
2218 
2219  const char *task = NULL;
2220  const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID);
2221 
2222  resource_t *rsc = NULL;
2223  GListPtr op_list = NULL;
2224  GListPtr sorted_op_list = NULL;
2225 
2226  xmlNode *migrate_op = NULL;
2227  xmlNode *rsc_op = NULL;
2228  xmlNode *last_failure = NULL;
2229 
2230  enum action_fail_response on_fail = FALSE;
2231  enum rsc_role_e saved_role = RSC_ROLE_UNKNOWN;
2232 
2233  crm_trace("[%s] Processing %s on %s",
2234  crm_element_name(rsc_entry), rsc_id, node->details->uname);
2235 
2236  /* extract operations */
2237  op_list = NULL;
2238  sorted_op_list = NULL;
2239 
2240  for (rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next_element(rsc_op)) {
2241  if (crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) {
2242  op_list = g_list_prepend(op_list, rsc_op);
2243  }
2244  }
2245 
2246  if (op_list == NULL) {
2247  /* if there are no operations, there is nothing to do */
2248  return NULL;
2249  }
2250 
2251  /* find the resource */
2252  rsc = unpack_find_resource(data_set, node, rsc_id, rsc_entry);
2253  if (rsc == NULL) {
2254  rsc = process_orphan_resource(rsc_entry, node, data_set);
2255  }
2256  CRM_ASSERT(rsc != NULL);
2257 
2258  /* process operations */
2259  saved_role = rsc->role;
2260  on_fail = action_fail_ignore;
2261  rsc->role = RSC_ROLE_UNKNOWN;
2262  sorted_op_list = g_list_sort(op_list, sort_op_by_callid);
2263 
2264  for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
2265  xmlNode *rsc_op = (xmlNode *) gIter->data;
2266 
2267  task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
2268  if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
2269  migrate_op = rsc_op;
2270  }
2271 
2272  unpack_rsc_op(rsc, node, rsc_op, &last_failure, &on_fail, data_set);
2273  }
2274 
2275  /* create active recurring operations as optional */
2276  calculate_active_ops(sorted_op_list, &start_index, &stop_index);
2277  process_recurring(node, rsc, start_index, stop_index, sorted_op_list, data_set);
2278 
2279  /* no need to free the contents */
2280  g_list_free(sorted_op_list);
2281 
2282  process_rsc_state(rsc, node, on_fail, migrate_op, data_set);
2283 
2284  if (get_target_role(rsc, &req_role)) {
2285  if (rsc->next_role == RSC_ROLE_UNKNOWN || req_role < rsc->next_role) {
2286  pe_rsc_debug(rsc, "%s: Overwriting calculated next role %s"
2287  " with requested next role %s",
2288  rsc->id, role2text(rsc->next_role), role2text(req_role));
2289  rsc->next_role = req_role;
2290 
2291  } else if (req_role > rsc->next_role) {
2292  pe_rsc_info(rsc, "%s: Not overwriting calculated next role %s"
2293  " with requested next role %s",
2294  rsc->id, role2text(rsc->next_role), role2text(req_role));
2295  }
2296  }
2297 
2298  if (saved_role > rsc->role) {
2299  rsc->role = saved_role;
2300  }
2301 
2302  return rsc;
2303 }
2304 
2305 static void
2306 handle_orphaned_container_fillers(xmlNode * lrm_rsc_list, pe_working_set_t * data_set)
2307 {
2308  xmlNode *rsc_entry = NULL;
2309  for (rsc_entry = __xml_first_child(lrm_rsc_list); rsc_entry != NULL;
2310  rsc_entry = __xml_next_element(rsc_entry)) {
2311 
2312  resource_t *rsc;
2313  resource_t *container;
2314  const char *rsc_id;
2315  const char *container_id;
2316 
2317  if (safe_str_neq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE)) {
2318  continue;
2319  }
2320 
2321  container_id = crm_element_value(rsc_entry, XML_RSC_ATTR_CONTAINER);
2322  rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID);
2323  if (container_id == NULL || rsc_id == NULL) {
2324  continue;
2325  }
2326 
2327  container = pe_find_resource(data_set->resources, container_id);
2328  if (container == NULL) {
2329  continue;
2330  }
2331 
2332  rsc = pe_find_resource(data_set->resources, rsc_id);
2333  if (rsc == NULL ||
2334  is_set(rsc->flags, pe_rsc_orphan_container_filler) == FALSE ||
2335  rsc->container != NULL) {
2336  continue;
2337  }
2338 
2339  pe_rsc_trace(rsc, "Mapped orphaned rsc %s's container to %s", rsc->id, container_id);
2340  rsc->container = container;
2341  container->fillers = g_list_append(container->fillers, rsc);
2342  }
2343 }
2344 
2345 gboolean
2346 unpack_lrm_resources(node_t * node, xmlNode * lrm_rsc_list, pe_working_set_t * data_set)
2347 {
2348  xmlNode *rsc_entry = NULL;
2349  gboolean found_orphaned_container_filler = FALSE;
2350  GListPtr unexpected_containers = NULL;
2351  GListPtr gIter = NULL;
2352  resource_t *remote = NULL;
2353 
2354  CRM_CHECK(node != NULL, return FALSE);
2355 
2356  crm_trace("Unpacking resources on %s", node->details->uname);
2357 
2358  for (rsc_entry = __xml_first_child(lrm_rsc_list); rsc_entry != NULL;
2359  rsc_entry = __xml_next_element(rsc_entry)) {
2360 
2361  if (crm_str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, TRUE)) {
2362  resource_t *rsc;
2363  rsc = unpack_lrm_rsc_state(node, rsc_entry, data_set);
2364  if (!rsc) {
2365  continue;
2366  }
2367  if (is_set(rsc->flags, pe_rsc_orphan_container_filler)) {
2368  found_orphaned_container_filler = TRUE;
2369  }
2370  if (is_set(rsc->flags, pe_rsc_unexpectedly_running)) {
2371  remote = rsc_contains_remote_node(data_set, rsc);
2372  if (remote) {
2373  unexpected_containers = g_list_append(unexpected_containers, remote);
2374  }
2375  }
2376  }
2377  }
2378 
2379  /* If a container resource is unexpectedly up... and the remote-node
2380  * connection resource for that container is not up, the entire container
2381  * must be recovered. */
2382  for (gIter = unexpected_containers; gIter != NULL; gIter = gIter->next) {
2383  remote = (resource_t *) gIter->data;
2384  if (remote->role != RSC_ROLE_STARTED) {
2385  crm_warn("Recovering container resource %s. Resource is unexpectedly running and involves a remote-node.", remote->container->id);
2386  set_bit(remote->container->flags, pe_rsc_failed);
2387  }
2388  }
2389 
2390  /* now that all the resource state has been unpacked for this node
2391  * we have to go back and map any orphaned container fillers to their
2392  * container resource */
2393  if (found_orphaned_container_filler) {
2394  handle_orphaned_container_fillers(lrm_rsc_list, data_set);
2395  }
2396  g_list_free(unexpected_containers);
2397  return TRUE;
2398 }
2399 
2400 static void
2401 set_active(resource_t * rsc)
2402 {
2403  resource_t *top = uber_parent(rsc);
2404 
2405  if (top && top->variant == pe_master) {
2406  rsc->role = RSC_ROLE_SLAVE;
2407  } else {
2408  rsc->role = RSC_ROLE_STARTED;
2409  }
2410 }
2411 
2412 static void
2413 set_node_score(gpointer key, gpointer value, gpointer user_data)
2414 {
2415  node_t *node = value;
2416  int *score = user_data;
2417 
2418  node->weight = *score;
2419 }
2420 
2421 #define STATUS_PATH_MAX 1024
2422 static xmlNode *
2423 find_lrm_op(const char *resource, const char *op, const char *node, const char *source,
2424  pe_working_set_t * data_set)
2425 {
2426  int offset = 0;
2427  char xpath[STATUS_PATH_MAX];
2428 
2429  offset += snprintf(xpath + offset, STATUS_PATH_MAX - offset, "//node_state[@uname='%s']", node);
2430  offset +=
2431  snprintf(xpath + offset, STATUS_PATH_MAX - offset, "//" XML_LRM_TAG_RESOURCE "[@id='%s']",
2432  resource);
2433 
2434  /* Need to check against transition_magic too? */
2435  if (source && safe_str_eq(op, CRMD_ACTION_MIGRATE)) {
2436  offset +=
2437  snprintf(xpath + offset, STATUS_PATH_MAX - offset,
2438  "/" XML_LRM_TAG_RSC_OP "[@operation='%s' and @migrate_target='%s']", op,
2439  source);
2440  } else if (source && safe_str_eq(op, CRMD_ACTION_MIGRATED)) {
2441  offset +=
2442  snprintf(xpath + offset, STATUS_PATH_MAX - offset,
2443  "/" XML_LRM_TAG_RSC_OP "[@operation='%s' and @migrate_source='%s']", op,
2444  source);
2445  } else {
2446  offset +=
2447  snprintf(xpath + offset, STATUS_PATH_MAX - offset,
2448  "/" XML_LRM_TAG_RSC_OP "[@operation='%s']", op);
2449  }
2450 
2451  CRM_LOG_ASSERT(offset > 0);
2452  return get_xpath_object(xpath, data_set->input, LOG_DEBUG);
2453 }
2454 
2455 static void
2456 unpack_rsc_migration(resource_t *rsc, node_t *node, xmlNode *xml_op, pe_working_set_t * data_set)
2457 {
2458 
2459  /*
2460  * The normal sequence is (now): migrate_to(Src) -> migrate_from(Tgt) -> stop(Src)
2461  *
2462  * So if a migrate_to is followed by a stop, then we don't need to care what
2463  * happened on the target node
2464  *
2465  * Without the stop, we need to look for a successful migrate_from.
2466  * This would also imply we're no longer running on the source
2467  *
2468  * Without the stop, and without a migrate_from op we make sure the resource
2469  * gets stopped on both source and target (assuming the target is up)
2470  *
2471  */
2472  int stop_id = 0;
2473  int task_id = 0;
2474  xmlNode *stop_op =
2475  find_lrm_op(rsc->id, CRMD_ACTION_STOP, node->details->id, NULL, data_set);
2476 
2477  if (stop_op) {
2478  crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id);
2479  }
2480 
2481  crm_element_value_int(xml_op, XML_LRM_ATTR_CALLID, &task_id);
2482 
2483  if (stop_op == NULL || stop_id < task_id) {
2484  int from_rc = 0, from_status = 0;
2485  const char *migrate_source =
2487  const char *migrate_target =
2489 
2490  node_t *target = pe_find_node(data_set->nodes, migrate_target);
2491  node_t *source = pe_find_node(data_set->nodes, migrate_source);
2492  xmlNode *migrate_from =
2493  find_lrm_op(rsc->id, CRMD_ACTION_MIGRATED, migrate_target, migrate_source,
2494  data_set);
2495 
2496  rsc->role = RSC_ROLE_STARTED; /* can be master? */
2497  if (migrate_from) {
2498  crm_element_value_int(migrate_from, XML_LRM_ATTR_RC, &from_rc);
2499  crm_element_value_int(migrate_from, XML_LRM_ATTR_OPSTATUS, &from_status);
2500  pe_rsc_trace(rsc, "%s op on %s exited with status=%d, rc=%d",
2501  ID(migrate_from), migrate_target, from_status, from_rc);
2502  }
2503 
2504  if (migrate_from && from_rc == PCMK_OCF_OK
2505  && from_status == PCMK_LRM_OP_DONE) {
2506  pe_rsc_trace(rsc, "Detected dangling migration op: %s on %s", ID(xml_op),
2507  migrate_source);
2508 
2509  /* all good
2510  * just need to arrange for the stop action to get sent
2511  * but _without_ affecting the target somehow
2512  */
2513  rsc->role = RSC_ROLE_STOPPED;
2514  rsc->dangling_migrations = g_list_prepend(rsc->dangling_migrations, node);
2515 
2516  } else if (migrate_from) { /* Failed */
2517  if (target && target->details->online) {
2518  pe_rsc_trace(rsc, "Marking active on %s %p %d", migrate_target, target,
2519  target->details->online);
2520  native_add_running(rsc, target, data_set);
2521  }
2522 
2523  } else { /* Pending or complete but erased */
2524  if (target && target->details->online) {
2525  pe_rsc_trace(rsc, "Marking active on %s %p %d", migrate_target, target,
2526  target->details->online);
2527 
2528  native_add_running(rsc, target, data_set);
2529  if (source && source->details->online) {
2530  /* If we make it here we have a partial migration. The migrate_to
2531  * has completed but the migrate_from on the target has not. Hold on
2532  * to the target and source on the resource. Later on if we detect that
2533  * the resource is still going to run on that target, we may continue
2534  * the migration */
2535  rsc->partial_migration_target = target;
2536  rsc->partial_migration_source = source;
2537  }
2538  } else {
2539  /* Consider it failed here - forces a restart, prevents migration */
2540  set_bit(rsc->flags, pe_rsc_failed);
2542  }
2543  }
2544  }
2545 }
2546 
2547 static void
2548 unpack_rsc_migration_failure(resource_t *rsc, node_t *node, xmlNode *xml_op, pe_working_set_t * data_set)
2549 {
2550  const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
2551 
2552  CRM_ASSERT(rsc);
2553  if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
2554  int stop_id = 0;
2555  int migrate_id = 0;
2556  const char *migrate_source = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_SOURCE);
2557  const char *migrate_target = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET);
2558 
2559  xmlNode *stop_op =
2560  find_lrm_op(rsc->id, CRMD_ACTION_STOP, migrate_source, NULL, data_set);
2561  xmlNode *migrate_op =
2562  find_lrm_op(rsc->id, CRMD_ACTION_MIGRATE, migrate_source, migrate_target,
2563  data_set);
2564 
2565  if (stop_op) {
2566  crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id);
2567  }
2568  if (migrate_op) {
2569  crm_element_value_int(migrate_op, XML_LRM_ATTR_CALLID, &migrate_id);
2570  }
2571 
2572  /* Get our state right */
2573  rsc->role = RSC_ROLE_STARTED; /* can be master? */
2574 
2575  if (stop_op == NULL || stop_id < migrate_id) {
2576  node_t *source = pe_find_node(data_set->nodes, migrate_source);
2577 
2578  if (source && source->details->online) {
2579  native_add_running(rsc, source, data_set);
2580  }
2581  }
2582 
2583  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) {
2584  int stop_id = 0;
2585  int migrate_id = 0;
2586  const char *migrate_source = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_SOURCE);
2587  const char *migrate_target = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET);
2588 
2589  xmlNode *stop_op =
2590  find_lrm_op(rsc->id, CRMD_ACTION_STOP, migrate_target, NULL, data_set);
2591  xmlNode *migrate_op =
2592  find_lrm_op(rsc->id, CRMD_ACTION_MIGRATED, migrate_target, migrate_source,
2593  data_set);
2594 
2595  if (stop_op) {
2596  crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id);
2597  }
2598  if (migrate_op) {
2599  crm_element_value_int(migrate_op, XML_LRM_ATTR_CALLID, &migrate_id);
2600  }
2601 
2602  /* Get our state right */
2603  rsc->role = RSC_ROLE_STARTED; /* can be master? */
2604 
2605  if (stop_op == NULL || stop_id < migrate_id) {
2606  node_t *target = pe_find_node(data_set->nodes, migrate_target);
2607 
2608  pe_rsc_trace(rsc, "Stop: %p %d, Migrated: %p %d", stop_op, stop_id, migrate_op,
2609  migrate_id);
2610  if (target && target->details->online) {
2611  native_add_running(rsc, target, data_set);
2612  }
2613 
2614  } else if (migrate_op == NULL) {
2615  /* Make sure it gets cleaned up, the stop may pre-date the migrate_from */
2616  rsc->dangling_migrations = g_list_prepend(rsc->dangling_migrations, node);
2617  }
2618  }
2619 }
2620 
2621 static void
2622 record_failed_op(xmlNode *op, node_t* node, pe_working_set_t * data_set)
2623 {
2624  xmlNode *xIter = NULL;
2625  const char *op_key = crm_element_value(op, XML_LRM_ATTR_TASK_KEY);
2626 
2627  if (node->details->online == FALSE) {
2628  return;
2629  }
2630 
2631  for (xIter = data_set->failed->children; xIter; xIter = xIter->next) {
2632  const char *key = crm_element_value(xIter, XML_LRM_ATTR_TASK_KEY);
2633  const char *uname = crm_element_value(xIter, XML_ATTR_UNAME);
2634 
2635  if(safe_str_eq(op_key, key) && safe_str_eq(uname, node->details->uname)) {
2636  crm_trace("Skipping duplicate entry %s on %s", op_key, node->details->uname);
2637  return;
2638  }
2639  }
2640 
2641  crm_trace("Adding entry %s on %s", op_key, node->details->uname);
2642  crm_xml_add(op, XML_ATTR_UNAME, node->details->uname);
2643  add_node_copy(data_set->failed, op);
2644 }
2645 
2646 static const char *get_op_key(xmlNode *xml_op)
2647 {
2648  const char *key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
2649  if(key == NULL) {
2650  key = ID(xml_op);
2651  }
2652  return key;
2653 }
2654 
2655 static void
2656 unpack_rsc_op_failure(resource_t * rsc, node_t * node, int rc, xmlNode * xml_op, xmlNode ** last_failure,
2657  enum action_fail_response * on_fail, pe_working_set_t * data_set)
2658 {
2659  int interval = 0;
2660  bool is_probe = FALSE;
2661  action_t *action = NULL;
2662 
2663  const char *key = get_op_key(xml_op);
2664  const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
2665  const char *op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
2666 
2667  CRM_ASSERT(rsc);
2668 
2669  *last_failure = xml_op;
2670 
2671  crm_element_value_int(xml_op, XML_LRM_ATTR_INTERVAL, &interval);
2672  if(interval == 0 && safe_str_eq(task, CRMD_ACTION_STATUS)) {
2673  is_probe = TRUE;
2674  pe_rsc_trace(rsc, "is a probe: %s", key);
2675  }
2676 
2677  if (rc != PCMK_OCF_NOT_INSTALLED || is_set(data_set->flags, pe_flag_symmetric_cluster)) {
2678  crm_warn("Processing failed op %s for %s on %s: %s (%d)",
2679  task, rsc->id, node->details->uname, services_ocf_exitcode_str(rc),
2680  rc);
2681 
2682  record_failed_op(xml_op, node, data_set);
2683 
2684  } else {
2685  crm_trace("Processing failed op %s for %s on %s: %s (%d)",
2686  task, rsc->id, node->details->uname, services_ocf_exitcode_str(rc),
2687  rc);
2688  }
2689 
2690  action = custom_action(rsc, strdup(key), task, NULL, TRUE, FALSE, data_set);
2691  if ((action->on_fail <= action_fail_fence && *on_fail < action->on_fail) ||
2692  (action->on_fail == action_fail_reset_remote && *on_fail <= action_fail_recover) ||
2693  (action->on_fail == action_fail_restart_container && *on_fail <= action_fail_recover) ||
2694  (*on_fail == action_fail_restart_container && action->on_fail >= action_fail_migrate)) {
2695  pe_rsc_trace(rsc, "on-fail %s -> %s for %s (%s)", fail2text(*on_fail),
2696  fail2text(action->on_fail), action->uuid, key);
2697  *on_fail = action->on_fail;
2698  }
2699 
2700  if (safe_str_eq(task, CRMD_ACTION_STOP)) {
2701  resource_location(rsc, node, -INFINITY, "__stop_fail__", data_set);
2702 
2703  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE) || safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
2704  unpack_rsc_migration_failure(rsc, node, xml_op, data_set);
2705 
2706  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) {
2707  rsc->role = RSC_ROLE_MASTER;
2708 
2709  } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) {
2710  /*
2711  * staying in role=master ends up putting the PE/TE into a loop
2712  * setting role=slave is not dangerous because no master will be
2713  * promoted until the failed resource has been fully stopped
2714  */
2715  if (action->on_fail == action_fail_block) {
2716  rsc->role = RSC_ROLE_MASTER;
2717  rsc->next_role = RSC_ROLE_STOPPED;
2718 
2719  } else if(rc == PCMK_OCF_NOT_RUNNING) {
2720  rsc->role = RSC_ROLE_STOPPED;
2721 
2722  } else {
2723  crm_warn("Forcing %s to stop after a failed demote action", rsc->id);
2724  rsc->role = RSC_ROLE_SLAVE;
2725  rsc->next_role = RSC_ROLE_STOPPED;
2726  }
2727 
2728  } else if (compare_version("2.0", op_version) > 0 && safe_str_eq(task, CRMD_ACTION_START)) {
2729  crm_warn("Compatibility handling for failed op %s on %s", key, node->details->uname);
2730  resource_location(rsc, node, -INFINITY, "__legacy_start__", data_set);
2731  }
2732 
2733  if(is_probe && rc == PCMK_OCF_NOT_INSTALLED) {
2734  /* leave stopped */
2735  pe_rsc_trace(rsc, "Leaving %s stopped", rsc->id);
2736  rsc->role = RSC_ROLE_STOPPED;
2737 
2738  } else if (rsc->role < RSC_ROLE_STARTED) {
2739  pe_rsc_trace(rsc, "Setting %s active", rsc->id);
2740  set_active(rsc);
2741  }
2742 
2743  pe_rsc_trace(rsc, "Resource %s: role=%s, unclean=%s, on_fail=%s, fail_role=%s",
2744  rsc->id, role2text(rsc->role),
2745  node->details->unclean ? "true" : "false",
2746  fail2text(action->on_fail), role2text(action->fail_role));
2747 
2748  if (action->fail_role != RSC_ROLE_STARTED && rsc->next_role < action->fail_role) {
2749  rsc->next_role = action->fail_role;
2750  }
2751 
2752  if (action->fail_role == RSC_ROLE_STOPPED) {
2753  int score = -INFINITY;
2754 
2755  resource_t *fail_rsc = rsc;
2756 
2757  if (fail_rsc->parent) {
2758  resource_t *parent = uber_parent(fail_rsc);
2759 
2760  if (pe_rsc_is_clone(parent)
2761  && is_not_set(parent->flags, pe_rsc_unique)) {
2762  /* for clone and master resources, if a child fails on an operation
2763  * with on-fail = stop, all the resources fail. Do this by preventing
2764  * the parent from coming up again. */
2765  fail_rsc = parent;
2766  }
2767  }
2768  crm_warn("Making sure %s doesn't come up again", fail_rsc->id);
2769  /* make sure it doesn't come up again */
2770  g_hash_table_destroy(fail_rsc->allowed_nodes);
2771  fail_rsc->allowed_nodes = node_hash_from_list(data_set->nodes);
2772  g_hash_table_foreach(fail_rsc->allowed_nodes, set_node_score, &score);
2773  }
2774 
2775  pe_free_action(action);
2776 }
2777 
2778 static int
2779 determine_op_status(
2780  resource_t *rsc, int rc, int target_rc, node_t * node, xmlNode * xml_op, enum action_fail_response * on_fail, pe_working_set_t * data_set)
2781 {
2782  int interval = 0;
2783  int result = PCMK_LRM_OP_DONE;
2784 
2785  const char *key = get_op_key(xml_op);
2786  const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
2787 
2788  bool is_probe = FALSE;
2789 
2790  CRM_ASSERT(rsc);
2791  crm_element_value_int(xml_op, XML_LRM_ATTR_INTERVAL, &interval);
2792  if (interval == 0 && safe_str_eq(task, CRMD_ACTION_STATUS)) {
2793  is_probe = TRUE;
2794  }
2795 
2796  if (target_rc >= 0 && target_rc != rc) {
2797  result = PCMK_LRM_OP_ERROR;
2798  pe_rsc_debug(rsc, "%s on %s returned '%s' (%d) instead of the expected value: '%s' (%d)",
2799  key, node->details->uname,
2800  services_ocf_exitcode_str(rc), rc,
2801  services_ocf_exitcode_str(target_rc), target_rc);
2802  }
2803 
2804  /* we could clean this up significantly except for old LRMs and CRMs that
2805  * didn't include target_rc and liked to remap status
2806  */
2807  switch (rc) {
2808  case PCMK_OCF_OK:
2809  if (is_probe && target_rc == 7) {
2810  result = PCMK_LRM_OP_DONE;
2812  pe_rsc_info(rsc, "Operation %s found resource %s active on %s",
2813  task, rsc->id, node->details->uname);
2814 
2815  /* legacy code for pre-0.6.5 operations */
2816  } else if (target_rc < 0 && interval > 0 && rsc->role == RSC_ROLE_MASTER) {
2817  /* catch status ops that return 0 instead of 8 while they
2818  * are supposed to be in master mode
2819  */
2820  result = PCMK_LRM_OP_ERROR;
2821  }
2822  break;
2823 
2824  case PCMK_OCF_NOT_RUNNING:
2825  if (is_probe || target_rc == rc || is_not_set(rsc->flags, pe_rsc_managed)) {
2826  result = PCMK_LRM_OP_DONE;
2827  rsc->role = RSC_ROLE_STOPPED;
2828 
2829  /* clear any previous failure actions */
2830  *on_fail = action_fail_ignore;
2831  rsc->next_role = RSC_ROLE_UNKNOWN;
2832 
2833  } else if (safe_str_neq(task, CRMD_ACTION_STOP)) {
2834  result = PCMK_LRM_OP_ERROR;
2835  }
2836  break;
2837 
2839  if (is_probe) {
2840  result = PCMK_LRM_OP_DONE;
2841  pe_rsc_info(rsc, "Operation %s found resource %s active in master mode on %s",
2842  task, rsc->id, node->details->uname);
2843 
2844  } else if (target_rc == rc) {
2845  /* nothing to do */
2846 
2847  } else if (target_rc >= 0) {
2848  result = PCMK_LRM_OP_ERROR;
2849 
2850  /* legacy code for pre-0.6.5 operations */
2851  } else if (safe_str_neq(task, CRMD_ACTION_STATUS)
2852  || rsc->role != RSC_ROLE_MASTER) {
2853  result = PCMK_LRM_OP_ERROR;
2854  if (rsc->role != RSC_ROLE_MASTER) {
2855  crm_err("%s reported %s in master mode on %s",
2856  key, rsc->id, node->details->uname);
2857  }
2858  }
2859  rsc->role = RSC_ROLE_MASTER;
2860  break;
2861 
2864  rsc->role = RSC_ROLE_MASTER;
2865  result = PCMK_LRM_OP_ERROR;
2866  break;
2867 
2869  result = PCMK_LRM_OP_ERROR_FATAL;
2870  break;
2871 
2876  if (rc == PCMK_OCF_UNIMPLEMENT_FEATURE && interval > 0) {
2877  result = PCMK_LRM_OP_NOTSUPPORTED;
2878  break;
2879 
2880  } else if (pe_can_fence(data_set, node) == FALSE
2881  && safe_str_eq(task, CRMD_ACTION_STOP)) {
2882  /* If a stop fails and we can't fence, there's nothing else we can do */
2883  pe_proc_err("No further recovery can be attempted for %s: %s action failed with '%s' (%d)",
2884  rsc->id, task, services_ocf_exitcode_str(rc), rc);
2886  set_bit(rsc->flags, pe_rsc_block);
2887  }
2888  result = PCMK_LRM_OP_ERROR_HARD;
2889  break;
2890 
2891  default:
2892  if (result == PCMK_LRM_OP_DONE) {
2893  crm_info("Treating %s (rc=%d) on %s as an ERROR",
2894  key, rc, node->details->uname);
2895  result = PCMK_LRM_OP_ERROR;
2896  }
2897  }
2898 
2899  return result;
2900 }
2901 
2902 static bool check_operation_expiry(resource_t *rsc, node_t *node, int rc, xmlNode *xml_op, pe_working_set_t * data_set)
2903 {
2904  bool expired = FALSE;
2905  time_t last_failure = 0;
2906  int interval = 0;
2907  int failure_timeout = rsc->failure_timeout;
2908  const char *key = get_op_key(xml_op);
2909  const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
2910  const char *clear_reason = NULL;
2911 
2912  /* clearing recurring monitor operation failures automatically
2913  * needs to be carefully considered */
2914  if (safe_str_eq(crm_element_value(xml_op, XML_LRM_ATTR_TASK), "monitor") &&
2916 
2917  /* TODO, in the future we should consider not clearing recurring monitor
2918  * op failures unless the last action for a resource was a "stop" action.
2919  * otherwise it is possible that clearing the monitor failure will result
2920  * in the resource being in an undeterministic state.
2921  *
2922  * For now we handle this potential undeterministic condition for remote
2923  * node connection resources by not clearing a recurring monitor op failure
2924  * until after the node has been fenced. */
2925 
2926  if (is_set(data_set->flags, pe_flag_stonith_enabled) &&
2927  (rsc->remote_reconnect_interval)) {
2928 
2929  node_t *remote_node = pe_find_node(data_set->nodes, rsc->id);
2930  if (remote_node && remote_node->details->remote_was_fenced == 0) {
2931  if (strstr(ID(xml_op), "last_failure")) {
2932  crm_info("Waiting to clear monitor failure for remote node %s until fencing has occurred", rsc->id);
2933  }
2934  /* disabling failure timeout for this operation because we believe
2935  * fencing of the remote node should occur first. */
2936  failure_timeout = 0;
2937  }
2938  }
2939  }
2940 
2941  if (failure_timeout > 0) {
2942  int last_run = 0;
2943 
2944  if (crm_element_value_int(xml_op, XML_RSC_OP_LAST_CHANGE, &last_run) == 0) {
2945  time_t now = get_effective_time(data_set);
2946 
2947  if (now > (last_run + failure_timeout)) {
2948  expired = TRUE;
2949  }
2950  }
2951  }
2952 
2953  if (expired) {
2954  if (failure_timeout > 0) {
2955  int fc = get_failcount_full(node, rsc, &last_failure, FALSE, xml_op, data_set);
2956  if(fc) {
2957  if (get_failcount_full(node, rsc, &last_failure, TRUE, xml_op, data_set) == 0) {
2958  clear_reason = "it expired";
2959 
2960  } else {
2961  expired = FALSE;
2962  }
2963  } else if (rsc->remote_reconnect_interval && strstr(ID(xml_op), "last_failure")) {
2964  /* always clear last failure when reconnect interval is set */
2965  clear_reason = "reconnect interval is set";
2966  }
2967  }
2968 
2969  } else if (strstr(ID(xml_op), "last_failure") &&
2970  ((strcmp(task, "start") == 0) || (strcmp(task, "monitor") == 0))) {
2971 
2972  op_digest_cache_t *digest_data = NULL;
2973 
2974  digest_data = rsc_action_digest_cmp(rsc, xml_op, node, data_set);
2975 
2976  if (digest_data->rc == RSC_DIGEST_UNKNOWN) {
2977  crm_trace("rsc op %s/%s on node %s does not have a op digest to compare against", rsc->id,
2978  key, node->details->id);
2979  } else if (digest_data->rc != RSC_DIGEST_MATCH) {
2980  clear_reason = "resource parameters have changed";
2981  }
2982  }
2983 
2984  if (clear_reason != NULL) {
2985  char *key = generate_op_key(rsc->id, CRM_OP_CLEAR_FAILCOUNT, 0);
2986  action_t *clear_op = custom_action(rsc, key, CRM_OP_CLEAR_FAILCOUNT,
2987  node, FALSE, TRUE, data_set);
2988 
2990 
2991  crm_notice("Clearing failure of %s on %s because %s " CRM_XS " %s",
2992  rsc->id, node->details->uname, clear_reason, clear_op->uuid);
2993  }
2994 
2995  crm_element_value_int(xml_op, XML_LRM_ATTR_INTERVAL, &interval);
2996  if(expired && interval == 0 && safe_str_eq(task, CRMD_ACTION_STATUS)) {
2997  switch(rc) {
2998  case PCMK_OCF_OK:
2999  case PCMK_OCF_NOT_RUNNING:
3001  case PCMK_OCF_DEGRADED:
3003  /* Don't expire probes that return these values */
3004  expired = FALSE;
3005  break;
3006  }
3007  }
3008 
3009  return expired;
3010 }
3011 
3012 int get_target_rc(xmlNode *xml_op)
3013 {
3014  int dummy = 0;
3015  int target_rc = 0;
3016  char *dummy_string = NULL;
3017  const char *key = crm_element_value(xml_op, XML_ATTR_TRANSITION_KEY);
3018  if (key == NULL) {
3019  return -1;
3020  }
3021 
3022  decode_transition_key(key, &dummy_string, &dummy, &dummy, &target_rc);
3023  free(dummy_string);
3024 
3025  return target_rc;
3026 }
3027 
3028 static enum action_fail_response
3029 get_action_on_fail(resource_t *rsc, const char *key, const char *task, pe_working_set_t * data_set)
3030 {
3031  int result = action_fail_recover;
3032  action_t *action = custom_action(rsc, strdup(key), task, NULL, TRUE, FALSE, data_set);
3033 
3034  result = action->on_fail;
3035  pe_free_action(action);
3036 
3037  return result;
3038 }
3039 
3040 static void
3041 update_resource_state(resource_t * rsc, node_t * node, xmlNode * xml_op, const char * task, int rc,
3042  xmlNode * last_failure, enum action_fail_response * on_fail, pe_working_set_t * data_set)
3043 {
3044  gboolean clear_past_failure = FALSE;
3045 
3046  CRM_ASSERT(rsc);
3047  CRM_ASSERT(xml_op);
3048 
3049  if (rc == PCMK_OCF_NOT_RUNNING) {
3050  clear_past_failure = TRUE;
3051 
3052  } else if (rc == PCMK_OCF_NOT_INSTALLED) {
3053  rsc->role = RSC_ROLE_STOPPED;
3054 
3055  } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
3056  if (last_failure) {
3057  const char *op_key = get_op_key(xml_op);
3058  const char *last_failure_key = get_op_key(last_failure);
3059 
3060  if (safe_str_eq(op_key, last_failure_key)) {
3061  clear_past_failure = TRUE;
3062  }
3063  }
3064 
3065  if (rsc->role < RSC_ROLE_STARTED) {
3066  set_active(rsc);
3067  }
3068 
3069  } else if (safe_str_eq(task, CRMD_ACTION_START)) {
3070  rsc->role = RSC_ROLE_STARTED;
3071  clear_past_failure = TRUE;
3072 
3073  } else if (safe_str_eq(task, CRMD_ACTION_STOP)) {
3074  rsc->role = RSC_ROLE_STOPPED;
3075  clear_past_failure = TRUE;
3076 
3077  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) {
3078  rsc->role = RSC_ROLE_MASTER;
3079  clear_past_failure = TRUE;
3080 
3081  } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) {
3082  /* Demote from Master does not clear an error */
3083  rsc->role = RSC_ROLE_SLAVE;
3084 
3085  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
3086  rsc->role = RSC_ROLE_STARTED;
3087  clear_past_failure = TRUE;
3088 
3089  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) {
3090  unpack_rsc_migration(rsc, node, xml_op, data_set);
3091 
3092  } else if (rsc->role < RSC_ROLE_STARTED) {
3093  pe_rsc_trace(rsc, "%s active on %s", rsc->id, node->details->uname);
3094  set_active(rsc);
3095  }
3096 
3097  /* clear any previous failure actions */
3098  if (clear_past_failure) {
3099  switch (*on_fail) {
3100  case action_fail_stop:
3101  case action_fail_fence:
3102  case action_fail_migrate:
3103  case action_fail_standby:
3104  pe_rsc_trace(rsc, "%s.%s is not cleared by a completed stop",
3105  rsc->id, fail2text(*on_fail));
3106  break;
3107 
3108  case action_fail_block:
3109  case action_fail_ignore:
3110  case action_fail_recover:
3112  *on_fail = action_fail_ignore;
3113  rsc->next_role = RSC_ROLE_UNKNOWN;
3114  break;
3116  if (rsc->remote_reconnect_interval == 0) {
3117  /* when reconnect delay is not in use, the connection is allowed
3118  * to start again after the remote node is fenced and completely
3119  * stopped. Otherwise, with reconnect delay we wait for the failure
3120  * to be cleared entirely before reconnected can be attempted. */
3121  *on_fail = action_fail_ignore;
3122  rsc->next_role = RSC_ROLE_UNKNOWN;
3123  }
3124  break;
3125  }
3126  }
3127 }
3128 
3129 
3130 gboolean
3131 unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, xmlNode ** last_failure,
3132  enum action_fail_response * on_fail, pe_working_set_t * data_set)
3133 {
3134  int task_id = 0;
3135 
3136  const char *key = NULL;
3137  const char *task = NULL;
3138  const char *task_key = NULL;
3139 
3140  int rc = 0;
3141  int status = PCMK_LRM_OP_PENDING-1;
3142  int target_rc = get_target_rc(xml_op);
3143  int interval = 0;
3144 
3145  gboolean expired = FALSE;
3146  resource_t *parent = rsc;
3147  enum action_fail_response failure_strategy = action_fail_recover;
3148 
3149  CRM_CHECK(rsc != NULL, return FALSE);
3150  CRM_CHECK(node != NULL, return FALSE);
3151  CRM_CHECK(xml_op != NULL, return FALSE);
3152 
3153  task_key = get_op_key(xml_op);
3154 
3155  task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
3157 
3158  crm_element_value_int(xml_op, XML_LRM_ATTR_RC, &rc);
3159  crm_element_value_int(xml_op, XML_LRM_ATTR_CALLID, &task_id);
3160  crm_element_value_int(xml_op, XML_LRM_ATTR_OPSTATUS, &status);
3161  crm_element_value_int(xml_op, XML_LRM_ATTR_INTERVAL, &interval);
3162 
3163  CRM_CHECK(task != NULL, return FALSE);
3164  CRM_CHECK(status <= PCMK_LRM_OP_NOT_INSTALLED, return FALSE);
3165  CRM_CHECK(status >= PCMK_LRM_OP_PENDING, return FALSE);
3166 
3167  if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) {
3168  /* safe to ignore these */
3169  return TRUE;
3170  }
3171 
3172  if (is_not_set(rsc->flags, pe_rsc_unique)) {
3173  parent = uber_parent(rsc);
3174  }
3175 
3176  pe_rsc_trace(rsc, "Unpacking task %s/%s (call_id=%d, status=%d, rc=%d) on %s (role=%s)",
3177  task_key, task, task_id, status, rc, node->details->uname, role2text(rsc->role));
3178 
3179  if (node->details->unclean) {
3180  pe_rsc_trace(rsc, "Node %s (where %s is running) is unclean."
3181  " Further action depends on the value of the stop's on-fail attribute",
3182  node->details->uname, rsc->id);
3183  }
3184 
3185  if (status == PCMK_LRM_OP_ERROR) {
3186  /* Older versions set this if rc != 0 but it's up to us to decide */
3187  status = PCMK_LRM_OP_DONE;
3188  }
3189 
3190  if(status != PCMK_LRM_OP_NOT_INSTALLED) {
3191  expired = check_operation_expiry(rsc, node, rc, xml_op, data_set);
3192  }
3193 
3194  /* Degraded results are informational only, re-map them to their error-free equivalents */
3195  if (rc == PCMK_OCF_DEGRADED && safe_str_eq(task, CRMD_ACTION_STATUS)) {
3196  rc = PCMK_OCF_OK;
3197 
3198  /* Add them to the failed list to highlight them for the user */
3199  if ((node->details->shutdown == FALSE) || (node->details->online == TRUE)) {
3200  crm_trace("Remapping %d to %d", PCMK_OCF_DEGRADED, PCMK_OCF_OK);
3201  record_failed_op(xml_op, node, data_set);
3202  }
3203 
3204  } else if (rc == PCMK_OCF_DEGRADED_MASTER && safe_str_eq(task, CRMD_ACTION_STATUS)) {
3206 
3207  /* Add them to the failed list to highlight them for the user */
3208  if ((node->details->shutdown == FALSE) || (node->details->online == TRUE)) {
3210  record_failed_op(xml_op, node, data_set);
3211  }
3212  }
3213 
3214  if (expired && target_rc != rc) {
3215  const char *magic = crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC);
3216 
3217  pe_rsc_debug(rsc, "Expired operation '%s' on %s returned '%s' (%d) instead of the expected value: '%s' (%d)",
3218  key, node->details->uname,
3219  services_ocf_exitcode_str(rc), rc,
3220  services_ocf_exitcode_str(target_rc), target_rc);
3221 
3222  if(interval == 0) {
3223  crm_notice("Ignoring expired calculated failure %s (rc=%d, magic=%s) on %s",
3224  task_key, rc, magic, node->details->uname);
3225  goto done;
3226 
3227  } else if(node->details->online && node->details->unclean == FALSE) {
3228  crm_notice("Re-initiated expired calculated failure %s (rc=%d, magic=%s) on %s",
3229  task_key, rc, magic, node->details->uname);
3230  /* This is SO horrible, but we don't have access to CancelXmlOp() yet */
3231  crm_xml_add(xml_op, XML_LRM_ATTR_RESTART_DIGEST, "calculated-failure-timeout");
3232  goto done;
3233  }
3234  }
3235 
3236  if(status == PCMK_LRM_OP_DONE || status == PCMK_LRM_OP_ERROR) {
3237  status = determine_op_status(rsc, rc, target_rc, node, xml_op, on_fail, data_set);
3238  }
3239 
3240  pe_rsc_trace(rsc, "Handling status: %d", status);
3241  switch (status) {
3242  case PCMK_LRM_OP_CANCELLED:
3243  /* do nothing?? */
3244  pe_err("Don't know what to do for cancelled ops yet");
3245  break;
3246 
3247  case PCMK_LRM_OP_PENDING:
3248  if (safe_str_eq(task, CRMD_ACTION_START)) {
3250  set_active(rsc);
3251 
3252  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) {
3253  rsc->role = RSC_ROLE_MASTER;
3254 
3255  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE) && node->details->unclean) {
3256  /* If a pending migrate_to action is out on a unclean node,
3257  * we have to force the stop action on the target. */
3258  const char *migrate_target = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET);
3259  node_t *target = pe_find_node(data_set->nodes, migrate_target);
3260  if (target) {
3261  stop_action(rsc, target, FALSE);
3262  }
3263  }
3264 
3265  if (rsc->pending_task == NULL) {
3266  if (safe_str_eq(task, CRMD_ACTION_STATUS) && interval == 0) {
3267  /* Pending probes are not printed, even if pending
3268  * operations are requested. If someone ever requests that
3269  * behavior, uncomment this and the corresponding part of
3270  * native.c:native_pending_task().
3271  */
3272  /*rsc->pending_task = strdup("probe");*/
3273 
3274  } else {
3275  rsc->pending_task = strdup(task);
3276  }
3277  }
3278  break;
3279 
3280  case PCMK_LRM_OP_DONE:
3281  pe_rsc_trace(rsc, "%s/%s completed on %s", rsc->id, task, node->details->uname);
3282  update_resource_state(rsc, node, xml_op, task, rc, *last_failure, on_fail, data_set);
3283  break;
3284 
3286  failure_strategy = get_action_on_fail(rsc, task_key, task, data_set);
3287  if (failure_strategy == action_fail_ignore) {
3288  crm_warn("Cannot ignore failed %s (status=%d, rc=%d) on %s: "
3289  "Resource agent doesn't exist",
3290  task_key, status, rc, node->details->uname);
3291  /* Also for printing it as "FAILED" by marking it as pe_rsc_failed later */
3292  *on_fail = action_fail_migrate;
3293  }
3294  resource_location(parent, node, -INFINITY, "hard-error", data_set);
3295  unpack_rsc_op_failure(rsc, node, rc, xml_op, last_failure, on_fail, data_set);
3296  break;
3297 
3298  case PCMK_LRM_OP_ERROR:
3301  case PCMK_LRM_OP_TIMEOUT:
3303 
3304  failure_strategy = get_action_on_fail(rsc, task_key, task, data_set);
3305  if ((failure_strategy == action_fail_ignore)
3306  || (failure_strategy == action_fail_restart_container
3307  && safe_str_eq(task, CRMD_ACTION_STOP))) {
3308 
3309  crm_warn("Pretending the failure of %s (rc=%d) on %s succeeded",
3310  task_key, rc, node->details->uname);
3311 
3312  update_resource_state(rsc, node, xml_op, task, target_rc, *last_failure, on_fail, data_set);
3313  crm_xml_add(xml_op, XML_ATTR_UNAME, node->details->uname);
3315 
3316  record_failed_op(xml_op, node, data_set);
3317 
3318  if (failure_strategy == action_fail_restart_container && *on_fail <= action_fail_recover) {
3319  *on_fail = failure_strategy;
3320  }
3321 
3322  } else {
3323  unpack_rsc_op_failure(rsc, node, rc, xml_op, last_failure, on_fail, data_set);
3324 
3325  if(status == PCMK_LRM_OP_ERROR_HARD) {
3326  do_crm_log(rc != PCMK_OCF_NOT_INSTALLED?LOG_ERR:LOG_NOTICE,
3327  "Preventing %s from re-starting on %s: operation %s failed '%s' (%d)",
3328  parent->id, node->details->uname,
3329  task, services_ocf_exitcode_str(rc), rc);
3330 
3331  resource_location(parent, node, -INFINITY, "hard-error", data_set);
3332 
3333  } else if(status == PCMK_LRM_OP_ERROR_FATAL) {
3334  crm_err("Preventing %s from re-starting anywhere: operation %s failed '%s' (%d)",
3335  parent->id, task, services_ocf_exitcode_str(rc), rc);
3336 
3337  resource_location(parent, NULL, -INFINITY, "fatal-error", data_set);
3338  }
3339  }
3340  break;
3341  }
3342 
3343  done:
3344  pe_rsc_trace(rsc, "Resource %s after %s: role=%s, next=%s", rsc->id, task, role2text(rsc->role), role2text(rsc->next_role));
3345  return TRUE;
3346 }
3347 
3348 gboolean
3349 add_node_attrs(xmlNode * xml_obj, node_t * node, gboolean overwrite, pe_working_set_t * data_set)
3350 {
3351  const char *cluster_name = NULL;
3352 
3353  g_hash_table_insert(node->details->attrs,
3354  strdup("#uname"), strdup(node->details->uname));
3355 
3356  g_hash_table_insert(node->details->attrs, strdup("#" XML_ATTR_ID), strdup(node->details->id));
3357  if (safe_str_eq(node->details->id, data_set->dc_uuid)) {
3358  data_set->dc_node = node;
3359  node->details->is_dc = TRUE;
3360  g_hash_table_insert(node->details->attrs,
3361  strdup("#" XML_ATTR_DC), strdup(XML_BOOLEAN_TRUE));
3362  } else {
3363  g_hash_table_insert(node->details->attrs,
3364  strdup("#" XML_ATTR_DC), strdup(XML_BOOLEAN_FALSE));
3365  }
3366 
3367  cluster_name = g_hash_table_lookup(data_set->config_hash, "cluster-name");
3368  if (cluster_name) {
3369  g_hash_table_insert(node->details->attrs, strdup("#cluster-name"), strdup(cluster_name));
3370  }
3371 
3372  unpack_instance_attributes(data_set->input, xml_obj, XML_TAG_ATTR_SETS, NULL,
3373  node->details->attrs, NULL, overwrite, data_set->now);
3374 
3375  if (g_hash_table_lookup(node->details->attrs, "#site-name") == NULL) {
3376  const char *site_name = g_hash_table_lookup(node->details->attrs, "site-name");
3377 
3378  if (site_name) {
3379  /* Prefix '#' to the key */
3380  g_hash_table_insert(node->details->attrs, strdup("#site-name"), strdup(site_name));
3381 
3382  } else if (cluster_name) {
3383  /* Default to cluster-name if unset */
3384  g_hash_table_insert(node->details->attrs, strdup("#site-name"), strdup(cluster_name));
3385  }
3386  }
3387  return TRUE;
3388 }
3389 
3390 static GListPtr
3391 extract_operations(const char *node, const char *rsc, xmlNode * rsc_entry, gboolean active_filter)
3392 {
3393  int counter = -1;
3394  int stop_index = -1;
3395  int start_index = -1;
3396 
3397  xmlNode *rsc_op = NULL;
3398 
3399  GListPtr gIter = NULL;
3400  GListPtr op_list = NULL;
3401  GListPtr sorted_op_list = NULL;
3402 
3403  /* extract operations */
3404  op_list = NULL;
3405  sorted_op_list = NULL;
3406 
3407  for (rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next_element(rsc_op)) {
3408  if (crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) {
3409  crm_xml_add(rsc_op, "resource", rsc);
3410  crm_xml_add(rsc_op, XML_ATTR_UNAME, node);
3411  op_list = g_list_prepend(op_list, rsc_op);
3412  }
3413  }
3414 
3415  if (op_list == NULL) {
3416  /* if there are no operations, there is nothing to do */
3417  return NULL;
3418  }
3419 
3420  sorted_op_list = g_list_sort(op_list, sort_op_by_callid);
3421 
3422  /* create active recurring operations as optional */
3423  if (active_filter == FALSE) {
3424  return sorted_op_list;
3425  }
3426 
3427  op_list = NULL;
3428 
3429  calculate_active_ops(sorted_op_list, &start_index, &stop_index);
3430 
3431  for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
3432  xmlNode *rsc_op = (xmlNode *) gIter->data;
3433 
3434  counter++;
3435 
3436  if (start_index < stop_index) {
3437  crm_trace("Skipping %s: not active", ID(rsc_entry));
3438  break;
3439 
3440  } else if (counter < start_index) {
3441  crm_trace("Skipping %s: old", ID(rsc_op));
3442  continue;
3443  }
3444  op_list = g_list_append(op_list, rsc_op);
3445  }
3446 
3447  g_list_free(sorted_op_list);
3448  return op_list;
3449 }
3450 
3451 GListPtr
3452 find_operations(const char *rsc, const char *node, gboolean active_filter,
3453  pe_working_set_t * data_set)
3454 {
3455  GListPtr output = NULL;
3456  GListPtr intermediate = NULL;
3457 
3458  xmlNode *tmp = NULL;
3459  xmlNode *status = find_xml_node(data_set->input, XML_CIB_TAG_STATUS, TRUE);
3460 
3461  node_t *this_node = NULL;
3462 
3463  xmlNode *node_state = NULL;
3464 
3465  for (node_state = __xml_first_child(status); node_state != NULL;
3466  node_state = __xml_next_element(node_state)) {
3467 
3468  if (crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE)) {
3469  const char *uname = crm_element_value(node_state, XML_ATTR_UNAME);
3470 
3471  if (node != NULL && safe_str_neq(uname, node)) {
3472  continue;
3473  }
3474 
3475  this_node = pe_find_node(data_set->nodes, uname);
3476  if(this_node == NULL) {
3477  CRM_LOG_ASSERT(this_node != NULL);
3478  continue;
3479 
3480  } else if (is_remote_node(this_node)) {
3481  determine_remote_online_status(data_set, this_node);
3482 
3483  } else {
3484  determine_online_status(node_state, this_node, data_set);
3485  }
3486 
3487  if (this_node->details->online || is_set(data_set->flags, pe_flag_stonith_enabled)) {
3488  /* offline nodes run no resources...
3489  * unless stonith is enabled in which case we need to
3490  * make sure rsc start events happen after the stonith
3491  */
3492  xmlNode *lrm_rsc = NULL;
3493 
3494  tmp = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
3495  tmp = find_xml_node(tmp, XML_LRM_TAG_RESOURCES, FALSE);
3496 
3497  for (lrm_rsc = __xml_first_child(tmp); lrm_rsc != NULL;
3498  lrm_rsc = __xml_next_element(lrm_rsc)) {
3499  if (crm_str_eq((const char *)lrm_rsc->name, XML_LRM_TAG_RESOURCE, TRUE)) {
3500 
3501  const char *rsc_id = crm_element_value(lrm_rsc, XML_ATTR_ID);
3502 
3503  if (rsc != NULL && safe_str_neq(rsc_id, rsc)) {
3504  continue;
3505  }
3506 
3507  intermediate = extract_operations(uname, rsc_id, lrm_rsc, active_filter);
3508  output = g_list_concat(output, intermediate);
3509  }
3510  }
3511  }
3512  }
3513  }
3514 
3515  return output;
3516 }
GHashTable * tags
Definition: status.h:125
Services API.
gboolean unpack_config(xmlNode *config, pe_working_set_t *data_set)
Definition: unpack.c:141
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:164
GListPtr nodes
Definition: status.h:102
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:292
gboolean unpack_rsc_op(resource_t *rsc, node_t *node, xmlNode *xml_op, xmlNode **last_failure, enum action_fail_response *failed, pe_working_set_t *data_set)
Definition: unpack.c:3131
void verify_pe_options(GHashTable *options)
Definition: common.c:181
#define STATUS_PATH_MAX
Definition: unpack.c:2421
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:2234
const char * uname
Definition: status.h:134
A dumping ground.
#define crm_notice(fmt, args...)
Definition: logging.h:250
#define CRMD_ACTION_MIGRATED
Definition: crm.h:160
xmlNode * failed
Definition: status.h:110
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:24
#define pe_flag_have_stonith_resource
Definition: status.h:64
node_t * pe_create_node(const char *id, const char *uname, const char *type, const char *score, pe_working_set_t *data_set)
Definition: unpack.c:328
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:150
#define INFINITY
Definition: crm.h:83
gint sort_rsc_priority(gconstpointer a, gconstpointer b)
Definition: utils.c:344
gboolean determine_online_status(xmlNode *node_state, node_t *this_node, pe_working_set_t *data_set)
Definition: unpack.c:1511
gboolean get_target_role(resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:1483
#define XML_NODE_IS_FENCED
Definition: msg_xml.h:261
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:372
node_t * node_copy(const node_t *this_node)
Definition: utils.c:79
#define stop_action(rsc, node, optional)
Definition: internal.h:185
#define pe_flag_enable_unfencing
Definition: status.h:65
#define pe_rsc_orphan_container_filler
Definition: status.h:182
int default_resource_stickiness
Definition: status.h:95
const char * id
Definition: status.h:133
char * clone_strip(const char *last_rsc_id)
Definition: unpack.c:1583
#define XML_ATTR_QUORUM_PANIC
Definition: msg_xml.h:88
int weight
Definition: status.h:170
#define XML_ATTR_TYPE
Definition: msg_xml.h:104
bool pe_can_fence(pe_working_set_t *data_set, node_t *node)
Definition: utils.c:52
#define XML_TAG_UTILIZATION
Definition: msg_xml.h:185
time_t last_granted
Definition: status.h:372
#define pe_flag_have_remote_nodes
Definition: status.h:77
void(* free)(resource_t *)
Definition: complex.h:51
#define XML_RULE_ATTR_SCORE
Definition: msg_xml.h:308
#define XML_BOOLEAN_FALSE
Definition: msg_xml.h:117
#define crm_config_err(fmt...)
Definition: crm_internal.h:258
int get_target_rc(xmlNode *xml_op)
Definition: unpack.c:3012
enum action_fail_response on_fail
Definition: status.h:332
#define pe_rsc_orphan
Definition: status.h:179
resource_t * rsc_contains_remote_node(pe_working_set_t *data_set, resource_t *rsc)
Definition: remote.c:71
int char2score(const char *score)
Definition: utils.c:233
#define pe_proc_warn(fmt...)
Definition: internal.h:30
#define XML_TAG_TRANSIENT_NODEATTRS
Definition: msg_xml.h:378
#define CRMD_ACTION_NOTIFY
Definition: crm.h:173
#define pe_flag_startup_probes
Definition: status.h:75
long long crm_get_msec(const char *input)
Definition: utils.c:586
GListPtr running_rsc
Definition: status.h:148
GListPtr find_actions(GListPtr input, const char *key, const node_t *on_node)
Definition: utils.c:1216
gboolean common_unpack(xmlNode *xml_obj, resource_t **rsc, resource_t *parent, pe_working_set_t *data_set)
Definition: complex.c:426
enum pe_obj_types variant
Definition: status.h:260
#define XML_CIB_TAG_TAG
Definition: msg_xml.h:405
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:271
#define XML_LRM_TAG_RESOURCE
Definition: msg_xml.h:239
#define pe_flag_stop_rsc_orphans
Definition: status.h:68
gboolean pending
Definition: status.h:140
#define XML_ATTR_TIMEOUT
Definition: msg_xml.h:95
node_t * partial_migration_source
Definition: status.h:300
#define CRMD_ACTION_PROMOTE
Definition: crm.h:168
int crm_parse_int(const char *text, const char *default_text)
Definition: strings.c:125
gboolean fixed
Definition: status.h:171
GListPtr resources
Definition: status.h:103
#define XML_NVPAIR_ATTR_NAME
Definition: msg_xml.h:354
#define XML_NODE_IS_MAINTENANCE
Definition: msg_xml.h:262
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
Definition: utils.c:1353
#define XML_NODE_EXPECTED
Definition: msg_xml.h:257
node_t * pe_find_node(GListPtr node_list, const char *uname)
Definition: status.c:298
#define XML_CIB_TAG_RSC_TEMPLATE
Definition: msg_xml.h:194
AIS_Host host
Definition: internal.h:52
resource_t * create_child_clone(resource_t *rsc, int sub_id, pe_working_set_t *data_set)
Definition: clone.c:84
time_t get_effective_time(pe_working_set_t *data_set)
Definition: utils.c:1468
no_quorum_policy_t no_quorum_policy
Definition: status.h:96
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:150
const char * pe_pref(GHashTable *options, const char *name)
Definition: common.c:187
char * clone_name
Definition: status.h:253
xmlNode * params_restart
Definition: internal.h:267
resource_t * uber_parent(resource_t *rsc)
Definition: complex.c:841
resource_t * remote_rsc
Definition: status.h:151
#define clear_bit(word, bit)
Definition: crm_internal.h:193
void copy_in_properties(xmlNode *target, xmlNode *src)
Definition: xml.c:2286
#define CRMD_JOINSTATE_NACK
Definition: crm.h:153
#define XML_CIB_TAG_LRM
Definition: msg_xml.h:237
GHashTable * tickets
Definition: status.h:99
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:174
node_t * dc_node
Definition: status.h:88
enum rsc_role_e role
Definition: status.h:289
#define pe_rsc_allow_migrate
Definition: status.h:206
GListPtr children
Definition: status.h:296
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:224
#define pe_proc_err(fmt...)
Definition: internal.h:29
action_fail_response
Definition: common.h:29
char * strndup(const char *str, size_t len)
char * dc_uuid
Definition: status.h:87
gboolean is_remote_node
Definition: status.h:274
int stonith_timeout
Definition: status.h:94
gboolean standby
Definition: status.h:138
#define XML_CIB_TAG_PROPSET
Definition: msg_xml.h:176
char * id
Definition: status.h:252
gboolean decode_transition_key(const char *key, char **uuid, int *action, int *transition_id, int *target_rc)
Definition: utils.c:832
gboolean unpack_resources(xmlNode *xml_resources, pe_working_set_t *data_set)
Definition: unpack.c:782
#define CRMD_ACTION_START
Definition: crm.h:162
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:273
#define pe_rsc_block
Definition: status.h:181
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:177
GHashTable * utilization
Definition: status.h:156
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:272
const char * role2text(enum rsc_role_e role)
Definition: common.c:343
char uname[MAX_NAME]
Definition: internal.h:53
gboolean is_remote_node(node_t *node)
Definition: remote.c:62
#define CRMD_ACTION_STOP
Definition: crm.h:165
#define CRM_OP_CLEAR_FAILCOUNT
Definition: crm.h:124
struct node_shared_s * details
Definition: status.h:173
gboolean unpack_status(xmlNode *status, pe_working_set_t *data_set)
Definition: unpack.c:1179
#define CRMD_JOINSTATE_DOWN
Definition: crm.h:150
#define crm_warn(fmt, args...)
Definition: logging.h:249
resource_t * find_container_child(const char *stem, resource_t *rsc, node_t *node)
Definition: container.c:848
#define CRMD_ACTION_DEMOTE
Definition: crm.h:170
#define set_bit(word, bit)
Definition: crm_internal.h:192
#define crm_atoi(text, default_text)
Definition: util.h:73
#define PCMK_RESOURCE_CLASS_OCF
Definition: services.h:56
gboolean unclean
Definition: status.h:141
#define XML_ATTR_OP
Definition: msg_xml.h:109
uint32_t id
Definition: internal.h:48
#define crm_debug(fmt, args...)
Definition: logging.h:253
void native_add_running(resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: native.c:32
#define XML_CIB_ATTR_SHUTDOWN
Definition: msg_xml.h:264
#define XML_RSC_ATTR_CONTAINER
Definition: msg_xml.h:221
Utility functions.
#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
gboolean unpack_nodes(xmlNode *xml_nodes, pe_working_set_t *data_set)
Definition: unpack.c:584
int get_failcount_full(node_t *node, resource_t *rsc, time_t *last_failure, bool effective, xmlNode *xml_op, pe_working_set_t *data_set)
Definition: failcounts.c:244
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:116
#define XML_CIB_TAG_STATE
Definition: msg_xml.h:170
#define pe_rsc_failed
Definition: status.h:198
char * digest_all_calc
Definition: internal.h:268
#define stop_key(rsc)
Definition: internal.h:184
node_t * partial_migration_target
Definition: status.h:299
resource_object_functions_t * fns
Definition: status.h:261
resource_t * container
Definition: status.h:302
GHashTable * allowed_nodes
Definition: status.h:287
GHashTable * digest_cache
Definition: status.h:159
#define set_config_flag(data_set, option, flag)
Definition: unpack.c:34
#define XML_NODE_IS_PEER
Definition: msg_xml.h:259
#define crm_trace(fmt, args...)
Definition: logging.h:254
#define CRMD_JOINSTATE_MEMBER
Definition: crm.h:152
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:129
enum rsc_digest_cmp_val rc
Definition: internal.h:264
gboolean is_baremetal_remote_node(node_t *node)
Definition: remote.c:44
char * digest_secure_calc
Definition: internal.h:269
gboolean unpack_remote_nodes(xmlNode *xml_resources, pe_working_set_t *data_set)
Definition: unpack.c:669
gboolean add_node_attrs(xmlNode *xml_obj, node_t *node, gboolean overwrite, pe_working_set_t *data_set)
Definition: unpack.c:3349
GHashTable * meta
Definition: status.h:342
gboolean is_container_remote_node(node_t *node)
Definition: remote.c:53
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:2404
GListPtr refs
Definition: status.h:379
gboolean unpacked
Definition: status.h:166
const char * stonith_action
Definition: status.h:89
#define crm_log_xml_debug(xml, text)
Definition: logging.h:261
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:244
#define XML_ATTR_DC
Definition: msg_xml.h:110
#define XML_TAG_META_SETS
Definition: msg_xml.h:178
Wrappers for and extensions to libxml2.
#define XML_ATTR_TE_NOWAIT
Definition: msg_xml.h:375
GHashTable * config_hash
Definition: status.h:98
#define XML_ATTR_UNAME
Definition: msg_xml.h:129
gboolean add_tag_ref(GHashTable *tags, const char *tag_name, const char *obj_ref)
Definition: utils.c:1933
#define XML_BOOLEAN_YES
Definition: msg_xml.h:118
#define XML_RSC_ATTR_MANAGED
Definition: msg_xml.h:210
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:2587
gboolean is_dc
Definition: status.h:145
int crm_element_value_int(xmlNode *data, const char *name, int *dest)
Definition: xml.c:3868
char * clone_zero(const char *last_rsc_id)
Definition: unpack.c:1622
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5134
action_t * custom_action(resource_t *rsc, char *key, const char *task, node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Definition: utils.c:371
unsigned long long flags
Definition: status.h:276
#define pe_flag_maintenance_mode
Definition: status.h:61
resource_t * parent
Definition: status.h:258
node_t *(* location)(resource_t *, GListPtr *, gboolean)
Definition: complex.h:50
#define XML_LRM_ATTR_MIGRATE_TARGET
Definition: msg_xml.h:298
#define CIB_OPTIONS_FIRST
Definition: msg_xml.h:53
#define XML_RSC_ATTR_REMOTE_NODE
Definition: msg_xml.h:224
char * uuid
Definition: status.h:327
#define XML_LRM_ATTR_RESTART_DIGEST
Definition: msg_xml.h:288
GListPtr dangling_migrations
Definition: status.h:297
void free_xml(xmlNode *child)
Definition: xml.c:2705
#define pe_flag_stop_everything
Definition: status.h:70
xmlNode * input
Definition: status.h:83
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:213
#define XML_CIB_TAG_NODE
Definition: msg_xml.h:171
GListPtr fillers
Definition: status.h:303
const char * placement_strategy
Definition: status.h:90
gboolean unseen
Definition: status.h:142
int failure_timeout
Definition: status.h:270
xmlNode * params_all
Definition: internal.h:265
uint32_t counter
Definition: internal.h:50
int remote_reconnect_interval
Definition: status.h:309
gboolean remote_maintenance
Definition: status.h:165
#define crm_config_warn(fmt...)
Definition: crm_internal.h:259
GListPtr actions
Definition: status.h:281
#define XML_ATTR_TRANSITION_KEY
Definition: msg_xml.h:373
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Definition: xml.c:2489
#define CRM_XS
Definition: logging.h:42
gboolean maintenance
Definition: status.h:161
#define pe_rsc_unique
Definition: status.h:185
GHashTable * node_hash_from_list(GListPtr list)
Definition: utils.c:135
const char * localhost
Definition: status.h:124
GHashTable * meta
Definition: status.h:292
gboolean xml_contains_remote_node(xmlNode *xml)
Definition: remote.c:91
node_t * pe_find_node_any(GListPtr node_list, const char *id, const char *uname)
Definition: status.c:270
const char * fail2text(enum action_fail_response fail)
Definition: common.c:193
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:419
#define pe_flag_quick_location
Definition: status.h:79
#define pe_rsc_start_pending
Definition: status.h:201
#define XML_LRM_TAG_RESOURCES
Definition: msg_xml.h:238
gboolean standby_onfail
Definition: status.h:139
#define crm_err(fmt, args...)
Definition: logging.h:248
resource_t *(* find_rsc)(resource_t *parent, const char *search, node_t *node, int flags)
Definition: complex.h:44
#define XML_CIB_TAG_TICKET_STATE
Definition: msg_xml.h:402
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1309
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:145
void pe_fence_node(pe_working_set_t *data_set, node_t *node, const char *reason)
Schedule a fence action for a node.
Definition: unpack.c:74
ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
Definition: utils.c:1600
void crm_xml_set_id(xmlNode *xml, const char *format,...) __attribute__((__format__(__printf__
GHashTable * attrs
Definition: status.h:153
bool remote_id_conflict(const char *remote_name, pe_working_set_t *data)
Definition: unpack.c:392
enum rsc_role_e next_role
Definition: status.h:290
gboolean online
Definition: status.h:137
#define XML_ATTR_HAVE_WATCHDOG
Definition: msg_xml.h:90
#define XML_NODE_ATTR_RSC_DISCOVERY
Definition: msg_xml.h:358
gboolean shutdown
Definition: status.h:143
int compare_version(const char *version1, const char *version2)
Definition: utils.c:474
gboolean rsc_discovery_enabled
Definition: status.h:162
#define pe_flag_remove_after_stop
Definition: status.h:73
#define pe_rsc_failure_ignored
Definition: status.h:208
xmlNode * params_secure
Definition: internal.h:266
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:284
#define pe_rsc_managed
Definition: status.h:180
#define CRMD_ACTION_MIGRATE
Definition: crm.h:159
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:355
int node_score_red
Definition: utils.c:75
enum rsc_role_e fail_role
Definition: status.h:333
gboolean remote_requires_reset
Definition: status.h:163
char * id
Definition: status.h:378
#define XML_RSC_ATTR_INTERNAL_RSC
Definition: msg_xml.h:222
#define CRM_ASSERT(expr)
Definition: error.h:35
char data[0]
Definition: internal.h:58
#define crm_str(x)
Definition: logging.h:274
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:84
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:282
gboolean unpack_lrm_resources(node_t *node, xmlNode *lrm_rsc_list, pe_working_set_t *data_set)
Definition: unpack.c:2346
#define CRMD_JOINSTATE_PENDING
Definition: crm.h:151
enum node_type type
Definition: status.h:154
rsc_role_e
Definition: common.h:81
enum pe_action_flags flags
Definition: status.h:330
GHashTable * known_on
Definition: status.h:286
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:283
gboolean standby
Definition: status.h:373
Definition: status.h:377
GListPtr find_operations(const char *rsc, const char *node, gboolean active_filter, pe_working_set_t *data_set)
Definition: unpack.c:3452
#define XML_NODE_JOIN_STATE
Definition: msg_xml.h:256
gboolean expected_up
Definition: status.h:144
void pe_free_action(action_t *action)
Definition: utils.c:1107
#define pe_flag_have_quorum
Definition: status.h:58
void destroy_ticket(gpointer data)
Definition: utils.c:1588
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:157
#define XML_CIB_TAG_OBJ_REF
Definition: msg_xml.h:406
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
gboolean granted
Definition: status.h:371
Definition: status.h:169
gboolean remote_was_fenced
Definition: status.h:164
#define XML_NODE_IN_CLUSTER
Definition: msg_xml.h:258
#define pe_flag_stop_action_orphans
Definition: status.h:69
#define NORMALNODE
Definition: util.h:39
gboolean crm_is_true(const char *s)
Definition: strings.c:165
void calculate_active_ops(GListPtr sorted_op_list, int *start_index, int *stop_index)
Definition: unpack.c:2164
#define XML_CIB_TAG_GROUP
Definition: msg_xml.h:189
CRM_TRACE_INIT_DATA(pe_status)
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:242
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:25
#define pe_flag_symmetric_cluster
Definition: status.h:59
#define ID(x)
Definition: msg_xml.h:434
unsigned long long flags
Definition: status.h:92
char * generate_op_key(const char *rsc_id, const char *op_type, int interval)
Generate an operation key.
Definition: utils.c:652
#define pe_err(fmt...)
Definition: internal.h:27
void print_resource(int log_level, const char *pre_text, resource_t *rsc, gboolean details)
Definition: utils.c:1091
gboolean unpack_tags(xmlNode *xml_tags, pe_working_set_t *data_set)
Definition: unpack.c:842
resource_t * pe_find_resource(GListPtr rsc_list, const char *id_rh)
Definition: status.c:252
#define safe_str_eq(a, b)
Definition: util.h:64
int node_score_green
Definition: utils.c:76
#define ONLINESTATUS
Definition: util.h:49
char * id
Definition: status.h:370
op_digest_cache_t * rsc_action_digest_cmp(resource_t *rsc, xmlNode *xml_op, node_t *node, pe_working_set_t *data_set)
Definition: utils.c:1715
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define crm_str_hash
Definition: crm.h:208
#define XML_LRM_ATTR_MIGRATE_SOURCE
Definition: msg_xml.h:297
#define LOG_DEBUG_3
Definition: logging.h:32
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:45
gint sort_node_uname(gconstpointer a, gconstpointer b)
Definition: utils.c:177
GList * GListPtr
Definition: crm.h:202
int node_score_yellow
Definition: utils.c:77
#define XML_CIB_TAG_TICKETS
Definition: msg_xml.h:401
crm_time_t * now
Definition: status.h:84
#define crm_info(fmt, args...)
Definition: logging.h:251
char * digest_restart_calc
Definition: internal.h:270
void g_hash_destroy_str(gpointer data)
Definition: strings.c:74
GHashTable * template_rsc_sets
Definition: status.h:123
#define pe_rsc_unexpectedly_running
Definition: status.h:209
#define pe_flag_concurrent_fencing
Definition: status.h:66
GHashTable * state
Definition: status.h:374
#define XML_OP_ATTR_ALLOW_MIGRATE
Definition: msg_xml.h:232
#define pe_flag_start_failure_fatal
Definition: status.h:72
#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
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:243
#define CRMD_ACTION_STATUS
Definition: crm.h:176
GListPtr running_on
Definition: status.h:285