pacemaker  1.1.15-e174ec8
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 group that the resource belongs to is configured with multiple-active=block, */
95  /* block the whole group. */
96  if (rsc->parent
97  && rsc->parent->variant == pe_group
98  && rsc->parent->recovery_type == recovery_block) {
99  GListPtr gIter = rsc->parent->children;
100 
101  for (; gIter != NULL; gIter = gIter->next) {
102  resource_t *child = (resource_t *) gIter->data;
103 
104  clear_bit(child->flags, pe_rsc_managed);
105  set_bit(child->flags, pe_rsc_block);
106  }
107  }
108  break;
109  }
110  crm_debug("%s is active on %d nodes including %s: %s",
111  rsc->id, g_list_length(rsc->running_on), node->details->uname,
112  recovery2text(rsc->recovery_type));
113 
114  } else {
115  pe_rsc_trace(rsc, "Resource %s is active on: %s", rsc->id, node->details->uname);
116  }
117 
118  if (rsc->parent != NULL) {
119  native_add_running(rsc->parent, node, data_set);
120  }
121 }
122 
123 extern void force_non_unique_clone(resource_t * rsc, const char *rid, pe_working_set_t * data_set);
124 
125 gboolean
127 {
128  resource_t *parent = uber_parent(rsc);
129  native_variant_data_t *native_data = NULL;
130  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
131 
132  pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
133 
134  native_data = calloc(1, sizeof(native_variant_data_t));
135  rsc->variant_opaque = native_data;
136 
137  if (is_set(rsc->flags, pe_rsc_unique) && rsc->parent) {
138 
139  if (safe_str_eq(class, "lsb")) {
140  resource_t *top = uber_parent(rsc);
141 
142  force_non_unique_clone(top, rsc->id, data_set);
143  }
144  }
145 
146  if (safe_str_eq(class, "ocf") == FALSE) {
147  const char *stateful = g_hash_table_lookup(parent->meta, "stateful");
148 
149  if (safe_str_eq(stateful, XML_BOOLEAN_TRUE)) {
150  pe_err
151  ("Resource %s is of type %s and therefore cannot be used as a master/slave resource",
152  rsc->id, class);
153  return FALSE;
154  }
155  }
156 
157  return TRUE;
158 }
159 
160 resource_t *
161 native_find_rsc(resource_t * rsc, const char *id, node_t * on_node, int flags)
162 {
163  gboolean match = FALSE;
164  resource_t *result = NULL;
165  GListPtr gIter = rsc->children;
166 
167  CRM_ASSERT(id != NULL);
168 
169  if (flags & pe_find_clone) {
170  const char *rid = ID(rsc->xml);
171 
172  if (rsc->parent == NULL) {
173  match = FALSE;
174 
175  } else if (safe_str_eq(rsc->id, id)) {
176  match = TRUE;
177 
178  } else if (safe_str_eq(rid, id)) {
179  match = TRUE;
180  }
181 
182  } else {
183  if (strcmp(rsc->id, id) == 0) {
184  match = TRUE;
185 
186  } else if (is_set(flags, pe_find_renamed)
187  && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
188  match = TRUE;
189  }
190  }
191 
192  if (match && on_node) {
193  pe_rsc_trace(rsc, "Now checking %s is on %s", rsc->id, on_node->details->uname);
194  if (is_set(flags, pe_find_current) && rsc->running_on) {
195 
196  GListPtr gIter = rsc->running_on;
197 
198  for (; gIter != NULL; gIter = gIter->next) {
199  node_t *loc = (node_t *) gIter->data;
200 
201  if (loc->details == on_node->details) {
202  return rsc;
203  }
204  }
205 
206  } else if (is_set(flags, pe_find_inactive) && rsc->running_on == NULL) {
207  return rsc;
208 
209  } else if (is_not_set(flags, pe_find_current) && rsc->allocated_to
210  && rsc->allocated_to->details == on_node->details) {
211  return rsc;
212  }
213 
214  } else if (match) {
215  return rsc;
216  }
217 
218  for (; gIter != NULL; gIter = gIter->next) {
219  resource_t *child = (resource_t *) gIter->data;
220 
221  result = rsc->fns->find_rsc(child, id, on_node, flags);
222  if (result) {
223  return result;
224  }
225  }
226  return NULL;
227 }
228 
229 char *
230 native_parameter(resource_t * rsc, node_t * node, gboolean create, const char *name,
231  pe_working_set_t * data_set)
232 {
233  char *value_copy = NULL;
234  const char *value = NULL;
235  GHashTable *hash = rsc->parameters;
236  GHashTable *local_hash = NULL;
237 
238  CRM_CHECK(rsc != NULL, return NULL);
239  CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
240 
241  pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
242 
243  if (create || g_hash_table_size(rsc->parameters) == 0) {
244  if (node != NULL) {
245  pe_rsc_trace(rsc, "Creating hash with node %s", node->details->uname);
246  } else {
247  pe_rsc_trace(rsc, "Creating default hash");
248  }
249 
250  local_hash = g_hash_table_new_full(crm_str_hash, g_str_equal,
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 void
364 native_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data)
365 {
366  enum rsc_role_e role = rsc->role;
367  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
368  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
369  const char *rsc_state = NULL;
370 
371  if(role == RSC_ROLE_STARTED && uber_parent(rsc)->variant == pe_master) {
372  role = RSC_ROLE_SLAVE;
373  }
374 
375  /* resource information. */
376  status_print("%s<resource ", pre_text);
377  status_print("id=\"%s\" ", rsc_printable_id(rsc));
378  status_print("resource_agent=\"%s%s%s:%s\" ",
379  class,
380  prov ? "::" : "", prov ? prov : "", crm_element_value(rsc->xml, XML_ATTR_TYPE));
381 
382  if (options & pe_print_pending) {
383  rsc_state = native_pending_state(rsc);
384  }
385  if (rsc_state == NULL) {
386  rsc_state = role2text(role);
387  }
388  status_print("role=\"%s\" ", rsc_state);
389  status_print("active=\"%s\" ", rsc->fns->active(rsc, TRUE) ? "true" : "false");
390  status_print("orphaned=\"%s\" ", is_set(rsc->flags, pe_rsc_orphan) ? "true" : "false");
391  status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false");
392  status_print("failed=\"%s\" ", is_set(rsc->flags, pe_rsc_failed) ? "true" : "false");
393  status_print("failure_ignored=\"%s\" ",
394  is_set(rsc->flags, pe_rsc_failure_ignored) ? "true" : "false");
395  status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
396 
397  if (options & pe_print_pending) {
398  const char *pending_task = native_pending_task(rsc);
399 
400  if (pending_task) {
401  status_print("pending=\"%s\" ", pending_task);
402  }
403  }
404 
405  if (options & pe_print_dev) {
406  status_print("provisional=\"%s\" ",
407  is_set(rsc->flags, pe_rsc_provisional) ? "true" : "false");
408  status_print("runnable=\"%s\" ", is_set(rsc->flags, pe_rsc_runnable) ? "true" : "false");
409  status_print("priority=\"%f\" ", (double)rsc->priority);
410  status_print("variant=\"%s\" ", crm_element_name(rsc->xml));
411  }
412 
413  /* print out the nodes this resource is running on */
414  if (options & pe_print_rsconly) {
415  status_print("/>\n");
416  /* do nothing */
417  } else if (g_list_length(rsc->running_on) > 0) {
418  GListPtr gIter = rsc->running_on;
419 
420  status_print(">\n");
421  for (; gIter != NULL; gIter = gIter->next) {
422  node_t *node = (node_t *) gIter->data;
423 
424  status_print("%s <node name=\"%s\" id=\"%s\" cached=\"%s\"/>\n", pre_text,
425  node->details->uname, node->details->id,
426  node->details->online ? "false" : "true");
427  }
428  status_print("%s</resource>\n", pre_text);
429  } else {
430  status_print("/>\n");
431  }
432 }
433 
434 
435 void
436 native_print(resource_t * rsc, const char *pre_text, long options, void *print_data)
437 {
438  node_t *node = NULL;
439  const char *desc = NULL;
440  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
441  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
442  const char *target_role = NULL;
443  enum rsc_role_e role = rsc->role;
444 
445  int offset = 0;
446  int flagOffset = 0;
447  char buffer[LINE_MAX];
448  char flagBuffer[LINE_MAX];
449 
450  CRM_ASSERT(rsc->variant == pe_native);
451  CRM_ASSERT(kind != NULL);
452 
453  if (rsc->meta) {
454  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
455  if (crm_is_true(is_internal)) {
456  crm_trace("skipping print of internal resource %s", rsc->id);
457  return;
458  }
459  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
460  }
461 
462  if(role == RSC_ROLE_STARTED && uber_parent(rsc)->variant == pe_master) {
463  role = RSC_ROLE_SLAVE;
464  }
465 
466  if (pre_text == NULL && (options & pe_print_printf)) {
467  pre_text = " ";
468  }
469 
470  if (options & pe_print_xml) {
471  native_print_xml(rsc, pre_text, options, print_data);
472  return;
473  }
474 
475  if (rsc->running_on != NULL) {
476  node = rsc->running_on->data;
477  }
478  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
479  node = NULL;
480  }
481 
482  if (options & pe_print_html) {
483  if (is_not_set(rsc->flags, pe_rsc_managed)) {
484  status_print("<font color=\"yellow\">");
485 
486  } else if (is_set(rsc->flags, pe_rsc_failed)) {
487  status_print("<font color=\"red\">");
488 
489  } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) {
490  status_print("<font color=\"red\">");
491 
492  } else if (g_list_length(rsc->running_on) > 1) {
493  status_print("<font color=\"orange\">");
494 
495  } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) {
496  status_print("<font color=\"yellow\">");
497 
498  } else {
499  status_print("<font color=\"green\">");
500  }
501  }
502 
503  if(pre_text) {
504  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", pre_text);
505  }
506  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_printable_id(rsc));
507  offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class);
508  if (safe_str_eq(class, "ocf")) {
509  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
510  offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
511  }
512  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s):\t", kind);
513  if(is_set(rsc->flags, pe_rsc_orphan)) {
514  offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED ");
515  }
516  if(role > RSC_ROLE_SLAVE && is_set(rsc->flags, pe_rsc_failed)) {
517  offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s", role2text(role));
518  } else if(is_set(rsc->flags, pe_rsc_failed)) {
519  offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED");
520  } else {
521  const char *rsc_state = NULL;
522  if (options & pe_print_pending) {
523  rsc_state = native_pending_state(rsc);
524  }
525  if (rsc_state == NULL) {
526  rsc_state = role2text(role);
527  }
528  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_state);
529  }
530 
531  if(node) {
532  offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", node->details->uname);
533 
534  if (node->details->online == FALSE && node->details->unclean) {
535  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sUNCLEAN", flagOffset?", ":"");
536  }
537  }
538 
539  if (options & pe_print_pending) {
540  const char *pending_task = native_pending_task(rsc);
541 
542  if (pending_task) {
543  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%s%s", flagOffset?", ":"", pending_task);
544  }
545  }
546 
547  if (target_role) {
548  enum rsc_role_e target_role_e = text2role(target_role);
549 
550  /* Ignore target role Started, as it is the default anyways
551  * (and would also allow a Master to be Master).
552  * Show if target role limits our abilities. */
553  if (target_role_e == RSC_ROLE_STOPPED) {
554  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sdisabled", flagOffset?", ":"");
555  rsc->cluster->disabled_resources++;
556 
557  } else if (uber_parent(rsc)->variant == pe_master
558  && target_role_e == RSC_ROLE_SLAVE) {
559  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%starget-role:%s", flagOffset?", ":"", target_role);
560  rsc->cluster->disabled_resources++;
561  }
562  }
563 
564  if (is_set(rsc->flags, pe_rsc_block)) {
565  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sblocked", flagOffset?", ":"");
566  rsc->cluster->blocked_resources++;
567 
568  } else if (is_not_set(rsc->flags, pe_rsc_managed)) {
569  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sunmanaged", flagOffset?", ":"");
570  }
571 
572  if(is_set(rsc->flags, pe_rsc_failure_ignored)) {
573  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sfailure ignored", flagOffset?", ":"");
574  }
575 
576  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
577  desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
578  }
579 
580  CRM_LOG_ASSERT(offset > 0);
581  if(flagOffset > 0) {
582  status_print("%s (%s)%s%s", buffer, flagBuffer, desc?" ":"", desc?desc:"");
583  } else {
584  status_print("%s%s%s", buffer, desc?" ":"", desc?desc:"");
585  }
586 
587 #if CURSES_ENABLED
588  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
589  /* Done */
590 
591  } else if (options & pe_print_ncurses) {
592  /* coverity[negative_returns] False positive */
593  move(-1, 0);
594  }
595 #endif
596 
597  if (options & pe_print_html) {
598  status_print(" </font> ");
599  }
600 
601  if ((options & pe_print_rsconly)) {
602 
603  } else if (g_list_length(rsc->running_on) > 1) {
604  GListPtr gIter = rsc->running_on;
605  int counter = 0;
606 
607  if (options & pe_print_html) {
608  status_print("<ul>\n");
609  } else if ((options & pe_print_printf)
610  || (options & pe_print_ncurses)) {
611  status_print("[");
612  }
613 
614  for (; gIter != NULL; gIter = gIter->next) {
615  node_t *node = (node_t *) gIter->data;
616 
617  counter++;
618 
619  if (options & pe_print_html) {
620  status_print("<li>\n%s", node->details->uname);
621 
622  } else if ((options & pe_print_printf)
623  || (options & pe_print_ncurses)) {
624  status_print(" %s", node->details->uname);
625 
626  } else if ((options & pe_print_log)) {
627  status_print("\t%d : %s", counter, node->details->uname);
628 
629  } else {
630  status_print("%s", node->details->uname);
631  }
632  if (options & pe_print_html) {
633  status_print("</li>\n");
634 
635  }
636  }
637 
638  if (options & pe_print_html) {
639  status_print("</ul>\n");
640  } else if ((options & pe_print_printf)
641  || (options & pe_print_ncurses)) {
642  status_print(" ]");
643  }
644  }
645 
646  if (options & pe_print_html) {
647  status_print("<br/>\n");
648  } else if (options & pe_print_suppres_nl) {
649  /* nothing */
650  } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
651  status_print("\n");
652  }
653 
654  if (options & pe_print_details) {
655  struct print_data_s pdata;
656 
657  pdata.options = options;
658  pdata.print_data = print_data;
659  g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata);
660  }
661 
662  if (options & pe_print_dev) {
663  GHashTableIter iter;
664  node_t *node = NULL;
665 
666  status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text,
667  is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "",
668  is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ",
669  crm_element_name(rsc->xml), (double)rsc->priority);
670  status_print("%s\tAllowed Nodes", pre_text);
671  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
672  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
673  status_print("%s\t * %s %d", pre_text, node->details->uname, node->weight);
674  }
675  }
676 
677  if (options & pe_print_max_details) {
678  GHashTableIter iter;
679  node_t *node = NULL;
680 
681  status_print("%s\t=== Allowed Nodes\n", pre_text);
682  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
683  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
684  print_node("\t", node, FALSE);
685  }
686  }
687 }
688 
689 void
691 {
692  pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
693  common_free(rsc);
694 }
695 
696 enum rsc_role_e
697 native_resource_state(const resource_t * rsc, gboolean current)
698 {
699  enum rsc_role_e role = rsc->next_role;
700 
701  if (current) {
702  role = rsc->role;
703  }
704  pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
705  return role;
706 }
707 
708 node_t *
709 native_location(resource_t * rsc, GListPtr * list, gboolean current)
710 {
711  node_t *one = NULL;
712  GListPtr result = NULL;
713 
714  if (rsc->children) {
715  GListPtr gIter = rsc->children;
716 
717  for (; gIter != NULL; gIter = gIter->next) {
718  resource_t *child = (resource_t *) gIter->data;
719 
720  child->fns->location(child, &result, current);
721  }
722 
723  } else if (current && rsc->running_on) {
724  result = g_list_copy(rsc->running_on);
725 
726  } else if (current == FALSE && rsc->allocated_to) {
727  result = g_list_append(NULL, rsc->allocated_to);
728  }
729 
730  if (result && g_list_length(result) == 1) {
731  one = g_list_nth_data(result, 0);
732  }
733 
734  if (list) {
735  GListPtr gIter = result;
736 
737  for (; gIter != NULL; gIter = gIter->next) {
738  node_t *node = (node_t *) gIter->data;
739 
740  if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
741  *list = g_list_append(*list, node);
742  }
743  }
744  }
745 
746  g_list_free(result);
747  return one;
748 }
749 
750 static void
751 get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_table)
752 {
753  GListPtr gIter = rsc_list;
754 
755  for (; gIter != NULL; gIter = gIter->next) {
756  resource_t *rsc = (resource_t *) gIter->data;
757 
758  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
759  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
760 
761  int offset = 0;
762  char buffer[LINE_MAX];
763 
764  int *rsc_counter = NULL;
765  int *active_counter = NULL;
766 
767  if (rsc->variant != pe_native) {
768  continue;
769  }
770 
771  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
772  if (safe_str_eq(class, "ocf")) {
773  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
774  offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
775  }
776  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
777  CRM_LOG_ASSERT(offset > 0);
778 
779  if (rsc_table) {
780  rsc_counter = g_hash_table_lookup(rsc_table, buffer);
781  if (rsc_counter == NULL) {
782  rsc_counter = calloc(1, sizeof(int));
783  *rsc_counter = 0;
784  g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
785  }
786  (*rsc_counter)++;
787  }
788 
789  if (active_table) {
790  GListPtr gIter2 = rsc->running_on;
791 
792  for (; gIter2 != NULL; gIter2 = gIter2->next) {
793  node_t *node = (node_t *) gIter2->data;
794  GHashTable *node_table = NULL;
795 
796  if (node->details->unclean == FALSE && node->details->online == FALSE) {
797  continue;
798  }
799 
800  node_table = g_hash_table_lookup(active_table, node->details->uname);
801  if (node_table == NULL) {
802  node_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
803  g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
804  }
805 
806  active_counter = g_hash_table_lookup(node_table, buffer);
807  if (active_counter == NULL) {
808  active_counter = calloc(1, sizeof(int));
809  *active_counter = 0;
810  g_hash_table_insert(node_table, strdup(buffer), active_counter);
811  }
812  (*active_counter)++;
813  }
814  }
815  }
816 }
817 
818 static void
819 destroy_node_table(gpointer data)
820 {
821  GHashTable *node_table = data;
822 
823  if (node_table) {
824  g_hash_table_destroy(node_table);
825  }
826 }
827 
828 void
829 print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options,
830  void *print_data, gboolean print_all)
831 {
832  GHashTable *rsc_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
833  GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal,
834  free, destroy_node_table);
835  GHashTableIter hash_iter;
836  char *type = NULL;
837  int *rsc_counter = NULL;
838 
839  get_rscs_brief(rsc_list, rsc_table, active_table);
840 
841  g_hash_table_iter_init(&hash_iter, rsc_table);
842  while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
843  GHashTableIter hash_iter2;
844  char *node_name = NULL;
845  GHashTable *node_table = NULL;
846  int active_counter_all = 0;
847 
848  g_hash_table_iter_init(&hash_iter2, active_table);
849  while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
850  int *active_counter = g_hash_table_lookup(node_table, type);
851 
852  if (active_counter == NULL || *active_counter == 0) {
853  continue;
854 
855  } else {
856  active_counter_all += *active_counter;
857  }
858 
859  if (options & pe_print_rsconly) {
860  node_name = NULL;
861  }
862 
863  if (options & pe_print_html) {
864  status_print("<li>\n");
865  }
866 
867  if (print_all) {
868  status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
869  active_counter ? *active_counter : 0,
870  rsc_counter ? *rsc_counter : 0, type,
871  active_counter && (*active_counter > 0) && node_name ? node_name : "");
872  } else {
873  status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
874  active_counter ? *active_counter : 0, type,
875  active_counter && (*active_counter > 0) && node_name ? node_name : "");
876  }
877 
878  if (options & pe_print_html) {
879  status_print("</li>\n");
880  }
881  }
882 
883  if (print_all && active_counter_all == 0) {
884  if (options & pe_print_html) {
885  status_print("<li>\n");
886  }
887 
888  status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
889  active_counter_all,
890  rsc_counter ? *rsc_counter : 0, type);
891 
892  if (options & pe_print_html) {
893  status_print("</li>\n");
894  }
895  }
896  }
897 
898  if (rsc_table) {
899  g_hash_table_destroy(rsc_table);
900  rsc_table = NULL;
901  }
902  if (active_table) {
903  g_hash_table_destroy(active_table);
904  active_table = NULL;
905  }
906 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:164
GListPtr nodes
Definition: status.h:101
const char * uname
Definition: status.h:133
#define CRMD_ACTION_MIGRATED
Definition: crm.h:150
xmlNode * xml
Definition: status.h:246
#define INFINITY
Definition: crm.h:77
void native_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:436
char * native_parameter(resource_t *rsc, node_t *node, gboolean create, const char *name, pe_working_set_t *data_set)
Definition: native.c:230
resource_t * native_find_rsc(resource_t *rsc, const char *id, node_t *on_node, int flags)
Definition: native.c:161
const char * id
Definition: status.h:132
int weight
Definition: status.h:166
#define XML_ATTR_TYPE
Definition: msg_xml.h:103
#define pe_rsc_orphan
Definition: status.h:175
enum rsc_role_e native_resource_state(const resource_t *rsc, gboolean current)
Definition: native.c:697
#define CRMD_ACTION_NOTIFY
Definition: crm.h:163
#define pe_rsc_provisional
Definition: status.h:184
GListPtr running_rsc
Definition: status.h:146
enum pe_obj_types variant
Definition: status.h:252
void common_free(resource_t *rsc)
Definition: complex.c:795
gboolean native_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: native.c:126
#define status_print(fmt, args...)
Definition: unpack.h:83
#define CRMD_ACTION_PROMOTE
Definition: crm.h:158
void get_rsc_attributes(GHashTable *meta_hash, resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: complex.c:153
void print_node(const char *pre_text, node_t *node, gboolean details)
Definition: utils.c:1024
void g_hash_destroy_str(gpointer data)
Definition: utils.c:615
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:150
char * clone_name
Definition: status.h:245
resource_t * uber_parent(resource_t *rsc)
Definition: complex.c:781
#define clear_bit(word, bit)
Definition: crm_internal.h:200
enum rsc_role_e role
Definition: status.h:281
GListPtr children
Definition: status.h:288
char * id
Definition: status.h:244
GHashTable * parameters
Definition: status.h:285
#define CRMD_ACTION_START
Definition: crm.h:152
#define pe_rsc_block
Definition: status.h:177
gboolean native_active(resource_t *rsc, gboolean all)
Definition: native.c:274
const char * role2text(enum rsc_role_e role)
Definition: common.c:340
void force_non_unique_clone(resource_t *rsc, const char *rid, pe_working_set_t *data_set)
Definition: clone.c:50
#define CRMD_ACTION_STOP
Definition: crm.h:155
struct node_shared_s * details
Definition: status.h:169
#define CRMD_ACTION_DEMOTE
Definition: crm.h:160
#define set_bit(word, bit)
Definition: crm_internal.h:199
gboolean unclean
Definition: status.h:139
#define crm_debug(fmt, args...)
Definition: logging.h:253
char * pending_task
Definition: status.h:297
enum rsc_recovery_type recovery_type
Definition: status.h:256
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:115
#define pe_rsc_failed
Definition: status.h:192
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:253
GHashTable * allowed_nodes
Definition: status.h:279
#define crm_trace(fmt, args...)
Definition: logging.h:254
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:237
#define pe_rsc_runnable
Definition: status.h:194
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5842
#define XML_ATTR_DESC
Definition: msg_xml.h:99
unsigned long long flags
Definition: status.h:268
resource_t * parent
Definition: status.h:250
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:206
node_t *(* location)(resource_t *, GListPtr *, gboolean)
Definition: complex.h:49
enum rsc_role_e text2role(const char *role)
Definition: common.c:360
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:829
node_t * native_location(resource_t *rsc, GListPtr *list, gboolean current)
Definition: native.c:709
gboolean maintenance
Definition: status.h:159
#define pe_rsc_unique
Definition: status.h:181
GHashTable * node_hash_from_list(GListPtr list)
Definition: utils.c:122
GHashTable * meta
Definition: status.h:284
resource_t *(* find_rsc)(resource_t *parent, const char *search, node_t *node, int flags)
Definition: complex.h:43
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1282
enum rsc_role_e next_role
Definition: status.h:282
gboolean online
Definition: status.h:135
#define pe_rsc_failure_ignored
Definition: status.h:202
#define pe_rsc_managed
Definition: status.h:176
#define CRMD_ACTION_MIGRATE
Definition: crm.h:149
#define XML_RSC_ATTR_INTERNAL_RSC
Definition: msg_xml.h:217
#define CRM_ASSERT(expr)
Definition: error.h:35
char data[0]
Definition: internal.h:58
node_t * allocated_to
Definition: status.h:276
rsc_role_e
Definition: common.h:81
node_t * pe_find_node_id(GListPtr node_list, const char *id)
Definition: status.c:282
Definition: status.h:165
gboolean crm_is_true(const char *s)
Definition: utils.c:711
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:25
#define ID(x)
Definition: msg_xml.h:419
#define pe_err(fmt...)
Definition: internal.h:27
#define safe_str_eq(a, b)
Definition: util.h:74
#define crm_str_hash
Definition: crm.h:198
GList * GListPtr
Definition: crm.h:192
void native_free(resource_t *rsc)
Definition: native.c:690
const char * rsc_printable_id(resource_t *rsc)
Definition: utils.c:2013
uint64_t flags
Definition: remote.c:121
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:236
#define CRMD_ACTION_STATUS
Definition: crm.h:166
GListPtr running_on
Definition: status.h:277