This source file includes following definitions.
- native_add_running
- 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
- comma_if
- common_print
- native_print
- native_free
- native_resource_state
- native_location
- get_rscs_brief
- destroy_node_table
- print_rscs_brief
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20
21 #include <crm/pengine/rules.h>
22 #include <crm/pengine/status.h>
23 #include <crm/pengine/complex.h>
24 #include <crm/pengine/internal.h>
25 #include <unpack.h>
26 #include <crm/msg_xml.h>
27
28 #define VARIANT_NATIVE 1
29 #include "./variant.h"
30
31 void
32 native_add_running(resource_t * rsc, node_t * node, pe_working_set_t * data_set)
33 {
34 GListPtr gIter = rsc->running_on;
35
36 CRM_CHECK(node != NULL, return);
37 for (; gIter != NULL; gIter = gIter->next) {
38 node_t *a_node = (node_t *) gIter->data;
39
40 CRM_CHECK(a_node != NULL, return);
41 if (safe_str_eq(a_node->details->id, node->details->id)) {
42 return;
43 }
44 }
45
46 pe_rsc_trace(rsc, "Adding %s to %s %s", rsc->id, node->details->uname,
47 is_set(rsc->flags, pe_rsc_managed)?"":"(unmanaged)");
48
49 rsc->running_on = g_list_append(rsc->running_on, node);
50 if (rsc->variant == pe_native) {
51 node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
52 }
53
54 if (rsc->variant == pe_native && node->details->maintenance) {
55 clear_bit(rsc->flags, pe_rsc_managed);
56 }
57
58 if (is_not_set(rsc->flags, pe_rsc_managed)) {
59 resource_t *p = rsc->parent;
60
61 pe_rsc_info(rsc, "resource %s isn't managed", rsc->id);
62 resource_location(rsc, node, INFINITY, "not_managed_default", data_set);
63
64 while(p && node->details->online) {
65
66 p->running_on = g_list_append(p->running_on, node);
67 p = p->parent;
68 }
69 return;
70 }
71
72 if (rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) {
73 switch (rsc->recovery_type) {
74 case recovery_stop_only:
75 {
76 GHashTableIter gIter;
77 node_t *local_node = NULL;
78
79
80 g_hash_table_destroy(rsc->allowed_nodes);
81 rsc->allowed_nodes = node_hash_from_list(data_set->nodes);
82 g_hash_table_iter_init(&gIter, rsc->allowed_nodes);
83 while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
84 local_node->weight = -INFINITY;
85 }
86 }
87 break;
88 case recovery_stop_start:
89 break;
90 case recovery_block:
91 clear_bit(rsc->flags, pe_rsc_managed);
92 set_bit(rsc->flags, pe_rsc_block);
93
94
95
96
97 if (rsc->parent
98 && (rsc->parent->variant == pe_group || rsc->parent->variant == pe_container)
99 && rsc->parent->recovery_type == recovery_block) {
100 GListPtr gIter = rsc->parent->children;
101
102 for (; gIter != NULL; gIter = gIter->next) {
103 resource_t *child = (resource_t *) gIter->data;
104
105 clear_bit(child->flags, pe_rsc_managed);
106 set_bit(child->flags, pe_rsc_block);
107 }
108 }
109 break;
110 }
111 crm_debug("%s is active on %d nodes including %s: %s",
112 rsc->id, g_list_length(rsc->running_on), node->details->uname,
113 recovery2text(rsc->recovery_type));
114
115 } else {
116 pe_rsc_trace(rsc, "Resource %s is active on: %s", rsc->id, node->details->uname);
117 }
118
119 if (rsc->parent != NULL) {
120 native_add_running(rsc->parent, node, data_set);
121 }
122 }
123
124 extern void force_non_unique_clone(resource_t * rsc, const char *rid, pe_working_set_t * data_set);
125
126 gboolean
127 native_unpack(resource_t * rsc, pe_working_set_t * data_set)
128 {
129 resource_t *parent = uber_parent(rsc);
130 native_variant_data_t *native_data = NULL;
131 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
132
133 pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
134
135 native_data = calloc(1, sizeof(native_variant_data_t));
136 rsc->variant_opaque = native_data;
137
138 if (is_set(rsc->flags, pe_rsc_unique) && rsc->parent) {
139
140 if (safe_str_eq(class, PCMK_RESOURCE_CLASS_LSB)) {
141 resource_t *top = uber_parent(rsc);
142
143 force_non_unique_clone(top, rsc->id, data_set);
144 }
145 }
146
147 if (safe_str_eq(class, PCMK_RESOURCE_CLASS_OCF) == FALSE) {
148 const char *stateful = g_hash_table_lookup(parent->meta, "stateful");
149
150 if (safe_str_eq(stateful, XML_BOOLEAN_TRUE)) {
151 pe_err
152 ("Resource %s is of type %s and therefore cannot be used as a master/slave resource",
153 rsc->id, class);
154 return FALSE;
155 }
156 }
157
158 return TRUE;
159 }
160
161 static bool
162 rsc_is_on_node(resource_t *rsc, node_t *node, int flags)
163 {
164 pe_rsc_trace(rsc, "Checking whether %s is on %s",
165 rsc->id, node->details->uname);
166
167 if (is_set(flags, pe_find_current) && rsc->running_on) {
168
169 for (GListPtr iter = rsc->running_on; iter; iter = iter->next) {
170 node_t *loc = (node_t *) iter->data;
171
172 if (loc->details == node->details) {
173 return TRUE;
174 }
175 }
176
177 } else if (is_set(flags, pe_find_inactive) && (rsc->running_on == NULL)) {
178 return TRUE;
179
180 } else if (is_not_set(flags, pe_find_current) && rsc->allocated_to
181 && (rsc->allocated_to->details == node->details)) {
182 return TRUE;
183 }
184 return FALSE;
185 }
186
187 resource_t *
188 native_find_rsc(resource_t * rsc, const char *id, node_t * on_node, int flags)
189 {
190 bool match = FALSE;
191 resource_t *result = NULL;
192
193 CRM_CHECK(id && rsc && rsc->id, return NULL);
194
195 if (flags & pe_find_clone) {
196 const char *rid = ID(rsc->xml);
197
198 if (!pe_rsc_is_clone(uber_parent(rsc))) {
199 match = FALSE;
200
201 } else if (!strcmp(id, rsc->id) || safe_str_eq(id, rid)) {
202 match = TRUE;
203 }
204
205 } else if (!strcmp(id, rsc->id)) {
206 match = TRUE;
207
208 } else if (is_set(flags, pe_find_renamed)
209 && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
210 match = TRUE;
211
212 } else if (is_set(flags, pe_find_any)
213 || (is_set(flags, pe_find_anon)
214 && is_not_set(rsc->flags, pe_rsc_unique))) {
215 match = pe_base_name_eq(rsc, id);
216 }
217
218 if (match && on_node) {
219 bool match_node = rsc_is_on_node(rsc, on_node, flags);
220
221 if (match_node == FALSE) {
222 match = FALSE;
223 }
224 }
225
226 if (match) {
227 return rsc;
228 }
229
230 for (GListPtr gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
231 resource_t *child = (resource_t *) gIter->data;
232
233 result = rsc->fns->find_rsc(child, id, on_node, flags);
234 if (result) {
235 return result;
236 }
237 }
238 return NULL;
239 }
240
241 char *
242 native_parameter(resource_t * rsc, node_t * node, gboolean create, const char *name,
243 pe_working_set_t * data_set)
244 {
245 char *value_copy = NULL;
246 const char *value = NULL;
247 GHashTable *hash = rsc->parameters;
248 GHashTable *local_hash = NULL;
249
250 CRM_CHECK(rsc != NULL, return NULL);
251 CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
252
253 pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
254
255 if (create || g_hash_table_size(rsc->parameters) == 0) {
256 if (node != NULL) {
257 pe_rsc_trace(rsc, "Creating hash with node %s", node->details->uname);
258 } else {
259 pe_rsc_trace(rsc, "Creating default hash");
260 }
261
262 local_hash = crm_str_table_new();
263
264 get_rsc_attributes(local_hash, rsc, node, data_set);
265
266 hash = local_hash;
267 }
268
269 value = g_hash_table_lookup(hash, name);
270 if (value == NULL) {
271
272 value = g_hash_table_lookup(rsc->meta, name);
273 }
274
275 if (value != NULL) {
276 value_copy = strdup(value);
277 }
278 if (local_hash != NULL) {
279 g_hash_table_destroy(local_hash);
280 }
281 return value_copy;
282 }
283
284 gboolean
285 native_active(resource_t * rsc, gboolean all)
286 {
287 GListPtr gIter = rsc->running_on;
288
289 for (; gIter != NULL; gIter = gIter->next) {
290 node_t *a_node = (node_t *) gIter->data;
291
292 if (a_node->details->unclean) {
293 crm_debug("Resource %s: node %s is unclean", rsc->id, a_node->details->uname);
294 return TRUE;
295 } else if (a_node->details->online == FALSE) {
296 crm_debug("Resource %s: node %s is offline", rsc->id, a_node->details->uname);
297 } else {
298 crm_debug("Resource %s active on %s", rsc->id, a_node->details->uname);
299 return TRUE;
300 }
301 }
302
303 return FALSE;
304 }
305
306 struct print_data_s {
307 long options;
308 void *print_data;
309 };
310
311 static void
312 native_print_attr(gpointer key, gpointer value, gpointer user_data)
313 {
314 long options = ((struct print_data_s *)user_data)->options;
315 void *print_data = ((struct print_data_s *)user_data)->print_data;
316
317 status_print("Option: %s = %s\n", (char *)key, (char *)value);
318 }
319
320 static const char *
321 native_pending_state(resource_t * rsc)
322 {
323 const char *pending_state = NULL;
324
325 if (safe_str_eq(rsc->pending_task, CRMD_ACTION_START)) {
326 pending_state = "Starting";
327
328 } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STOP)) {
329 pending_state = "Stopping";
330
331 } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATE)) {
332 pending_state = "Migrating";
333
334 } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATED)) {
335
336 pending_state = "Migrating";
337
338 } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_PROMOTE)) {
339 pending_state = "Promoting";
340
341 } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_DEMOTE)) {
342 pending_state = "Demoting";
343 }
344
345 return pending_state;
346 }
347
348 static const char *
349 native_pending_task(resource_t * rsc)
350 {
351 const char *pending_task = NULL;
352
353 if (safe_str_eq(rsc->pending_task, CRMD_ACTION_NOTIFY)) {
354
355 pending_task = NULL;
356
357 } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STATUS)) {
358 pending_task = "Monitoring";
359
360
361
362
363
364
365
366
367
368
369 }
370
371 return pending_task;
372 }
373
374 static enum rsc_role_e
375 native_displayable_role(resource_t *rsc)
376 {
377 enum rsc_role_e role = rsc->role;
378
379 if ((role == RSC_ROLE_STARTED)
380 && (uber_parent(rsc)->variant == pe_master)) {
381
382 role = RSC_ROLE_SLAVE;
383 }
384 return role;
385 }
386
387 static const char *
388 native_displayable_state(resource_t *rsc, long options)
389 {
390 const char *rsc_state = NULL;
391
392 if (options & pe_print_pending) {
393 rsc_state = native_pending_state(rsc);
394 }
395 if (rsc_state == NULL) {
396 rsc_state = role2text(native_displayable_role(rsc));
397 }
398 return rsc_state;
399 }
400
401 static void
402 native_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data)
403 {
404 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
405 const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
406 const char *rsc_state = native_displayable_state(rsc, options);
407 const char *target_role = NULL;
408
409
410 status_print("%s<resource ", pre_text);
411 status_print("id=\"%s\" ", rsc_printable_id(rsc));
412 status_print("resource_agent=\"%s%s%s:%s\" ",
413 class,
414 prov ? "::" : "", prov ? prov : "", crm_element_value(rsc->xml, XML_ATTR_TYPE));
415
416 status_print("role=\"%s\" ", rsc_state);
417 if (rsc->meta) {
418 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
419 }
420 if (target_role) {
421 status_print("target_role=\"%s\" ", target_role);
422 }
423 status_print("active=\"%s\" ", rsc->fns->active(rsc, TRUE) ? "true" : "false");
424 status_print("orphaned=\"%s\" ", is_set(rsc->flags, pe_rsc_orphan) ? "true" : "false");
425 status_print("blocked=\"%s\" ", is_set(rsc->flags, pe_rsc_block) ? "true" : "false");
426 status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false");
427 status_print("failed=\"%s\" ", is_set(rsc->flags, pe_rsc_failed) ? "true" : "false");
428 status_print("failure_ignored=\"%s\" ",
429 is_set(rsc->flags, pe_rsc_failure_ignored) ? "true" : "false");
430 status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
431
432 if (options & pe_print_pending) {
433 const char *pending_task = native_pending_task(rsc);
434
435 if (pending_task) {
436 status_print("pending=\"%s\" ", pending_task);
437 }
438 }
439
440 if (options & pe_print_dev) {
441 status_print("provisional=\"%s\" ",
442 is_set(rsc->flags, pe_rsc_provisional) ? "true" : "false");
443 status_print("runnable=\"%s\" ", is_set(rsc->flags, pe_rsc_runnable) ? "true" : "false");
444 status_print("priority=\"%f\" ", (double)rsc->priority);
445 status_print("variant=\"%s\" ", crm_element_name(rsc->xml));
446 }
447
448
449 if (options & pe_print_rsconly) {
450 status_print("/>\n");
451
452 } else if (g_list_length(rsc->running_on) > 0) {
453 GListPtr gIter = rsc->running_on;
454
455 status_print(">\n");
456 for (; gIter != NULL; gIter = gIter->next) {
457 node_t *node = (node_t *) gIter->data;
458
459 status_print("%s <node name=\"%s\" id=\"%s\" cached=\"%s\"/>\n", pre_text,
460 node->details->uname, node->details->id,
461 node->details->online ? "false" : "true");
462 }
463 status_print("%s</resource>\n", pre_text);
464 } else {
465 status_print("/>\n");
466 }
467 }
468
469
470
471
472 static inline const char *
473 comma_if(int i)
474 {
475 return i? ", " : "";
476 }
477
478 void
479 common_print(resource_t * rsc, const char *pre_text, const char *name, node_t *node, long options, void *print_data)
480 {
481 const char *desc = NULL;
482 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
483 const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
484 const char *target_role = NULL;
485 enum rsc_role_e role = native_displayable_role(rsc);
486
487 int offset = 0;
488 int flagOffset = 0;
489 char buffer[LINE_MAX];
490 char flagBuffer[LINE_MAX];
491
492 CRM_ASSERT(rsc->variant == pe_native);
493 CRM_ASSERT(kind != NULL);
494
495 if (rsc->meta) {
496 const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
497 if (crm_is_true(is_internal) && is_not_set(options, pe_print_implicit)) {
498 crm_trace("skipping print of internal resource %s", rsc->id);
499 return;
500 }
501 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
502 }
503
504 if (pre_text == NULL && (options & pe_print_printf)) {
505 pre_text = " ";
506 }
507
508 if (options & pe_print_xml) {
509 native_print_xml(rsc, pre_text, options, print_data);
510 return;
511 }
512
513 if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
514 node = NULL;
515 }
516
517 if (options & pe_print_html) {
518 if (is_not_set(rsc->flags, pe_rsc_managed)) {
519 status_print("<font color=\"yellow\">");
520
521 } else if (is_set(rsc->flags, pe_rsc_failed)) {
522 status_print("<font color=\"red\">");
523
524 } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) {
525 status_print("<font color=\"red\">");
526
527 } else if (g_list_length(rsc->running_on) > 1) {
528 status_print("<font color=\"orange\">");
529
530 } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) {
531 status_print("<font color=\"yellow\">");
532
533 } else {
534 status_print("<font color=\"green\">");
535 }
536 }
537
538 if(pre_text) {
539 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", pre_text);
540 }
541 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", name);
542 offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class);
543 if (crm_provider_required(class)) {
544 const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
545 offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
546 }
547 offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s):\t", kind);
548 if(is_set(rsc->flags, pe_rsc_orphan)) {
549 offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED ");
550 }
551 if(role > RSC_ROLE_SLAVE && is_set(rsc->flags, pe_rsc_failed)) {
552 offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s", role2text(role));
553 } else if(is_set(rsc->flags, pe_rsc_failed)) {
554 offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED");
555 } else {
556 const char *rsc_state = native_displayable_state(rsc, options);
557
558 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_state);
559 }
560
561 if(node) {
562 offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", node->details->uname);
563
564 if (node->details->online == FALSE && node->details->unclean) {
565 flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
566 "%sUNCLEAN", comma_if(flagOffset));
567 }
568 }
569
570 if (options & pe_print_pending) {
571 const char *pending_task = native_pending_task(rsc);
572
573 if (pending_task) {
574 flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
575 "%s%s", comma_if(flagOffset), pending_task);
576 }
577 }
578
579 if (target_role) {
580 enum rsc_role_e target_role_e = text2role(target_role);
581
582
583
584
585 if (target_role_e == RSC_ROLE_STOPPED) {
586 flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
587 "%sdisabled", comma_if(flagOffset));
588 rsc->cluster->disabled_resources++;
589
590 } else if (uber_parent(rsc)->variant == pe_master
591 && target_role_e == RSC_ROLE_SLAVE) {
592 flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
593 "%starget-role:%s", comma_if(flagOffset), target_role);
594 rsc->cluster->disabled_resources++;
595 }
596 }
597
598 if (is_set(rsc->flags, pe_rsc_block)) {
599 flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
600 "%sblocked", comma_if(flagOffset));
601 rsc->cluster->blocked_resources++;
602
603 } else if (is_not_set(rsc->flags, pe_rsc_managed)) {
604 flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
605 "%sunmanaged", comma_if(flagOffset));
606 }
607
608 if(is_set(rsc->flags, pe_rsc_failure_ignored)) {
609 flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
610 "%sfailure ignored", comma_if(flagOffset));
611 }
612
613 if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
614 desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
615 }
616
617 CRM_LOG_ASSERT(offset > 0);
618 if(flagOffset > 0) {
619 status_print("%s (%s)%s%s", buffer, flagBuffer, desc?" ":"", desc?desc:"");
620 } else {
621 status_print("%s%s%s", buffer, desc?" ":"", desc?desc:"");
622 }
623
624 #if CURSES_ENABLED
625 if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
626
627
628 } else if (options & pe_print_ncurses) {
629
630 move(-1, 0);
631 }
632 #endif
633
634 if (options & pe_print_html) {
635 status_print(" </font> ");
636 }
637
638 if ((options & pe_print_rsconly)) {
639
640 } else if (g_list_length(rsc->running_on) > 1) {
641 GListPtr gIter = rsc->running_on;
642 int counter = 0;
643
644 if (options & pe_print_html) {
645 status_print("<ul>\n");
646 } else if ((options & pe_print_printf)
647 || (options & pe_print_ncurses)) {
648 status_print("[");
649 }
650
651 for (; gIter != NULL; gIter = gIter->next) {
652 node_t *n = (node_t *) gIter->data;
653
654 counter++;
655
656 if (options & pe_print_html) {
657 status_print("<li>\n%s", n->details->uname);
658
659 } else if ((options & pe_print_printf)
660 || (options & pe_print_ncurses)) {
661 status_print(" %s", n->details->uname);
662
663 } else if ((options & pe_print_log)) {
664 status_print("\t%d : %s", counter, n->details->uname);
665
666 } else {
667 status_print("%s", n->details->uname);
668 }
669 if (options & pe_print_html) {
670 status_print("</li>\n");
671
672 }
673 }
674
675 if (options & pe_print_html) {
676 status_print("</ul>\n");
677 } else if ((options & pe_print_printf)
678 || (options & pe_print_ncurses)) {
679 status_print(" ]");
680 }
681 }
682
683 if (options & pe_print_html) {
684 status_print("<br/>\n");
685 } else if (options & pe_print_suppres_nl) {
686
687 } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
688 status_print("\n");
689 }
690
691 if (options & pe_print_details) {
692 struct print_data_s pdata;
693
694 pdata.options = options;
695 pdata.print_data = print_data;
696 g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata);
697 }
698
699 if (options & pe_print_dev) {
700 GHashTableIter iter;
701 node_t *n = NULL;
702
703 status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text,
704 is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "",
705 is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ",
706 crm_element_name(rsc->xml), (double)rsc->priority);
707 status_print("%s\tAllowed Nodes", pre_text);
708 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
709 while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
710 status_print("%s\t * %s %d", pre_text, n->details->uname, n->weight);
711 }
712 }
713
714 if (options & pe_print_max_details) {
715 GHashTableIter iter;
716 node_t *n = NULL;
717
718 status_print("%s\t=== Allowed Nodes\n", pre_text);
719 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
720 while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
721 print_node("\t", n, FALSE);
722 }
723 }
724 }
725
726 void
727 native_print(resource_t * rsc, const char *pre_text, long options, void *print_data)
728 {
729 node_t *node = NULL;
730
731 CRM_ASSERT(rsc->variant == pe_native);
732 if (options & pe_print_xml) {
733 native_print_xml(rsc, pre_text, options, print_data);
734 return;
735 }
736
737 if (rsc->running_on != NULL) {
738 node = rsc->running_on->data;
739 }
740 common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
741 }
742
743 void
744 native_free(resource_t * rsc)
745 {
746 pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
747 common_free(rsc);
748 }
749
750 enum rsc_role_e
751 native_resource_state(const resource_t * rsc, gboolean current)
752 {
753 enum rsc_role_e role = rsc->next_role;
754
755 if (current) {
756 role = rsc->role;
757 }
758 pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
759 return role;
760 }
761
762 node_t *
763 native_location(resource_t * rsc, GListPtr * list, gboolean current)
764 {
765 node_t *one = NULL;
766 GListPtr result = NULL;
767
768 if (rsc->children) {
769 GListPtr gIter = rsc->children;
770
771 for (; gIter != NULL; gIter = gIter->next) {
772 resource_t *child = (resource_t *) gIter->data;
773
774 child->fns->location(child, &result, current);
775 }
776
777 } else if (current && rsc->running_on) {
778 result = g_list_copy(rsc->running_on);
779
780 } else if (current == FALSE && rsc->allocated_to) {
781 result = g_list_append(NULL, rsc->allocated_to);
782 }
783
784 if (result && g_list_length(result) == 1) {
785 one = g_list_nth_data(result, 0);
786 }
787
788 if (list) {
789 GListPtr gIter = result;
790
791 for (; gIter != NULL; gIter = gIter->next) {
792 node_t *node = (node_t *) gIter->data;
793
794 if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
795 *list = g_list_append(*list, node);
796 }
797 }
798 }
799
800 g_list_free(result);
801 return one;
802 }
803
804 static void
805 get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_table)
806 {
807 GListPtr gIter = rsc_list;
808
809 for (; gIter != NULL; gIter = gIter->next) {
810 resource_t *rsc = (resource_t *) gIter->data;
811
812 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
813 const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
814
815 int offset = 0;
816 char buffer[LINE_MAX];
817
818 int *rsc_counter = NULL;
819 int *active_counter = NULL;
820
821 if (rsc->variant != pe_native) {
822 continue;
823 }
824
825 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
826 if (crm_provider_required(class)) {
827 const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
828 offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
829 }
830 offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
831 CRM_LOG_ASSERT(offset > 0);
832
833 if (rsc_table) {
834 rsc_counter = g_hash_table_lookup(rsc_table, buffer);
835 if (rsc_counter == NULL) {
836 rsc_counter = calloc(1, sizeof(int));
837 *rsc_counter = 0;
838 g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
839 }
840 (*rsc_counter)++;
841 }
842
843 if (active_table) {
844 GListPtr gIter2 = rsc->running_on;
845
846 for (; gIter2 != NULL; gIter2 = gIter2->next) {
847 node_t *node = (node_t *) gIter2->data;
848 GHashTable *node_table = NULL;
849
850 if (node->details->unclean == FALSE && node->details->online == FALSE) {
851 continue;
852 }
853
854 node_table = g_hash_table_lookup(active_table, node->details->uname);
855 if (node_table == NULL) {
856 node_table = crm_str_table_new();
857 g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
858 }
859
860 active_counter = g_hash_table_lookup(node_table, buffer);
861 if (active_counter == NULL) {
862 active_counter = calloc(1, sizeof(int));
863 *active_counter = 0;
864 g_hash_table_insert(node_table, strdup(buffer), active_counter);
865 }
866 (*active_counter)++;
867 }
868 }
869 }
870 }
871
872 static void
873 destroy_node_table(gpointer data)
874 {
875 GHashTable *node_table = data;
876
877 if (node_table) {
878 g_hash_table_destroy(node_table);
879 }
880 }
881
882 void
883 print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options,
884 void *print_data, gboolean print_all)
885 {
886 GHashTable *rsc_table = crm_str_table_new();
887 GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal,
888 free, destroy_node_table);
889 GHashTableIter hash_iter;
890 char *type = NULL;
891 int *rsc_counter = NULL;
892
893 get_rscs_brief(rsc_list, rsc_table, active_table);
894
895 g_hash_table_iter_init(&hash_iter, rsc_table);
896 while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
897 GHashTableIter hash_iter2;
898 char *node_name = NULL;
899 GHashTable *node_table = NULL;
900 int active_counter_all = 0;
901
902 g_hash_table_iter_init(&hash_iter2, active_table);
903 while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
904 int *active_counter = g_hash_table_lookup(node_table, type);
905
906 if (active_counter == NULL || *active_counter == 0) {
907 continue;
908
909 } else {
910 active_counter_all += *active_counter;
911 }
912
913 if (options & pe_print_rsconly) {
914 node_name = NULL;
915 }
916
917 if (options & pe_print_html) {
918 status_print("<li>\n");
919 }
920
921 if (print_all) {
922 status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
923 active_counter ? *active_counter : 0,
924 rsc_counter ? *rsc_counter : 0, type,
925 active_counter && (*active_counter > 0) && node_name ? node_name : "");
926 } else {
927 status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
928 active_counter ? *active_counter : 0, type,
929 active_counter && (*active_counter > 0) && node_name ? node_name : "");
930 }
931
932 if (options & pe_print_html) {
933 status_print("</li>\n");
934 }
935 }
936
937 if (print_all && active_counter_all == 0) {
938 if (options & pe_print_html) {
939 status_print("<li>\n");
940 }
941
942 status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
943 active_counter_all,
944 rsc_counter ? *rsc_counter : 0, type);
945
946 if (options & pe_print_html) {
947 status_print("</li>\n");
948 }
949 }
950 }
951
952 if (rsc_table) {
953 g_hash_table_destroy(rsc_table);
954 rsc_table = NULL;
955 }
956 if (active_table) {
957 g_hash_table_destroy(active_table);
958 active_table = NULL;
959 }
960 }