pacemaker  1.1.14-70404b0
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
native.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <crm_internal.h>
20 
21 #include <crm/pengine/rules.h>
22 #include <crm/pengine/status.h>
23 #include <crm/pengine/complex.h>
24 #include <crm/pengine/internal.h>
25 #include <unpack.h>
26 #include <crm/msg_xml.h>
27 
28 #define VARIANT_NATIVE 1
29 #include "./variant.h"
30 
31 void
33 {
34  GListPtr gIter = rsc->running_on;
35 
36  CRM_CHECK(node != NULL, return);
37  for (; gIter != NULL; gIter = gIter->next) {
38  node_t *a_node = (node_t *) gIter->data;
39 
40  CRM_CHECK(a_node != NULL, return);
41  if (safe_str_eq(a_node->details->id, node->details->id)) {
42  return;
43  }
44  }
45 
46  pe_rsc_trace(rsc, "Adding %s to %s %s", rsc->id, node->details->uname,
47  is_set(rsc->flags, pe_rsc_managed)?"":"(unmanaged)");
48 
49  rsc->running_on = g_list_append(rsc->running_on, node);
50  if (rsc->variant == pe_native) {
51  node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
52  }
53 
54  if (rsc->variant == pe_native && node->details->maintenance) {
56  }
57 
58  if (is_not_set(rsc->flags, pe_rsc_managed)) {
59  resource_t *p = rsc->parent;
60 
61  pe_rsc_info(rsc, "resource %s isn't managed", rsc->id);
62  resource_location(rsc, node, INFINITY, "not_managed_default", data_set);
63 
64  while(p && node->details->online) {
65  /* add without the additional location constraint */
66  p->running_on = g_list_append(p->running_on, node);
67  p = p->parent;
68  }
69  return;
70  }
71 
72  if (rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) {
73  switch (rsc->recovery_type) {
74  case recovery_stop_only:
75  {
76  GHashTableIter gIter;
77  node_t *local_node = NULL;
78 
79  /* make sure it doesn't come up again */
80  g_hash_table_destroy(rsc->allowed_nodes);
81  rsc->allowed_nodes = node_hash_from_list(data_set->nodes);
82  g_hash_table_iter_init(&gIter, rsc->allowed_nodes);
83  while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
84  local_node->weight = -INFINITY;
85  }
86  }
87  break;
89  break;
90  case recovery_block:
92  set_bit(rsc->flags, pe_rsc_block);
93 
94  /* If the 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 *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
440  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
441  const char *target_role = NULL;
442 
443  int offset = 0;
444  char buffer[LINE_MAX];
445 
446  CRM_ASSERT(rsc->variant == pe_native);
447  CRM_ASSERT(kind != NULL);
448 
449  if (rsc->meta) {
450  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
451  if (crm_is_true(is_internal)) {
452  crm_trace("skipping print of internal resource %s", rsc->id);
453  return;
454  }
455  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
456  }
457 
458  if (pre_text == NULL && (options & pe_print_printf)) {
459  pre_text = " ";
460  }
461 
462  if (options & pe_print_xml) {
463  native_print_xml(rsc, pre_text, options, print_data);
464  return;
465  }
466 
467  if (rsc->running_on != NULL) {
468  node = rsc->running_on->data;
469  }
470  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
471  node = NULL;
472  }
473 
474  if (options & pe_print_html) {
475  if (is_not_set(rsc->flags, pe_rsc_managed)) {
476  status_print("<font color=\"yellow\">");
477 
478  } else if (is_set(rsc->flags, pe_rsc_failed)) {
479  status_print("<font color=\"red\">");
480 
481  } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) {
482  status_print("<font color=\"red\">");
483 
484  } else if (g_list_length(rsc->running_on) > 1) {
485  status_print("<font color=\"orange\">");
486 
487  } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) {
488  status_print("<font color=\"yellow\">");
489 
490  } else {
491  status_print("<font color=\"green\">");
492  }
493  }
494 
495  if(pre_text) {
496  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", pre_text);
497  }
498  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_printable_id(rsc));
499  offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class);
500  if (safe_str_eq(class, "ocf")) {
501  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
502  offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
503  }
504  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s):\t", kind);
505  if(is_set(rsc->flags, pe_rsc_orphan)) {
506  offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED ");
507  }
508  if(rsc->role > RSC_ROLE_SLAVE && is_set(rsc->flags, pe_rsc_failed)) {
509  offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s", role2text(rsc->role));
510  } else if(is_set(rsc->flags, pe_rsc_failed)) {
511  offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED");
512  } else {
513  const char *rsc_state = NULL;
514 
515  if (options & pe_print_pending) {
516  rsc_state = native_pending_state(rsc);
517  }
518  if (rsc_state == NULL) {
519  rsc_state = role2text(rsc->role);
520  }
521  if (target_role) {
522  enum rsc_role_e target_role_e = text2role(target_role);
523 
524  /* Ignore target role Started, as it is the default anyways
525  * (and would also allow a Master to be Master).
526  * Show if current role differs from target role,
527  * or if target role limits our abilities. */
528  if (target_role_e != RSC_ROLE_STARTED && (
529  target_role_e == RSC_ROLE_SLAVE ||
530  target_role_e == RSC_ROLE_STOPPED ||
531  safe_str_neq(target_role, rsc_state)))
532  {
533  offset += snprintf(buffer + offset, LINE_MAX - offset, "(target-role:%s) ", target_role);
534  }
535  }
536  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_state);
537  }
538 
539  if(node) {
540  offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", node->details->uname);
541 
542  if (node->details->online == FALSE && node->details->unclean) {
543  offset += snprintf(buffer + offset, LINE_MAX - offset, " (UNCLEAN)");
544  }
545  }
546 
547  if (options & pe_print_pending) {
548  const char *pending_task = native_pending_task(rsc);
549 
550  if (pending_task) {
551  offset += snprintf(buffer + offset, LINE_MAX - offset, " (%s)", pending_task);
552  }
553  }
554 
555  if(is_not_set(rsc->flags, pe_rsc_managed)) {
556  offset += snprintf(buffer + offset, LINE_MAX - offset, " (unmanaged)");
557  }
558  if(is_set(rsc->flags, pe_rsc_failure_ignored)) {
559  offset += snprintf(buffer + offset, LINE_MAX - offset, " (failure ignored)");
560  }
561 
562  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
563  const char *desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
564  if(desc) {
565  offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", desc);
566  }
567  }
568 
569  CRM_LOG_ASSERT(offset > 0);
570  status_print("%s", buffer);
571 
572 #if CURSES_ENABLED
573  if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
574  /* Done */
575 
576  } else if (options & pe_print_ncurses) {
577  /* coverity[negative_returns] False positive */
578  move(-1, 0);
579  }
580 #endif
581 
582  if (options & pe_print_html) {
583  status_print(" </font> ");
584  }
585 
586  if ((options & pe_print_rsconly)) {
587 
588  } else if (g_list_length(rsc->running_on) > 1) {
589  GListPtr gIter = rsc->running_on;
590  int counter = 0;
591 
592  if (options & pe_print_html) {
593  status_print("<ul>\n");
594  } else if ((options & pe_print_printf)
595  || (options & pe_print_ncurses)) {
596  status_print("[");
597  }
598 
599  for (; gIter != NULL; gIter = gIter->next) {
600  node_t *node = (node_t *) gIter->data;
601 
602  counter++;
603 
604  if (options & pe_print_html) {
605  status_print("<li>\n%s", node->details->uname);
606 
607  } else if ((options & pe_print_printf)
608  || (options & pe_print_ncurses)) {
609  status_print(" %s", node->details->uname);
610 
611  } else if ((options & pe_print_log)) {
612  status_print("\t%d : %s", counter, node->details->uname);
613 
614  } else {
615  status_print("%s", node->details->uname);
616  }
617  if (options & pe_print_html) {
618  status_print("</li>\n");
619 
620  }
621  }
622 
623  if (options & pe_print_html) {
624  status_print("</ul>\n");
625  } else if ((options & pe_print_printf)
626  || (options & pe_print_ncurses)) {
627  status_print(" ]");
628  }
629  }
630 
631  if (options & pe_print_html) {
632  status_print("<br/>\n");
633  } else if (options & pe_print_suppres_nl) {
634  /* nothing */
635  } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
636  status_print("\n");
637  }
638 
639  if (options & pe_print_details) {
640  struct print_data_s pdata;
641 
642  pdata.options = options;
643  pdata.print_data = print_data;
644  g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata);
645  }
646 
647  if (options & pe_print_dev) {
648  GHashTableIter iter;
649  node_t *node = NULL;
650 
651  status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text,
652  is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "",
653  is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ",
654  crm_element_name(rsc->xml), (double)rsc->priority);
655  status_print("%s\tAllowed Nodes", pre_text);
656  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
657  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
658  status_print("%s\t * %s %d", pre_text, node->details->uname, node->weight);
659  }
660  }
661 
662  if (options & pe_print_max_details) {
663  GHashTableIter iter;
664  node_t *node = NULL;
665 
666  status_print("%s\t=== Allowed Nodes\n", pre_text);
667  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
668  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
669  print_node("\t", node, FALSE);
670  }
671  }
672 }
673 
674 void
676 {
677  pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
678  common_free(rsc);
679 }
680 
681 enum rsc_role_e
682 native_resource_state(const resource_t * rsc, gboolean current)
683 {
684  enum rsc_role_e role = rsc->next_role;
685 
686  if (current) {
687  role = rsc->role;
688  }
689  pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
690  return role;
691 }
692 
693 node_t *
694 native_location(resource_t * rsc, GListPtr * list, gboolean current)
695 {
696  node_t *one = NULL;
697  GListPtr result = NULL;
698 
699  if (rsc->children) {
700  GListPtr gIter = rsc->children;
701 
702  for (; gIter != NULL; gIter = gIter->next) {
703  resource_t *child = (resource_t *) gIter->data;
704 
705  child->fns->location(child, &result, current);
706  }
707 
708  } else if (current && rsc->running_on) {
709  result = g_list_copy(rsc->running_on);
710 
711  } else if (current == FALSE && rsc->allocated_to) {
712  result = g_list_append(NULL, rsc->allocated_to);
713  }
714 
715  if (result && g_list_length(result) == 1) {
716  one = g_list_nth_data(result, 0);
717  }
718 
719  if (list) {
720  GListPtr gIter = result;
721 
722  for (; gIter != NULL; gIter = gIter->next) {
723  node_t *node = (node_t *) gIter->data;
724 
725  if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
726  *list = g_list_append(*list, node);
727  }
728  }
729  }
730 
731  g_list_free(result);
732  return one;
733 }
734 
735 static void
736 get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_table)
737 {
738  GListPtr gIter = rsc_list;
739 
740  for (; gIter != NULL; gIter = gIter->next) {
741  resource_t *rsc = (resource_t *) gIter->data;
742 
743  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
744  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
745 
746  int offset = 0;
747  char buffer[LINE_MAX];
748 
749  int *rsc_counter = NULL;
750  int *active_counter = NULL;
751 
752  if (rsc->variant != pe_native) {
753  continue;
754  }
755 
756  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
757  if (safe_str_eq(class, "ocf")) {
758  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
759  offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
760  }
761  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
762  CRM_LOG_ASSERT(offset > 0);
763 
764  if (rsc_table) {
765  rsc_counter = g_hash_table_lookup(rsc_table, buffer);
766  if (rsc_counter == NULL) {
767  rsc_counter = calloc(1, sizeof(int));
768  *rsc_counter = 0;
769  g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
770  }
771  (*rsc_counter)++;
772  }
773 
774  if (active_table) {
775  GListPtr gIter2 = rsc->running_on;
776 
777  for (; gIter2 != NULL; gIter2 = gIter2->next) {
778  node_t *node = (node_t *) gIter2->data;
779  GHashTable *node_table = NULL;
780 
781  if (node->details->unclean == FALSE && node->details->online == FALSE) {
782  continue;
783  }
784 
785  node_table = g_hash_table_lookup(active_table, node->details->uname);
786  if (node_table == NULL) {
787  node_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
788  g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
789  }
790 
791  active_counter = g_hash_table_lookup(node_table, buffer);
792  if (active_counter == NULL) {
793  active_counter = calloc(1, sizeof(int));
794  *active_counter = 0;
795  g_hash_table_insert(node_table, strdup(buffer), active_counter);
796  }
797  (*active_counter)++;
798  }
799  }
800  }
801 }
802 
803 static void
804 destroy_node_table(gpointer data)
805 {
806  GHashTable *node_table = data;
807 
808  if (node_table) {
809  g_hash_table_destroy(node_table);
810  }
811 }
812 
813 void
814 print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options,
815  void *print_data, gboolean print_all)
816 {
817  GHashTable *rsc_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
818  GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal,
819  free, destroy_node_table);
820  GHashTableIter hash_iter;
821  char *type = NULL;
822  int *rsc_counter = NULL;
823 
824  get_rscs_brief(rsc_list, rsc_table, active_table);
825 
826  g_hash_table_iter_init(&hash_iter, rsc_table);
827  while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
828  GHashTableIter hash_iter2;
829  char *node_name = NULL;
830  GHashTable *node_table = NULL;
831  int active_counter_all = 0;
832 
833  g_hash_table_iter_init(&hash_iter2, active_table);
834  while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
835  int *active_counter = g_hash_table_lookup(node_table, type);
836 
837  if (active_counter == NULL || *active_counter == 0) {
838  continue;
839 
840  } else {
841  active_counter_all += *active_counter;
842  }
843 
844  if (options & pe_print_rsconly) {
845  node_name = NULL;
846  }
847 
848  if (options & pe_print_html) {
849  status_print("<li>\n");
850  }
851 
852  if (print_all) {
853  status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
854  active_counter ? *active_counter : 0,
855  rsc_counter ? *rsc_counter : 0, type,
856  active_counter && (*active_counter > 0) && node_name ? node_name : "");
857  } else {
858  status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
859  active_counter ? *active_counter : 0, type,
860  active_counter && (*active_counter > 0) && node_name ? node_name : "");
861  }
862 
863  if (options & pe_print_html) {
864  status_print("</li>\n");
865  }
866  }
867 
868  if (print_all && active_counter_all == 0) {
869  if (options & pe_print_html) {
870  status_print("<li>\n");
871  }
872 
873  status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
874  active_counter_all,
875  rsc_counter ? *rsc_counter : 0, type);
876 
877  if (options & pe_print_html) {
878  status_print("</li>\n");
879  }
880  }
881  }
882 
883  if (rsc_table) {
884  g_hash_table_destroy(rsc_table);
885  rsc_table = NULL;
886  }
887  if (active_table) {
888  g_hash_table_destroy(active_table);
889  active_table = NULL;
890  }
891 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:164
GListPtr nodes
Definition: status.h:100
const char * uname
Definition: status.h:129
#define CRMD_ACTION_MIGRATED
Definition: crm.h:148
xmlNode * xml
Definition: status.h:242
node_t *(* location)(resource_t *, GListPtr *, gboolean)
Definition: complex.h:49
gboolean safe_str_neq(const char *a, const char *b)
Definition: utils.c:668
#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:128
int weight
Definition: status.h:162
#define XML_ATTR_TYPE
Definition: msg_xml.h:103
#define pe_rsc_orphan
Definition: status.h:171
enum rsc_role_e native_resource_state(const resource_t *rsc, gboolean current)
Definition: native.c:682
#define CRMD_ACTION_NOTIFY
Definition: crm.h:161
#define pe_rsc_provisional
Definition: status.h:180
GListPtr running_rsc
Definition: status.h:142
enum pe_obj_types variant
Definition: status.h:248
void common_free(resource_t *rsc)
Definition: complex.c:794
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:156
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:1026
void g_hash_destroy_str(gpointer data)
Definition: utils.c:587
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:150
char * clone_name
Definition: status.h:241
resource_t * uber_parent(resource_t *rsc)
Definition: complex.c:780
#define clear_bit(word, bit)
Definition: crm_internal.h:199
enum rsc_role_e role
Definition: status.h:277
resource_t *(* find_rsc)(resource_t *parent, const char *search, node_t *node, int flags)
Definition: complex.h:43
GListPtr children
Definition: status.h:284
char * id
Definition: status.h:240
GHashTable * parameters
Definition: status.h:281
#define CRMD_ACTION_START
Definition: crm.h:150
#define pe_rsc_block
Definition: status.h:173
gboolean native_active(resource_t *rsc, gboolean all)
Definition: native.c:274
const char * role2text(enum rsc_role_e role)
Definition: common.c:338
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:153
gboolean(* active)(resource_t *, gboolean)
Definition: complex.h:47
struct node_shared_s * details
Definition: status.h:165
#define CRMD_ACTION_DEMOTE
Definition: crm.h:158
#define set_bit(word, bit)
Definition: crm_internal.h:198
gboolean unclean
Definition: status.h:135
uint64_t flags
Definition: remote.c:121
#define crm_debug(fmt, args...)
Definition: logging.h:253
char * pending_task
Definition: status.h:293
enum rsc_recovery_type recovery_type
Definition: status.h:252
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:115
#define pe_rsc_failed
Definition: status.h:188
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:249
GHashTable * allowed_nodes
Definition: status.h:275
#define crm_trace(fmt, args...)
Definition: logging.h:254
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:234
#define pe_rsc_runnable
Definition: status.h:190
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5839
#define XML_ATTR_DESC
Definition: msg_xml.h:99
unsigned long long flags
Definition: status.h:264
resource_t * parent
Definition: status.h:246
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:203
enum rsc_role_e text2role(const char *role)
Definition: common.c:358
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:814
node_t * native_location(resource_t *rsc, GListPtr *list, gboolean current)
Definition: native.c:694
gboolean maintenance
Definition: status.h:155
#define pe_rsc_unique
Definition: status.h:177
GHashTable * node_hash_from_list(GListPtr list)
Definition: utils.c:123
GHashTable * meta
Definition: status.h:280
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1284
enum rsc_role_e next_role
Definition: status.h:278
gboolean online
Definition: status.h:131
#define pe_rsc_failure_ignored
Definition: status.h:198
#define pe_rsc_managed
Definition: status.h:172
#define CRMD_ACTION_MIGRATE
Definition: crm.h:147
#define XML_RSC_ATTR_INTERNAL_RSC
Definition: msg_xml.h:214
#define CRM_ASSERT(expr)
Definition: error.h:35
char data[0]
Definition: internal.h:58
node_t * allocated_to
Definition: status.h:272
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:161
gboolean crm_is_true(const char *s)
Definition: utils.c:683
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:24
#define ID(x)
Definition: msg_xml.h:408
#define pe_err(fmt...)
Definition: internal.h:26
#define safe_str_eq(a, b)
Definition: util.h:74
#define crm_str_hash
Definition: crm.h:196
GList * GListPtr
Definition: crm.h:190
void native_free(resource_t *rsc)
Definition: native.c:675
const char * rsc_printable_id(resource_t *rsc)
Definition: utils.c:2015
enum crm_ais_msg_types type
Definition: internal.h:51
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:22
int priority
Definition: status.h:255
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:233
#define CRMD_ACTION_STATUS
Definition: crm.h:164
GListPtr running_on
Definition: status.h:273