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