pacemaker  2.1.0-7c3f660
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
native.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2021 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <crm/pengine/rules.h>
13 #include <crm/pengine/status.h>
14 #include <crm/pengine/complex.h>
15 #include <crm/pengine/internal.h>
16 #include <crm/msg_xml.h>
17 #include <pe_status_private.h>
18 
19 #define VARIANT_NATIVE 1
20 #include "./variant.h"
21 
22 #ifdef PCMK__COMPAT_2_0
23 #define PROVIDER_SEP "::"
24 #else
25 #define PROVIDER_SEP ":"
26 #endif
27 
32 static bool
33 is_multiply_active(pe_resource_t *rsc)
34 {
35  unsigned int count = 0;
36 
37  if (rsc->variant == pe_native) {
38  pe__find_active_requires(rsc, &count);
39  }
40  return count > 1;
41 }
42 
43 static void
44 native_priority_to_node(pe_resource_t * rsc, pe_node_t * node, gboolean failed)
45 {
46  int priority = 0;
47 
48  if ((rsc->priority == 0) || (failed == TRUE)) {
49  return;
50  }
51 
52  if (rsc->role == RSC_ROLE_PROMOTED) {
53  // Promoted instance takes base priority + 1
54  priority = rsc->priority + 1;
55 
56  } else {
57  priority = rsc->priority;
58  }
59 
60  node->details->priority += priority;
61  pe_rsc_trace(rsc, "Node '%s' now has priority %d with %s'%s' (priority: %d%s)",
62  node->details->uname, node->details->priority,
63  (rsc->role == RSC_ROLE_PROMOTED)? "promoted " : "",
64  rsc->id, rsc->priority,
65  (rsc->role == RSC_ROLE_PROMOTED)? " + 1" : "");
66 
67  /* Priority of a resource running on a guest node is added to the cluster
68  * node as well. */
69  if (node->details->remote_rsc
70  && node->details->remote_rsc->container) {
71  GList *gIter = node->details->remote_rsc->container->running_on;
72 
73  for (; gIter != NULL; gIter = gIter->next) {
74  pe_node_t *a_node = gIter->data;
75 
76  a_node->details->priority += priority;
77  pe_rsc_trace(rsc, "Node '%s' now has priority %d with %s'%s' (priority: %d%s) "
78  "from guest node '%s'",
79  a_node->details->uname, a_node->details->priority,
80  (rsc->role == RSC_ROLE_PROMOTED)? "promoted " : "",
81  rsc->id, rsc->priority,
82  (rsc->role == RSC_ROLE_PROMOTED)? " + 1" : "",
83  node->details->uname);
84  }
85  }
86 }
87 
88 void
89 native_add_running(pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set, gboolean failed)
90 {
91  GList *gIter = rsc->running_on;
92 
93  CRM_CHECK(node != NULL, return);
94  for (; gIter != NULL; gIter = gIter->next) {
95  pe_node_t *a_node = (pe_node_t *) gIter->data;
96 
97  CRM_CHECK(a_node != NULL, return);
98  if (pcmk__str_eq(a_node->details->id, node->details->id, pcmk__str_casei)) {
99  return;
100  }
101  }
102 
103  pe_rsc_trace(rsc, "Adding %s to %s %s", rsc->id, node->details->uname,
104  pcmk_is_set(rsc->flags, pe_rsc_managed)? "" : "(unmanaged)");
105 
106  rsc->running_on = g_list_append(rsc->running_on, node);
107  if (rsc->variant == pe_native) {
108  node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
109 
110  native_priority_to_node(rsc, node, failed);
111  }
112 
113  if (rsc->variant == pe_native && node->details->maintenance) {
115  }
116 
117  if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
118  pe_resource_t *p = rsc->parent;
119 
120  pe_rsc_info(rsc, "resource %s isn't managed", rsc->id);
121  resource_location(rsc, node, INFINITY, "not_managed_default", data_set);
122 
123  while(p && node->details->online) {
124  /* add without the additional location constraint */
125  p->running_on = g_list_append(p->running_on, node);
126  p = p->parent;
127  }
128  return;
129  }
130 
131  if (is_multiply_active(rsc)) {
132  switch (rsc->recovery_type) {
133  case recovery_stop_only:
134  {
135  GHashTableIter gIter;
136  pe_node_t *local_node = NULL;
137 
138  /* make sure it doesn't come up again */
139  if (rsc->allowed_nodes != NULL) {
140  g_hash_table_destroy(rsc->allowed_nodes);
141  }
142  rsc->allowed_nodes = pe__node_list2table(data_set->nodes);
143  g_hash_table_iter_init(&gIter, rsc->allowed_nodes);
144  while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
145  local_node->weight = -INFINITY;
146  }
147  }
148  break;
149  case recovery_stop_start:
150  break;
151  case recovery_block:
154 
155  /* If the resource belongs to a group or bundle configured with
156  * multiple-active=block, block the entire entity.
157  */
158  if (rsc->parent
159  && (rsc->parent->variant == pe_group || rsc->parent->variant == pe_container)
160  && rsc->parent->recovery_type == recovery_block) {
161  GList *gIter = rsc->parent->children;
162 
163  for (; gIter != NULL; gIter = gIter->next) {
164  pe_resource_t *child = (pe_resource_t *) gIter->data;
165 
168  }
169  }
170  break;
171  }
172  crm_debug("%s is active on multiple nodes including %s: %s",
173  rsc->id, node->details->uname,
174  recovery2text(rsc->recovery_type));
175 
176  } else {
177  pe_rsc_trace(rsc, "Resource %s is active on: %s", rsc->id, node->details->uname);
178  }
179 
180  if (rsc->parent != NULL) {
181  native_add_running(rsc->parent, node, data_set, FALSE);
182  }
183 }
184 
185 static void
186 recursive_clear_unique(pe_resource_t *rsc)
187 {
190 
191  for (GList *child = rsc->children; child != NULL; child = child->next) {
192  recursive_clear_unique((pe_resource_t *) child->data);
193  }
194 }
195 
196 gboolean
198 {
199  pe_resource_t *parent = uber_parent(rsc);
200  native_variant_data_t *native_data = NULL;
201  const char *standard = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
202  uint32_t ra_caps = pcmk_get_ra_caps(standard);
203 
204  pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
205 
206  native_data = calloc(1, sizeof(native_variant_data_t));
207  rsc->variant_opaque = native_data;
208 
209  // Only some agent standards support unique and promotable clones
210  if (!pcmk_is_set(ra_caps, pcmk_ra_cap_unique)
211  && pcmk_is_set(rsc->flags, pe_rsc_unique) && pe_rsc_is_clone(parent)) {
212 
213  /* @COMPAT We should probably reject this situation as an error (as we
214  * do for promotable below) rather than warn and convert, but that would
215  * be a backward-incompatible change that we should probably do with a
216  * transform at a schema major version bump.
217  */
218  pe__force_anon(standard, parent, rsc->id, data_set);
219 
220  /* Clear globally-unique on the parent and all its descendents unpacked
221  * so far (clearing the parent should make any future children unpacking
222  * correct). We have to clear this resource explicitly because it isn't
223  * hooked into the parent's children yet.
224  */
225  recursive_clear_unique(parent);
226  recursive_clear_unique(rsc);
227  }
228  if (!pcmk_is_set(ra_caps, pcmk_ra_cap_promotable)
229  && pcmk_is_set(parent->flags, pe_rsc_promotable)) {
230 
231  pe_err("Resource %s is of type %s and therefore "
232  "cannot be used as a promotable clone resource",
233  rsc->id, standard);
234  return FALSE;
235  }
236  return TRUE;
237 }
238 
239 static bool
240 rsc_is_on_node(pe_resource_t *rsc, const pe_node_t *node, int flags)
241 {
242  pe_rsc_trace(rsc, "Checking whether %s is on %s",
243  rsc->id, node->details->uname);
244 
245  if (pcmk_is_set(flags, pe_find_current) && rsc->running_on) {
246 
247  for (GList *iter = rsc->running_on; iter; iter = iter->next) {
248  pe_node_t *loc = (pe_node_t *) iter->data;
249 
250  if (loc->details == node->details) {
251  return TRUE;
252  }
253  }
254 
255  } else if (pcmk_is_set(flags, pe_find_inactive)
256  && (rsc->running_on == NULL)) {
257  return TRUE;
258 
259  } else if (!pcmk_is_set(flags, pe_find_current) && rsc->allocated_to
260  && (rsc->allocated_to->details == node->details)) {
261  return TRUE;
262  }
263  return FALSE;
264 }
265 
267 native_find_rsc(pe_resource_t * rsc, const char *id, const pe_node_t *on_node,
268  int flags)
269 {
270  bool match = FALSE;
271  pe_resource_t *result = NULL;
272 
273  CRM_CHECK(id && rsc && rsc->id, return NULL);
274 
275  if (flags & pe_find_clone) {
276  const char *rid = ID(rsc->xml);
277 
278  if (!pe_rsc_is_clone(uber_parent(rsc))) {
279  match = FALSE;
280 
281  } else if (!strcmp(id, rsc->id) || pcmk__str_eq(id, rid, pcmk__str_casei)) {
282  match = TRUE;
283  }
284 
285  } else if (!strcmp(id, rsc->id)) {
286  match = TRUE;
287 
288  } else if (pcmk_is_set(flags, pe_find_renamed)
289  && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
290  match = TRUE;
291 
292  } else if (pcmk_is_set(flags, pe_find_any)
293  || (pcmk_is_set(flags, pe_find_anon)
294  && !pcmk_is_set(rsc->flags, pe_rsc_unique))) {
295  match = pe_base_name_eq(rsc, id);
296  }
297 
298  if (match && on_node) {
299  bool match_node = rsc_is_on_node(rsc, on_node, flags);
300 
301  if (match_node == FALSE) {
302  match = FALSE;
303  }
304  }
305 
306  if (match) {
307  return rsc;
308  }
309 
310  for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
311  pe_resource_t *child = (pe_resource_t *) gIter->data;
312 
313  result = rsc->fns->find_rsc(child, id, on_node, flags);
314  if (result) {
315  return result;
316  }
317  }
318  return NULL;
319 }
320 
321 // create is ignored
322 char *
323 native_parameter(pe_resource_t * rsc, pe_node_t * node, gboolean create, const char *name,
324  pe_working_set_t * data_set)
325 {
326  char *value_copy = NULL;
327  const char *value = NULL;
328  GHashTable *params = NULL;
329 
330  CRM_CHECK(rsc != NULL, return NULL);
331  CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
332 
333  pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
334  params = pe_rsc_params(rsc, node, data_set);
335  value = g_hash_table_lookup(params, name);
336  if (value == NULL) {
337  /* try meta attributes instead */
338  value = g_hash_table_lookup(rsc->meta, name);
339  }
340  if (value != NULL) {
341  value_copy = strdup(value);
342  }
343  return value_copy;
344 }
345 
346 gboolean
347 native_active(pe_resource_t * rsc, gboolean all)
348 {
349  for (GList *gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
350  pe_node_t *a_node = (pe_node_t *) gIter->data;
351 
352  if (a_node->details->unclean) {
353  pe_rsc_trace(rsc, "Resource %s: node %s is unclean",
354  rsc->id, a_node->details->uname);
355  return TRUE;
356  } else if (a_node->details->online == FALSE) {
357  pe_rsc_trace(rsc, "Resource %s: node %s is offline",
358  rsc->id, a_node->details->uname);
359  } else {
360  pe_rsc_trace(rsc, "Resource %s active on %s",
361  rsc->id, a_node->details->uname);
362  return TRUE;
363  }
364  }
365  return FALSE;
366 }
367 
368 struct print_data_s {
369  long options;
370  void *print_data;
371 };
372 
373 static const char *
374 native_pending_state(pe_resource_t * rsc)
375 {
376  const char *pending_state = NULL;
377 
378  if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_START, pcmk__str_casei)) {
379  pending_state = "Starting";
380 
381  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_STOP, pcmk__str_casei)) {
382  pending_state = "Stopping";
383 
384  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_MIGRATE, pcmk__str_casei)) {
385  pending_state = "Migrating";
386 
387  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_MIGRATED, pcmk__str_casei)) {
388  /* Work might be done in here. */
389  pending_state = "Migrating";
390 
391  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_PROMOTE, pcmk__str_casei)) {
392  pending_state = "Promoting";
393 
394  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_DEMOTE, pcmk__str_casei)) {
395  pending_state = "Demoting";
396  }
397 
398  return pending_state;
399 }
400 
401 static const char *
402 native_pending_task(pe_resource_t * rsc)
403 {
404  const char *pending_task = NULL;
405 
406  if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_STATUS, pcmk__str_casei)) {
407  pending_task = "Monitoring";
408 
409  /* Pending probes are not printed, even if pending
410  * operations are requested. If someone ever requests that
411  * behavior, uncomment this and the corresponding part of
412  * unpack.c:unpack_rsc_op().
413  */
414  /*
415  } else if (pcmk__str_eq(rsc->pending_task, "probe", pcmk__str_casei)) {
416  pending_task = "Checking";
417  */
418  }
419 
420  return pending_task;
421 }
422 
423 static enum rsc_role_e
424 native_displayable_role(pe_resource_t *rsc)
425 {
426  enum rsc_role_e role = rsc->role;
427 
428  if ((role == RSC_ROLE_STARTED)
429  && pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable)) {
430 
431  role = RSC_ROLE_UNPROMOTED;
432  }
433  return role;
434 }
435 
436 static const char *
437 native_displayable_state(pe_resource_t *rsc, long options)
438 {
439  const char *rsc_state = NULL;
440 
441  if (options & pe_print_pending) {
442  rsc_state = native_pending_state(rsc);
443  }
444  if (rsc_state == NULL) {
445  rsc_state = role2text(native_displayable_role(rsc));
446  }
447  return rsc_state;
448 }
449 
450 static void
451 native_print_xml(pe_resource_t * rsc, const char *pre_text, long options, void *print_data)
452 {
453  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
454  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
455  const char *rsc_state = native_displayable_state(rsc, options);
456  const char *target_role = NULL;
457 
458  /* resource information. */
459  status_print("%s<resource ", pre_text);
460  status_print("id=\"%s\" ", rsc_printable_id(rsc));
461  status_print("resource_agent=\"%s%s%s:%s\" ", class,
462  ((prov == NULL)? "" : PROVIDER_SEP),
463  ((prov == NULL)? "" : prov),
465 
466  status_print("role=\"%s\" ", rsc_state);
467  if (rsc->meta) {
468  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
469  }
470  if (target_role) {
471  status_print("target_role=\"%s\" ", target_role);
472  }
473  status_print("active=\"%s\" ", pcmk__btoa(rsc->fns->active(rsc, TRUE)));
474  status_print("orphaned=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_orphan));
475  status_print("blocked=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_block));
476  status_print("managed=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_managed));
477  status_print("failed=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_failed));
478  status_print("failure_ignored=\"%s\" ",
479  pe__rsc_bool_str(rsc, pe_rsc_failure_ignored));
480  status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
481 
482  if (options & pe_print_pending) {
483  const char *pending_task = native_pending_task(rsc);
484 
485  if (pending_task) {
486  status_print("pending=\"%s\" ", pending_task);
487  }
488  }
489 
490  /* print out the nodes this resource is running on */
491  if (options & pe_print_rsconly) {
492  status_print("/>\n");
493  /* do nothing */
494  } else if (rsc->running_on != NULL) {
495  GList *gIter = rsc->running_on;
496 
497  status_print(">\n");
498  for (; gIter != NULL; gIter = gIter->next) {
499  pe_node_t *node = (pe_node_t *) gIter->data;
500 
501  status_print("%s <node name=\"%s\" id=\"%s\" cached=\"%s\"/>\n", pre_text,
502  node->details->uname, node->details->id,
503  pcmk__btoa(node->details->online == FALSE));
504  }
505  status_print("%s</resource>\n", pre_text);
506  } else {
507  status_print("/>\n");
508  }
509 }
510 
511 // Append a flag to resource description string's flags list
512 static bool
513 add_output_flag(GString *s, const char *flag_desc, bool have_flags)
514 {
515  g_string_append(s, (have_flags? ", " : " ("));
516  g_string_append(s, flag_desc);
517  return true;
518 }
519 
520 // Append a node name to resource description string's node list
521 static bool
522 add_output_node(GString *s, const char *node, bool have_nodes)
523 {
524  g_string_append(s, (have_nodes? " " : " [ "));
525  g_string_append(s, node);
526  return true;
527 }
528 
543 gchar *
545  long options, const char *target_role, bool show_nodes)
546 {
547  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
548  const char *provider = NULL;
549  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
550  gchar *retval = NULL;
551  GString *outstr = NULL;
552  bool have_flags = false;
553 
554  if (rsc->variant != pe_native) {
555  return NULL;
556  }
557 
558  CRM_CHECK(name != NULL, name = "unknown");
559  CRM_CHECK(kind != NULL, kind = "unknown");
560  CRM_CHECK(class != NULL, class = "unknown");
561 
563  provider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
564  }
565 
566  if ((node == NULL) && (rsc->lock_node != NULL)) {
567  node = rsc->lock_node;
568  }
569  if (pcmk_is_set(options, pe_print_rsconly)
570  || pcmk__list_of_multiple(rsc->running_on)) {
571  node = NULL;
572  }
573 
574  // We need a string of at least this size
575  outstr = g_string_sized_new(strlen(name) + strlen(class) + strlen(kind)
576  + (provider? (strlen(provider) + 2) : 0)
577  + (node? strlen(node->details->uname) + 1 : 0)
578  + 11);
579 
580  // Resource name and agent
581  g_string_printf(outstr, "%s\t(%s%s%s:%s):\t", name, class,
582  ((provider == NULL)? "" : PROVIDER_SEP),
583  ((provider == NULL)? "" : provider), kind);
584 
585  // State on node
586  if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
587  g_string_append(outstr, " ORPHANED");
588  }
589  if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
590  enum rsc_role_e role = native_displayable_role(rsc);
591 
592  if (role > RSC_ROLE_UNPROMOTED) {
593  g_string_append_printf(outstr, " FAILED %s", role2text(role));
594  } else {
595  g_string_append(outstr, " FAILED");
596  }
597  } else {
598  g_string_append_printf(outstr, " %s", native_displayable_state(rsc, options));
599  }
600  if (node) {
601  g_string_append_printf(outstr, " %s", node->details->uname);
602  }
603 
604  // Flags, as: (<flag> [...])
605  if (node && !(node->details->online) && node->details->unclean) {
606  have_flags = add_output_flag(outstr, "UNCLEAN", have_flags);
607  }
608  if (node && (node == rsc->lock_node)) {
609  have_flags = add_output_flag(outstr, "LOCKED", have_flags);
610  }
611  if (pcmk_is_set(options, pe_print_pending)) {
612  const char *pending_task = native_pending_task(rsc);
613 
614  if (pending_task) {
615  have_flags = add_output_flag(outstr, pending_task, have_flags);
616  }
617  }
618  if (target_role) {
619  enum rsc_role_e target_role_e = text2role(target_role);
620 
621  /* Only show target role if it limits our abilities (i.e. ignore
622  * Started, as it is the default anyways, and doesn't prevent the
623  * resource from becoming promoted).
624  */
625  if (target_role_e == RSC_ROLE_STOPPED) {
626  have_flags = add_output_flag(outstr, "disabled", have_flags);
627 
628  } else if (pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable)
629  && target_role_e == RSC_ROLE_UNPROMOTED) {
630  have_flags = add_output_flag(outstr, "target-role:", have_flags);
631  g_string_append(outstr, target_role);
632  }
633  }
634  if (pcmk_is_set(rsc->flags, pe_rsc_block)) {
635  have_flags = add_output_flag(outstr, "blocked", have_flags);
636  } else if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
637  have_flags = add_output_flag(outstr, "unmanaged", have_flags);
638  }
639  if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
640  have_flags = add_output_flag(outstr, "failure ignored", have_flags);
641  }
642  if (have_flags) {
643  g_string_append(outstr, ")");
644  }
645 
646  // User-supplied description
647  if (pcmk_is_set(options, pe_print_rsconly)
648  || pcmk__list_of_multiple(rsc->running_on)) {
649  const char *desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
650 
651  if (desc) {
652  g_string_append_printf(outstr, " %s", desc);
653  }
654  }
655 
656  if (show_nodes && !pcmk_is_set(options, pe_print_rsconly)
657  && pcmk__list_of_multiple(rsc->running_on)) {
658  bool have_nodes = false;
659 
660  for (GList *iter = rsc->running_on; iter != NULL; iter = iter->next) {
661  pe_node_t *n = (pe_node_t *) iter->data;
662 
663  have_nodes = add_output_node(outstr, n->details->uname, have_nodes);
664  }
665  if (have_nodes) {
666  g_string_append(outstr, " ]");
667  }
668  }
669 
670  retval = outstr->str;
671  g_string_free(outstr, FALSE);
672  return retval;
673 }
674 
675 int
677  const char *name, pe_node_t *node, long options)
678 {
679  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
680  const char *target_role = NULL;
681 
682  xmlNodePtr list_node = NULL;
683  const char *cl = NULL;
684 
685  CRM_ASSERT(rsc->variant == pe_native);
686  CRM_ASSERT(kind != NULL);
687 
688  if (rsc->meta) {
689  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
690 
691  if (crm_is_true(is_internal)
692  && !pcmk_is_set(options, pe_print_implicit)) {
693 
694  crm_trace("skipping print of internal resource %s", rsc->id);
695  return pcmk_rc_no_output;
696  }
697  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
698  }
699 
700  if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
701  cl = "rsc-managed";
702 
703  } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
704  cl = "rsc-failed";
705 
706  } else if (rsc->variant == pe_native && (rsc->running_on == NULL)) {
707  cl = "rsc-failed";
708 
709  } else if (pcmk__list_of_multiple(rsc->running_on)) {
710  cl = "rsc-multiple";
711 
712  } else if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
713  cl = "rsc-failure-ignored";
714 
715  } else {
716  cl = "rsc-ok";
717  }
718 
719  {
720  gchar *s = pcmk__native_output_string(rsc, name, node, options,
721  target_role, true);
722 
723  list_node = pcmk__output_create_html_node(out, "li", NULL, NULL, NULL);
724  pcmk_create_html_node(list_node, "span", NULL, cl, s);
725  g_free(s);
726  }
727 
728  return pcmk_rc_ok;
729 }
730 
731 int
733  const char *name, pe_node_t *node, long options)
734 {
735  const char *target_role = NULL;
736 
737  CRM_ASSERT(rsc->variant == pe_native);
738 
739  if (rsc->meta) {
740  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
741 
742  if (crm_is_true(is_internal)
743  && !pcmk_is_set(options, pe_print_implicit)) {
744 
745  crm_trace("skipping print of internal resource %s", rsc->id);
746  return pcmk_rc_no_output;
747  }
748  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
749  }
750 
751  {
752  gchar *s = pcmk__native_output_string(rsc, name, node, options,
753  target_role, true);
754 
755  out->list_item(out, NULL, "%s", s);
756  g_free(s);
757  }
758 
759  return pcmk_rc_ok;
760 }
761 
762 void
763 common_print(pe_resource_t * rsc, const char *pre_text, const char *name, pe_node_t *node, long options, void *print_data)
764 {
765  const char *target_role = NULL;
766 
767  CRM_ASSERT(rsc->variant == pe_native);
768 
769  if (rsc->meta) {
770  const char *is_internal = g_hash_table_lookup(rsc->meta,
772 
773  if (crm_is_true(is_internal)
774  && !pcmk_is_set(options, pe_print_implicit)) {
775 
776  crm_trace("skipping print of internal resource %s", rsc->id);
777  return;
778  }
779  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
780  }
781 
782  if (options & pe_print_xml) {
783  native_print_xml(rsc, pre_text, options, print_data);
784  return;
785  }
786 
787  if ((pre_text == NULL) && (options & pe_print_printf)) {
788  pre_text = " ";
789  }
790 
791  if (options & pe_print_html) {
792  if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
793  status_print("<font color=\"yellow\">");
794 
795  } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
796  status_print("<font color=\"red\">");
797 
798  } else if (rsc->running_on == NULL) {
799  status_print("<font color=\"red\">");
800 
801  } else if (pcmk__list_of_multiple(rsc->running_on)) {
802  status_print("<font color=\"orange\">");
803 
804  } else if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
805  status_print("<font color=\"yellow\">");
806 
807  } else {
808  status_print("<font color=\"green\">");
809  }
810  }
811 
812  {
813  gchar *resource_s = pcmk__native_output_string(rsc, name, node, options,
814  target_role, false);
815  status_print("%s%s", (pre_text? pre_text : ""), resource_s);
816  g_free(resource_s);
817  }
818 
819  if (pcmk_is_set(options, pe_print_html)) {
820  status_print(" </font> ");
821  }
822 
823  if (!pcmk_is_set(options, pe_print_rsconly)
824  && pcmk__list_of_multiple(rsc->running_on)) {
825 
826  GList *gIter = rsc->running_on;
827  int counter = 0;
828 
829  if (options & pe_print_html) {
830  status_print("<ul>\n");
831  } else if ((options & pe_print_printf)
832  || (options & pe_print_ncurses)) {
833  status_print("[");
834  }
835 
836  for (; gIter != NULL; gIter = gIter->next) {
837  pe_node_t *n = (pe_node_t *) gIter->data;
838 
839  counter++;
840 
841  if (options & pe_print_html) {
842  status_print("<li>\n%s", n->details->uname);
843 
844  } else if ((options & pe_print_printf)
845  || (options & pe_print_ncurses)) {
846  status_print(" %s", n->details->uname);
847 
848  } else if ((options & pe_print_log)) {
849  status_print("\t%d : %s", counter, n->details->uname);
850 
851  } else {
852  status_print("%s", n->details->uname);
853  }
854  if (options & pe_print_html) {
855  status_print("</li>\n");
856 
857  }
858  }
859 
860  if (options & pe_print_html) {
861  status_print("</ul>\n");
862  } else if ((options & pe_print_printf)
863  || (options & pe_print_ncurses)) {
864  status_print(" ]");
865  }
866  }
867 
868  if (options & pe_print_html) {
869  status_print("<br/>\n");
870  } else if (options & pe_print_suppres_nl) {
871  /* nothing */
872  } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
873  status_print("\n");
874  }
875 }
876 
877 void
878 native_print(pe_resource_t * rsc, const char *pre_text, long options, void *print_data)
879 {
880  pe_node_t *node = NULL;
881 
882  CRM_ASSERT(rsc->variant == pe_native);
883  if (options & pe_print_xml) {
884  native_print_xml(rsc, pre_text, options, print_data);
885  return;
886  }
887 
888  node = pe__current_node(rsc);
889 
890  if (node == NULL) {
891  // This is set only if a non-probe action is pending on this node
892  node = rsc->pending_node;
893  }
894 
895  common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
896 }
897 
898 PCMK__OUTPUT_ARGS("primitive", "unsigned int", "pe_resource_t *", "GList *", "GList *")
899 int
900 pe__resource_xml(pcmk__output_t *out, va_list args)
901 {
902  unsigned int options = va_arg(args, unsigned int);
903  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
904  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
905  GList *only_rsc = va_arg(args, GList *);
906 
907  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
908  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
909  const char *rsc_state = native_displayable_state(rsc, options);
910 
911  long is_print_pending = options & pe_print_pending;
912 
913  char ra_name[LINE_MAX];
914  char *nodes_running_on = NULL;
915  char *priority = NULL;
916  int rc = pcmk_rc_no_output;
917  const char *target_role = NULL;
918 
919  if (rsc->meta != NULL) {
920  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
921  }
922 
923  CRM_ASSERT(rsc->variant == pe_native);
924 
925  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
926  return pcmk_rc_no_output;
927  }
928 
929  /* resource information. */
930  snprintf(ra_name, LINE_MAX, "%s%s%s:%s", class,
931  ((prov == NULL)? "" : PROVIDER_SEP), ((prov == NULL)? "" : prov),
932  crm_element_value(rsc->xml, XML_ATTR_TYPE));
933 
934  nodes_running_on = pcmk__itoa(g_list_length(rsc->running_on));
935  priority = pcmk__ftoa(rsc->priority);
936 
937  rc = pe__name_and_nvpairs_xml(out, true, "resource", 12,
938  "id", rsc_printable_id(rsc),
939  "resource_agent", ra_name,
940  "role", rsc_state,
941  "target_role", target_role,
942  "active", pcmk__btoa(rsc->fns->active(rsc, TRUE)),
943  "orphaned", pe__rsc_bool_str(rsc, pe_rsc_orphan),
944  "blocked", pe__rsc_bool_str(rsc, pe_rsc_block),
945  "managed", pe__rsc_bool_str(rsc, pe_rsc_managed),
946  "failed", pe__rsc_bool_str(rsc, pe_rsc_failed),
947  "failure_ignored", pe__rsc_bool_str(rsc, pe_rsc_failure_ignored),
948  "nodes_running_on", nodes_running_on,
949  "pending", (is_print_pending? native_pending_task(rsc) : NULL));
950  free(priority);
951  free(nodes_running_on);
952 
953  CRM_ASSERT(rc == pcmk_rc_ok);
954 
955  if (rsc->running_on != NULL) {
956  GList *gIter = rsc->running_on;
957 
958  for (; gIter != NULL; gIter = gIter->next) {
959  pe_node_t *node = (pe_node_t *) gIter->data;
960 
961  rc = pe__name_and_nvpairs_xml(out, false, "node", 3,
962  "name", node->details->uname,
963  "id", node->details->id,
964  "cached", pcmk__btoa(node->details->online));
965  CRM_ASSERT(rc == pcmk_rc_ok);
966  }
967  }
968 
970  return rc;
971 }
972 
973 PCMK__OUTPUT_ARGS("primitive", "unsigned int", "pe_resource_t *", "GList *", "GList *")
974 int
976 {
977  unsigned int options = va_arg(args, unsigned int);
978  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
979  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
980  GList *only_rsc = va_arg(args, GList *);
981 
982  pe_node_t *node = pe__current_node(rsc);
983 
984  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
985  return pcmk_rc_no_output;
986  }
987 
988  CRM_ASSERT(rsc->variant == pe_native);
989 
990  if (node == NULL) {
991  // This is set only if a non-probe action is pending on this node
992  node = rsc->pending_node;
993  }
994  return pe__common_output_html(out, rsc, rsc_printable_id(rsc), node, options);
995 }
996 
997 PCMK__OUTPUT_ARGS("primitive", "unsigned int", "pe_resource_t *", "GList *", "GList *")
998 int
1000 {
1001  unsigned int options = va_arg(args, unsigned int);
1002  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1003  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
1004  GList *only_rsc = va_arg(args, GList *);
1005 
1006  pe_node_t *node = pe__current_node(rsc);
1007 
1008  CRM_ASSERT(rsc->variant == pe_native);
1009 
1010  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1011  return pcmk_rc_no_output;
1012  }
1013 
1014  if (node == NULL) {
1015  // This is set only if a non-probe action is pending on this node
1016  node = rsc->pending_node;
1017  }
1018  return pe__common_output_text(out, rsc, rsc_printable_id(rsc), node, options);
1019 }
1020 
1021 void
1023 {
1024  pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
1025  common_free(rsc);
1026 }
1027 
1028 enum rsc_role_e
1029 native_resource_state(const pe_resource_t * rsc, gboolean current)
1030 {
1031  enum rsc_role_e role = rsc->next_role;
1032 
1033  if (current) {
1034  role = rsc->role;
1035  }
1036  pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
1037  return role;
1038 }
1039 
1051 pe_node_t *
1052 native_location(const pe_resource_t *rsc, GList **list, int current)
1053 {
1054  pe_node_t *one = NULL;
1055  GList *result = NULL;
1056 
1057  if (rsc->children) {
1058  GList *gIter = rsc->children;
1059 
1060  for (; gIter != NULL; gIter = gIter->next) {
1061  pe_resource_t *child = (pe_resource_t *) gIter->data;
1062 
1063  child->fns->location(child, &result, current);
1064  }
1065 
1066  } else if (current) {
1067 
1068  if (rsc->running_on) {
1069  result = g_list_copy(rsc->running_on);
1070  }
1071  if ((current == 2) && rsc->pending_node
1072  && !pe_find_node_id(result, rsc->pending_node->details->id)) {
1073  result = g_list_append(result, rsc->pending_node);
1074  }
1075 
1076  } else if (current == FALSE && rsc->allocated_to) {
1077  result = g_list_append(NULL, rsc->allocated_to);
1078  }
1079 
1080  if (result && (result->next == NULL)) {
1081  one = result->data;
1082  }
1083 
1084  if (list) {
1085  GList *gIter = result;
1086 
1087  for (; gIter != NULL; gIter = gIter->next) {
1088  pe_node_t *node = (pe_node_t *) gIter->data;
1089 
1090  if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
1091  *list = g_list_append(*list, node);
1092  }
1093  }
1094  }
1095 
1096  g_list_free(result);
1097  return one;
1098 }
1099 
1100 static void
1101 get_rscs_brief(GList *rsc_list, GHashTable * rsc_table, GHashTable * active_table)
1102 {
1103  GList *gIter = rsc_list;
1104 
1105  for (; gIter != NULL; gIter = gIter->next) {
1106  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1107 
1108  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1109  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
1110 
1111  int offset = 0;
1112  char buffer[LINE_MAX];
1113 
1114  int *rsc_counter = NULL;
1115  int *active_counter = NULL;
1116 
1117  if (rsc->variant != pe_native) {
1118  continue;
1119  }
1120 
1121  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
1123  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
1124 
1125  if (prov != NULL) {
1126  offset += snprintf(buffer + offset, LINE_MAX - offset,
1127  PROVIDER_SEP "%s", prov);
1128  }
1129  }
1130  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
1131  CRM_LOG_ASSERT(offset > 0);
1132 
1133  if (rsc_table) {
1134  rsc_counter = g_hash_table_lookup(rsc_table, buffer);
1135  if (rsc_counter == NULL) {
1136  rsc_counter = calloc(1, sizeof(int));
1137  *rsc_counter = 0;
1138  g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
1139  }
1140  (*rsc_counter)++;
1141  }
1142 
1143  if (active_table) {
1144  GList *gIter2 = rsc->running_on;
1145 
1146  for (; gIter2 != NULL; gIter2 = gIter2->next) {
1147  pe_node_t *node = (pe_node_t *) gIter2->data;
1148  GHashTable *node_table = NULL;
1149 
1150  if (node->details->unclean == FALSE && node->details->online == FALSE) {
1151  continue;
1152  }
1153 
1154  node_table = g_hash_table_lookup(active_table, node->details->uname);
1155  if (node_table == NULL) {
1156  node_table = pcmk__strkey_table(free, free);
1157  g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
1158  }
1159 
1160  active_counter = g_hash_table_lookup(node_table, buffer);
1161  if (active_counter == NULL) {
1162  active_counter = calloc(1, sizeof(int));
1163  *active_counter = 0;
1164  g_hash_table_insert(node_table, strdup(buffer), active_counter);
1165  }
1166  (*active_counter)++;
1167  }
1168  }
1169  }
1170 }
1171 
1172 static void
1173 destroy_node_table(gpointer data)
1174 {
1175  GHashTable *node_table = data;
1176 
1177  if (node_table) {
1178  g_hash_table_destroy(node_table);
1179  }
1180 }
1181 
1182 void
1183 print_rscs_brief(GList *rsc_list, const char *pre_text, long options,
1184  void *print_data, gboolean print_all)
1185 {
1186  GHashTable *rsc_table = pcmk__strkey_table(free, free);
1187  GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1188  GHashTableIter hash_iter;
1189  char *type = NULL;
1190  int *rsc_counter = NULL;
1191 
1192  get_rscs_brief(rsc_list, rsc_table, active_table);
1193 
1194  g_hash_table_iter_init(&hash_iter, rsc_table);
1195  while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
1196  GHashTableIter hash_iter2;
1197  char *node_name = NULL;
1198  GHashTable *node_table = NULL;
1199  int active_counter_all = 0;
1200 
1201  g_hash_table_iter_init(&hash_iter2, active_table);
1202  while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
1203  int *active_counter = g_hash_table_lookup(node_table, type);
1204 
1205  if (active_counter == NULL || *active_counter == 0) {
1206  continue;
1207 
1208  } else {
1209  active_counter_all += *active_counter;
1210  }
1211 
1212  if (options & pe_print_rsconly) {
1213  node_name = NULL;
1214  }
1215 
1216  if (options & pe_print_html) {
1217  status_print("<li>\n");
1218  }
1219 
1220  if (print_all) {
1221  status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1222  active_counter ? *active_counter : 0,
1223  rsc_counter ? *rsc_counter : 0, type,
1224  active_counter && (*active_counter > 0) && node_name ? node_name : "");
1225  } else {
1226  status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1227  active_counter ? *active_counter : 0, type,
1228  active_counter && (*active_counter > 0) && node_name ? node_name : "");
1229  }
1230 
1231  if (options & pe_print_html) {
1232  status_print("</li>\n");
1233  }
1234  }
1235 
1236  if (print_all && active_counter_all == 0) {
1237  if (options & pe_print_html) {
1238  status_print("<li>\n");
1239  }
1240 
1241  status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
1242  active_counter_all,
1243  rsc_counter ? *rsc_counter : 0, type);
1244 
1245  if (options & pe_print_html) {
1246  status_print("</li>\n");
1247  }
1248  }
1249  }
1250 
1251  if (rsc_table) {
1252  g_hash_table_destroy(rsc_table);
1253  rsc_table = NULL;
1254  }
1255  if (active_table) {
1256  g_hash_table_destroy(active_table);
1257  active_table = NULL;
1258  }
1259 }
1260 
1261 int
1262 pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, long options, gboolean print_all)
1263 {
1264  GHashTable *rsc_table = pcmk__strkey_table(free, free);
1265  GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1266  GList *sorted_rscs;
1267  int rc = pcmk_rc_no_output;
1268 
1269  get_rscs_brief(rsc_list, rsc_table, active_table);
1270 
1271  /* Make a list of the rsc_table keys so that it can be sorted. This is to make sure
1272  * output order stays consistent between systems.
1273  */
1274  sorted_rscs = g_hash_table_get_keys(rsc_table);
1275  sorted_rscs = g_list_sort(sorted_rscs, (GCompareFunc) strcmp);
1276 
1277  for (GList *gIter = sorted_rscs; gIter; gIter = gIter->next) {
1278  char *type = (char *) gIter->data;
1279  int *rsc_counter = g_hash_table_lookup(rsc_table, type);
1280 
1281  GHashTableIter hash_iter2;
1282  char *node_name = NULL;
1283  GHashTable *node_table = NULL;
1284  int active_counter_all = 0;
1285 
1286  g_hash_table_iter_init(&hash_iter2, active_table);
1287  while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
1288  int *active_counter = g_hash_table_lookup(node_table, type);
1289 
1290  if (active_counter == NULL || *active_counter == 0) {
1291  continue;
1292 
1293  } else {
1294  active_counter_all += *active_counter;
1295  }
1296 
1297  if (options & pe_print_rsconly) {
1298  node_name = NULL;
1299  }
1300 
1301  if (print_all) {
1302  out->list_item(out, NULL, "%d/%d\t(%s):\tActive %s",
1303  *active_counter,
1304  rsc_counter ? *rsc_counter : 0, type,
1305  (*active_counter > 0) && node_name ? node_name : "");
1306  } else {
1307  out->list_item(out, NULL, "%d\t(%s):\tActive %s",
1308  *active_counter, type,
1309  (*active_counter > 0) && node_name ? node_name : "");
1310  }
1311 
1312  rc = pcmk_rc_ok;
1313  }
1314 
1315  if (print_all && active_counter_all == 0) {
1316  out->list_item(out, NULL, "%d/%d\t(%s):\tActive",
1317  active_counter_all,
1318  rsc_counter ? *rsc_counter : 0, type);
1319  rc = pcmk_rc_ok;
1320  }
1321  }
1322 
1323  if (rsc_table) {
1324  g_hash_table_destroy(rsc_table);
1325  rsc_table = NULL;
1326  }
1327  if (active_table) {
1328  g_hash_table_destroy(active_table);
1329  active_table = NULL;
1330  }
1331  if (sorted_rscs) {
1332  g_list_free(sorted_rscs);
1333  }
1334 
1335  return rc;
1336 }
1337 
1338 gboolean
1339 pe__native_is_filtered(pe_resource_t *rsc, GList *only_rsc, gboolean check_parent)
1340 {
1341  if (pcmk__str_in_list(only_rsc, rsc_printable_id(rsc)) ||
1342  pcmk__str_in_list(only_rsc, rsc->id)) {
1343  return FALSE;
1344  } else if (check_parent) {
1345  pe_resource_t *up = uber_parent(rsc);
1346 
1347  if (pe_rsc_is_bundled(rsc)) {
1348  return up->parent->fns->is_filtered(up->parent, only_rsc, FALSE);
1349  } else {
1350  return up->fns->is_filtered(up, only_rsc, FALSE);
1351  }
1352  }
1353 
1354  return TRUE;
1355 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:218
GHashTable * pe__node_list2table(GList *list)
Definition: utils.c:204
int pe__common_output_html(pcmk__output_t *out, pe_resource_t *rsc, const char *name, pe_node_t *node, long options)
Definition: native.c:676
#define CRMD_ACTION_MIGRATED
Definition: crm.h:174
char data[0]
Definition: cpg.c:55
#define INFINITY
Definition: crm.h:99
pe_resource_t * container
Definition: pe_types.h:379
#define XML_ATTR_TYPE
Definition: msg_xml.h:132
int pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, long options, gboolean print_all)
Definition: native.c:1262
enum rsc_role_e role
Definition: pe_types.h:369
GList * children
Definition: pe_types.h:376
#define XML_BOOLEAN_FALSE
Definition: msg_xml.h:141
#define PROVIDER_SEP
Definition: native.c:25
xmlNode * xml
Definition: pe_types.h:322
gboolean pcmk__str_in_list(GList *lst, const gchar *s)
Definition: strings.c:881
enum rsc_role_e next_role
Definition: pe_types.h:370
xmlNode * pcmk_create_html_node(xmlNode *parent, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: xml.c:733
pe_resource_t * remote_rsc
Definition: pe_types.h:230
pe_node_t * native_location(const pe_resource_t *rsc, GList **list, int current)
Definition: native.c:1052
void pe__force_anon(const char *standard, pe_resource_t *rsc, const char *rid, pe_working_set_t *data_set)
Definition: clone.c:31
GHashTable * meta
Definition: pe_types.h:372
match resource not running anywhere
Definition: pe_types.h:88
#define pe_rsc_unique
Definition: pe_types.h:254
resource_object_functions_t * fns
Definition: pe_types.h:331
#define CRMD_ACTION_PROMOTE
Definition: crm.h:182
void print_rscs_brief(GList *rsc_list, const char *pre_text, long options, void *print_data, gboolean print_all)
Definition: native.c:1183
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:202
void resource_location(pe_resource_t *rsc, pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1588
enum crm_ais_msg_types type
Definition: cpg.c:48
#define resource_s
pe_node_t * allocated_to
Definition: pe_types.h:362
xmlNodePtr pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: output_html.c:417
int pe__resource_text(pcmk__output_t *out, va_list args)
Definition: native.c:999
char * pending_task
Definition: pe_types.h:345
void native_free(pe_resource_t *rsc)
Definition: native.c:1022
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:47
GList * nodes
Definition: pe_types.h:157
#define CRMD_ACTION_START
Definition: crm.h:176
const char * role2text(enum rsc_role_e role)
Definition: common.c:459
#define CRMD_ACTION_STOP
Definition: crm.h:179
int weight
Definition: pe_types.h:241
#define CRMD_ACTION_DEMOTE
Definition: crm.h:184
gboolean pe__native_is_filtered(pe_resource_t *rsc, GList *only_rsc, gboolean check_parent)
Definition: native.c:1339
int rc
Definition: pcmk_fence.c:35
#define pe_rsc_failed
Definition: pe_types.h:267
#define crm_debug(fmt, args...)
Definition: logging.h:355
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:903
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:530
#define PCMK__OUTPUT_ARGS(ARGS...)
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name, size_t pairs_count,...)
Definition: pe_output.c:552
pe_resource_t *(* find_rsc)(pe_resource_t *parent, const char *search, const pe_node_t *node, int flags)
Definition: pe_types.h:45
match only clone instances
Definition: pe_types.h:86
char * native_parameter(pe_resource_t *rsc, pe_node_t *node, gboolean create, const char *name, pe_working_set_t *data_set)
Definition: native.c:323
#define crm_trace(fmt, args...)
Definition: logging.h:356
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:114
struct pe_node_shared_s * details
Definition: pe_types.h:244
enum rsc_recovery_type recovery_type
Definition: pe_types.h:334
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:267
void common_free(pe_resource_t *rsc)
Definition: complex.c:917
unsigned long long flags
Definition: pe_types.h:347
const char * uname
Definition: pe_types.h:209
#define pe_rsc_promotable
Definition: pe_types.h:256
GHashTable * pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters.
Definition: complex.c:457
char * clone_name
Definition: pe_types.h:321
#define XML_ATTR_DESC
Definition: msg_xml.h:128
enum rsc_role_e native_resource_state(const pe_resource_t *rsc, gboolean current)
Definition: native.c:1029
void native_print(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:878
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:233
match base name of any clone instance
Definition: pe_types.h:89
enum rsc_role_e text2role(const char *role)
Definition: common.c:488
enum pe_obj_types variant
Definition: pe_types.h:329
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:511
void common_print(pe_resource_t *rsc, const char *pre_text, const char *name, pe_node_t *node, long options, void *print_data)
Definition: native.c:763
const char * id
Definition: pe_types.h:208
gboolean native_active(pe_resource_t *rsc, gboolean all)
Definition: native.c:347
int pe__resource_xml(pcmk__output_t *out, va_list args)
Definition: native.c:900
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:234
pe_node_t * pe_find_node_id(GList *node_list, const char *id)
Definition: status.c:418
GList * running_rsc
Definition: pe_types.h:231
match resource ID or LRM history ID
Definition: pe_types.h:84
gboolean(* is_filtered)(pe_resource_t *, GList *, gboolean)
Definition: pe_types.h:57
Cluster status and scheduling.
pe_resource_t * native_find_rsc(pe_resource_t *rsc, const char *id, const pe_node_t *node, int flags)
Definition: native.c:267
pe_node_t * pending_node
Definition: pe_types.h:382
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:610
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:579
void * variant_opaque
Definition: pe_types.h:330
#define CRM_ASSERT(expr)
Definition: results.h:42
const char * rsc_printable_id(pe_resource_t *rsc)
Definition: utils.c:1911
#define status_print(fmt, args...)
This structure contains everything that makes up a single output formatter.
#define CRMD_ACTION_MIGRATE
Definition: crm.h:173
void native_add_running(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set, gboolean failed)
Definition: native.c:89
#define XML_RSC_ATTR_INTERNAL_RSC
Definition: msg_xml.h:242
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:53
int pe__resource_html(pcmk__output_t *out, va_list args)
Definition: native.c:975
rsc_role_e
Possible roles that a resource can be in.
Definition: common.h:92
GList * running_on
Definition: pe_types.h:365
#define pe_rsc_block
Definition: pe_types.h:250
gboolean maintenance
Definition: pe_types.h:222
#define pe_rsc_failure_ignored
Definition: pe_types.h:275
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition: pe_types.h:54
gchar * pcmk__native_output_string(pe_resource_t *rsc, const char *name, pe_node_t *node, long options, const char *target_role, bool show_nodes)
Definition: native.c:544
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition: agents.c:31
gboolean crm_is_true(const char *s)
Definition: strings.c:415
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:20
gboolean(* active)(pe_resource_t *, gboolean)
Definition: pe_types.h:52
pe_node_t * pe__find_active_requires(const pe_resource_t *rsc, unsigned int *count)
Definition: complex.c:1079
#define ID(x)
Definition: msg_xml.h:456
#define pe_err(fmt...)
Definition: internal.h:22
char * name
Definition: pcmk_fence.c:31
gboolean native_unpack(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: native.c:197
int pe__common_output_text(pcmk__output_t *out, pe_resource_t *rsc, const char *name, pe_node_t *node, long options)
Definition: native.c:732
gboolean unclean
Definition: pe_types.h:217
#define pe_rsc_managed
Definition: pe_types.h:249
#define pe_rsc_orphan
Definition: pe_types.h:248
gboolean online
Definition: pe_types.h:213
uint64_t flags
Definition: remote.c:149
match resource active on specified node
Definition: pe_types.h:87
pe_resource_t * parent
Definition: pe_types.h:327
void(*) void(* list_item)(pcmk__output_t *out, const char *name, const char *format,...) G_GNUC_PRINTF(3
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:18
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:266
char * id
Definition: pe_types.h:320
GHashTable * allowed_nodes
Definition: pe_types.h:367
match base name of anonymous clone instances
Definition: pe_types.h:85
#define CRMD_ACTION_STATUS
Definition: crm.h:190