This source file includes following definitions.
- is_multiply_active
- native_priority_to_node
- native_add_running
- recursive_clear_unique
- native_unpack
- rsc_is_on_node
- native_find_rsc
- native_parameter
- native_active
- native_print_attr
- native_pending_state
- native_pending_task
- native_displayable_role
- native_displayable_state
- native_print_xml
- add_output_flag
- add_output_node
- native_output_string
- pe__common_output_html
- pe__common_output_text
- common_print
- native_print
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- native_free
- native_resource_state
- native_location
- get_rscs_brief
- destroy_node_table
- print_rscs_brief
- pe__rscs_brief_output
- pe__native_is_filtered
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/pengine/rules.h>
13 #include <crm/pengine/status.h>
14 #include <crm/pengine/complex.h>
15 #include <crm/pengine/internal.h>
16 #include <crm/msg_xml.h>
17 #include <pe_status_private.h>
18
19 #define VARIANT_NATIVE 1
20 #include "./variant.h"
21
22
23
24
25
26 static bool
27 is_multiply_active(pe_resource_t *rsc)
28 {
29 unsigned int count = 0;
30
31 if (rsc->variant == pe_native) {
32 pe__find_active_requires(rsc, &count);
33 }
34 return count > 1;
35 }
36
37 static void
38 native_priority_to_node(pe_resource_t * rsc, pe_node_t * node)
39 {
40 int priority = 0;
41
42 if (rsc->priority == 0) {
43 return;
44 }
45
46 if (rsc->role == RSC_ROLE_MASTER) {
47
48 priority = rsc->priority + 1;
49
50 } else {
51 priority = rsc->priority;
52 }
53
54 node->details->priority += priority;
55 pe_rsc_trace(rsc, "Node '%s' now has priority %d with %s'%s' (priority: %d%s)",
56 node->details->uname, node->details->priority,
57 rsc->role == RSC_ROLE_MASTER ? "promoted " : "",
58 rsc->id, rsc->priority,
59 rsc->role == RSC_ROLE_MASTER ? " + 1" : "");
60
61
62
63 if (node->details->remote_rsc
64 && node->details->remote_rsc->container) {
65 GListPtr gIter = node->details->remote_rsc->container->running_on;
66
67 for (; gIter != NULL; gIter = gIter->next) {
68 pe_node_t *a_node = gIter->data;
69
70 a_node->details->priority += priority;
71 pe_rsc_trace(rsc, "Node '%s' now has priority %d with %s'%s' (priority: %d%s) "
72 "from guest node '%s'",
73 a_node->details->uname, a_node->details->priority,
74 rsc->role == RSC_ROLE_MASTER ? "promoted " : "",
75 rsc->id, rsc->priority,
76 rsc->role == RSC_ROLE_MASTER ? " + 1" : "",
77 node->details->uname);
78 }
79 }
80 }
81
82 void
83 native_add_running(pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set)
84 {
85 GListPtr gIter = rsc->running_on;
86
87 CRM_CHECK(node != NULL, return);
88 for (; gIter != NULL; gIter = gIter->next) {
89 pe_node_t *a_node = (pe_node_t *) gIter->data;
90
91 CRM_CHECK(a_node != NULL, return);
92 if (pcmk__str_eq(a_node->details->id, node->details->id, pcmk__str_casei)) {
93 return;
94 }
95 }
96
97 pe_rsc_trace(rsc, "Adding %s to %s %s", rsc->id, node->details->uname,
98 pcmk_is_set(rsc->flags, pe_rsc_managed)? "" : "(unmanaged)");
99
100 rsc->running_on = g_list_append(rsc->running_on, node);
101 if (rsc->variant == pe_native) {
102 node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
103
104 native_priority_to_node(rsc, node);
105 }
106
107 if (rsc->variant == pe_native && node->details->maintenance) {
108 pe__clear_resource_flags(rsc, pe_rsc_managed);
109 }
110
111 if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
112 pe_resource_t *p = rsc->parent;
113
114 pe_rsc_info(rsc, "resource %s isn't managed", rsc->id);
115 resource_location(rsc, node, INFINITY, "not_managed_default", data_set);
116
117 while(p && node->details->online) {
118
119 p->running_on = g_list_append(p->running_on, node);
120 p = p->parent;
121 }
122 return;
123 }
124
125 if (is_multiply_active(rsc)) {
126 switch (rsc->recovery_type) {
127 case recovery_stop_only:
128 {
129 GHashTableIter gIter;
130 pe_node_t *local_node = NULL;
131
132
133 if (rsc->allowed_nodes != NULL) {
134 g_hash_table_destroy(rsc->allowed_nodes);
135 }
136 rsc->allowed_nodes = pe__node_list2table(data_set->nodes);
137 g_hash_table_iter_init(&gIter, rsc->allowed_nodes);
138 while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
139 local_node->weight = -INFINITY;
140 }
141 }
142 break;
143 case recovery_stop_start:
144 break;
145 case recovery_block:
146 pe__clear_resource_flags(rsc, pe_rsc_managed);
147 pe__set_resource_flags(rsc, pe_rsc_block);
148
149
150
151
152 if (rsc->parent
153 && (rsc->parent->variant == pe_group || rsc->parent->variant == pe_container)
154 && rsc->parent->recovery_type == recovery_block) {
155 GListPtr gIter = rsc->parent->children;
156
157 for (; gIter != NULL; gIter = gIter->next) {
158 pe_resource_t *child = (pe_resource_t *) gIter->data;
159
160 pe__clear_resource_flags(child, pe_rsc_managed);
161 pe__set_resource_flags(child, pe_rsc_block);
162 }
163 }
164 break;
165 }
166 crm_debug("%s is active on multiple nodes including %s: %s",
167 rsc->id, node->details->uname,
168 recovery2text(rsc->recovery_type));
169
170 } else {
171 pe_rsc_trace(rsc, "Resource %s is active on: %s", rsc->id, node->details->uname);
172 }
173
174 if (rsc->parent != NULL) {
175 native_add_running(rsc->parent, node, data_set);
176 }
177 }
178
179 static void
180 recursive_clear_unique(pe_resource_t *rsc)
181 {
182 pe__clear_resource_flags(rsc, pe_rsc_unique);
183 add_hash_param(rsc->meta, XML_RSC_ATTR_UNIQUE, XML_BOOLEAN_FALSE);
184
185 for (GList *child = rsc->children; child != NULL; child = child->next) {
186 recursive_clear_unique((pe_resource_t *) child->data);
187 }
188 }
189
190 gboolean
191 native_unpack(pe_resource_t * rsc, pe_working_set_t * data_set)
192 {
193 pe_resource_t *parent = uber_parent(rsc);
194 native_variant_data_t *native_data = NULL;
195 const char *standard = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
196 uint32_t ra_caps = pcmk_get_ra_caps(standard);
197
198 pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
199
200 native_data = calloc(1, sizeof(native_variant_data_t));
201 rsc->variant_opaque = native_data;
202
203
204 if (!pcmk_is_set(ra_caps, pcmk_ra_cap_unique)
205 && pcmk_is_set(rsc->flags, pe_rsc_unique) && pe_rsc_is_clone(parent)) {
206
207
208
209
210
211
212 pe__force_anon(standard, parent, rsc->id, data_set);
213
214
215
216
217
218
219 recursive_clear_unique(parent);
220 recursive_clear_unique(rsc);
221 }
222 if (!pcmk_is_set(ra_caps, pcmk_ra_cap_promotable)
223 && pcmk_is_set(parent->flags, pe_rsc_promotable)) {
224
225 pe_err("Resource %s is of type %s and therefore "
226 "cannot be used as a promotable clone resource",
227 rsc->id, standard);
228 return FALSE;
229 }
230 return TRUE;
231 }
232
233 static bool
234 rsc_is_on_node(pe_resource_t *rsc, const pe_node_t *node, int flags)
235 {
236 pe_rsc_trace(rsc, "Checking whether %s is on %s",
237 rsc->id, node->details->uname);
238
239 if (pcmk_is_set(flags, pe_find_current) && rsc->running_on) {
240
241 for (GListPtr iter = rsc->running_on; iter; iter = iter->next) {
242 pe_node_t *loc = (pe_node_t *) iter->data;
243
244 if (loc->details == node->details) {
245 return TRUE;
246 }
247 }
248
249 } else if (pcmk_is_set(flags, pe_find_inactive)
250 && (rsc->running_on == NULL)) {
251 return TRUE;
252
253 } else if (!pcmk_is_set(flags, pe_find_current) && rsc->allocated_to
254 && (rsc->allocated_to->details == node->details)) {
255 return TRUE;
256 }
257 return FALSE;
258 }
259
260 pe_resource_t *
261 native_find_rsc(pe_resource_t * rsc, const char *id, const pe_node_t *on_node,
262 int flags)
263 {
264 bool match = FALSE;
265 pe_resource_t *result = NULL;
266
267 CRM_CHECK(id && rsc && rsc->id, return NULL);
268
269 if (flags & pe_find_clone) {
270 const char *rid = ID(rsc->xml);
271
272 if (!pe_rsc_is_clone(uber_parent(rsc))) {
273 match = FALSE;
274
275 } else if (!strcmp(id, rsc->id) || pcmk__str_eq(id, rid, pcmk__str_casei)) {
276 match = TRUE;
277 }
278
279 } else if (!strcmp(id, rsc->id)) {
280 match = TRUE;
281
282 } else if (pcmk_is_set(flags, pe_find_renamed)
283 && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
284 match = TRUE;
285
286 } else if (pcmk_is_set(flags, pe_find_any)
287 || (pcmk_is_set(flags, pe_find_anon)
288 && !pcmk_is_set(rsc->flags, pe_rsc_unique))) {
289 match = pe_base_name_eq(rsc, id);
290 }
291
292 if (match && on_node) {
293 bool match_node = rsc_is_on_node(rsc, on_node, flags);
294
295 if (match_node == FALSE) {
296 match = FALSE;
297 }
298 }
299
300 if (match) {
301 return rsc;
302 }
303
304 for (GListPtr gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
305 pe_resource_t *child = (pe_resource_t *) gIter->data;
306
307 result = rsc->fns->find_rsc(child, id, on_node, flags);
308 if (result) {
309 return result;
310 }
311 }
312 return NULL;
313 }
314
315 char *
316 native_parameter(pe_resource_t * rsc, pe_node_t * node, gboolean create, const char *name,
317 pe_working_set_t * data_set)
318 {
319 char *value_copy = NULL;
320 const char *value = NULL;
321 GHashTable *hash = NULL;
322 GHashTable *local_hash = NULL;
323
324 CRM_CHECK(rsc != NULL, return NULL);
325 CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
326
327 pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
328
329 if (create || g_hash_table_size(rsc->parameters) == 0) {
330 if (node != NULL) {
331 pe_rsc_trace(rsc, "Creating hash with node %s", node->details->uname);
332 } else {
333 pe_rsc_trace(rsc, "Creating default hash");
334 }
335
336 local_hash = crm_str_table_new();
337
338 get_rsc_attributes(local_hash, rsc, node, data_set);
339
340 hash = local_hash;
341 } else {
342 hash = rsc->parameters;
343 }
344
345 value = g_hash_table_lookup(hash, name);
346 if (value == NULL) {
347
348 value = g_hash_table_lookup(rsc->meta, name);
349 }
350
351 if (value != NULL) {
352 value_copy = strdup(value);
353 }
354 if (local_hash != NULL) {
355 g_hash_table_destroy(local_hash);
356 }
357 return value_copy;
358 }
359
360 gboolean
361 native_active(pe_resource_t * rsc, gboolean all)
362 {
363 for (GList *gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
364 pe_node_t *a_node = (pe_node_t *) gIter->data;
365
366 if (a_node->details->unclean) {
367 pe_rsc_trace(rsc, "Resource %s: node %s is unclean",
368 rsc->id, a_node->details->uname);
369 return TRUE;
370 } else if (a_node->details->online == FALSE) {
371 pe_rsc_trace(rsc, "Resource %s: node %s is offline",
372 rsc->id, a_node->details->uname);
373 } else {
374 pe_rsc_trace(rsc, "Resource %s active on %s",
375 rsc->id, a_node->details->uname);
376 return TRUE;
377 }
378 }
379 return FALSE;
380 }
381
382 struct print_data_s {
383 long options;
384 void *print_data;
385 };
386
387 static void
388 native_print_attr(gpointer key, gpointer value, gpointer user_data)
389 {
390 long options = ((struct print_data_s *)user_data)->options;
391 void *print_data = ((struct print_data_s *)user_data)->print_data;
392
393 status_print("Option: %s = %s\n", (char *)key, (char *)value);
394 }
395
396 static const char *
397 native_pending_state(pe_resource_t * rsc)
398 {
399 const char *pending_state = NULL;
400
401 if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_START, pcmk__str_casei)) {
402 pending_state = "Starting";
403
404 } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_STOP, pcmk__str_casei)) {
405 pending_state = "Stopping";
406
407 } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_MIGRATE, pcmk__str_casei)) {
408 pending_state = "Migrating";
409
410 } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_MIGRATED, pcmk__str_casei)) {
411
412 pending_state = "Migrating";
413
414 } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_PROMOTE, pcmk__str_casei)) {
415 pending_state = "Promoting";
416
417 } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_DEMOTE, pcmk__str_casei)) {
418 pending_state = "Demoting";
419 }
420
421 return pending_state;
422 }
423
424 static const char *
425 native_pending_task(pe_resource_t * rsc)
426 {
427 const char *pending_task = NULL;
428
429 if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_STATUS, pcmk__str_casei)) {
430 pending_task = "Monitoring";
431
432
433
434
435
436
437
438
439
440
441 }
442
443 return pending_task;
444 }
445
446 static enum rsc_role_e
447 native_displayable_role(pe_resource_t *rsc)
448 {
449 enum rsc_role_e role = rsc->role;
450
451 if ((role == RSC_ROLE_STARTED)
452 && pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable)) {
453
454 role = RSC_ROLE_SLAVE;
455 }
456 return role;
457 }
458
459 static const char *
460 native_displayable_state(pe_resource_t *rsc, long options)
461 {
462 const char *rsc_state = NULL;
463
464 if (options & pe_print_pending) {
465 rsc_state = native_pending_state(rsc);
466 }
467 if (rsc_state == NULL) {
468 rsc_state = role2text(native_displayable_role(rsc));
469 }
470 return rsc_state;
471 }
472
473 static void
474 native_print_xml(pe_resource_t * rsc, const char *pre_text, long options, void *print_data)
475 {
476 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
477 const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
478 const char *rsc_state = native_displayable_state(rsc, options);
479 const char *target_role = NULL;
480
481
482 status_print("%s<resource ", pre_text);
483 status_print("id=\"%s\" ", rsc_printable_id(rsc));
484 status_print("resource_agent=\"%s%s%s:%s\" ",
485 class,
486 prov ? "::" : "", prov ? prov : "", crm_element_value(rsc->xml, XML_ATTR_TYPE));
487
488 status_print("role=\"%s\" ", rsc_state);
489 if (rsc->meta) {
490 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
491 }
492 if (target_role) {
493 status_print("target_role=\"%s\" ", target_role);
494 }
495 status_print("active=\"%s\" ", pcmk__btoa(rsc->fns->active(rsc, TRUE)));
496 status_print("orphaned=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_orphan));
497 status_print("blocked=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_block));
498 status_print("managed=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_managed));
499 status_print("failed=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_failed));
500 status_print("failure_ignored=\"%s\" ",
501 pe__rsc_bool_str(rsc, pe_rsc_failure_ignored));
502 status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
503
504 if (options & pe_print_pending) {
505 const char *pending_task = native_pending_task(rsc);
506
507 if (pending_task) {
508 status_print("pending=\"%s\" ", pending_task);
509 }
510 }
511
512 if (options & pe_print_dev) {
513 status_print("provisional=\"%s\" ",
514 pe__rsc_bool_str(rsc, pe_rsc_provisional));
515 status_print("runnable=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_runnable));
516 status_print("priority=\"%f\" ", (double)rsc->priority);
517 status_print("variant=\"%s\" ", crm_element_name(rsc->xml));
518 }
519
520
521 if (options & pe_print_rsconly) {
522 status_print("/>\n");
523
524 } else if (rsc->running_on != NULL) {
525 GListPtr gIter = rsc->running_on;
526
527 status_print(">\n");
528 for (; gIter != NULL; gIter = gIter->next) {
529 pe_node_t *node = (pe_node_t *) gIter->data;
530
531 status_print("%s <node name=\"%s\" id=\"%s\" cached=\"%s\"/>\n", pre_text,
532 node->details->uname, node->details->id,
533 pcmk__btoa(node->details->online == FALSE));
534 }
535 status_print("%s</resource>\n", pre_text);
536 } else {
537 status_print("/>\n");
538 }
539 }
540
541
542 static bool
543 add_output_flag(GString *s, const char *flag_desc, bool have_flags)
544 {
545 g_string_append(s, (have_flags? ", " : " ("));
546 g_string_append(s, flag_desc);
547 return true;
548 }
549
550
551 static bool
552 add_output_node(GString *s, const char *node, bool have_nodes)
553 {
554 g_string_append(s, (have_nodes? " " : " [ "));
555 g_string_append(s, node);
556 return true;
557 }
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573 static gchar *
574 native_output_string(pe_resource_t *rsc, const char *name, pe_node_t *node,
575 long options, const char *target_role, bool show_nodes)
576 {
577 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
578 const char *provider = NULL;
579 const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
580 char *retval = NULL;
581 GString *outstr = NULL;
582 bool have_flags = false;
583
584 CRM_CHECK(name != NULL, name = "unknown");
585 CRM_CHECK(kind != NULL, kind = "unknown");
586 CRM_CHECK(class != NULL, class = "unknown");
587
588 if (pcmk_is_set(pcmk_get_ra_caps(class), pcmk_ra_cap_provider)) {
589 provider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
590 }
591
592 if ((node == NULL) && (rsc->lock_node != NULL)) {
593 node = rsc->lock_node;
594 }
595 if (pcmk_is_set(options, pe_print_rsconly)
596 || pcmk__list_of_multiple(rsc->running_on)) {
597 node = NULL;
598 }
599
600
601 outstr = g_string_sized_new(strlen(name) + strlen(class) + strlen(kind)
602 + (provider? (strlen(provider) + 2) : 0)
603 + (node? strlen(node->details->uname) + 1 : 0)
604 + 11);
605
606
607 g_string_printf(outstr, "%s\t(%s%s%s:%s):\t", name, class,
608
609
610
611
612 (provider? "::" : ""), (provider? provider : ""), kind);
613
614
615 if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
616 g_string_append(outstr, " ORPHANED");
617 }
618 if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
619 enum rsc_role_e role = native_displayable_role(rsc);
620
621 if (role > RSC_ROLE_SLAVE) {
622 g_string_append_printf(outstr, " FAILED %s", role2text(role));
623 } else {
624 g_string_append(outstr, " FAILED");
625 }
626 } else {
627 g_string_append_printf(outstr, " %s", native_displayable_state(rsc, options));
628 }
629 if (node) {
630 g_string_append_printf(outstr, " %s", node->details->uname);
631 }
632
633
634 if (node && !(node->details->online) && node->details->unclean) {
635 have_flags = add_output_flag(outstr, "UNCLEAN", have_flags);
636 }
637 if (node && (node == rsc->lock_node)) {
638 have_flags = add_output_flag(outstr, "LOCKED", have_flags);
639 }
640 if (pcmk_is_set(options, pe_print_pending)) {
641 const char *pending_task = native_pending_task(rsc);
642
643 if (pending_task) {
644 have_flags = add_output_flag(outstr, pending_task, have_flags);
645 }
646 }
647 if (target_role) {
648 enum rsc_role_e target_role_e = text2role(target_role);
649
650
651
652
653
654 if (target_role_e == RSC_ROLE_STOPPED) {
655 have_flags = add_output_flag(outstr, "disabled", have_flags);
656
657 } else if (pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable)
658 && target_role_e == RSC_ROLE_SLAVE) {
659 have_flags = add_output_flag(outstr, "target-role:", have_flags);
660 g_string_append(outstr, target_role);
661 }
662 }
663 if (pcmk_is_set(rsc->flags, pe_rsc_block)) {
664 have_flags = add_output_flag(outstr, "blocked", have_flags);
665 } else if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
666 have_flags = add_output_flag(outstr, "unmanaged", have_flags);
667 }
668 if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
669 have_flags = add_output_flag(outstr, "failure ignored", have_flags);
670 }
671 if (pcmk_is_set(options, pe_print_dev)) {
672 if (pcmk_is_set(options, pe_rsc_provisional)) {
673 have_flags = add_output_flag(outstr, "provisional", have_flags);
674 }
675 if (!pcmk_is_set(options, pe_rsc_runnable)) {
676 have_flags = add_output_flag(outstr, "non-startable", have_flags);
677 }
678 have_flags = add_output_flag(outstr, "variant:", have_flags);
679 g_string_append_printf(outstr, "%s priority:%f",
680 crm_element_name(rsc->xml),
681 (double) (rsc->priority));
682 }
683 if (have_flags) {
684 g_string_append(outstr, ")");
685 }
686
687
688 if (pcmk_is_set(options, pe_print_rsconly)
689 || pcmk__list_of_multiple(rsc->running_on)) {
690 const char *desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
691
692 if (desc) {
693 g_string_append_printf(outstr, " %s", desc);
694 }
695 }
696
697 if (show_nodes && !pcmk_is_set(options, pe_print_rsconly)
698 && pcmk__list_of_multiple(rsc->running_on)) {
699 bool have_nodes = false;
700
701 for (GList *iter = rsc->running_on; iter != NULL; iter = iter->next) {
702 pe_node_t *n = (pe_node_t *) iter->data;
703
704 have_nodes = add_output_node(outstr, n->details->uname, have_nodes);
705 }
706 if (have_nodes) {
707 g_string_append(outstr, " ]");
708 }
709 }
710
711 retval = outstr->str;
712 g_string_free(outstr, FALSE);
713 return retval;
714 }
715
716 int
717 pe__common_output_html(pcmk__output_t *out, pe_resource_t * rsc,
718 const char *name, pe_node_t *node, long options)
719 {
720 const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
721 const char *target_role = NULL;
722
723 xmlNodePtr list_node = NULL;
724 const char *cl = NULL;
725
726 CRM_ASSERT(rsc->variant == pe_native);
727 CRM_ASSERT(kind != NULL);
728
729 if (rsc->meta) {
730 const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
731
732 if (crm_is_true(is_internal)
733 && !pcmk_is_set(options, pe_print_implicit)) {
734
735 crm_trace("skipping print of internal resource %s", rsc->id);
736 return pcmk_rc_no_output;
737 }
738 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
739 }
740
741 if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
742 cl = "rsc-managed";
743
744 } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
745 cl = "rsc-failed";
746
747 } else if (rsc->variant == pe_native && (rsc->running_on == NULL)) {
748 cl = "rsc-failed";
749
750 } else if (pcmk__list_of_multiple(rsc->running_on)) {
751 cl = "rsc-multiple";
752
753 } else if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
754 cl = "rsc-failure-ignored";
755
756 } else {
757 cl = "rsc-ok";
758 }
759
760 {
761 gchar *s = native_output_string(rsc, name, node, options, target_role,
762 true);
763
764 list_node = pcmk__output_create_html_node(out, "li", NULL, NULL, NULL);
765 pcmk_create_html_node(list_node, "span", NULL, cl, s);
766 g_free(s);
767 }
768
769 if (pcmk_is_set(options, pe_print_details)) {
770 GHashTableIter iter;
771 gpointer key, value;
772
773 out->begin_list(out, NULL, NULL, "Options");
774 g_hash_table_iter_init(&iter, rsc->parameters);
775 while (g_hash_table_iter_next(&iter, &key, &value)) {
776 out->list_item(out, NULL, "Option: %s = %s", (char *) key, (char *) value);
777 }
778 out->end_list(out);
779 }
780
781 if (pcmk_is_set(options, pe_print_dev)) {
782 GHashTableIter iter;
783 pe_node_t *n = NULL;
784
785 out->begin_list(out, NULL, NULL, "Allowed Nodes");
786 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
787 while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
788 out->list_item(out, NULL, "%s %d", n->details->uname, n->weight);
789 }
790 out->end_list(out);
791 }
792
793 if (pcmk_is_set(options, pe_print_max_details)) {
794 GHashTableIter iter;
795 pe_node_t *n = NULL;
796
797 out->begin_list(out, NULL, NULL, "=== Allowed Nodes");
798 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
799 while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
800 pe__output_node(n, FALSE, out);
801 }
802 out->end_list(out);
803 }
804
805 return pcmk_rc_ok;
806 }
807
808 int
809 pe__common_output_text(pcmk__output_t *out, pe_resource_t * rsc,
810 const char *name, pe_node_t *node, long options)
811 {
812 const char *target_role = NULL;
813
814 CRM_ASSERT(rsc->variant == pe_native);
815
816 if (rsc->meta) {
817 const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
818
819 if (crm_is_true(is_internal)
820 && !pcmk_is_set(options, pe_print_implicit)) {
821
822 crm_trace("skipping print of internal resource %s", rsc->id);
823 return pcmk_rc_no_output;
824 }
825 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
826 }
827
828 {
829 gchar *s = native_output_string(rsc, name, node, options, target_role,
830 true);
831
832 out->list_item(out, NULL, "%s", s);
833 g_free(s);
834 }
835
836 if (pcmk_is_set(options, pe_print_details)) {
837 GHashTableIter iter;
838 gpointer key, value;
839
840 out->begin_list(out, NULL, NULL, "Options");
841 g_hash_table_iter_init(&iter, rsc->parameters);
842 while (g_hash_table_iter_next(&iter, &key, &value)) {
843 out->list_item(out, NULL, "Option: %s = %s", (char *) key, (char *) value);
844 }
845 out->end_list(out);
846 }
847
848 if (pcmk_is_set(options, pe_print_dev)) {
849 GHashTableIter iter;
850 pe_node_t *n = NULL;
851
852 out->begin_list(out, NULL, NULL, "Allowed Nodes");
853 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
854 while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
855 out->list_item(out, NULL, "%s %d", n->details->uname, n->weight);
856 }
857 out->end_list(out);
858 }
859
860 if (pcmk_is_set(options, pe_print_max_details)) {
861 GHashTableIter iter;
862 pe_node_t *n = NULL;
863
864 out->begin_list(out, NULL, NULL, "=== Allowed Nodes");
865 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
866 while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
867 pe__output_node(n, FALSE, out);
868 }
869 out->end_list(out);
870 }
871
872 return pcmk_rc_ok;
873 }
874
875 void
876 common_print(pe_resource_t * rsc, const char *pre_text, const char *name, pe_node_t *node, long options, void *print_data)
877 {
878 const char *target_role = NULL;
879
880 CRM_ASSERT(rsc->variant == pe_native);
881
882 if (rsc->meta) {
883 const char *is_internal = g_hash_table_lookup(rsc->meta,
884 XML_RSC_ATTR_INTERNAL_RSC);
885
886 if (crm_is_true(is_internal)
887 && !pcmk_is_set(options, pe_print_implicit)) {
888
889 crm_trace("skipping print of internal resource %s", rsc->id);
890 return;
891 }
892 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
893 }
894
895 if (options & pe_print_xml) {
896 native_print_xml(rsc, pre_text, options, print_data);
897 return;
898 }
899
900 if ((pre_text == NULL) && (options & pe_print_printf)) {
901 pre_text = " ";
902 }
903
904 if (options & pe_print_html) {
905 if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
906 status_print("<font color=\"yellow\">");
907
908 } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
909 status_print("<font color=\"red\">");
910
911 } else if (rsc->running_on == NULL) {
912 status_print("<font color=\"red\">");
913
914 } else if (pcmk__list_of_multiple(rsc->running_on)) {
915 status_print("<font color=\"orange\">");
916
917 } else if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
918 status_print("<font color=\"yellow\">");
919
920 } else {
921 status_print("<font color=\"green\">");
922 }
923 }
924
925 {
926 gchar *resource_s = native_output_string(rsc, name, node, options,
927 target_role, false);
928 status_print("%s%s", (pre_text? pre_text : ""), resource_s);
929 g_free(resource_s);
930 }
931
932 #if CURSES_ENABLED
933 if (pcmk_is_set(options, pe_print_ncurses)
934 && !pcmk_is_set(options, pe_print_rsconly)
935 && !pcmk__list_of_multiple(rsc->running_on)) {
936
937 move(-1, 0);
938 }
939 #endif
940
941 if (pcmk_is_set(options, pe_print_html)) {
942 status_print(" </font> ");
943 }
944
945 if (!pcmk_is_set(options, pe_print_rsconly)
946 && pcmk__list_of_multiple(rsc->running_on)) {
947
948 GListPtr gIter = rsc->running_on;
949 int counter = 0;
950
951 if (options & pe_print_html) {
952 status_print("<ul>\n");
953 } else if ((options & pe_print_printf)
954 || (options & pe_print_ncurses)) {
955 status_print("[");
956 }
957
958 for (; gIter != NULL; gIter = gIter->next) {
959 pe_node_t *n = (pe_node_t *) gIter->data;
960
961 counter++;
962
963 if (options & pe_print_html) {
964 status_print("<li>\n%s", n->details->uname);
965
966 } else if ((options & pe_print_printf)
967 || (options & pe_print_ncurses)) {
968 status_print(" %s", n->details->uname);
969
970 } else if ((options & pe_print_log)) {
971 status_print("\t%d : %s", counter, n->details->uname);
972
973 } else {
974 status_print("%s", n->details->uname);
975 }
976 if (options & pe_print_html) {
977 status_print("</li>\n");
978
979 }
980 }
981
982 if (options & pe_print_html) {
983 status_print("</ul>\n");
984 } else if ((options & pe_print_printf)
985 || (options & pe_print_ncurses)) {
986 status_print(" ]");
987 }
988 }
989
990 if (options & pe_print_html) {
991 status_print("<br/>\n");
992 } else if (options & pe_print_suppres_nl) {
993
994 } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
995 status_print("\n");
996 }
997
998 if (options & pe_print_details) {
999 struct print_data_s pdata;
1000
1001 pdata.options = options;
1002 pdata.print_data = print_data;
1003 g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata);
1004 }
1005
1006 if (options & pe_print_dev) {
1007 GHashTableIter iter;
1008 pe_node_t *n = NULL;
1009
1010 status_print("%s\tAllowed Nodes", pre_text);
1011 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1012 while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
1013 status_print("%s\t * %s %d", pre_text, n->details->uname, n->weight);
1014 }
1015 }
1016
1017 if (options & pe_print_max_details) {
1018 GHashTableIter iter;
1019 pe_node_t *n = NULL;
1020
1021 status_print("%s\t=== Allowed Nodes\n", pre_text);
1022 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1023 while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
1024 print_node("\t", n, FALSE);
1025 }
1026 }
1027 }
1028
1029 void
1030 native_print(pe_resource_t * rsc, const char *pre_text, long options, void *print_data)
1031 {
1032 pe_node_t *node = NULL;
1033
1034 CRM_ASSERT(rsc->variant == pe_native);
1035 if (options & pe_print_xml) {
1036 native_print_xml(rsc, pre_text, options, print_data);
1037 return;
1038 }
1039
1040 node = pe__current_node(rsc);
1041
1042 if (node == NULL) {
1043
1044 node = rsc->pending_node;
1045 }
1046
1047 common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
1048 }
1049
1050 PCMK__OUTPUT_ARGS("primitive", "unsigned int", "pe_resource_t *", "GListPtr", "GListPtr")
1051 int
1052 pe__resource_xml(pcmk__output_t *out, va_list args)
1053 {
1054 unsigned int options = va_arg(args, unsigned int);
1055 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1056 GListPtr only_node G_GNUC_UNUSED = va_arg(args, GListPtr);
1057 GListPtr only_rsc = va_arg(args, GListPtr);
1058
1059 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1060 const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
1061 const char *rsc_state = native_displayable_state(rsc, options);
1062
1063 long is_print_pending = options & pe_print_pending;
1064 long is_print_dev = options & pe_print_dev;
1065
1066 char ra_name[LINE_MAX];
1067 char *nodes_running_on = NULL;
1068 char *priority = NULL;
1069 int rc = pcmk_rc_no_output;
1070 const char *target_role = NULL;
1071
1072 if (rsc->meta != NULL) {
1073 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
1074 }
1075
1076 CRM_ASSERT(rsc->variant == pe_native);
1077
1078 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1079 return pcmk_rc_no_output;
1080 }
1081
1082
1083 sprintf(ra_name, "%s%s%s:%s", class, prov ? "::" : "", prov ? prov : ""
1084 , crm_element_value(rsc->xml, XML_ATTR_TYPE));
1085
1086 nodes_running_on = crm_itoa(g_list_length(rsc->running_on));
1087 priority = crm_ftoa(rsc->priority);
1088
1089 rc = pe__name_and_nvpairs_xml(out, true, "resource", 16,
1090 "id", rsc_printable_id(rsc),
1091 "resource_agent", ra_name,
1092 "role", rsc_state,
1093 "target_role", target_role,
1094 "active", pcmk__btoa(rsc->fns->active(rsc, TRUE)),
1095 "orphaned", pe__rsc_bool_str(rsc, pe_rsc_orphan),
1096 "blocked", pe__rsc_bool_str(rsc, pe_rsc_block),
1097 "managed", pe__rsc_bool_str(rsc, pe_rsc_managed),
1098 "failed", pe__rsc_bool_str(rsc, pe_rsc_failed),
1099 "failure_ignored", pe__rsc_bool_str(rsc, pe_rsc_failure_ignored),
1100 "nodes_running_on", nodes_running_on,
1101 "pending", (is_print_pending? native_pending_task(rsc) : NULL),
1102 "provisional", (is_print_dev? pe__rsc_bool_str(rsc, pe_rsc_provisional) : NULL),
1103 "runnable", (is_print_dev? pe__rsc_bool_str(rsc, pe_rsc_runnable) : NULL),
1104 "priority", (is_print_dev? priority : NULL),
1105 "variant", (is_print_dev? crm_element_name(rsc->xml) : NULL));
1106 free(priority);
1107 free(nodes_running_on);
1108
1109 CRM_ASSERT(rc == pcmk_rc_ok);
1110
1111 if (rsc->running_on != NULL) {
1112 GListPtr gIter = rsc->running_on;
1113
1114 for (; gIter != NULL; gIter = gIter->next) {
1115 pe_node_t *node = (pe_node_t *) gIter->data;
1116
1117 rc = pe__name_and_nvpairs_xml(out, false, "node", 3,
1118 "name", node->details->uname,
1119 "id", node->details->id,
1120 "cached", pcmk__btoa(node->details->online));
1121 CRM_ASSERT(rc == pcmk_rc_ok);
1122 }
1123 }
1124
1125 pcmk__output_xml_pop_parent(out);
1126 return rc;
1127 }
1128
1129 PCMK__OUTPUT_ARGS("primitive", "unsigned int", "pe_resource_t *", "GListPtr", "GListPtr")
1130 int
1131 pe__resource_html(pcmk__output_t *out, va_list args)
1132 {
1133 unsigned int options = va_arg(args, unsigned int);
1134 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1135 GListPtr only_node G_GNUC_UNUSED = va_arg(args, GListPtr);
1136 GListPtr only_rsc = va_arg(args, GListPtr);
1137
1138 pe_node_t *node = pe__current_node(rsc);
1139
1140 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1141 return pcmk_rc_no_output;
1142 }
1143
1144 CRM_ASSERT(rsc->variant == pe_native);
1145
1146 if (node == NULL) {
1147
1148 node = rsc->pending_node;
1149 }
1150 return pe__common_output_html(out, rsc, rsc_printable_id(rsc), node, options);
1151 }
1152
1153 PCMK__OUTPUT_ARGS("primitive", "unsigned int", "pe_resource_t *", "GListPtr", "GListPtr")
1154 int
1155 pe__resource_text(pcmk__output_t *out, va_list args)
1156 {
1157 unsigned int options = va_arg(args, unsigned int);
1158 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1159 GListPtr only_node G_GNUC_UNUSED = va_arg(args, GListPtr);
1160 GListPtr only_rsc = va_arg(args, GListPtr);
1161
1162 pe_node_t *node = pe__current_node(rsc);
1163
1164 CRM_ASSERT(rsc->variant == pe_native);
1165
1166 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1167 return pcmk_rc_no_output;
1168 }
1169
1170 if (node == NULL) {
1171
1172 node = rsc->pending_node;
1173 }
1174 return pe__common_output_text(out, rsc, rsc_printable_id(rsc), node, options);
1175 }
1176
1177 void
1178 native_free(pe_resource_t * rsc)
1179 {
1180 pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
1181 common_free(rsc);
1182 }
1183
1184 enum rsc_role_e
1185 native_resource_state(const pe_resource_t * rsc, gboolean current)
1186 {
1187 enum rsc_role_e role = rsc->next_role;
1188
1189 if (current) {
1190 role = rsc->role;
1191 }
1192 pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
1193 return role;
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206 pe_node_t *
1207 native_location(const pe_resource_t *rsc, GList **list, int current)
1208 {
1209 pe_node_t *one = NULL;
1210 GListPtr result = NULL;
1211
1212 if (rsc->children) {
1213 GListPtr gIter = rsc->children;
1214
1215 for (; gIter != NULL; gIter = gIter->next) {
1216 pe_resource_t *child = (pe_resource_t *) gIter->data;
1217
1218 child->fns->location(child, &result, current);
1219 }
1220
1221 } else if (current) {
1222
1223 if (rsc->running_on) {
1224 result = g_list_copy(rsc->running_on);
1225 }
1226 if ((current == 2) && rsc->pending_node
1227 && !pe_find_node_id(result, rsc->pending_node->details->id)) {
1228 result = g_list_append(result, rsc->pending_node);
1229 }
1230
1231 } else if (current == FALSE && rsc->allocated_to) {
1232 result = g_list_append(NULL, rsc->allocated_to);
1233 }
1234
1235 if (result && (result->next == NULL)) {
1236 one = result->data;
1237 }
1238
1239 if (list) {
1240 GListPtr gIter = result;
1241
1242 for (; gIter != NULL; gIter = gIter->next) {
1243 pe_node_t *node = (pe_node_t *) gIter->data;
1244
1245 if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
1246 *list = g_list_append(*list, node);
1247 }
1248 }
1249 }
1250
1251 g_list_free(result);
1252 return one;
1253 }
1254
1255 static void
1256 get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_table)
1257 {
1258 GListPtr gIter = rsc_list;
1259
1260 for (; gIter != NULL; gIter = gIter->next) {
1261 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1262
1263 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1264 const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
1265
1266 int offset = 0;
1267 char buffer[LINE_MAX];
1268
1269 int *rsc_counter = NULL;
1270 int *active_counter = NULL;
1271
1272 if (rsc->variant != pe_native) {
1273 continue;
1274 }
1275
1276 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
1277 if (pcmk_is_set(pcmk_get_ra_caps(class), pcmk_ra_cap_provider)) {
1278 const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
1279 offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
1280 }
1281 offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
1282 CRM_LOG_ASSERT(offset > 0);
1283
1284 if (rsc_table) {
1285 rsc_counter = g_hash_table_lookup(rsc_table, buffer);
1286 if (rsc_counter == NULL) {
1287 rsc_counter = calloc(1, sizeof(int));
1288 *rsc_counter = 0;
1289 g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
1290 }
1291 (*rsc_counter)++;
1292 }
1293
1294 if (active_table) {
1295 GListPtr gIter2 = rsc->running_on;
1296
1297 for (; gIter2 != NULL; gIter2 = gIter2->next) {
1298 pe_node_t *node = (pe_node_t *) gIter2->data;
1299 GHashTable *node_table = NULL;
1300
1301 if (node->details->unclean == FALSE && node->details->online == FALSE) {
1302 continue;
1303 }
1304
1305 node_table = g_hash_table_lookup(active_table, node->details->uname);
1306 if (node_table == NULL) {
1307 node_table = crm_str_table_new();
1308 g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
1309 }
1310
1311 active_counter = g_hash_table_lookup(node_table, buffer);
1312 if (active_counter == NULL) {
1313 active_counter = calloc(1, sizeof(int));
1314 *active_counter = 0;
1315 g_hash_table_insert(node_table, strdup(buffer), active_counter);
1316 }
1317 (*active_counter)++;
1318 }
1319 }
1320 }
1321 }
1322
1323 static void
1324 destroy_node_table(gpointer data)
1325 {
1326 GHashTable *node_table = data;
1327
1328 if (node_table) {
1329 g_hash_table_destroy(node_table);
1330 }
1331 }
1332
1333 void
1334 print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options,
1335 void *print_data, gboolean print_all)
1336 {
1337 GHashTable *rsc_table = crm_str_table_new();
1338 GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal,
1339 free, destroy_node_table);
1340 GHashTableIter hash_iter;
1341 char *type = NULL;
1342 int *rsc_counter = NULL;
1343
1344 get_rscs_brief(rsc_list, rsc_table, active_table);
1345
1346 g_hash_table_iter_init(&hash_iter, rsc_table);
1347 while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
1348 GHashTableIter hash_iter2;
1349 char *node_name = NULL;
1350 GHashTable *node_table = NULL;
1351 int active_counter_all = 0;
1352
1353 g_hash_table_iter_init(&hash_iter2, active_table);
1354 while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
1355 int *active_counter = g_hash_table_lookup(node_table, type);
1356
1357 if (active_counter == NULL || *active_counter == 0) {
1358 continue;
1359
1360 } else {
1361 active_counter_all += *active_counter;
1362 }
1363
1364 if (options & pe_print_rsconly) {
1365 node_name = NULL;
1366 }
1367
1368 if (options & pe_print_html) {
1369 status_print("<li>\n");
1370 }
1371
1372 if (print_all) {
1373 status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1374 active_counter ? *active_counter : 0,
1375 rsc_counter ? *rsc_counter : 0, type,
1376 active_counter && (*active_counter > 0) && node_name ? node_name : "");
1377 } else {
1378 status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1379 active_counter ? *active_counter : 0, type,
1380 active_counter && (*active_counter > 0) && node_name ? node_name : "");
1381 }
1382
1383 if (options & pe_print_html) {
1384 status_print("</li>\n");
1385 }
1386 }
1387
1388 if (print_all && active_counter_all == 0) {
1389 if (options & pe_print_html) {
1390 status_print("<li>\n");
1391 }
1392
1393 status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
1394 active_counter_all,
1395 rsc_counter ? *rsc_counter : 0, type);
1396
1397 if (options & pe_print_html) {
1398 status_print("</li>\n");
1399 }
1400 }
1401 }
1402
1403 if (rsc_table) {
1404 g_hash_table_destroy(rsc_table);
1405 rsc_table = NULL;
1406 }
1407 if (active_table) {
1408 g_hash_table_destroy(active_table);
1409 active_table = NULL;
1410 }
1411 }
1412
1413 int
1414 pe__rscs_brief_output(pcmk__output_t *out, GListPtr rsc_list, long options, gboolean print_all)
1415 {
1416 GHashTable *rsc_table = crm_str_table_new();
1417 GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal,
1418 free, destroy_node_table);
1419 GListPtr sorted_rscs;
1420 int rc = pcmk_rc_no_output;
1421
1422 get_rscs_brief(rsc_list, rsc_table, active_table);
1423
1424
1425
1426
1427 sorted_rscs = g_hash_table_get_keys(rsc_table);
1428 sorted_rscs = g_list_sort(sorted_rscs, (GCompareFunc) strcmp);
1429
1430 for (GListPtr gIter = sorted_rscs; gIter; gIter = gIter->next) {
1431 char *type = (char *) gIter->data;
1432 int *rsc_counter = g_hash_table_lookup(rsc_table, type);
1433
1434 GHashTableIter hash_iter2;
1435 char *node_name = NULL;
1436 GHashTable *node_table = NULL;
1437 int active_counter_all = 0;
1438
1439 g_hash_table_iter_init(&hash_iter2, active_table);
1440 while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
1441 int *active_counter = g_hash_table_lookup(node_table, type);
1442
1443 if (active_counter == NULL || *active_counter == 0) {
1444 continue;
1445
1446 } else {
1447 active_counter_all += *active_counter;
1448 }
1449
1450 if (options & pe_print_rsconly) {
1451 node_name = NULL;
1452 }
1453
1454 if (print_all) {
1455 out->list_item(out, NULL, " %d/%d\t(%s):\tActive %s",
1456 *active_counter,
1457 rsc_counter ? *rsc_counter : 0, type,
1458 (*active_counter > 0) && node_name ? node_name : "");
1459 } else {
1460 out->list_item(out, NULL, " %d\t(%s):\tActive %s",
1461 *active_counter, type,
1462 (*active_counter > 0) && node_name ? node_name : "");
1463 }
1464
1465 rc = pcmk_rc_ok;
1466 }
1467
1468 if (print_all && active_counter_all == 0) {
1469 out->list_item(out, NULL, " %d/%d\t(%s):\tActive",
1470 active_counter_all,
1471 rsc_counter ? *rsc_counter : 0, type);
1472 rc = pcmk_rc_ok;
1473 }
1474 }
1475
1476 if (rsc_table) {
1477 g_hash_table_destroy(rsc_table);
1478 rsc_table = NULL;
1479 }
1480 if (active_table) {
1481 g_hash_table_destroy(active_table);
1482 active_table = NULL;
1483 }
1484 if (sorted_rscs) {
1485 g_list_free(sorted_rscs);
1486 }
1487
1488 return rc;
1489 }
1490
1491 gboolean
1492 pe__native_is_filtered(pe_resource_t *rsc, GListPtr only_rsc, gboolean check_parent)
1493 {
1494 if (pcmk__str_in_list(only_rsc, rsc_printable_id(rsc)) ||
1495 pcmk__str_in_list(only_rsc, rsc->id)) {
1496 return FALSE;
1497 } else if (check_parent) {
1498 pe_resource_t *up = uber_parent(rsc);
1499
1500 if (pe_rsc_is_bundled(rsc)) {
1501 return up->parent->fns->is_filtered(up->parent, only_rsc, FALSE);
1502 } else {
1503 return up->fns->is_filtered(up, only_rsc, FALSE);
1504 }
1505 }
1506
1507 return TRUE;
1508 }