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