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