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