pacemaker  1.1.15-04d2066
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 
444  int offset = 0;
445  int flagOffset = 0;
446  char buffer[LINE_MAX];
447  char flagBuffer[LINE_MAX];
448 
449  CRM_ASSERT(rsc->variant == pe_native);
450  CRM_ASSERT(kind != NULL);
451 
452  if (rsc->meta) {
453  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
454  if (crm_is_true(is_internal)) {
455  crm_trace("skipping print of internal resource %s", rsc->id);
456  return;
457  }
458  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
459  }
460 
461  if (pre_text == NULL && (options & pe_print_printf)) {
462  pre_text = " ";
463  }
464 
465  if (options & pe_print_xml) {
466  native_print_xml(rsc, pre_text, options, print_data);
467  return;
468  }
469 
470  if (rsc->running_on != NULL) {
471  node = rsc->running_on->data;
472  }
473  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
474  node = NULL;
475  }
476 
477  if (options & pe_print_html) {
478  if (is_not_set(rsc->flags, pe_rsc_managed)) {
479  status_print("<font color=\"yellow\">");
480 
481  } else if (is_set(rsc->flags, pe_rsc_failed)) {
482  status_print("<font color=\"red\">");
483 
484  } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) {
485  status_print("<font color=\"red\">");
486 
487  } else if (g_list_length(rsc->running_on) > 1) {
488  status_print("<font color=\"orange\">");
489 
490  } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) {
491  status_print("<font color=\"yellow\">");
492 
493  } else {
494  status_print("<font color=\"green\">");
495  }
496  }
497 
498  if(pre_text) {
499  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", pre_text);
500  }
501  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_printable_id(rsc));
502  offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class);
503  if (safe_str_eq(class, "ocf")) {
504  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
505  offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
506  }
507  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s):\t", kind);
508  if(is_set(rsc->flags, pe_rsc_orphan)) {
509  offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED ");
510  }
511  if(rsc->role > RSC_ROLE_SLAVE && is_set(rsc->flags, pe_rsc_failed)) {
512  offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s", role2text(rsc->role));
513  } else if(is_set(rsc->flags, pe_rsc_failed)) {
514  offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED");
515  } else {
516  const char *rsc_state = NULL;
517 
518  if (options & pe_print_pending) {
519  rsc_state = native_pending_state(rsc);
520  }
521  if (rsc_state == NULL) {
522  rsc_state = role2text(rsc->role);
523  }
524  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_state);
525  }
526 
527  if(node) {
528  offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", node->details->uname);
529 
530  if (node->details->online == FALSE && node->details->unclean) {
531  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sUNCLEAN", flagOffset?", ":"");
532  }
533  }
534 
535  if (options & pe_print_pending) {
536  const char *pending_task = native_pending_task(rsc);
537 
538  if (pending_task) {
539  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%s%s", flagOffset?", ":"", pending_task);
540  }
541  }
542 
543  if (target_role) {
544  enum rsc_role_e target_role_e = text2role(target_role);
545 
546  /* Ignore target role Started, as it is the default anyways
547  * (and would also allow a Master to be Master).
548  * Show if current role differs from target role,
549  * or if target role limits our abilities. */
550  if (target_role_e == RSC_ROLE_STOPPED) {
551  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sdisabled", flagOffset?", ":"");
552  rsc->cluster->disabled_resources++;
553 
554  } else if (uber_parent(rsc)->variant == pe_master
555  && target_role_e > RSC_ROLE_STOPPED
556  && target_role_e < RSC_ROLE_MASTER
557  && safe_str_neq(target_role, role2text(rsc->role))) {
558  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%starget-role:%s", flagOffset?", ":"", target_role);
559  rsc->cluster->disabled_resources++;
560  }
561  }
562 
563  if (is_set(rsc->flags, pe_rsc_block)) {
564  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sblocked", flagOffset?", ":"");
565  rsc->cluster->blocked_resources++;
566 
567  } else if (is_not_set(rsc->flags, pe_rsc_managed)) {
568  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sunmanaged", flagOffset?", ":"");
569  }
570 
571  if(is_set(rsc->flags, pe_rsc_failure_ignored)) {
572  flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset, "%sfailure ignored", flagOffset?", ":"");
573  }
574 
575  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
576  desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
577  }
578 
579  CRM_LOG_ASSERT(offset > 0);
580  if(flagOffset > 0) {
581  status_print("%s ( %s ) %s", buffer, flagBuffer, desc?desc:"");
582  } else {
583  status_print("%s %s", buffer, desc?desc:"");
584  }
585 
586 #if CURSES_ENABLED
587  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
588  /* Done */
589 
590  } else if (options & pe_print_ncurses) {
591  /* coverity[negative_returns] False positive */
592  move(-1, 0);
593  }
594 #endif
595 
596  if (options & pe_print_html) {
597  status_print(" </font> ");
598  }
599 
600  if ((options & pe_print_rsconly)) {
601 
602  } else if (g_list_length(rsc->running_on) > 1) {
603  GListPtr gIter = rsc->running_on;
604  int counter = 0;
605 
606  if (options & pe_print_html) {
607  status_print("<ul>\n");
608  } else if ((options & pe_print_printf)
609  || (options & pe_print_ncurses)) {
610  status_print("[");
611  }
612 
613  for (; gIter != NULL; gIter = gIter->next) {
614  node_t *node = (node_t *) gIter->data;
615 
616  counter++;
617 
618  if (options & pe_print_html) {
619  status_print("<li>\n%s", node->details->uname);
620 
621  } else if ((options & pe_print_printf)
622  || (options & pe_print_ncurses)) {
623  status_print(" %s", node->details->uname);
624 
625  } else if ((options & pe_print_log)) {
626  status_print("\t%d : %s", counter, node->details->uname);
627 
628  } else {
629  status_print("%s", node->details->uname);
630  }
631  if (options & pe_print_html) {
632  status_print("</li>\n");
633 
634  }
635  }
636 
637  if (options & pe_print_html) {
638  status_print("</ul>\n");
639  } else if ((options & pe_print_printf)
640  || (options & pe_print_ncurses)) {
641  status_print(" ]");
642  }
643  }
644 
645  if (options & pe_print_html) {
646  status_print("<br/>\n");
647  } else if (options & pe_print_suppres_nl) {
648  /* nothing */
649  } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
650  status_print("\n");
651  }
652 
653  if (options & pe_print_details) {
654  struct print_data_s pdata;
655 
656  pdata.options = options;
657  pdata.print_data = print_data;
658  g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata);
659  }
660 
661  if (options & pe_print_dev) {
662  GHashTableIter iter;
663  node_t *node = NULL;
664 
665  status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text,
666  is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "",
667  is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ",
668  crm_element_name(rsc->xml), (double)rsc->priority);
669  status_print("%s\tAllowed Nodes", pre_text);
670  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
671  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
672  status_print("%s\t * %s %d", pre_text, node->details->uname, node->weight);
673  }
674  }
675 
676  if (options & pe_print_max_details) {
677  GHashTableIter iter;
678  node_t *node = NULL;
679 
680  status_print("%s\t=== Allowed Nodes\n", pre_text);
681  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
682  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
683  print_node("\t", node, FALSE);
684  }
685  }
686 }
687 
688 void
690 {
691  pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
692  common_free(rsc);
693 }
694 
695 enum rsc_role_e
696 native_resource_state(const resource_t * rsc, gboolean current)
697 {
698  enum rsc_role_e role = rsc->next_role;
699 
700  if (current) {
701  role = rsc->role;
702  }
703  pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
704  return role;
705 }
706 
707 node_t *
708 native_location(resource_t * rsc, GListPtr * list, gboolean current)
709 {
710  node_t *one = NULL;
711  GListPtr result = NULL;
712 
713  if (rsc->children) {
714  GListPtr gIter = rsc->children;
715 
716  for (; gIter != NULL; gIter = gIter->next) {
717  resource_t *child = (resource_t *) gIter->data;
718 
719  child->fns->location(child, &result, current);
720  }
721 
722  } else if (current && rsc->running_on) {
723  result = g_list_copy(rsc->running_on);
724 
725  } else if (current == FALSE && rsc->allocated_to) {
726  result = g_list_append(NULL, rsc->allocated_to);
727  }
728 
729  if (result && g_list_length(result) == 1) {
730  one = g_list_nth_data(result, 0);
731  }
732 
733  if (list) {
734  GListPtr gIter = result;
735 
736  for (; gIter != NULL; gIter = gIter->next) {
737  node_t *node = (node_t *) gIter->data;
738 
739  if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
740  *list = g_list_append(*list, node);
741  }
742  }
743  }
744 
745  g_list_free(result);
746  return one;
747 }
748 
749 static void
750 get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_table)
751 {
752  GListPtr gIter = rsc_list;
753 
754  for (; gIter != NULL; gIter = gIter->next) {
755  resource_t *rsc = (resource_t *) gIter->data;
756 
757  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
758  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
759 
760  int offset = 0;
761  char buffer[LINE_MAX];
762 
763  int *rsc_counter = NULL;
764  int *active_counter = NULL;
765 
766  if (rsc->variant != pe_native) {
767  continue;
768  }
769 
770  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
771  if (safe_str_eq(class, "ocf")) {
772  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
773  offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
774  }
775  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
776  CRM_LOG_ASSERT(offset > 0);
777 
778  if (rsc_table) {
779  rsc_counter = g_hash_table_lookup(rsc_table, buffer);
780  if (rsc_counter == NULL) {
781  rsc_counter = calloc(1, sizeof(int));
782  *rsc_counter = 0;
783  g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
784  }
785  (*rsc_counter)++;
786  }
787 
788  if (active_table) {
789  GListPtr gIter2 = rsc->running_on;
790 
791  for (; gIter2 != NULL; gIter2 = gIter2->next) {
792  node_t *node = (node_t *) gIter2->data;
793  GHashTable *node_table = NULL;
794 
795  if (node->details->unclean == FALSE && node->details->online == FALSE) {
796  continue;
797  }
798 
799  node_table = g_hash_table_lookup(active_table, node->details->uname);
800  if (node_table == NULL) {
801  node_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
802  g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
803  }
804 
805  active_counter = g_hash_table_lookup(node_table, buffer);
806  if (active_counter == NULL) {
807  active_counter = calloc(1, sizeof(int));
808  *active_counter = 0;
809  g_hash_table_insert(node_table, strdup(buffer), active_counter);
810  }
811  (*active_counter)++;
812  }
813  }
814  }
815 }
816 
817 static void
818 destroy_node_table(gpointer data)
819 {
820  GHashTable *node_table = data;
821 
822  if (node_table) {
823  g_hash_table_destroy(node_table);
824  }
825 }
826 
827 void
828 print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options,
829  void *print_data, gboolean print_all)
830 {
831  GHashTable *rsc_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
832  GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal,
833  free, destroy_node_table);
834  GHashTableIter hash_iter;
835  char *type = NULL;
836  int *rsc_counter = NULL;
837 
838  get_rscs_brief(rsc_list, rsc_table, active_table);
839 
840  g_hash_table_iter_init(&hash_iter, rsc_table);
841  while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
842  GHashTableIter hash_iter2;
843  char *node_name = NULL;
844  GHashTable *node_table = NULL;
845  int active_counter_all = 0;
846 
847  g_hash_table_iter_init(&hash_iter2, active_table);
848  while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
849  int *active_counter = g_hash_table_lookup(node_table, type);
850 
851  if (active_counter == NULL || *active_counter == 0) {
852  continue;
853 
854  } else {
855  active_counter_all += *active_counter;
856  }
857 
858  if (options & pe_print_rsconly) {
859  node_name = NULL;
860  }
861 
862  if (options & pe_print_html) {
863  status_print("<li>\n");
864  }
865 
866  if (print_all) {
867  status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
868  active_counter ? *active_counter : 0,
869  rsc_counter ? *rsc_counter : 0, type,
870  active_counter && (*active_counter > 0) && node_name ? node_name : "");
871  } else {
872  status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
873  active_counter ? *active_counter : 0, type,
874  active_counter && (*active_counter > 0) && node_name ? node_name : "");
875  }
876 
877  if (options & pe_print_html) {
878  status_print("</li>\n");
879  }
880  }
881 
882  if (print_all && active_counter_all == 0) {
883  if (options & pe_print_html) {
884  status_print("<li>\n");
885  }
886 
887  status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
888  active_counter_all,
889  rsc_counter ? *rsc_counter : 0, type);
890 
891  if (options & pe_print_html) {
892  status_print("</li>\n");
893  }
894  }
895  }
896 
897  if (rsc_table) {
898  g_hash_table_destroy(rsc_table);
899  rsc_table = NULL;
900  }
901  if (active_table) {
902  g_hash_table_destroy(active_table);
903  active_table = NULL;
904  }
905 }
#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
gboolean safe_str_neq(const char *a, const char *b)
Definition: utils.c:696
#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:696
#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:828
node_t * native_location(resource_t *rsc, GListPtr *list, gboolean current)
Definition: native.c:708
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:689
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