pacemaker  2.0.2-debe490
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-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #include <crm/pengine/rules.h>
11 #include <crm/pengine/status.h>
12 #include <crm/pengine/complex.h>
13 #include <crm/pengine/internal.h>
14 #include <unpack.h>
15 #include <crm/msg_xml.h>
16 #include <pe_status_private.h>
17 
18 #define VARIANT_NATIVE 1
19 #include "./variant.h"
20 
25 static bool
26 is_multiply_active(pe_resource_t *rsc)
27 {
28  unsigned int count = 0;
29 
30  if (rsc->variant == pe_native) {
31  pe__find_active_requires(rsc, &count);
32  }
33  return count > 1;
34 }
35 
36 void
38 {
39  GListPtr gIter = rsc->running_on;
40 
41  CRM_CHECK(node != NULL, return);
42  for (; gIter != NULL; gIter = gIter->next) {
43  node_t *a_node = (node_t *) gIter->data;
44 
45  CRM_CHECK(a_node != NULL, return);
46  if (safe_str_eq(a_node->details->id, node->details->id)) {
47  return;
48  }
49  }
50 
51  pe_rsc_trace(rsc, "Adding %s to %s %s", rsc->id, node->details->uname,
52  is_set(rsc->flags, pe_rsc_managed)?"":"(unmanaged)");
53 
54  rsc->running_on = g_list_append(rsc->running_on, node);
55  if (rsc->variant == pe_native) {
56  node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
57  }
58 
59  if (rsc->variant == pe_native && node->details->maintenance) {
61  }
62 
63  if (is_not_set(rsc->flags, pe_rsc_managed)) {
64  resource_t *p = rsc->parent;
65 
66  pe_rsc_info(rsc, "resource %s isn't managed", rsc->id);
67  resource_location(rsc, node, INFINITY, "not_managed_default", data_set);
68 
69  while(p && node->details->online) {
70  /* add without the additional location constraint */
71  p->running_on = g_list_append(p->running_on, node);
72  p = p->parent;
73  }
74  return;
75  }
76 
77  if (is_multiply_active(rsc)) {
78  switch (rsc->recovery_type) {
79  case recovery_stop_only:
80  {
81  GHashTableIter gIter;
82  node_t *local_node = NULL;
83 
84  /* make sure it doesn't come up again */
85  if (rsc->allowed_nodes != NULL) {
86  g_hash_table_destroy(rsc->allowed_nodes);
87  }
88  rsc->allowed_nodes = node_hash_from_list(data_set->nodes);
89  g_hash_table_iter_init(&gIter, rsc->allowed_nodes);
90  while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
91  local_node->weight = -INFINITY;
92  }
93  }
94  break;
96  break;
97  case recovery_block:
99  set_bit(rsc->flags, pe_rsc_block);
100 
101  /* If the resource belongs to a group or bundle configured with
102  * multiple-active=block, block the entire entity.
103  */
104  if (rsc->parent
105  && (rsc->parent->variant == pe_group || rsc->parent->variant == pe_container)
106  && rsc->parent->recovery_type == recovery_block) {
107  GListPtr gIter = rsc->parent->children;
108 
109  for (; gIter != NULL; gIter = gIter->next) {
110  resource_t *child = (resource_t *) gIter->data;
111 
112  clear_bit(child->flags, pe_rsc_managed);
113  set_bit(child->flags, pe_rsc_block);
114  }
115  }
116  break;
117  }
118  crm_debug("%s is active on multiple nodes including %s: %s",
119  rsc->id, node->details->uname,
120  recovery2text(rsc->recovery_type));
121 
122  } else {
123  pe_rsc_trace(rsc, "Resource %s is active on: %s", rsc->id, node->details->uname);
124  }
125 
126  if (rsc->parent != NULL) {
127  native_add_running(rsc->parent, node, data_set);
128  }
129 }
130 
131 static void
132 recursive_clear_unique(pe_resource_t *rsc)
133 {
136 
137  for (GList *child = rsc->children; child != NULL; child = child->next) {
138  recursive_clear_unique((pe_resource_t *) child->data);
139  }
140 }
141 
142 gboolean
144 {
145  resource_t *parent = uber_parent(rsc);
146  native_variant_data_t *native_data = NULL;
147  const char *standard = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
148  uint32_t ra_caps = pcmk_get_ra_caps(standard);
149 
150  pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
151 
152  native_data = calloc(1, sizeof(native_variant_data_t));
153  rsc->variant_opaque = native_data;
154 
155  // Only some agent standards support unique and promotable clones
156  if (is_not_set(ra_caps, pcmk_ra_cap_unique)
157  && is_set(rsc->flags, pe_rsc_unique) && pe_rsc_is_clone(parent)) {
158 
159  /* @COMPAT We should probably reject this situation as an error (as we
160  * do for promotable below) rather than warn and convert, but that would
161  * be a backward-incompatible change that we should probably do with a
162  * transform at a schema major version bump.
163  */
164  pe__force_anon(standard, parent, rsc->id, data_set);
165 
166  /* Clear globally-unique on the parent and all its descendents unpacked
167  * so far (clearing the parent should make any future children unpacking
168  * correct). We have to clear this resource explicitly because it isn't
169  * hooked into the parent's children yet.
170  */
171  recursive_clear_unique(parent);
172  recursive_clear_unique(rsc);
173  }
174  if (is_not_set(ra_caps, pcmk_ra_cap_promotable)
175  && is_set(parent->flags, pe_rsc_promotable)) {
176 
177  pe_err("Resource %s is of type %s and therefore "
178  "cannot be used as a promotable clone resource",
179  rsc->id, standard);
180  return FALSE;
181  }
182  return TRUE;
183 }
184 
185 static bool
186 rsc_is_on_node(resource_t *rsc, const node_t *node, int flags)
187 {
188  pe_rsc_trace(rsc, "Checking whether %s is on %s",
189  rsc->id, node->details->uname);
190 
191  if (is_set(flags, pe_find_current) && rsc->running_on) {
192 
193  for (GListPtr iter = rsc->running_on; iter; iter = iter->next) {
194  node_t *loc = (node_t *) iter->data;
195 
196  if (loc->details == node->details) {
197  return TRUE;
198  }
199  }
200 
201  } else if (is_set(flags, pe_find_inactive) && (rsc->running_on == NULL)) {
202  return TRUE;
203 
204  } else if (is_not_set(flags, pe_find_current) && rsc->allocated_to
205  && (rsc->allocated_to->details == node->details)) {
206  return TRUE;
207  }
208  return FALSE;
209 }
210 
211 resource_t *
212 native_find_rsc(resource_t * rsc, const char *id, const node_t *on_node,
213  int flags)
214 {
215  bool match = FALSE;
216  resource_t *result = NULL;
217 
218  CRM_CHECK(id && rsc && rsc->id, return NULL);
219 
220  if (flags & pe_find_clone) {
221  const char *rid = ID(rsc->xml);
222 
223  if (!pe_rsc_is_clone(uber_parent(rsc))) {
224  match = FALSE;
225 
226  } else if (!strcmp(id, rsc->id) || safe_str_eq(id, rid)) {
227  match = TRUE;
228  }
229 
230  } else if (!strcmp(id, rsc->id)) {
231  match = TRUE;
232 
233  } else if (is_set(flags, pe_find_renamed)
234  && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
235  match = TRUE;
236 
237  } else if (is_set(flags, pe_find_any)
238  || (is_set(flags, pe_find_anon)
239  && is_not_set(rsc->flags, pe_rsc_unique))) {
240  match = pe_base_name_eq(rsc, id);
241  }
242 
243  if (match && on_node) {
244  bool match_node = rsc_is_on_node(rsc, on_node, flags);
245 
246  if (match_node == FALSE) {
247  match = FALSE;
248  }
249  }
250 
251  if (match) {
252  return rsc;
253  }
254 
255  for (GListPtr gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
256  resource_t *child = (resource_t *) gIter->data;
257 
258  result = rsc->fns->find_rsc(child, id, on_node, flags);
259  if (result) {
260  return result;
261  }
262  }
263  return NULL;
264 }
265 
266 char *
267 native_parameter(resource_t * rsc, node_t * node, gboolean create, const char *name,
268  pe_working_set_t * data_set)
269 {
270  char *value_copy = NULL;
271  const char *value = NULL;
272  GHashTable *hash = NULL;
273  GHashTable *local_hash = NULL;
274 
275  CRM_CHECK(rsc != NULL, return NULL);
276  CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
277 
278  pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
279 
280  if (create || g_hash_table_size(rsc->parameters) == 0) {
281  if (node != NULL) {
282  pe_rsc_trace(rsc, "Creating hash with node %s", node->details->uname);
283  } else {
284  pe_rsc_trace(rsc, "Creating default hash");
285  }
286 
287  local_hash = crm_str_table_new();
288 
289  get_rsc_attributes(local_hash, rsc, node, data_set);
290 
291  hash = local_hash;
292  } else {
293  hash = rsc->parameters;
294  }
295 
296  value = g_hash_table_lookup(hash, name);
297  if (value == NULL) {
298  /* try meta attributes instead */
299  value = g_hash_table_lookup(rsc->meta, name);
300  }
301 
302  if (value != NULL) {
303  value_copy = strdup(value);
304  }
305  if (local_hash != NULL) {
306  g_hash_table_destroy(local_hash);
307  }
308  return value_copy;
309 }
310 
311 gboolean
312 native_active(resource_t * rsc, gboolean all)
313 {
314  GListPtr gIter = rsc->running_on;
315 
316  for (; gIter != NULL; gIter = gIter->next) {
317  node_t *a_node = (node_t *) gIter->data;
318 
319  if (a_node->details->unclean) {
320  crm_debug("Resource %s: node %s is unclean", rsc->id, a_node->details->uname);
321  return TRUE;
322  } else if (a_node->details->online == FALSE) {
323  crm_debug("Resource %s: node %s is offline", rsc->id, a_node->details->uname);
324  } else {
325  crm_debug("Resource %s active on %s", rsc->id, a_node->details->uname);
326  return TRUE;
327  }
328  }
329 
330  return FALSE;
331 }
332 
333 struct print_data_s {
334  long options;
335  void *print_data;
336 };
337 
338 static void
339 native_print_attr(gpointer key, gpointer value, gpointer user_data)
340 {
341  long options = ((struct print_data_s *)user_data)->options;
342  void *print_data = ((struct print_data_s *)user_data)->print_data;
343 
344  status_print("Option: %s = %s\n", (char *)key, (char *)value);
345 }
346 
347 static const char *
348 native_pending_state(resource_t * rsc)
349 {
350  const char *pending_state = NULL;
351 
353  pending_state = "Starting";
354 
355  } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STOP)) {
356  pending_state = "Stopping";
357 
358  } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATE)) {
359  pending_state = "Migrating";
360 
361  } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATED)) {
362  /* Work might be done in here. */
363  pending_state = "Migrating";
364 
365  } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_PROMOTE)) {
366  pending_state = "Promoting";
367 
368  } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_DEMOTE)) {
369  pending_state = "Demoting";
370  }
371 
372  return pending_state;
373 }
374 
375 static const char *
376 native_pending_task(resource_t * rsc)
377 {
378  const char *pending_task = NULL;
379 
381  pending_task = "Monitoring";
382 
383  /* Pending probes are not printed, even if pending
384  * operations are requested. If someone ever requests that
385  * behavior, uncomment this and the corresponding part of
386  * unpack.c:unpack_rsc_op().
387  */
388  /*
389  } else if (safe_str_eq(rsc->pending_task, "probe")) {
390  pending_task = "Checking";
391  */
392  }
393 
394  return pending_task;
395 }
396 
397 static enum rsc_role_e
398 native_displayable_role(resource_t *rsc)
399 {
400  enum rsc_role_e role = rsc->role;
401 
402  if ((role == RSC_ROLE_STARTED)
403  && is_set(uber_parent(rsc)->flags, pe_rsc_promotable)) {
404 
405  role = RSC_ROLE_SLAVE;
406  }
407  return role;
408 }
409 
410 static const char *
411 native_displayable_state(resource_t *rsc, long options)
412 {
413  const char *rsc_state = NULL;
414 
415  if (options & pe_print_pending) {
416  rsc_state = native_pending_state(rsc);
417  }
418  if (rsc_state == NULL) {
419  rsc_state = role2text(native_displayable_role(rsc));
420  }
421  return rsc_state;
422 }
423 
424 static void
425 native_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data)
426 {
427  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
428  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
429  const char *rsc_state = native_displayable_state(rsc, options);
430  const char *target_role = NULL;
431 
432  /* resource information. */
433  status_print("%s<resource ", pre_text);
434  status_print("id=\"%s\" ", rsc_printable_id(rsc));
435  status_print("resource_agent=\"%s%s%s:%s\" ",
436  class,
437  prov ? "::" : "", prov ? prov : "", crm_element_value(rsc->xml, XML_ATTR_TYPE));
438 
439  status_print("role=\"%s\" ", rsc_state);
440  if (rsc->meta) {
441  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
442  }
443  if (target_role) {
444  status_print("target_role=\"%s\" ", target_role);
445  }
446  status_print("active=\"%s\" ", rsc->fns->active(rsc, TRUE) ? "true" : "false");
447  status_print("orphaned=\"%s\" ", is_set(rsc->flags, pe_rsc_orphan) ? "true" : "false");
448  status_print("blocked=\"%s\" ", is_set(rsc->flags, pe_rsc_block) ? "true" : "false");
449  status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false");
450  status_print("failed=\"%s\" ", is_set(rsc->flags, pe_rsc_failed) ? "true" : "false");
451  status_print("failure_ignored=\"%s\" ",
452  is_set(rsc->flags, pe_rsc_failure_ignored) ? "true" : "false");
453  status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
454 
455  if (options & pe_print_pending) {
456  const char *pending_task = native_pending_task(rsc);
457 
458  if (pending_task) {
459  status_print("pending=\"%s\" ", pending_task);
460  }
461  }
462 
463  if (options & pe_print_dev) {
464  status_print("provisional=\"%s\" ",
465  is_set(rsc->flags, pe_rsc_provisional) ? "true" : "false");
466  status_print("runnable=\"%s\" ", is_set(rsc->flags, pe_rsc_runnable) ? "true" : "false");
467  status_print("priority=\"%f\" ", (double)rsc->priority);
468  status_print("variant=\"%s\" ", crm_element_name(rsc->xml));
469  }
470 
471  /* print out the nodes this resource is running on */
472  if (options & pe_print_rsconly) {
473  status_print("/>\n");
474  /* do nothing */
475  } else if (rsc->running_on != NULL) {
476  GListPtr gIter = rsc->running_on;
477 
478  status_print(">\n");
479  for (; gIter != NULL; gIter = gIter->next) {
480  node_t *node = (node_t *) gIter->data;
481 
482  status_print("%s <node name=\"%s\" id=\"%s\" cached=\"%s\"/>\n", pre_text,
483  node->details->uname, node->details->id,
484  node->details->online ? "false" : "true");
485  }
486  status_print("%s</resource>\n", pre_text);
487  } else {
488  status_print("/>\n");
489  }
490 }
491 
492 /* making this inline rather than a macro prevents a coverity "unreachable"
493  * warning on the first usage
494  */
495 static inline const char *
496 comma_if(int i)
497 {
498  return i? ", " : "";
499 }
500 
501 void
502 common_print(resource_t * rsc, const char *pre_text, const char *name, node_t *node, long options, void *print_data)
503 {
504  const char *desc = NULL;
505  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
506  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
507  const char *target_role = NULL;
508  enum rsc_role_e role = native_displayable_role(rsc);
509 
510  int offset = 0;
511  int flagOffset = 0;
512  char buffer[LINE_MAX];
513  char flagBuffer[LINE_MAX];
514 
515  CRM_ASSERT(rsc->variant == pe_native);
516  CRM_ASSERT(kind != NULL);
517 
518  if (rsc->meta) {
519  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
520  if (crm_is_true(is_internal) && is_not_set(options, pe_print_implicit)) {
521  crm_trace("skipping print of internal resource %s", rsc->id);
522  return;
523  }
524  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
525  }
526 
527  if (pre_text == NULL && (options & pe_print_printf)) {
528  pre_text = " ";
529  }
530 
531  if (options & pe_print_xml) {
532  native_print_xml(rsc, pre_text, options, print_data);
533  return;
534  }
535 
536  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
537  node = NULL;
538  }
539 
540  if (options & pe_print_html) {
541  if (is_not_set(rsc->flags, pe_rsc_managed)) {
542  status_print("<font color=\"yellow\">");
543 
544  } else if (is_set(rsc->flags, pe_rsc_failed)) {
545  status_print("<font color=\"red\">");
546 
547  } else if (rsc->variant == pe_native && (rsc->running_on == NULL)) {
548  status_print("<font color=\"red\">");
549 
550  } else if (g_list_length(rsc->running_on) > 1) {
551  status_print("<font color=\"orange\">");
552 
553  } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) {
554  status_print("<font color=\"yellow\">");
555 
556  } else {
557  status_print("<font color=\"green\">");
558  }
559  }
560 
561  if(pre_text) {
562  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", pre_text);
563  }
564  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", name);
565  offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class);
566  if (is_set(pcmk_get_ra_caps(class), pcmk_ra_cap_provider)) {
567  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
568  offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
569  }
570  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s):\t", kind);
571  if(is_set(rsc->flags, pe_rsc_orphan)) {
572  offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED ");
573  }
574  if(role > RSC_ROLE_SLAVE && is_set(rsc->flags, pe_rsc_failed)) {
575  offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s", role2text(role));
576  } else if(is_set(rsc->flags, pe_rsc_failed)) {
577  offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED");
578  } else {
579  const char *rsc_state = native_displayable_state(rsc, options);
580 
581  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_state);
582  }
583 
584  if(node) {
585  offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", node->details->uname);
586 
587  if (node->details->online == FALSE && node->details->unclean) {
588  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
589  "%sUNCLEAN", comma_if(flagOffset));
590  }
591  }
592 
593  if (options & pe_print_pending) {
594  const char *pending_task = native_pending_task(rsc);
595 
596  if (pending_task) {
597  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
598  "%s%s", comma_if(flagOffset), pending_task);
599  }
600  }
601 
602  if (target_role) {
603  enum rsc_role_e target_role_e = text2role(target_role);
604 
605  /* Ignore target role Started, as it is the default anyways
606  * (and would also allow a Master to be Master).
607  * Show if target role limits our abilities. */
608  if (target_role_e == RSC_ROLE_STOPPED) {
609  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
610  "%sdisabled", comma_if(flagOffset));
611  rsc->cluster->disabled_resources++;
612 
613  } else if (is_set(uber_parent(rsc)->flags, pe_rsc_promotable)
614  && target_role_e == RSC_ROLE_SLAVE) {
615  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
616  "%starget-role:%s", comma_if(flagOffset), target_role);
617  rsc->cluster->disabled_resources++;
618  }
619  }
620 
621  if (is_set(rsc->flags, pe_rsc_block)) {
622  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
623  "%sblocked", comma_if(flagOffset));
624  rsc->cluster->blocked_resources++;
625 
626  } else if (is_not_set(rsc->flags, pe_rsc_managed)) {
627  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
628  "%sunmanaged", comma_if(flagOffset));
629  }
630 
631  if(is_set(rsc->flags, pe_rsc_failure_ignored)) {
632  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
633  "%sfailure ignored", comma_if(flagOffset));
634  }
635 
636  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
637  desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
638  }
639 
640  CRM_LOG_ASSERT(offset > 0);
641  if(flagOffset > 0) {
642  status_print("%s (%s)%s%s", buffer, flagBuffer, desc?" ":"", desc?desc:"");
643  } else {
644  status_print("%s%s%s", buffer, desc?" ":"", desc?desc:"");
645  }
646 
647 #if CURSES_ENABLED
648  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
649  /* Done */
650 
651  } else if (options & pe_print_ncurses) {
652  /* coverity[negative_returns] False positive */
653  move(-1, 0);
654  }
655 #endif
656 
657  if (options & pe_print_html) {
658  status_print(" </font> ");
659  }
660 
661  if ((options & pe_print_rsconly)) {
662 
663  } else if (g_list_length(rsc->running_on) > 1) {
664  GListPtr gIter = rsc->running_on;
665  int counter = 0;
666 
667  if (options & pe_print_html) {
668  status_print("<ul>\n");
669  } else if ((options & pe_print_printf)
670  || (options & pe_print_ncurses)) {
671  status_print("[");
672  }
673 
674  for (; gIter != NULL; gIter = gIter->next) {
675  node_t *n = (node_t *) gIter->data;
676 
677  counter++;
678 
679  if (options & pe_print_html) {
680  status_print("<li>\n%s", n->details->uname);
681 
682  } else if ((options & pe_print_printf)
683  || (options & pe_print_ncurses)) {
684  status_print(" %s", n->details->uname);
685 
686  } else if ((options & pe_print_log)) {
687  status_print("\t%d : %s", counter, n->details->uname);
688 
689  } else {
690  status_print("%s", n->details->uname);
691  }
692  if (options & pe_print_html) {
693  status_print("</li>\n");
694 
695  }
696  }
697 
698  if (options & pe_print_html) {
699  status_print("</ul>\n");
700  } else if ((options & pe_print_printf)
701  || (options & pe_print_ncurses)) {
702  status_print(" ]");
703  }
704  }
705 
706  if (options & pe_print_html) {
707  status_print("<br/>\n");
708  } else if (options & pe_print_suppres_nl) {
709  /* nothing */
710  } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
711  status_print("\n");
712  }
713 
714  if (options & pe_print_details) {
715  struct print_data_s pdata;
716 
717  pdata.options = options;
718  pdata.print_data = print_data;
719  g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata);
720  }
721 
722  if (options & pe_print_dev) {
723  GHashTableIter iter;
724  node_t *n = NULL;
725 
726  status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text,
727  is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "",
728  is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ",
729  crm_element_name(rsc->xml), (double)rsc->priority);
730  status_print("%s\tAllowed Nodes", pre_text);
731  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
732  while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
733  status_print("%s\t * %s %d", pre_text, n->details->uname, n->weight);
734  }
735  }
736 
737  if (options & pe_print_max_details) {
738  GHashTableIter iter;
739  node_t *n = NULL;
740 
741  status_print("%s\t=== Allowed Nodes\n", pre_text);
742  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
743  while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
744  print_node("\t", n, FALSE);
745  }
746  }
747 }
748 
749 void
750 native_print(resource_t * rsc, const char *pre_text, long options, void *print_data)
751 {
752  node_t *node = NULL;
753 
754  CRM_ASSERT(rsc->variant == pe_native);
755  if (options & pe_print_xml) {
756  native_print_xml(rsc, pre_text, options, print_data);
757  return;
758  }
759 
760  node = pe__current_node(rsc);
761 
762  if (node == NULL) {
763  // This is set only if a non-probe action is pending on this node
764  node = rsc->pending_node;
765  }
766 
767  common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
768 }
769 
770 void
772 {
773  pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
774  common_free(rsc);
775 }
776 
777 enum rsc_role_e
778 native_resource_state(const resource_t * rsc, gboolean current)
779 {
780  enum rsc_role_e role = rsc->next_role;
781 
782  if (current) {
783  role = rsc->role;
784  }
785  pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
786  return role;
787 }
788 
799 pe_node_t *
800 native_location(const pe_resource_t *rsc, GList **list, int current)
801 {
802  node_t *one = NULL;
803  GListPtr result = NULL;
804 
805  if (rsc->children) {
806  GListPtr gIter = rsc->children;
807 
808  for (; gIter != NULL; gIter = gIter->next) {
809  resource_t *child = (resource_t *) gIter->data;
810 
811  child->fns->location(child, &result, current);
812  }
813 
814  } else if (current) {
815 
816  if (rsc->running_on) {
817  result = g_list_copy(rsc->running_on);
818  }
819  if ((current == 2) && rsc->pending_node
820  && !pe_find_node_id(result, rsc->pending_node->details->id)) {
821  result = g_list_append(result, rsc->pending_node);
822  }
823 
824  } else if (current == FALSE && rsc->allocated_to) {
825  result = g_list_append(NULL, rsc->allocated_to);
826  }
827 
828  if (result && (result->next == NULL)) {
829  one = result->data;
830  }
831 
832  if (list) {
833  GListPtr gIter = result;
834 
835  for (; gIter != NULL; gIter = gIter->next) {
836  node_t *node = (node_t *) gIter->data;
837 
838  if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
839  *list = g_list_append(*list, node);
840  }
841  }
842  }
843 
844  g_list_free(result);
845  return one;
846 }
847 
848 static void
849 get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_table)
850 {
851  GListPtr gIter = rsc_list;
852 
853  for (; gIter != NULL; gIter = gIter->next) {
854  resource_t *rsc = (resource_t *) gIter->data;
855 
856  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
857  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
858 
859  int offset = 0;
860  char buffer[LINE_MAX];
861 
862  int *rsc_counter = NULL;
863  int *active_counter = NULL;
864 
865  if (rsc->variant != pe_native) {
866  continue;
867  }
868 
869  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
870  if (is_set(pcmk_get_ra_caps(class), pcmk_ra_cap_provider)) {
871  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
872  offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
873  }
874  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
875  CRM_LOG_ASSERT(offset > 0);
876 
877  if (rsc_table) {
878  rsc_counter = g_hash_table_lookup(rsc_table, buffer);
879  if (rsc_counter == NULL) {
880  rsc_counter = calloc(1, sizeof(int));
881  *rsc_counter = 0;
882  g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
883  }
884  (*rsc_counter)++;
885  }
886 
887  if (active_table) {
888  GListPtr gIter2 = rsc->running_on;
889 
890  for (; gIter2 != NULL; gIter2 = gIter2->next) {
891  node_t *node = (node_t *) gIter2->data;
892  GHashTable *node_table = NULL;
893 
894  if (node->details->unclean == FALSE && node->details->online == FALSE) {
895  continue;
896  }
897 
898  node_table = g_hash_table_lookup(active_table, node->details->uname);
899  if (node_table == NULL) {
900  node_table = crm_str_table_new();
901  g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
902  }
903 
904  active_counter = g_hash_table_lookup(node_table, buffer);
905  if (active_counter == NULL) {
906  active_counter = calloc(1, sizeof(int));
907  *active_counter = 0;
908  g_hash_table_insert(node_table, strdup(buffer), active_counter);
909  }
910  (*active_counter)++;
911  }
912  }
913  }
914 }
915 
916 static void
917 destroy_node_table(gpointer data)
918 {
919  GHashTable *node_table = data;
920 
921  if (node_table) {
922  g_hash_table_destroy(node_table);
923  }
924 }
925 
926 void
927 print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options,
928  void *print_data, gboolean print_all)
929 {
930  GHashTable *rsc_table = crm_str_table_new();
931  GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal,
932  free, destroy_node_table);
933  GHashTableIter hash_iter;
934  char *type = NULL;
935  int *rsc_counter = NULL;
936 
937  get_rscs_brief(rsc_list, rsc_table, active_table);
938 
939  g_hash_table_iter_init(&hash_iter, rsc_table);
940  while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
941  GHashTableIter hash_iter2;
942  char *node_name = NULL;
943  GHashTable *node_table = NULL;
944  int active_counter_all = 0;
945 
946  g_hash_table_iter_init(&hash_iter2, active_table);
947  while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
948  int *active_counter = g_hash_table_lookup(node_table, type);
949 
950  if (active_counter == NULL || *active_counter == 0) {
951  continue;
952 
953  } else {
954  active_counter_all += *active_counter;
955  }
956 
957  if (options & pe_print_rsconly) {
958  node_name = NULL;
959  }
960 
961  if (options & pe_print_html) {
962  status_print("<li>\n");
963  }
964 
965  if (print_all) {
966  status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
967  active_counter ? *active_counter : 0,
968  rsc_counter ? *rsc_counter : 0, type,
969  active_counter && (*active_counter > 0) && node_name ? node_name : "");
970  } else {
971  status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
972  active_counter ? *active_counter : 0, type,
973  active_counter && (*active_counter > 0) && node_name ? node_name : "");
974  }
975 
976  if (options & pe_print_html) {
977  status_print("</li>\n");
978  }
979  }
980 
981  if (print_all && active_counter_all == 0) {
982  if (options & pe_print_html) {
983  status_print("<li>\n");
984  }
985 
986  status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
987  active_counter_all,
988  rsc_counter ? *rsc_counter : 0, type);
989 
990  if (options & pe_print_html) {
991  status_print("</li>\n");
992  }
993  }
994  }
995 
996  if (rsc_table) {
997  g_hash_table_destroy(rsc_table);
998  rsc_table = NULL;
999  }
1000  if (active_table) {
1001  g_hash_table_destroy(active_table);
1002  active_table = NULL;
1003  }
1004 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:156
GListPtr nodes
Definition: pe_types.h:133
#define CRMD_ACTION_MIGRATED
Definition: crm.h:147
#define INFINITY
Definition: crm.h:73
#define XML_ATTR_TYPE
Definition: msg_xml.h:99
#define pe_rsc_runnable
Definition: pe_types.h:235
enum rsc_role_e role
Definition: pe_types.h:333
#define XML_BOOLEAN_FALSE
Definition: msg_xml.h:108
xmlNode * xml
Definition: pe_types.h:286
enum rsc_role_e next_role
Definition: pe_types.h:334
char * native_parameter(resource_t *rsc, node_t *node, gboolean create, const char *name, pe_working_set_t *data_set)
Definition: native.c:267
pe_node_t * native_location(const pe_resource_t *rsc, GList **list, int current)
Definition: native.c:800
void pe__force_anon(const char *standard, pe_resource_t *rsc, const char *rid, pe_working_set_t *data_set)
Definition: clone.c:21
GHashTable * meta
Definition: pe_types.h:336
match resource not running anywhere
Definition: pe_types.h:83
#define pe_rsc_unique
Definition: pe_types.h:223
void common_free(resource_t *rsc)
Definition: complex.c:760
resource_object_functions_t * fns
Definition: pe_types.h:295
GHashTable * parameters
Definition: pe_types.h:337
#define status_print(fmt, args...)
Definition: unpack.h:67
#define CRMD_ACTION_PROMOTE
Definition: crm.h:155
void print_node(const char *pre_text, node_t *node, gboolean details)
Definition: utils.c:1253
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:142
#define clear_bit(word, bit)
Definition: crm_internal.h:168
pe_node_t * allocated_to
Definition: pe_types.h:326
void native_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:750
void print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options, void *print_data, gboolean print_all)
Definition: native.c:927
resource_t * native_find_rsc(resource_t *rsc, const char *id, const node_t *node, int flags)
Definition: native.c:212
char * pending_task
Definition: pe_types.h:309
pe_node_t * pe_find_node_id(GListPtr node_list, const char *id)
Definition: status.c:396
#define CRMD_ACTION_START
Definition: crm.h:149
#define pe_rsc_provisional
Definition: pe_types.h:227
const char * role2text(enum rsc_role_e role)
Definition: common.c:329
#define CRMD_ACTION_STOP
Definition: crm.h:152
int weight
Definition: pe_types.h:210
#define CRMD_ACTION_DEMOTE
Definition: crm.h:157
#define set_bit(word, bit)
Definition: crm_internal.h:167
#define pe_rsc_failed
Definition: pe_types.h:234
#define crm_debug(fmt, args...)
Definition: logging.h:245
void native_add_running(resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: native.c:37
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:746
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:423
pe_resource_t *(* find_rsc)(pe_resource_t *parent, const char *search, const pe_node_t *node, int flags)
Definition: pe_types.h:44
match only clone instances
Definition: pe_types.h:81
#define crm_trace(fmt, args...)
Definition: logging.h:246
struct pe_node_shared_s * details
Definition: pe_types.h:213
GListPtr running_on
Definition: pe_types.h:329
enum rsc_recovery_type recovery_type
Definition: pe_types.h:298
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:230
unsigned long long flags
Definition: pe_types.h:311
const char * uname
Definition: pe_types.h:179
#define pe_rsc_promotable
Definition: pe_types.h:225
char * clone_name
Definition: pe_types.h:285
#define XML_ATTR_DESC
Definition: msg_xml.h:95
enum rsc_role_e native_resource_state(const resource_t *rsc, gboolean current)
Definition: native.c:778
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition: agents.c:29
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:196
gboolean native_active(resource_t *rsc, gboolean all)
Definition: native.c:312
match base name of any clone instance
Definition: pe_types.h:84
enum rsc_role_e text2role(const char *role)
Definition: common.c:350
enum pe_obj_types variant
Definition: pe_types.h:293
const char * id
Definition: pe_types.h:178
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:197
void common_print(resource_t *rsc, const char *pre_text, const char *name, node_t *node, long options, void *print_data)
Definition: native.c:502
match resource ID or LRM history ID
Definition: pe_types.h:79
GListPtr running_rsc
Definition: pe_types.h:201
GHashTable * node_hash_from_list(GListPtr list)
Definition: utils.c:174
void get_rsc_attributes(GHashTable *meta_hash, pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Definition: complex.c:127
Cluster status and scheduling.
pe_node_t * pending_node
Definition: pe_types.h:346
GListPtr children
Definition: pe_types.h:340
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:406
void * variant_opaque
Definition: pe_types.h:294
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1565
#define CRM_ASSERT(expr)
Definition: results.h:42
const char * rsc_printable_id(pe_resource_t *rsc)
Definition: utils.c:2137
#define CRMD_ACTION_MIGRATE
Definition: crm.h:146
#define crm_str_hash
Definition: util.h:60
#define XML_RSC_ATTR_INTERNAL_RSC
Definition: msg_xml.h:206
char data[0]
Definition: internal.h:92
rsc_role_e
Definition: common.h:86
#define pe_rsc_block
Definition: pe_types.h:219
gboolean maintenance
Definition: pe_types.h:192
void native_free(resource_t *rsc)
Definition: native.c:771
#define pe_rsc_failure_ignored
Definition: pe_types.h:242
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition: pe_types.h:52
gboolean native_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: native.c:143
gboolean crm_is_true(const char *s)
Definition: strings.c:172
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:18
gboolean(* active)(pe_resource_t *, gboolean)
Definition: pe_types.h:50
pe_node_t * pe__find_active_requires(const pe_resource_t *rsc, unsigned int *count)
Definition: complex.c:922
#define ID(x)
Definition: msg_xml.h:414
#define pe_err(fmt...)
Definition: internal.h:20
#define safe_str_eq(a, b)
Definition: util.h:59
gboolean unclean
Definition: pe_types.h:187
GList * GListPtr
Definition: crm.h:192
#define pe_rsc_managed
Definition: pe_types.h:218
#define pe_rsc_orphan
Definition: pe_types.h:217
gboolean online
Definition: pe_types.h:183
uint64_t flags
Definition: remote.c:148
match resource active on specified node
Definition: pe_types.h:82
pe_resource_t * parent
Definition: pe_types.h:291
enum crm_ais_msg_types type
Definition: internal.h:85
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:16
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:229
char * id
Definition: pe_types.h:284
GHashTable * allowed_nodes
Definition: pe_types.h:331
match base name of anonymous clone instances
Definition: pe_types.h:80
#define CRMD_ACTION_STATUS
Definition: crm.h:163