This source file includes following definitions.
- colocations_header
- colocations_xml_node
- do_locations_list_xml
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- add_digest_xml
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- add_ticket_element_with_constraints
- add_resource_element
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- add_ticket_element
- PCMK__OUTPUT_ARGS
- pcmk__register_lib_messages
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/common/output.h>
12 #include <crm/common/results.h>
13 #include <crm/common/xml.h>
14 #include <crm/stonith-ng.h>
15 #include <crm/fencing/internal.h>
16 #include <crm/pengine/internal.h>
17 #include <libxml/tree.h>
18 #include <pacemaker-internal.h>
19
20 #include <inttypes.h>
21 #include <stdint.h>
22
23 static char *
24 colocations_header(pcmk_resource_t *rsc, pcmk__colocation_t *cons,
25 bool dependents) {
26 char *retval = NULL;
27
28 if (cons->primary_role > pcmk_role_started) {
29 retval = crm_strdup_printf("%s (score=%s, %s role=%s, id=%s)",
30 rsc->id, pcmk_readable_score(cons->score),
31 (dependents? "needs" : "with"),
32 pcmk_role_text(cons->primary_role),
33 cons->id);
34 } else {
35 retval = crm_strdup_printf("%s (score=%s, id=%s)",
36 rsc->id, pcmk_readable_score(cons->score),
37 cons->id);
38 }
39 return retval;
40 }
41
42 static void
43 colocations_xml_node(pcmk__output_t *out, pcmk_resource_t *rsc,
44 pcmk__colocation_t *cons) {
45 xmlNodePtr node = NULL;
46
47 node = pcmk__output_create_xml_node(out, PCMK_XE_RSC_COLOCATION,
48 PCMK_XA_ID, cons->id,
49 PCMK_XA_RSC, cons->dependent->id,
50 PCMK_XA_WITH_RSC, cons->primary->id,
51 PCMK_XA_SCORE,
52 pcmk_readable_score(cons->score),
53 NULL);
54
55 if (cons->node_attribute) {
56 xmlSetProp(node, (pcmkXmlStr) PCMK_XA_NODE_ATTRIBUTE,
57 (pcmkXmlStr) cons->node_attribute);
58 }
59
60 if (cons->dependent_role != pcmk_role_unknown) {
61 xmlSetProp(node, (pcmkXmlStr) PCMK_XA_RSC_ROLE,
62 (pcmkXmlStr) pcmk_role_text(cons->dependent_role));
63 }
64
65 if (cons->primary_role != pcmk_role_unknown) {
66 xmlSetProp(node, (pcmkXmlStr) PCMK_XA_WITH_RSC_ROLE,
67 (pcmkXmlStr) pcmk_role_text(cons->primary_role));
68 }
69 }
70
71 static int
72 do_locations_list_xml(pcmk__output_t *out, pcmk_resource_t *rsc,
73 bool add_header)
74 {
75 GList *lpc = NULL;
76 GList *list = rsc->rsc_location;
77 int rc = pcmk_rc_no_output;
78
79 for (lpc = list; lpc != NULL; lpc = lpc->next) {
80 pcmk__location_t *cons = lpc->data;
81
82 GList *lpc2 = NULL;
83
84 for (lpc2 = cons->nodes; lpc2 != NULL; lpc2 = lpc2->next) {
85 pcmk_node_t *node = (pcmk_node_t *) lpc2->data;
86
87 if (add_header) {
88 PCMK__OUTPUT_LIST_HEADER(out, false, rc, "locations");
89 }
90
91 pcmk__output_create_xml_node(out, PCMK_XE_RSC_LOCATION,
92 PCMK_XA_NODE, node->details->uname,
93 PCMK_XA_RSC, rsc->id,
94 PCMK_XA_ID, cons->id,
95 PCMK_XA_SCORE,
96 pcmk_readable_score(node->weight),
97 NULL);
98 }
99 }
100
101 if (add_header) {
102 PCMK__OUTPUT_LIST_FOOTER(out, rc);
103 }
104
105 return rc;
106 }
107
108 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pcmk_resource_t *",
109 "pcmk_node_t *", "pcmk_node_t *", "pcmk_action_t *",
110 "pcmk_action_t *")
111 static int
112 rsc_action_item(pcmk__output_t *out, va_list args)
113 {
114 const char *change = va_arg(args, const char *);
115 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
116 pcmk_node_t *origin = va_arg(args, pcmk_node_t *);
117 pcmk_node_t *destination = va_arg(args, pcmk_node_t *);
118 pcmk_action_t *action = va_arg(args, pcmk_action_t *);
119 pcmk_action_t *source = va_arg(args, pcmk_action_t *);
120
121 int len = 0;
122 char *reason = NULL;
123 char *details = NULL;
124 bool same_host = false;
125 bool same_role = false;
126 bool need_role = false;
127
128 static int rsc_width = 5;
129 static int detail_width = 5;
130
131 CRM_ASSERT(action);
132 CRM_ASSERT(destination != NULL || origin != NULL);
133
134 if (source == NULL) {
135 source = action;
136 }
137
138 len = strlen(rsc->id);
139 if (len > rsc_width) {
140 rsc_width = len + 2;
141 }
142
143 if ((rsc->role > pcmk_role_started)
144 || (rsc->next_role > pcmk_role_unpromoted)) {
145 need_role = true;
146 }
147
148 if (pcmk__same_node(origin, destination)) {
149 same_host = true;
150 }
151
152 if (rsc->role == rsc->next_role) {
153 same_role = true;
154 }
155
156 if (need_role && (origin == NULL)) {
157
158 details = crm_strdup_printf("%s -> %s %s", pcmk_role_text(rsc->role),
159 pcmk_role_text(rsc->next_role),
160 pcmk__node_name(destination));
161
162 } else if (origin == NULL) {
163
164 details = crm_strdup_printf("%s", pcmk__node_name(destination));
165
166 } else if (need_role && (destination == NULL)) {
167
168 details = crm_strdup_printf("%s %s", pcmk_role_text(rsc->role),
169 pcmk__node_name(origin));
170
171 } else if (destination == NULL) {
172
173 details = crm_strdup_printf("%s", pcmk__node_name(origin));
174
175 } else if (need_role && same_role && same_host) {
176
177 details = crm_strdup_printf("%s %s", pcmk_role_text(rsc->role),
178 pcmk__node_name(origin));
179
180 } else if (same_role && same_host) {
181
182 details = crm_strdup_printf("%s", pcmk__node_name(origin));
183
184 } else if (need_role && same_role) {
185
186 details = crm_strdup_printf("%s -> %s %s", pcmk__node_name(origin),
187 pcmk__node_name(destination),
188 pcmk_role_text(rsc->role));
189
190 } else if (same_role) {
191
192 details = crm_strdup_printf("%s -> %s", pcmk__node_name(origin),
193 pcmk__node_name(destination));
194
195 } else if (same_host) {
196
197 details = crm_strdup_printf("%s -> %s %s", pcmk_role_text(rsc->role),
198 pcmk_role_text(rsc->next_role),
199 pcmk__node_name(origin));
200
201 } else {
202
203 details = crm_strdup_printf("%s %s -> %s %s",
204 pcmk_role_text(rsc->role),
205 pcmk__node_name(origin),
206 pcmk_role_text(rsc->next_role),
207 pcmk__node_name(destination));
208 }
209
210 len = strlen(details);
211 if (len > detail_width) {
212 detail_width = len;
213 }
214
215 if ((source->reason != NULL)
216 && !pcmk_is_set(action->flags, pcmk_action_runnable)) {
217 reason = crm_strdup_printf("due to %s (blocked)", source->reason);
218
219 } else if (source->reason) {
220 reason = crm_strdup_printf("due to %s", source->reason);
221
222 } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
223 reason = strdup("blocked");
224
225 }
226
227 out->list_item(out, NULL, "%-8s %-*s ( %*s )%s%s",
228 change, rsc_width, rsc->id, detail_width, details,
229 ((reason == NULL)? "" : " "), pcmk__s(reason, ""));
230
231 free(details);
232 free(reason);
233 return pcmk_rc_ok;
234 }
235
236 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pcmk_resource_t *",
237 "pcmk_node_t *", "pcmk_node_t *", "pcmk_action_t *",
238 "pcmk_action_t *")
239 static int
240 rsc_action_item_xml(pcmk__output_t *out, va_list args)
241 {
242 const char *change = va_arg(args, const char *);
243 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
244 pcmk_node_t *origin = va_arg(args, pcmk_node_t *);
245 pcmk_node_t *destination = va_arg(args, pcmk_node_t *);
246 pcmk_action_t *action = va_arg(args, pcmk_action_t *);
247 pcmk_action_t *source = va_arg(args, pcmk_action_t *);
248
249 char *change_str = NULL;
250
251 bool same_host = false;
252 bool same_role = false;
253 bool need_role = false;
254 xmlNode *xml = NULL;
255
256 CRM_ASSERT(action);
257 CRM_ASSERT(destination != NULL || origin != NULL);
258
259 if (source == NULL) {
260 source = action;
261 }
262
263 if ((rsc->role > pcmk_role_started)
264 || (rsc->next_role > pcmk_role_unpromoted)) {
265 need_role = true;
266 }
267
268 if (pcmk__same_node(origin, destination)) {
269 same_host = true;
270 }
271
272 if (rsc->role == rsc->next_role) {
273 same_role = true;
274 }
275
276 change_str = g_ascii_strdown(change, -1);
277 xml = pcmk__output_create_xml_node(out, PCMK_XE_RSC_ACTION,
278 PCMK_XA_ACTION, change_str,
279 PCMK_XA_RESOURCE, rsc->id,
280 NULL);
281 g_free(change_str);
282
283 if (need_role && (origin == NULL)) {
284
285 pcmk__xe_set_props(xml,
286 PCMK_XA_ROLE, pcmk_role_text(rsc->role),
287 PCMK_XA_NEXT_ROLE, pcmk_role_text(rsc->next_role),
288 PCMK_XA_DEST, destination->details->uname,
289 NULL);
290
291 } else if (origin == NULL) {
292
293 crm_xml_add(xml, PCMK_XA_NODE, destination->details->uname);
294
295 } else if (need_role && (destination == NULL)) {
296
297 pcmk__xe_set_props(xml,
298 PCMK_XA_ROLE, pcmk_role_text(rsc->role),
299 PCMK_XA_NODE, origin->details->uname,
300 NULL);
301
302 } else if (destination == NULL) {
303
304 crm_xml_add(xml, PCMK_XA_NODE, origin->details->uname);
305
306 } else if (need_role && same_role && same_host) {
307
308 pcmk__xe_set_props(xml,
309 PCMK_XA_ROLE, pcmk_role_text(rsc->role),
310 PCMK_XA_SOURCE, origin->details->uname,
311 NULL);
312
313 } else if (same_role && same_host) {
314
315 crm_xml_add(xml, PCMK_XA_SOURCE, origin->details->uname);
316
317 } else if (need_role && same_role) {
318
319 pcmk__xe_set_props(xml,
320 PCMK_XA_SOURCE, origin->details->uname,
321 PCMK_XA_DEST, destination->details->uname,
322 PCMK_XA_ROLE, pcmk_role_text(rsc->role),
323 NULL);
324
325 } else if (same_role) {
326
327 pcmk__xe_set_props(xml,
328 PCMK_XA_SOURCE, origin->details->uname,
329 PCMK_XA_DEST, destination->details->uname,
330 NULL);
331
332 } else if (same_host) {
333
334 pcmk__xe_set_props(xml,
335 PCMK_XA_ROLE, pcmk_role_text(rsc->role),
336 PCMK_XA_NEXT_ROLE, pcmk_role_text(rsc->next_role),
337 PCMK_XA_SOURCE, origin->details->uname,
338 NULL);
339
340 } else {
341
342 pcmk__xe_set_props(xml,
343 PCMK_XA_ROLE, pcmk_role_text(rsc->role),
344 PCMK_XA_SOURCE, origin->details->uname,
345 PCMK_XA_NEXT_ROLE, pcmk_role_text(rsc->next_role),
346 PCMK_XA_DEST, destination->details->uname,
347 NULL);
348 }
349
350 if ((source->reason != NULL)
351 && !pcmk_is_set(action->flags, pcmk_action_runnable)) {
352 pcmk__xe_set_props(xml,
353 PCMK_XA_REASON, source->reason,
354 PCMK_XA_BLOCKED, PCMK_VALUE_TRUE,
355 NULL);
356
357 } else if (source->reason != NULL) {
358 crm_xml_add(xml, PCMK_XA_REASON, source->reason);
359
360 } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
361 pcmk__xe_set_bool_attr(xml, PCMK_XA_BLOCKED, true);
362
363 }
364
365 return pcmk_rc_ok;
366 }
367
368 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pcmk_resource_t *", "bool")
369 static int
370 rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
371 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
372 bool recursive = va_arg(args, int);
373
374 int rc = pcmk_rc_no_output;
375
376 if (pcmk_is_set(rsc->flags, pcmk_rsc_detect_loop)) {
377 return rc;
378 }
379
380
381
382
383 pcmk__set_rsc_flags(rsc, pcmk_rsc_detect_loop);
384 for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
385 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
386 char *hdr = NULL;
387
388 PCMK__OUTPUT_LIST_HEADER(out, false, rc,
389 "Resources %s is colocated with", rsc->id);
390
391 if (pcmk_is_set(cons->primary->flags, pcmk_rsc_detect_loop)) {
392 out->list_item(out, NULL, "%s (id=%s - loop)",
393 cons->primary->id, cons->id);
394 continue;
395 }
396
397 hdr = colocations_header(cons->primary, cons, false);
398 out->list_item(out, NULL, "%s", hdr);
399 free(hdr);
400
401
402 out->begin_list(out, NULL, NULL, NULL);
403
404 out->message(out, "locations-list", cons->primary);
405 if (recursive) {
406 out->message(out, "rsc-is-colocated-with-list",
407 cons->primary, recursive);
408 }
409
410 out->end_list(out);
411 }
412
413 PCMK__OUTPUT_LIST_FOOTER(out, rc);
414 return rc;
415 }
416
417 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pcmk_resource_t *", "bool")
418 static int
419 rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
420 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
421 bool recursive = va_arg(args, int);
422
423 int rc = pcmk_rc_no_output;
424
425 if (pcmk_is_set(rsc->flags, pcmk_rsc_detect_loop)) {
426 return rc;
427 }
428
429
430
431
432 pcmk__set_rsc_flags(rsc, pcmk_rsc_detect_loop);
433 for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
434 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
435
436 if (pcmk_is_set(cons->primary->flags, pcmk_rsc_detect_loop)) {
437 colocations_xml_node(out, cons->primary, cons);
438 continue;
439 }
440
441 colocations_xml_node(out, cons->primary, cons);
442 do_locations_list_xml(out, cons->primary, false);
443
444 if (recursive) {
445 out->message(out, "rsc-is-colocated-with-list",
446 cons->primary, recursive);
447 }
448 }
449
450 return rc;
451 }
452
453 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pcmk_resource_t *", "bool")
454 static int
455 rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
456 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
457 bool recursive = va_arg(args, int);
458
459 int rc = pcmk_rc_no_output;
460
461 if (pcmk_is_set(rsc->flags, pcmk_rsc_detect_loop)) {
462 return rc;
463 }
464
465
466
467
468
469 pcmk__set_rsc_flags(rsc, pcmk_rsc_detect_loop);
470 for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
471 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
472 char *hdr = NULL;
473
474 PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Resources colocated with %s",
475 rsc->id);
476
477 if (pcmk_is_set(cons->dependent->flags, pcmk_rsc_detect_loop)) {
478 out->list_item(out, NULL, "%s (id=%s - loop)",
479 cons->dependent->id, cons->id);
480 continue;
481 }
482
483 hdr = colocations_header(cons->dependent, cons, true);
484 out->list_item(out, NULL, "%s", hdr);
485 free(hdr);
486
487
488 out->begin_list(out, NULL, NULL, NULL);
489
490 out->message(out, "locations-list", cons->dependent);
491 if (recursive) {
492 out->message(out, "rscs-colocated-with-list",
493 cons->dependent, recursive);
494 }
495
496 out->end_list(out);
497 }
498
499 PCMK__OUTPUT_LIST_FOOTER(out, rc);
500 return rc;
501 }
502
503 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pcmk_resource_t *", "bool")
504 static int
505 rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
506 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
507 bool recursive = va_arg(args, int);
508
509 int rc = pcmk_rc_no_output;
510
511 if (pcmk_is_set(rsc->flags, pcmk_rsc_detect_loop)) {
512 return rc;
513 }
514
515
516
517
518
519 pcmk__set_rsc_flags(rsc, pcmk_rsc_detect_loop);
520 for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
521 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
522
523 if (pcmk_is_set(cons->dependent->flags, pcmk_rsc_detect_loop)) {
524 colocations_xml_node(out, cons->dependent, cons);
525 continue;
526 }
527
528 colocations_xml_node(out, cons->dependent, cons);
529 do_locations_list_xml(out, cons->dependent, false);
530
531 if (recursive) {
532 out->message(out, "rscs-colocated-with-list",
533 cons->dependent, recursive);
534 }
535 }
536
537 return rc;
538 }
539
540 PCMK__OUTPUT_ARGS("locations-list", "pcmk_resource_t *")
541 static int
542 locations_list(pcmk__output_t *out, va_list args) {
543 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
544
545 GList *lpc = NULL;
546 GList *list = rsc->rsc_location;
547 int rc = pcmk_rc_no_output;
548
549 for (lpc = list; lpc != NULL; lpc = lpc->next) {
550 pcmk__location_t *cons = lpc->data;
551
552 GList *lpc2 = NULL;
553
554 for (lpc2 = cons->nodes; lpc2 != NULL; lpc2 = lpc2->next) {
555 pcmk_node_t *node = (pcmk_node_t *) lpc2->data;
556
557 PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Locations");
558 out->list_item(out, NULL, "Node %s (score=%s, id=%s, rsc=%s)",
559 pcmk__node_name(node),
560 pcmk_readable_score(node->weight), cons->id,
561 rsc->id);
562 }
563 }
564
565 PCMK__OUTPUT_LIST_FOOTER(out, rc);
566 return rc;
567 }
568
569 PCMK__OUTPUT_ARGS("locations-list", "pcmk_resource_t *")
570 static int
571 locations_list_xml(pcmk__output_t *out, va_list args) {
572 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
573 return do_locations_list_xml(out, rsc, true);
574 }
575
576 PCMK__OUTPUT_ARGS("locations-and-colocations", "pcmk_resource_t *",
577 "bool", "bool")
578 static int
579 locations_and_colocations(pcmk__output_t *out, va_list args)
580 {
581 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
582 bool recursive = va_arg(args, int);
583 bool force = va_arg(args, int);
584
585 pcmk__unpack_constraints(rsc->cluster);
586
587
588 if (!force) {
589 rsc = uber_parent(rsc);
590 }
591
592 out->message(out, "locations-list", rsc);
593
594 pe__clear_resource_flags_on_all(rsc->cluster, pcmk_rsc_detect_loop);
595 out->message(out, "rscs-colocated-with-list", rsc, recursive);
596
597 pe__clear_resource_flags_on_all(rsc->cluster, pcmk_rsc_detect_loop);
598 out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
599 return pcmk_rc_ok;
600 }
601
602 PCMK__OUTPUT_ARGS("locations-and-colocations", "pcmk_resource_t *",
603 "bool", "bool")
604 static int
605 locations_and_colocations_xml(pcmk__output_t *out, va_list args)
606 {
607 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
608 bool recursive = va_arg(args, int);
609 bool force = va_arg(args, int);
610
611 pcmk__unpack_constraints(rsc->cluster);
612
613
614 if (!force) {
615 rsc = uber_parent(rsc);
616 }
617
618 pcmk__output_xml_create_parent(out, PCMK_XE_CONSTRAINTS, NULL);
619 do_locations_list_xml(out, rsc, false);
620
621 pe__clear_resource_flags_on_all(rsc->cluster, pcmk_rsc_detect_loop);
622 out->message(out, "rscs-colocated-with-list", rsc, recursive);
623
624 pe__clear_resource_flags_on_all(rsc->cluster, pcmk_rsc_detect_loop);
625 out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
626
627 pcmk__output_xml_pop_parent(out);
628 return pcmk_rc_ok;
629 }
630
631 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *",
632 "const char *")
633 static int
634 health(pcmk__output_t *out, va_list args)
635 {
636 const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
637 const char *host_from = va_arg(args, const char *);
638 const char *fsa_state = va_arg(args, const char *);
639 const char *result = va_arg(args, const char *);
640
641 return out->info(out, "Controller on %s in state %s: %s",
642 pcmk__s(host_from, "unknown node"),
643 pcmk__s(fsa_state, "unknown"),
644 pcmk__s(result, "unknown result"));
645 }
646
647 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *",
648 "const char *")
649 static int
650 health_text(pcmk__output_t *out, va_list args)
651 {
652 if (!out->is_quiet(out)) {
653 return health(out, args);
654 } else {
655 const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
656 const char *host_from G_GNUC_UNUSED = va_arg(args, const char *);
657 const char *fsa_state = va_arg(args, const char *);
658 const char *result G_GNUC_UNUSED = va_arg(args, const char *);
659
660 if (fsa_state != NULL) {
661 pcmk__formatted_printf(out, "%s\n", fsa_state);
662 return pcmk_rc_ok;
663 }
664 }
665
666 return pcmk_rc_no_output;
667 }
668
669 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *",
670 "const char *")
671 static int
672 health_xml(pcmk__output_t *out, va_list args)
673 {
674 const char *sys_from = va_arg(args, const char *);
675 const char *host_from = va_arg(args, const char *);
676 const char *fsa_state = va_arg(args, const char *);
677 const char *result = va_arg(args, const char *);
678
679 pcmk__output_create_xml_node(out, pcmk__s(sys_from, ""),
680 PCMK_XA_NODE_NAME, pcmk__s(host_from, ""),
681 PCMK_XA_STATE, pcmk__s(fsa_state, ""),
682 PCMK_XA_RESULT, pcmk__s(result, ""),
683 NULL);
684 return pcmk_rc_ok;
685 }
686
687 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
688 "enum pcmk_pacemakerd_state", "const char *", "time_t")
689 static int
690 pacemakerd_health(pcmk__output_t *out, va_list args)
691 {
692 const char *sys_from = va_arg(args, const char *);
693 enum pcmk_pacemakerd_state state =
694 (enum pcmk_pacemakerd_state) va_arg(args, int);
695 const char *state_s = va_arg(args, const char *);
696 time_t last_updated = va_arg(args, time_t);
697
698 char *last_updated_s = NULL;
699 int rc = pcmk_rc_ok;
700
701 if (sys_from == NULL) {
702 if (state == pcmk_pacemakerd_state_remote) {
703 sys_from = "pacemaker-remoted";
704 } else {
705 sys_from = CRM_SYSTEM_MCP;
706 }
707 }
708
709 if (state_s == NULL) {
710 state_s = pcmk__pcmkd_state_enum2friendly(state);
711 }
712
713 if (last_updated != 0) {
714 last_updated_s = pcmk__epoch2str(&last_updated,
715 crm_time_log_date
716 |crm_time_log_timeofday
717 |crm_time_log_with_timezone);
718 }
719
720 rc = out->info(out, "Status of %s: '%s' (last updated %s)",
721 sys_from, state_s,
722 pcmk__s(last_updated_s, "at unknown time"));
723
724 free(last_updated_s);
725 return rc;
726 }
727
728 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
729 "enum pcmk_pacemakerd_state", "const char *", "time_t")
730 static int
731 pacemakerd_health_html(pcmk__output_t *out, va_list args)
732 {
733 const char *sys_from = va_arg(args, const char *);
734 enum pcmk_pacemakerd_state state =
735 (enum pcmk_pacemakerd_state) va_arg(args, int);
736 const char *state_s = va_arg(args, const char *);
737 time_t last_updated = va_arg(args, time_t);
738
739 char *last_updated_s = NULL;
740 char *msg = NULL;
741
742 if (sys_from == NULL) {
743 if (state == pcmk_pacemakerd_state_remote) {
744 sys_from = "pacemaker-remoted";
745 } else {
746 sys_from = CRM_SYSTEM_MCP;
747 }
748 }
749
750 if (state_s == NULL) {
751 state_s = pcmk__pcmkd_state_enum2friendly(state);
752 }
753
754 if (last_updated != 0) {
755 last_updated_s = pcmk__epoch2str(&last_updated,
756 crm_time_log_date
757 |crm_time_log_timeofday
758 |crm_time_log_with_timezone);
759 }
760
761 msg = crm_strdup_printf("Status of %s: '%s' (last updated %s)",
762 sys_from, state_s,
763 pcmk__s(last_updated_s, "at unknown time"));
764 pcmk__output_create_html_node(out, "li", NULL, NULL, msg);
765
766 free(msg);
767 free(last_updated_s);
768 return pcmk_rc_ok;
769 }
770
771 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
772 "enum pcmk_pacemakerd_state", "const char *", "time_t")
773 static int
774 pacemakerd_health_text(pcmk__output_t *out, va_list args)
775 {
776 if (!out->is_quiet(out)) {
777 return pacemakerd_health(out, args);
778 } else {
779 const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
780 enum pcmk_pacemakerd_state state =
781 (enum pcmk_pacemakerd_state) va_arg(args, int);
782 const char *state_s = va_arg(args, const char *);
783 time_t last_updated G_GNUC_UNUSED = va_arg(args, time_t);
784
785 if (state_s == NULL) {
786 state_s = pcmk_pacemakerd_api_daemon_state_enum2text(state);
787 }
788 pcmk__formatted_printf(out, "%s\n", state_s);
789 return pcmk_rc_ok;
790 }
791 }
792
793 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
794 "enum pcmk_pacemakerd_state", "const char *", "time_t")
795 static int
796 pacemakerd_health_xml(pcmk__output_t *out, va_list args)
797 {
798 const char *sys_from = va_arg(args, const char *);
799 enum pcmk_pacemakerd_state state =
800 (enum pcmk_pacemakerd_state) va_arg(args, int);
801 const char *state_s = va_arg(args, const char *);
802 time_t last_updated = va_arg(args, time_t);
803
804 char *last_updated_s = NULL;
805
806 if (sys_from == NULL) {
807 if (state == pcmk_pacemakerd_state_remote) {
808 sys_from = "pacemaker-remoted";
809 } else {
810 sys_from = CRM_SYSTEM_MCP;
811 }
812 }
813
814 if (state_s == NULL) {
815 state_s = pcmk_pacemakerd_api_daemon_state_enum2text(state);
816 }
817
818 if (last_updated != 0) {
819 last_updated_s = pcmk__epoch2str(&last_updated,
820 crm_time_log_date
821 |crm_time_log_timeofday
822 |crm_time_log_with_timezone);
823 }
824
825 pcmk__output_create_xml_node(out, PCMK_XE_PACEMAKERD,
826 PCMK_XA_SYS_FROM, sys_from,
827 PCMK_XA_STATE, state_s,
828 PCMK_XA_LAST_UPDATED, last_updated_s,
829 NULL);
830 free(last_updated_s);
831 return pcmk_rc_ok;
832 }
833
834 PCMK__OUTPUT_ARGS("profile", "const char *", "clock_t", "clock_t")
835 static int
836 profile_default(pcmk__output_t *out, va_list args) {
837 const char *xml_file = va_arg(args, const char *);
838 clock_t start = va_arg(args, clock_t);
839 clock_t end = va_arg(args, clock_t);
840
841 out->list_item(out, NULL, "Testing %s ... %.2f secs", xml_file,
842 (end - start) / (float) CLOCKS_PER_SEC);
843
844 return pcmk_rc_ok;
845 }
846
847 PCMK__OUTPUT_ARGS("profile", "const char *", "clock_t", "clock_t")
848 static int
849 profile_xml(pcmk__output_t *out, va_list args) {
850 const char *xml_file = va_arg(args, const char *);
851 clock_t start = va_arg(args, clock_t);
852 clock_t end = va_arg(args, clock_t);
853
854 char *duration = pcmk__ftoa((end - start) / (float) CLOCKS_PER_SEC);
855
856 pcmk__output_create_xml_node(out, PCMK_XE_TIMING,
857 PCMK_XA_FILE, xml_file,
858 PCMK_XA_DURATION, duration,
859 NULL);
860
861 free(duration);
862 return pcmk_rc_ok;
863 }
864
865 PCMK__OUTPUT_ARGS("dc", "const char *")
866 static int
867 dc(pcmk__output_t *out, va_list args)
868 {
869 const char *dc = va_arg(args, const char *);
870
871 return out->info(out, "Designated Controller is: %s",
872 pcmk__s(dc, "not yet elected"));
873 }
874
875 PCMK__OUTPUT_ARGS("dc", "const char *")
876 static int
877 dc_text(pcmk__output_t *out, va_list args)
878 {
879 if (!out->is_quiet(out)) {
880 return dc(out, args);
881 } else {
882 const char *dc = va_arg(args, const char *);
883
884 if (dc != NULL) {
885 pcmk__formatted_printf(out, "%s\n", pcmk__s(dc, ""));
886 return pcmk_rc_ok;
887 }
888 }
889
890 return pcmk_rc_no_output;
891 }
892
893 PCMK__OUTPUT_ARGS("dc", "const char *")
894 static int
895 dc_xml(pcmk__output_t *out, va_list args)
896 {
897 const char *dc = va_arg(args, const char *);
898
899 pcmk__output_create_xml_node(out, PCMK_XE_DC,
900 PCMK_XA_NODE_NAME, pcmk__s(dc, ""),
901 NULL);
902 return pcmk_rc_ok;
903 }
904
905 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *",
906 "const char *", "bool")
907 static int
908 crmadmin_node(pcmk__output_t *out, va_list args)
909 {
910 const char *type = va_arg(args, const char *);
911 const char *name = va_arg(args, const char *);
912 const char *id = va_arg(args, const char *);
913 bool bash_export = va_arg(args, int);
914
915 if (bash_export) {
916 return out->info(out, "export %s=%s",
917 pcmk__s(name, "<null>"), pcmk__s(id, ""));
918 } else {
919 return out->info(out, "%s node: %s (%s)", type ? type : "cluster",
920 pcmk__s(name, "<null>"), pcmk__s(id, "<null>"));
921 }
922 }
923
924 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *",
925 "const char *", "bool")
926 static int
927 crmadmin_node_text(pcmk__output_t *out, va_list args)
928 {
929 if (!out->is_quiet(out)) {
930 return crmadmin_node(out, args);
931 } else {
932 const char *type G_GNUC_UNUSED = va_arg(args, const char *);
933 const char *name = va_arg(args, const char *);
934 const char *id G_GNUC_UNUSED = va_arg(args, const char *);
935 bool bash_export G_GNUC_UNUSED = va_arg(args, int);
936
937 pcmk__formatted_printf(out, "%s\n", pcmk__s(name, "<null>"));
938 return pcmk_rc_ok;
939 }
940 }
941
942 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *",
943 "const char *", "bool")
944 static int
945 crmadmin_node_xml(pcmk__output_t *out, va_list args)
946 {
947 const char *type = va_arg(args, const char *);
948 const char *name = va_arg(args, const char *);
949 const char *id = va_arg(args, const char *);
950 bool bash_export G_GNUC_UNUSED = va_arg(args, int);
951
952 pcmk__output_create_xml_node(out, PCMK_XE_NODE,
953 PCMK_XA_TYPE, pcmk__s(type, "cluster"),
954 PCMK_XA_NAME, pcmk__s(name, ""),
955 PCMK_XA_ID, pcmk__s(id, ""),
956 NULL);
957 return pcmk_rc_ok;
958 }
959
960 PCMK__OUTPUT_ARGS("digests", "const pcmk_resource_t *", "const pcmk_node_t *",
961 "const char *", "guint", "const pcmk__op_digest_t *")
962 static int
963 digests_text(pcmk__output_t *out, va_list args)
964 {
965 const pcmk_resource_t *rsc = va_arg(args, const pcmk_resource_t *);
966 const pcmk_node_t *node = va_arg(args, const pcmk_node_t *);
967 const char *task = va_arg(args, const char *);
968 guint interval_ms = va_arg(args, guint);
969 const pcmk__op_digest_t *digests = va_arg(args, const pcmk__op_digest_t *);
970
971 char *action_desc = NULL;
972 const char *rsc_desc = "unknown resource";
973 const char *node_desc = "unknown node";
974
975 if (interval_ms != 0) {
976 action_desc = crm_strdup_printf("%ums-interval %s action", interval_ms,
977 ((task == NULL)? "unknown" : task));
978 } else if (pcmk__str_eq(task, PCMK_ACTION_MONITOR, pcmk__str_none)) {
979 action_desc = strdup("probe action");
980 } else {
981 action_desc = crm_strdup_printf("%s action",
982 ((task == NULL)? "unknown" : task));
983 }
984 if ((rsc != NULL) && (rsc->id != NULL)) {
985 rsc_desc = rsc->id;
986 }
987 if ((node != NULL) && (node->details->uname != NULL)) {
988 node_desc = node->details->uname;
989 }
990 out->begin_list(out, NULL, NULL, "Digests for %s %s on %s",
991 rsc_desc, action_desc, node_desc);
992 free(action_desc);
993
994 if (digests == NULL) {
995 out->list_item(out, NULL, "none");
996 out->end_list(out);
997 return pcmk_rc_ok;
998 }
999 if (digests->digest_all_calc != NULL) {
1000 out->list_item(out, NULL, "%s (all parameters)",
1001 digests->digest_all_calc);
1002 }
1003 if (digests->digest_secure_calc != NULL) {
1004 out->list_item(out, NULL, "%s (non-private parameters)",
1005 digests->digest_secure_calc);
1006 }
1007 if (digests->digest_restart_calc != NULL) {
1008 out->list_item(out, NULL, "%s (non-reloadable parameters)",
1009 digests->digest_restart_calc);
1010 }
1011 out->end_list(out);
1012 return pcmk_rc_ok;
1013 }
1014
1015 static void
1016 add_digest_xml(xmlNode *parent, const char *type, const char *digest,
1017 xmlNode *digest_source)
1018 {
1019 if (digest != NULL) {
1020 xmlNodePtr digest_xml = pcmk__xe_create(parent, PCMK_XE_DIGEST);
1021
1022 crm_xml_add(digest_xml, PCMK_XA_TYPE, pcmk__s(type, "unspecified"));
1023 crm_xml_add(digest_xml, PCMK_XA_HASH, digest);
1024 pcmk__xml_copy(digest_xml, digest_source);
1025 }
1026 }
1027
1028 PCMK__OUTPUT_ARGS("digests", "const pcmk_resource_t *", "const pcmk_node_t *",
1029 "const char *", "guint", "const pcmk__op_digest_t *")
1030 static int
1031 digests_xml(pcmk__output_t *out, va_list args)
1032 {
1033 const pcmk_resource_t *rsc = va_arg(args, const pcmk_resource_t *);
1034 const pcmk_node_t *node = va_arg(args, const pcmk_node_t *);
1035 const char *task = va_arg(args, const char *);
1036 guint interval_ms = va_arg(args, guint);
1037 const pcmk__op_digest_t *digests = va_arg(args, const pcmk__op_digest_t *);
1038
1039 char *interval_s = crm_strdup_printf("%ums", interval_ms);
1040 xmlNode *xml = NULL;
1041
1042 xml = pcmk__output_create_xml_node(out, PCMK_XE_DIGESTS,
1043 PCMK_XA_RESOURCE, pcmk__s(rsc->id, ""),
1044 PCMK_XA_NODE,
1045 pcmk__s(node->details->uname, ""),
1046 PCMK_XA_TASK, pcmk__s(task, ""),
1047 PCMK_XA_INTERVAL, interval_s,
1048 NULL);
1049 free(interval_s);
1050 if (digests != NULL) {
1051 add_digest_xml(xml, "all", digests->digest_all_calc,
1052 digests->params_all);
1053 add_digest_xml(xml, "nonprivate", digests->digest_secure_calc,
1054 digests->params_secure);
1055 add_digest_xml(xml, "nonreloadable", digests->digest_restart_calc,
1056 digests->params_restart);
1057 }
1058 return pcmk_rc_ok;
1059 }
1060
1061 #define STOP_SANITY_ASSERT(lineno) do { \
1062 if ((current != NULL) && current->details->unclean) { \
1063 \
1064 } else if (stop == NULL) { \
1065 crm_err("%s:%d: No stop action exists for %s", \
1066 __func__, lineno, rsc->id); \
1067 CRM_ASSERT(stop != NULL); \
1068 } else if (pcmk_is_set(stop->flags, pcmk_action_optional)) { \
1069 crm_err("%s:%d: Action %s is still optional", \
1070 __func__, lineno, stop->uuid); \
1071 CRM_ASSERT(!pcmk_is_set(stop->flags, pcmk_action_optional));\
1072 } \
1073 } while (0)
1074
1075 PCMK__OUTPUT_ARGS("rsc-action", "pcmk_resource_t *", "pcmk_node_t *",
1076 "pcmk_node_t *")
1077 static int
1078 rsc_action_default(pcmk__output_t *out, va_list args)
1079 {
1080 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
1081 pcmk_node_t *current = va_arg(args, pcmk_node_t *);
1082 pcmk_node_t *next = va_arg(args, pcmk_node_t *);
1083
1084 GList *possible_matches = NULL;
1085 char *key = NULL;
1086 int rc = pcmk_rc_no_output;
1087 bool moving = false;
1088
1089 pcmk_node_t *start_node = NULL;
1090 pcmk_action_t *start = NULL;
1091 pcmk_action_t *stop = NULL;
1092 pcmk_action_t *promote = NULL;
1093 pcmk_action_t *demote = NULL;
1094 pcmk_action_t *reason_op = NULL;
1095
1096 if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)
1097 || (current == NULL && next == NULL)) {
1098 const bool managed = pcmk_is_set(rsc->flags, pcmk_rsc_managed);
1099
1100 pcmk__rsc_info(rsc, "Leave %s\t(%s%s)",
1101 rsc->id, pcmk_role_text(rsc->role),
1102 (managed? "" : " unmanaged"));
1103 return rc;
1104 }
1105
1106 moving = (current != NULL) && (next != NULL)
1107 && !pcmk__same_node(current, next);
1108
1109 possible_matches = pe__resource_actions(rsc, next, PCMK_ACTION_START,
1110 false);
1111 if (possible_matches) {
1112 start = possible_matches->data;
1113 g_list_free(possible_matches);
1114 }
1115
1116 if ((start == NULL)
1117 || !pcmk_is_set(start->flags, pcmk_action_runnable)) {
1118 start_node = NULL;
1119 } else {
1120 start_node = current;
1121 }
1122 possible_matches = pe__resource_actions(rsc, start_node, PCMK_ACTION_STOP,
1123 false);
1124 if (possible_matches) {
1125 stop = possible_matches->data;
1126 g_list_free(possible_matches);
1127 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_stop_unexpected)) {
1128
1129
1130
1131
1132 possible_matches = pe__resource_actions(rsc, NULL, PCMK_ACTION_STOP,
1133 false);
1134 if (possible_matches != NULL) {
1135 stop = possible_matches->data;
1136 g_list_free(possible_matches);
1137 }
1138 }
1139
1140 possible_matches = pe__resource_actions(rsc, next, PCMK_ACTION_PROMOTE,
1141 false);
1142 if (possible_matches) {
1143 promote = possible_matches->data;
1144 g_list_free(possible_matches);
1145 }
1146
1147 possible_matches = pe__resource_actions(rsc, next, PCMK_ACTION_DEMOTE,
1148 false);
1149 if (possible_matches) {
1150 demote = possible_matches->data;
1151 g_list_free(possible_matches);
1152 }
1153
1154 if (rsc->role == rsc->next_role) {
1155 pcmk_action_t *migrate_op = NULL;
1156
1157 CRM_CHECK(next != NULL, return rc);
1158
1159 possible_matches = pe__resource_actions(rsc, next,
1160 PCMK_ACTION_MIGRATE_FROM,
1161 false);
1162 if (possible_matches) {
1163 migrate_op = possible_matches->data;
1164 }
1165
1166 if ((migrate_op != NULL) && (current != NULL)
1167 && pcmk_is_set(migrate_op->flags, pcmk_action_runnable)) {
1168 rc = out->message(out, "rsc-action-item", "Migrate", rsc, current,
1169 next, start, NULL);
1170
1171 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_reload)) {
1172 rc = out->message(out, "rsc-action-item", "Reload", rsc, current,
1173 next, start, NULL);
1174
1175 } else if ((start == NULL)
1176 || pcmk_is_set(start->flags, pcmk_action_optional)) {
1177 if ((demote != NULL) && (promote != NULL)
1178 && !pcmk_is_set(demote->flags, pcmk_action_optional)
1179 && !pcmk_is_set(promote->flags, pcmk_action_optional)) {
1180 rc = out->message(out, "rsc-action-item", "Re-promote", rsc,
1181 current, next, promote, demote);
1182 } else {
1183 pcmk__rsc_info(rsc, "Leave %s\t(%s %s)", rsc->id,
1184 pcmk_role_text(rsc->role),
1185 pcmk__node_name(next));
1186 }
1187
1188 } else if (!pcmk_is_set(start->flags, pcmk_action_runnable)) {
1189 if ((stop == NULL) || (stop->reason == NULL)) {
1190 reason_op = start;
1191 } else {
1192 reason_op = stop;
1193 }
1194 rc = out->message(out, "rsc-action-item", "Stop", rsc, current,
1195 NULL, stop, reason_op);
1196 STOP_SANITY_ASSERT(__LINE__);
1197
1198 } else if (moving && current) {
1199 const bool failed = pcmk_is_set(rsc->flags, pcmk_rsc_failed);
1200
1201 rc = out->message(out, "rsc-action-item",
1202 (failed? "Recover" : "Move"), rsc, current, next,
1203 stop, NULL);
1204
1205 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
1206 rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
1207 NULL, stop, NULL);
1208 STOP_SANITY_ASSERT(__LINE__);
1209
1210 } else {
1211 rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1212 next, start, NULL);
1213 #if 0
1214
1215
1216
1217 STOP_SANITY_ASSERT(__LINE__);
1218 #endif
1219 }
1220
1221 g_list_free(possible_matches);
1222 return rc;
1223 }
1224
1225 if ((stop != NULL)
1226 && ((rsc->next_role == pcmk_role_stopped)
1227 || ((start != NULL)
1228 && !pcmk_is_set(start->flags, pcmk_action_runnable)))) {
1229
1230 key = stop_key(rsc);
1231 for (GList *iter = rsc->running_on; iter != NULL; iter = iter->next) {
1232 pcmk_node_t *node = iter->data;
1233 pcmk_action_t *stop_op = NULL;
1234
1235 reason_op = start;
1236 possible_matches = find_actions(rsc->actions, key, node);
1237 if (possible_matches) {
1238 stop_op = possible_matches->data;
1239 g_list_free(possible_matches);
1240 }
1241
1242 if (stop_op != NULL) {
1243 if (pcmk_is_set(stop_op->flags, pcmk_action_runnable)) {
1244 STOP_SANITY_ASSERT(__LINE__);
1245 }
1246 if (stop_op->reason != NULL) {
1247 reason_op = stop_op;
1248 }
1249 }
1250
1251 if (out->message(out, "rsc-action-item", "Stop", rsc, node, NULL,
1252 stop_op, reason_op) == pcmk_rc_ok) {
1253 rc = pcmk_rc_ok;
1254 }
1255 }
1256
1257 free(key);
1258
1259 } else if ((stop != NULL)
1260 && pcmk_all_flags_set(rsc->flags,
1261 pcmk_rsc_failed|pcmk_rsc_stop_if_failed)) {
1262
1263 rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
1264 next, stop, start);
1265 STOP_SANITY_ASSERT(__LINE__);
1266
1267 } else if (moving) {
1268 rc = out->message(out, "rsc-action-item", "Move", rsc, current, next,
1269 stop, NULL);
1270 STOP_SANITY_ASSERT(__LINE__);
1271
1272 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_reload)) {
1273 rc = out->message(out, "rsc-action-item", "Reload", rsc, current, next,
1274 start, NULL);
1275
1276 } else if ((stop != NULL)
1277 && !pcmk_is_set(stop->flags, pcmk_action_optional)) {
1278 rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1279 next, start, NULL);
1280 STOP_SANITY_ASSERT(__LINE__);
1281
1282 } else if (rsc->role == pcmk_role_promoted) {
1283 CRM_LOG_ASSERT(current != NULL);
1284 rc = out->message(out, "rsc-action-item", "Demote", rsc, current,
1285 next, demote, NULL);
1286
1287 } else if (rsc->next_role == pcmk_role_promoted) {
1288 CRM_LOG_ASSERT(next);
1289 rc = out->message(out, "rsc-action-item", "Promote", rsc, current,
1290 next, promote, NULL);
1291
1292 } else if ((rsc->role == pcmk_role_stopped)
1293 && (rsc->next_role > pcmk_role_stopped)) {
1294 rc = out->message(out, "rsc-action-item", "Start", rsc, current, next,
1295 start, NULL);
1296 }
1297
1298 return rc;
1299 }
1300
1301 PCMK__OUTPUT_ARGS("node-action", "const char *", "const char *", "const char *")
1302 static int
1303 node_action(pcmk__output_t *out, va_list args)
1304 {
1305 const char *task = va_arg(args, const char *);
1306 const char *node_name = va_arg(args, const char *);
1307 const char *reason = va_arg(args, const char *);
1308
1309 if (task == NULL) {
1310 return pcmk_rc_no_output;
1311 } else if (reason) {
1312 out->list_item(out, NULL, "%s %s '%s'", task, node_name, reason);
1313 } else {
1314 crm_notice(" * %s %s", task, node_name);
1315 }
1316
1317 return pcmk_rc_ok;
1318 }
1319
1320 PCMK__OUTPUT_ARGS("node-action", "const char *", "const char *", "const char *")
1321 static int
1322 node_action_xml(pcmk__output_t *out, va_list args)
1323 {
1324 const char *task = va_arg(args, const char *);
1325 const char *node_name = va_arg(args, const char *);
1326 const char *reason = va_arg(args, const char *);
1327
1328 if (task == NULL) {
1329 return pcmk_rc_no_output;
1330 } else if (reason) {
1331 pcmk__output_create_xml_node(out, PCMK_XE_NODE_ACTION,
1332 PCMK_XA_TASK, task,
1333 PCMK_XA_NODE, node_name,
1334 PCMK_XA_REASON, reason,
1335 NULL);
1336 } else {
1337 crm_notice(" * %s %s", task, node_name);
1338 }
1339
1340 return pcmk_rc_ok;
1341 }
1342
1343 PCMK__OUTPUT_ARGS("node-info", "uint32_t", "const char *", "const char *",
1344 "const char *", "bool", "bool")
1345 static int
1346 node_info_default(pcmk__output_t *out, va_list args)
1347 {
1348 uint32_t node_id = va_arg(args, uint32_t);
1349 const char *node_name = va_arg(args, const char *);
1350 const char *uuid = va_arg(args, const char *);
1351 const char *state = va_arg(args, const char *);
1352 bool have_quorum = (bool) va_arg(args, int);
1353 bool is_remote = (bool) va_arg(args, int);
1354
1355 return out->info(out,
1356 "Node %" PRIu32 ": %s "
1357 "(uuid=%s, state=%s, have_quorum=%s, is_remote=%s)",
1358 node_id, pcmk__s(node_name, "unknown"),
1359 pcmk__s(uuid, "unknown"), pcmk__s(state, "unknown"),
1360 pcmk__btoa(have_quorum), pcmk__btoa(is_remote));
1361 }
1362
1363 PCMK__OUTPUT_ARGS("node-info", "uint32_t", "const char *", "const char *",
1364 "const char *", "bool", "bool")
1365 static int
1366 node_info_xml(pcmk__output_t *out, va_list args)
1367 {
1368 uint32_t node_id = va_arg(args, uint32_t);
1369 const char *node_name = va_arg(args, const char *);
1370 const char *uuid = va_arg(args, const char *);
1371 const char *state = va_arg(args, const char *);
1372 bool have_quorum = (bool) va_arg(args, int);
1373 bool is_remote = (bool) va_arg(args, int);
1374
1375 char *id_s = crm_strdup_printf("%" PRIu32, node_id);
1376
1377 pcmk__output_create_xml_node(out, PCMK_XE_NODE_INFO,
1378 PCMK_XA_NODEID, id_s,
1379 PCMK_XA_UNAME, node_name,
1380 PCMK_XA_ID, uuid,
1381 PCMK_XA_CRMD, state,
1382 PCMK_XA_HAVE_QUORUM, pcmk__btoa(have_quorum),
1383 PCMK_XA_REMOTE_NODE, pcmk__btoa(is_remote),
1384 NULL);
1385 free(id_s);
1386 return pcmk_rc_ok;
1387 }
1388
1389 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *",
1390 "xmlNode *")
1391 static int
1392 inject_cluster_action(pcmk__output_t *out, va_list args)
1393 {
1394 const char *node = va_arg(args, const char *);
1395 const char *task = va_arg(args, const char *);
1396 xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1397
1398 if (out->is_quiet(out)) {
1399 return pcmk_rc_no_output;
1400 }
1401
1402 if (rsc != NULL) {
1403 out->list_item(out, NULL, "Cluster action: %s for %s on %s",
1404 task, pcmk__xe_id(rsc), node);
1405 } else {
1406 out->list_item(out, NULL, "Cluster action: %s on %s", task, node);
1407 }
1408
1409 return pcmk_rc_ok;
1410 }
1411
1412 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *",
1413 "xmlNode *")
1414 static int
1415 inject_cluster_action_xml(pcmk__output_t *out, va_list args)
1416 {
1417 const char *node = va_arg(args, const char *);
1418 const char *task = va_arg(args, const char *);
1419 xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1420
1421 xmlNodePtr xml_node = NULL;
1422
1423 if (out->is_quiet(out)) {
1424 return pcmk_rc_no_output;
1425 }
1426
1427 xml_node = pcmk__output_create_xml_node(out, PCMK_XE_CLUSTER_ACTION,
1428 PCMK_XA_TASK, task,
1429 PCMK_XA_NODE, node,
1430 NULL);
1431
1432 if (rsc) {
1433 crm_xml_add(xml_node, PCMK_XA_ID, pcmk__xe_id(rsc));
1434 }
1435
1436 return pcmk_rc_ok;
1437 }
1438
1439 PCMK__OUTPUT_ARGS("inject-fencing-action", "const char *", "const char *")
1440 static int
1441 inject_fencing_action(pcmk__output_t *out, va_list args)
1442 {
1443 const char *target = va_arg(args, const char *);
1444 const char *op = va_arg(args, const char *);
1445
1446 if (out->is_quiet(out)) {
1447 return pcmk_rc_no_output;
1448 }
1449
1450 out->list_item(out, NULL, "Fencing %s (%s)", target, op);
1451 return pcmk_rc_ok;
1452 }
1453
1454 PCMK__OUTPUT_ARGS("inject-fencing-action", "const char *", "const char *")
1455 static int
1456 inject_fencing_action_xml(pcmk__output_t *out, va_list args)
1457 {
1458 const char *target = va_arg(args, const char *);
1459 const char *op = va_arg(args, const char *);
1460
1461 if (out->is_quiet(out)) {
1462 return pcmk_rc_no_output;
1463 }
1464
1465 pcmk__output_create_xml_node(out, PCMK_XE_FENCING_ACTION,
1466 PCMK_XA_TARGET, target,
1467 PCMK_XA_OP, op,
1468 NULL);
1469 return pcmk_rc_ok;
1470 }
1471
1472 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNode *")
1473 static int
1474 inject_attr(pcmk__output_t *out, va_list args)
1475 {
1476 const char *name = va_arg(args, const char *);
1477 const char *value = va_arg(args, const char *);
1478 xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1479
1480 xmlChar *node_path = NULL;
1481
1482 if (out->is_quiet(out)) {
1483 return pcmk_rc_no_output;
1484 }
1485
1486 node_path = xmlGetNodePath(cib_node);
1487
1488 out->list_item(out, NULL, "Injecting attribute %s=%s into %s '%s'",
1489 name, value, node_path, pcmk__xe_id(cib_node));
1490
1491 free(node_path);
1492 return pcmk_rc_ok;
1493 }
1494
1495 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNode *")
1496 static int
1497 inject_attr_xml(pcmk__output_t *out, va_list args)
1498 {
1499 const char *name = va_arg(args, const char *);
1500 const char *value = va_arg(args, const char *);
1501 xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1502
1503 xmlChar *node_path = NULL;
1504
1505 if (out->is_quiet(out)) {
1506 return pcmk_rc_no_output;
1507 }
1508
1509 node_path = xmlGetNodePath(cib_node);
1510
1511 pcmk__output_create_xml_node(out, PCMK_XE_INJECT_ATTR,
1512 PCMK_XA_NAME, name,
1513 PCMK_XA_VALUE, value,
1514 PCMK_XA_NODE_PATH, node_path,
1515 PCMK_XA_CIB_NODE, pcmk__xe_id(cib_node),
1516 NULL);
1517 free(node_path);
1518 return pcmk_rc_ok;
1519 }
1520
1521 PCMK__OUTPUT_ARGS("inject-spec", "const char *")
1522 static int
1523 inject_spec(pcmk__output_t *out, va_list args)
1524 {
1525 const char *spec = va_arg(args, const char *);
1526
1527 if (out->is_quiet(out)) {
1528 return pcmk_rc_no_output;
1529 }
1530
1531 out->list_item(out, NULL, "Injecting %s into the configuration", spec);
1532 return pcmk_rc_ok;
1533 }
1534
1535 PCMK__OUTPUT_ARGS("inject-spec", "const char *")
1536 static int
1537 inject_spec_xml(pcmk__output_t *out, va_list args)
1538 {
1539 const char *spec = va_arg(args, const char *);
1540
1541 if (out->is_quiet(out)) {
1542 return pcmk_rc_no_output;
1543 }
1544
1545 pcmk__output_create_xml_node(out, PCMK_XE_INJECT_SPEC,
1546 PCMK_XA_SPEC, spec,
1547 NULL);
1548 return pcmk_rc_ok;
1549 }
1550
1551 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1552 static int
1553 inject_modify_config(pcmk__output_t *out, va_list args)
1554 {
1555 const char *quorum = va_arg(args, const char *);
1556 const char *watchdog = va_arg(args, const char *);
1557
1558 if (out->is_quiet(out)) {
1559 return pcmk_rc_no_output;
1560 }
1561
1562 out->begin_list(out, NULL, NULL, "Performing Requested Modifications");
1563
1564 if (quorum) {
1565 out->list_item(out, NULL, "Setting quorum: %s", quorum);
1566 }
1567
1568 if (watchdog) {
1569 out->list_item(out, NULL, "Setting watchdog: %s", watchdog);
1570 }
1571
1572 return pcmk_rc_ok;
1573 }
1574
1575 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1576 static int
1577 inject_modify_config_xml(pcmk__output_t *out, va_list args)
1578 {
1579 const char *quorum = va_arg(args, const char *);
1580 const char *watchdog = va_arg(args, const char *);
1581
1582 xmlNodePtr node = NULL;
1583
1584 if (out->is_quiet(out)) {
1585 return pcmk_rc_no_output;
1586 }
1587
1588 node = pcmk__output_xml_create_parent(out, PCMK_XE_MODIFICATIONS, NULL);
1589
1590 if (quorum) {
1591 crm_xml_add(node, PCMK_XA_QUORUM, quorum);
1592 }
1593
1594 if (watchdog) {
1595 crm_xml_add(node, PCMK_XA_WATCHDOG, watchdog);
1596 }
1597
1598 pcmk__output_xml_pop_parent(out);
1599 return pcmk_rc_ok;
1600 }
1601
1602 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "const char *")
1603 static int
1604 inject_modify_node(pcmk__output_t *out, va_list args)
1605 {
1606 const char *action = va_arg(args, const char *);
1607 const char *node = va_arg(args, const char *);
1608
1609 if (out->is_quiet(out)) {
1610 return pcmk_rc_no_output;
1611 }
1612
1613 if (pcmk__str_eq(action, "Online", pcmk__str_none)) {
1614 out->list_item(out, NULL, "Bringing node %s online", node);
1615 return pcmk_rc_ok;
1616 } else if (pcmk__str_eq(action, "Offline", pcmk__str_none)) {
1617 out->list_item(out, NULL, "Taking node %s offline", node);
1618 return pcmk_rc_ok;
1619 } else if (pcmk__str_eq(action, "Failing", pcmk__str_none)) {
1620 out->list_item(out, NULL, "Failing node %s", node);
1621 return pcmk_rc_ok;
1622 }
1623
1624 return pcmk_rc_no_output;
1625 }
1626
1627 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "const char *")
1628 static int
1629 inject_modify_node_xml(pcmk__output_t *out, va_list args)
1630 {
1631 const char *action = va_arg(args, const char *);
1632 const char *node = va_arg(args, const char *);
1633
1634 if (out->is_quiet(out)) {
1635 return pcmk_rc_no_output;
1636 }
1637
1638 pcmk__output_create_xml_node(out, PCMK_XE_MODIFY_NODE,
1639 PCMK_XA_ACTION, action,
1640 PCMK_XA_NODE, node,
1641 NULL);
1642 return pcmk_rc_ok;
1643 }
1644
1645 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "const char *")
1646 static int
1647 inject_modify_ticket(pcmk__output_t *out, va_list args)
1648 {
1649 const char *action = va_arg(args, const char *);
1650 const char *ticket = va_arg(args, const char *);
1651
1652 if (out->is_quiet(out)) {
1653 return pcmk_rc_no_output;
1654 }
1655
1656 if (pcmk__str_eq(action, "Standby", pcmk__str_none)) {
1657 out->list_item(out, NULL, "Making ticket %s standby", ticket);
1658 } else {
1659 out->list_item(out, NULL, "%s ticket %s", action, ticket);
1660 }
1661
1662 return pcmk_rc_ok;
1663 }
1664
1665 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "const char *")
1666 static int
1667 inject_modify_ticket_xml(pcmk__output_t *out, va_list args)
1668 {
1669 const char *action = va_arg(args, const char *);
1670 const char *ticket = va_arg(args, const char *);
1671
1672 if (out->is_quiet(out)) {
1673 return pcmk_rc_no_output;
1674 }
1675
1676 pcmk__output_create_xml_node(out, PCMK_XE_MODIFY_TICKET,
1677 PCMK_XA_ACTION, action,
1678 PCMK_XA_TICKET, ticket,
1679 NULL);
1680 return pcmk_rc_ok;
1681 }
1682
1683 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1684 static int
1685 inject_pseudo_action(pcmk__output_t *out, va_list args)
1686 {
1687 const char *node = va_arg(args, const char *);
1688 const char *task = va_arg(args, const char *);
1689
1690 if (out->is_quiet(out)) {
1691 return pcmk_rc_no_output;
1692 }
1693
1694 out->list_item(out, NULL, "Pseudo action: %s%s%s",
1695 task, ((node == NULL)? "" : " on "), pcmk__s(node, ""));
1696 return pcmk_rc_ok;
1697 }
1698
1699 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1700 static int
1701 inject_pseudo_action_xml(pcmk__output_t *out, va_list args)
1702 {
1703 const char *node = va_arg(args, const char *);
1704 const char *task = va_arg(args, const char *);
1705
1706 xmlNodePtr xml_node = NULL;
1707
1708 if (out->is_quiet(out)) {
1709 return pcmk_rc_no_output;
1710 }
1711
1712 xml_node = pcmk__output_create_xml_node(out, PCMK_XE_PSEUDO_ACTION,
1713 PCMK_XA_TASK, task,
1714 NULL);
1715 if (node) {
1716 crm_xml_add(xml_node, PCMK_XA_NODE, node);
1717 }
1718
1719 return pcmk_rc_ok;
1720 }
1721
1722 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *",
1723 "const char *", "guint")
1724 static int
1725 inject_rsc_action(pcmk__output_t *out, va_list args)
1726 {
1727 const char *rsc = va_arg(args, const char *);
1728 const char *operation = va_arg(args, const char *);
1729 const char *node = va_arg(args, const char *);
1730 guint interval_ms = va_arg(args, guint);
1731
1732 if (out->is_quiet(out)) {
1733 return pcmk_rc_no_output;
1734 }
1735
1736 if (interval_ms) {
1737 out->list_item(out, NULL, "Resource action: %-15s %s=%u on %s",
1738 rsc, operation, interval_ms, node);
1739 } else {
1740 out->list_item(out, NULL, "Resource action: %-15s %s on %s",
1741 rsc, operation, node);
1742 }
1743
1744 return pcmk_rc_ok;
1745 }
1746
1747 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *",
1748 "const char *", "guint")
1749 static int
1750 inject_rsc_action_xml(pcmk__output_t *out, va_list args)
1751 {
1752 const char *rsc = va_arg(args, const char *);
1753 const char *operation = va_arg(args, const char *);
1754 const char *node = va_arg(args, const char *);
1755 guint interval_ms = va_arg(args, guint);
1756
1757 xmlNodePtr xml_node = NULL;
1758
1759 if (out->is_quiet(out)) {
1760 return pcmk_rc_no_output;
1761 }
1762
1763 xml_node = pcmk__output_create_xml_node(out, PCMK_XE_RSC_ACTION,
1764 PCMK_XA_RESOURCE, rsc,
1765 PCMK_XA_OP, operation,
1766 PCMK_XA_NODE, node,
1767 NULL);
1768
1769 if (interval_ms) {
1770 char *interval_s = pcmk__itoa(interval_ms);
1771
1772 crm_xml_add(xml_node, PCMK_XA_INTERVAL, interval_s);
1773 free(interval_s);
1774 }
1775
1776 return pcmk_rc_ok;
1777 }
1778
1779 #define CHECK_RC(retcode, retval) \
1780 if (retval == pcmk_rc_ok) { \
1781 retcode = pcmk_rc_ok; \
1782 }
1783
1784 PCMK__OUTPUT_ARGS("cluster-status", "pcmk_scheduler_t *",
1785 "enum pcmk_pacemakerd_state", "crm_exit_t",
1786 "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
1787 "uint32_t", "const char *", "GList *", "GList *")
1788 int
1789 pcmk__cluster_status_text(pcmk__output_t *out, va_list args)
1790 {
1791 pcmk_scheduler_t *scheduler = va_arg(args, pcmk_scheduler_t *);
1792 enum pcmk_pacemakerd_state pcmkd_state =
1793 (enum pcmk_pacemakerd_state) va_arg(args, int);
1794 crm_exit_t history_rc = va_arg(args, crm_exit_t);
1795 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1796 enum pcmk__fence_history fence_history = va_arg(args, int);
1797 uint32_t section_opts = va_arg(args, uint32_t);
1798 uint32_t show_opts = va_arg(args, uint32_t);
1799 const char *prefix = va_arg(args, const char *);
1800 GList *unames = va_arg(args, GList *);
1801 GList *resources = va_arg(args, GList *);
1802
1803 int rc = pcmk_rc_no_output;
1804 bool already_printed_failure = false;
1805
1806 CHECK_RC(rc, out->message(out, "cluster-summary", scheduler, pcmkd_state,
1807 section_opts, show_opts));
1808
1809 if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
1810 CHECK_RC(rc, out->message(out, "node-list", scheduler->nodes, unames,
1811 resources, show_opts, rc == pcmk_rc_ok));
1812 }
1813
1814
1815 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1816 CHECK_RC(rc, out->message(out, "resource-list", scheduler, show_opts,
1817 true, unames, resources, rc == pcmk_rc_ok));
1818 }
1819
1820
1821 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1822 CHECK_RC(rc, out->message(out, "node-attribute-list", scheduler,
1823 show_opts, (rc == pcmk_rc_ok), unames,
1824 resources));
1825 }
1826
1827
1828
1829
1830 if (pcmk_any_flags_set(section_opts,
1831 pcmk_section_operations|pcmk_section_failcounts)) {
1832 CHECK_RC(rc, out->message(out, "node-summary", scheduler, unames,
1833 resources, section_opts, show_opts,
1834 (rc == pcmk_rc_ok)));
1835 }
1836
1837
1838 if (pcmk_is_set(section_opts, pcmk_section_failures)
1839 && (scheduler->failed != NULL)
1840 && (scheduler->failed->children != NULL)) {
1841
1842 CHECK_RC(rc, out->message(out, "failed-action-list", scheduler, unames,
1843 resources, show_opts, rc == pcmk_rc_ok));
1844 }
1845
1846
1847 if (pcmk_is_set(section_opts, pcmk_section_fence_failed) &&
1848 fence_history != pcmk__fence_history_none) {
1849 if (history_rc == 0) {
1850 stonith_history_t *hp = NULL;
1851
1852 hp = stonith__first_matching_event(stonith_history,
1853 stonith__event_state_eq,
1854 GINT_TO_POINTER(st_failed));
1855 if (hp) {
1856 CHECK_RC(rc, out->message(out, "failed-fencing-list",
1857 stonith_history, unames, section_opts,
1858 show_opts, rc == pcmk_rc_ok));
1859 }
1860 } else {
1861 PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
1862 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1863 out->list_item(out, NULL, "Failed to get fencing history: %s",
1864 crm_exit_str(history_rc));
1865 out->end_list(out);
1866
1867 already_printed_failure = true;
1868 }
1869 }
1870
1871
1872 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1873 CHECK_RC(rc, out->message(out, "ticket-list", scheduler->tickets,
1874 (rc == pcmk_rc_ok), false, false));
1875 }
1876
1877
1878 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1879 CHECK_RC(rc, out->message(out, "ban-list", scheduler, prefix, resources,
1880 show_opts, rc == pcmk_rc_ok));
1881 }
1882
1883
1884 if (pcmk_any_flags_set(section_opts, pcmk_section_fencing_all) &&
1885 fence_history != pcmk__fence_history_none) {
1886 if (history_rc != 0) {
1887 if (!already_printed_failure) {
1888 PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
1889 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1890 out->list_item(out, NULL, "Failed to get fencing history: %s",
1891 crm_exit_str(history_rc));
1892 out->end_list(out);
1893 }
1894 } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
1895 stonith_history_t *hp = NULL;
1896
1897 hp = stonith__first_matching_event(stonith_history,
1898 stonith__event_state_neq,
1899 GINT_TO_POINTER(st_failed));
1900 if (hp) {
1901 CHECK_RC(rc, out->message(out, "fencing-list", hp, unames,
1902 section_opts, show_opts,
1903 rc == pcmk_rc_ok));
1904 }
1905 } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
1906 stonith_history_t *hp = NULL;
1907
1908 hp = stonith__first_matching_event(stonith_history,
1909 stonith__event_state_pending,
1910 NULL);
1911 if (hp) {
1912 CHECK_RC(rc, out->message(out, "pending-fencing-list", hp,
1913 unames, section_opts, show_opts,
1914 rc == pcmk_rc_ok));
1915 }
1916 }
1917 }
1918
1919 return rc;
1920 }
1921
1922 PCMK__OUTPUT_ARGS("cluster-status", "pcmk_scheduler_t *",
1923 "enum pcmk_pacemakerd_state", "crm_exit_t",
1924 "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
1925 "uint32_t", "const char *", "GList *", "GList *")
1926 static int
1927 cluster_status_xml(pcmk__output_t *out, va_list args)
1928 {
1929 pcmk_scheduler_t *scheduler = va_arg(args, pcmk_scheduler_t *);
1930 enum pcmk_pacemakerd_state pcmkd_state =
1931 (enum pcmk_pacemakerd_state) va_arg(args, int);
1932 crm_exit_t history_rc = va_arg(args, crm_exit_t);
1933 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1934 enum pcmk__fence_history fence_history = va_arg(args, int);
1935 uint32_t section_opts = va_arg(args, uint32_t);
1936 uint32_t show_opts = va_arg(args, uint32_t);
1937 const char *prefix = va_arg(args, const char *);
1938 GList *unames = va_arg(args, GList *);
1939 GList *resources = va_arg(args, GList *);
1940
1941 out->message(out, "cluster-summary", scheduler, pcmkd_state, section_opts,
1942 show_opts);
1943
1944
1945 if (pcmk_is_set(section_opts, pcmk_section_nodes)) {
1946 out->message(out, "node-list", scheduler->nodes, unames, resources,
1947 show_opts, false);
1948 }
1949
1950
1951 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1952
1953 uint32_t full_show_opts = show_opts & ~pcmk_show_brief;
1954
1955 out->message(out, "resource-list", scheduler, full_show_opts,
1956 false, unames, resources, false);
1957 }
1958
1959
1960 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1961 out->message(out, "node-attribute-list", scheduler, show_opts, false,
1962 unames, resources);
1963 }
1964
1965
1966
1967
1968 if (pcmk_any_flags_set(section_opts,
1969 pcmk_section_operations|pcmk_section_failcounts)) {
1970 out->message(out, "node-summary", scheduler, unames,
1971 resources, section_opts, show_opts, false);
1972 }
1973
1974
1975 if (pcmk_is_set(section_opts, pcmk_section_failures)
1976 && (scheduler->failed != NULL)
1977 && (scheduler->failed->children != NULL)) {
1978
1979 out->message(out, "failed-action-list", scheduler, unames, resources,
1980 show_opts, false);
1981 }
1982
1983
1984 if (pcmk_is_set(section_opts, pcmk_section_fencing_all) &&
1985 fence_history != pcmk__fence_history_none) {
1986 out->message(out, "full-fencing-list", history_rc, stonith_history,
1987 unames, section_opts, show_opts, false);
1988 }
1989
1990
1991 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1992 out->message(out, "ticket-list", scheduler->tickets, false, false, false);
1993 }
1994
1995
1996 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1997 out->message(out, "ban-list", scheduler, prefix, resources, show_opts,
1998 false);
1999 }
2000
2001 return pcmk_rc_ok;
2002 }
2003
2004 PCMK__OUTPUT_ARGS("cluster-status", "pcmk_scheduler_t *",
2005 "enum pcmk_pacemakerd_state", "crm_exit_t",
2006 "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
2007 "uint32_t", "const char *", "GList *", "GList *")
2008 static int
2009 cluster_status_html(pcmk__output_t *out, va_list args)
2010 {
2011 pcmk_scheduler_t *scheduler = va_arg(args, pcmk_scheduler_t *);
2012 enum pcmk_pacemakerd_state pcmkd_state =
2013 (enum pcmk_pacemakerd_state) va_arg(args, int);
2014 crm_exit_t history_rc = va_arg(args, crm_exit_t);
2015 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
2016 enum pcmk__fence_history fence_history = va_arg(args, int);
2017 uint32_t section_opts = va_arg(args, uint32_t);
2018 uint32_t show_opts = va_arg(args, uint32_t);
2019 const char *prefix = va_arg(args, const char *);
2020 GList *unames = va_arg(args, GList *);
2021 GList *resources = va_arg(args, GList *);
2022 bool already_printed_failure = false;
2023
2024 out->message(out, "cluster-summary", scheduler, pcmkd_state, section_opts,
2025 show_opts);
2026
2027
2028 if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
2029 out->message(out, "node-list", scheduler->nodes, unames, resources,
2030 show_opts, false);
2031 }
2032
2033
2034 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
2035 out->message(out, "resource-list", scheduler, show_opts, true, unames,
2036 resources, false);
2037 }
2038
2039
2040 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
2041 out->message(out, "node-attribute-list", scheduler, show_opts, false,
2042 unames, resources);
2043 }
2044
2045
2046
2047
2048 if (pcmk_any_flags_set(section_opts,
2049 pcmk_section_operations|pcmk_section_failcounts)) {
2050 out->message(out, "node-summary", scheduler, unames,
2051 resources, section_opts, show_opts, false);
2052 }
2053
2054
2055 if (pcmk_is_set(section_opts, pcmk_section_failures)
2056 && (scheduler->failed != NULL)
2057 && (scheduler->failed->children != NULL)) {
2058
2059 out->message(out, "failed-action-list", scheduler, unames, resources,
2060 show_opts, false);
2061 }
2062
2063
2064 if (pcmk_is_set(section_opts, pcmk_section_fence_failed) &&
2065 fence_history != pcmk__fence_history_none) {
2066 if (history_rc == 0) {
2067 stonith_history_t *hp = NULL;
2068
2069 hp = stonith__first_matching_event(stonith_history,
2070 stonith__event_state_eq,
2071 GINT_TO_POINTER(st_failed));
2072 if (hp) {
2073 out->message(out, "failed-fencing-list", stonith_history,
2074 unames, section_opts, show_opts, false);
2075 }
2076 } else {
2077 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
2078 out->list_item(out, NULL, "Failed to get fencing history: %s",
2079 crm_exit_str(history_rc));
2080 out->end_list(out);
2081 }
2082 }
2083
2084
2085 if (pcmk_any_flags_set(section_opts, pcmk_section_fencing_all) &&
2086 fence_history != pcmk__fence_history_none) {
2087 if (history_rc != 0) {
2088 if (!already_printed_failure) {
2089 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
2090 out->list_item(out, NULL, "Failed to get fencing history: %s",
2091 crm_exit_str(history_rc));
2092 out->end_list(out);
2093 }
2094 } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
2095 stonith_history_t *hp = NULL;
2096
2097 hp = stonith__first_matching_event(stonith_history,
2098 stonith__event_state_neq,
2099 GINT_TO_POINTER(st_failed));
2100 if (hp) {
2101 out->message(out, "fencing-list", hp, unames, section_opts,
2102 show_opts, false);
2103 }
2104 } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
2105 stonith_history_t *hp = NULL;
2106
2107 hp = stonith__first_matching_event(stonith_history,
2108 stonith__event_state_pending,
2109 NULL);
2110 if (hp) {
2111 out->message(out, "pending-fencing-list", hp, unames,
2112 section_opts, show_opts, false);
2113 }
2114 }
2115 }
2116
2117
2118 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
2119 out->message(out, "ticket-list", scheduler->tickets, false, false, false);
2120 }
2121
2122
2123 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
2124 out->message(out, "ban-list", scheduler, prefix, resources, show_opts,
2125 false);
2126 }
2127
2128 return pcmk_rc_ok;
2129 }
2130
2131 #define KV_PAIR(k, v) do { \
2132 if (legacy) { \
2133 pcmk__g_strcat(s, k "=", pcmk__s(v, ""), " ", NULL); \
2134 } else { \
2135 pcmk__g_strcat(s, k "=\"", pcmk__s(v, ""), "\" ", NULL); \
2136 } \
2137 } while (0)
2138
2139 PCMK__OUTPUT_ARGS("attribute", "const char *", "const char *", "const char *",
2140 "const char *", "const char *", "bool", "bool")
2141 static int
2142 attribute_default(pcmk__output_t *out, va_list args)
2143 {
2144 const char *scope = va_arg(args, const char *);
2145 const char *instance = va_arg(args, const char *);
2146 const char *name = va_arg(args, const char *);
2147 const char *value = va_arg(args, const char *);
2148 const char *host = va_arg(args, const char *);
2149 bool quiet = va_arg(args, int);
2150 bool legacy = va_arg(args, int);
2151
2152 gchar *value_esc = NULL;
2153 GString *s = NULL;
2154
2155 if (quiet) {
2156 if (value != NULL) {
2157
2158 bool was_quiet = out->is_quiet(out);
2159
2160 if (was_quiet) {
2161 out->quiet = false;
2162 }
2163
2164 out->info(out, "%s", value);
2165
2166 out->quiet = was_quiet;
2167 }
2168
2169 return pcmk_rc_ok;
2170 }
2171
2172 s = g_string_sized_new(50);
2173
2174 if (pcmk__xml_needs_escape(value, pcmk__xml_escape_attr_pretty)) {
2175 value_esc = pcmk__xml_escape(value, pcmk__xml_escape_attr_pretty);
2176 value = value_esc;
2177 }
2178
2179 if (!pcmk__str_empty(scope)) {
2180 KV_PAIR(PCMK_XA_SCOPE, scope);
2181 }
2182
2183 if (!pcmk__str_empty(instance)) {
2184 KV_PAIR(PCMK_XA_ID, instance);
2185 }
2186
2187 KV_PAIR(PCMK_XA_NAME, name);
2188
2189 if (!pcmk__str_empty(host)) {
2190 KV_PAIR(PCMK_XA_HOST, host);
2191 }
2192
2193 if (legacy) {
2194 pcmk__g_strcat(s, PCMK_XA_VALUE "=", pcmk__s(value, "(null)"), NULL);
2195 } else {
2196 pcmk__g_strcat(s, PCMK_XA_VALUE "=\"", pcmk__s(value, ""), "\"", NULL);
2197 }
2198
2199 out->info(out, "%s", s->str);
2200
2201 g_free(value_esc);
2202 g_string_free(s, TRUE);
2203 return pcmk_rc_ok;
2204 }
2205
2206 PCMK__OUTPUT_ARGS("attribute", "const char *", "const char *", "const char *",
2207 "const char *", "const char *", "bool", "bool")
2208 static int
2209 attribute_xml(pcmk__output_t *out, va_list args)
2210 {
2211 const char *scope = va_arg(args, const char *);
2212 const char *instance = va_arg(args, const char *);
2213 const char *name = va_arg(args, const char *);
2214 const char *value = va_arg(args, const char *);
2215 const char *host = va_arg(args, const char *);
2216 bool quiet G_GNUC_UNUSED = va_arg(args, int);
2217 bool legacy G_GNUC_UNUSED = va_arg(args, int);
2218
2219 xmlNodePtr node = NULL;
2220
2221 node = pcmk__output_create_xml_node(out, PCMK_XE_ATTRIBUTE,
2222 PCMK_XA_NAME, name,
2223 PCMK_XA_VALUE, pcmk__s(value, ""),
2224 NULL);
2225
2226 if (!pcmk__str_empty(scope)) {
2227 crm_xml_add(node, PCMK_XA_SCOPE, scope);
2228 }
2229
2230 if (!pcmk__str_empty(instance)) {
2231 crm_xml_add(node, PCMK_XA_ID, instance);
2232 }
2233
2234 if (!pcmk__str_empty(host)) {
2235 crm_xml_add(node, PCMK_XA_HOST, host);
2236 }
2237
2238 return pcmk_rc_ok;
2239 }
2240
2241 PCMK__OUTPUT_ARGS("rule-check", "const char *", "int", "const char *")
2242 static int
2243 rule_check_default(pcmk__output_t *out, va_list args)
2244 {
2245 const char *rule_id = va_arg(args, const char *);
2246 int result = va_arg(args, int);
2247 const char *error = va_arg(args, const char *);
2248
2249 switch (result) {
2250 case pcmk_rc_within_range:
2251 return out->info(out, "Rule %s is still in effect", rule_id);
2252 case pcmk_rc_ok:
2253 return out->info(out, "Rule %s satisfies conditions", rule_id);
2254 case pcmk_rc_after_range:
2255 return out->info(out, "Rule %s is expired", rule_id);
2256 case pcmk_rc_before_range:
2257 return out->info(out, "Rule %s has not yet taken effect", rule_id);
2258 case pcmk_rc_op_unsatisfied:
2259 return out->info(out, "Rule %s does not satisfy conditions",
2260 rule_id);
2261 default:
2262 out->err(out,
2263 "Could not determine whether rule %s is in effect: %s",
2264 rule_id, ((error != NULL)? error : "unexpected error"));
2265 return pcmk_rc_ok;
2266 }
2267 }
2268
2269 PCMK__OUTPUT_ARGS("rule-check", "const char *", "int", "const char *")
2270 static int
2271 rule_check_xml(pcmk__output_t *out, va_list args)
2272 {
2273 const char *rule_id = va_arg(args, const char *);
2274 int result = va_arg(args, int);
2275 const char *error = va_arg(args, const char *);
2276
2277 char *rc_str = pcmk__itoa(pcmk_rc2exitc(result));
2278
2279 pcmk__output_create_xml_node(out, PCMK_XE_RULE_CHECK,
2280 PCMK_XA_RULE_ID, rule_id,
2281 PCMK_XA_RC, rc_str,
2282 NULL);
2283 free(rc_str);
2284
2285 switch (result) {
2286 case pcmk_rc_within_range:
2287 case pcmk_rc_ok:
2288 case pcmk_rc_after_range:
2289 case pcmk_rc_before_range:
2290 case pcmk_rc_op_unsatisfied:
2291 return pcmk_rc_ok;
2292 default:
2293 out->err(out,
2294 "Could not determine whether rule %s is in effect: %s",
2295 rule_id, ((error != NULL)? error : "unexpected error"));
2296 return pcmk_rc_ok;
2297 }
2298 }
2299
2300 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2301 static int
2302 result_code_none(pcmk__output_t *out, va_list args)
2303 {
2304 return pcmk_rc_no_output;
2305 }
2306
2307 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2308 static int
2309 result_code_text(pcmk__output_t *out, va_list args)
2310 {
2311 int code = va_arg(args, int);
2312 const char *name = va_arg(args, const char *);
2313 const char *desc = va_arg(args, const char *);
2314
2315 static int code_width = 0;
2316
2317 if (out->is_quiet(out)) {
2318
2319
2320
2321
2322 if ((name != NULL) && (desc != NULL)) {
2323 pcmk__formatted_printf(out, "%s - %s\n", name, desc);
2324
2325 } else if ((name != NULL) || (desc != NULL)) {
2326 pcmk__formatted_printf(out, "%s\n", ((name != NULL)? name : desc));
2327 }
2328 return pcmk_rc_ok;
2329 }
2330
2331
2332
2333
2334
2335 if (code_width == 0) {
2336 long long most_negative = pcmk_rc_error - (long long) pcmk__n_rc + 1;
2337 code_width = (int) snprintf(NULL, 0, "%lld", most_negative);
2338 }
2339
2340 if ((name != NULL) && (desc != NULL)) {
2341 static int name_width = 0;
2342
2343 if (name_width == 0) {
2344
2345 for (int lpc = 0; lpc < pcmk__n_rc; lpc++) {
2346 int len = (int) strlen(pcmk_rc_name(pcmk_rc_error - lpc));
2347 name_width = QB_MAX(name_width, len);
2348 }
2349 }
2350 return out->info(out, "% *d: %-*s %s", code_width, code, name_width,
2351 name, desc);
2352 }
2353
2354 if ((name != NULL) || (desc != NULL)) {
2355 return out->info(out, "% *d: %s", code_width, code,
2356 ((name != NULL)? name : desc));
2357 }
2358
2359 return out->info(out, "% *d", code_width, code);
2360 }
2361
2362 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2363 static int
2364 result_code_xml(pcmk__output_t *out, va_list args)
2365 {
2366 int code = va_arg(args, int);
2367 const char *name = va_arg(args, const char *);
2368 const char *desc = va_arg(args, const char *);
2369
2370 char *code_str = pcmk__itoa(code);
2371
2372 pcmk__output_create_xml_node(out, PCMK_XE_RESULT_CODE,
2373 PCMK_XA_CODE, code_str,
2374 PCMK_XA_NAME, name,
2375 PCMK_XA_DESCRIPTION, desc,
2376 NULL);
2377 free(code_str);
2378 return pcmk_rc_ok;
2379 }
2380
2381 PCMK__OUTPUT_ARGS("ticket-attribute", "const char *", "const char *", "const char *")
2382 static int
2383 ticket_attribute_default(pcmk__output_t *out, va_list args)
2384 {
2385 const char *ticket_id G_GNUC_UNUSED = va_arg(args, const char *);
2386 const char *name G_GNUC_UNUSED = va_arg(args, const char *);
2387 const char *value = va_arg(args, const char *);
2388
2389 out->info(out, "%s", value);
2390 return pcmk_rc_ok;
2391 }
2392
2393 PCMK__OUTPUT_ARGS("ticket-attribute", "const char *", "const char *", "const char *")
2394 static int
2395 ticket_attribute_xml(pcmk__output_t *out, va_list args)
2396 {
2397 const char *ticket_id = va_arg(args, const char *);
2398 const char *name = va_arg(args, const char *);
2399 const char *value = va_arg(args, const char *);
2400
2401
2402
2403
2404
2405
2406
2407
2408 pcmk__output_xml_create_parent(out, PCMK_XE_TICKETS, NULL);
2409 pcmk__output_xml_create_parent(out, PCMK_XE_TICKET,
2410 PCMK_XA_ID, ticket_id, NULL);
2411 pcmk__output_create_xml_node(out, PCMK_XA_ATTRIBUTE,
2412 PCMK_XA_NAME, name,
2413 PCMK_XA_VALUE, value,
2414 NULL);
2415 pcmk__output_xml_pop_parent(out);
2416 pcmk__output_xml_pop_parent(out);
2417
2418 return pcmk_rc_ok;
2419 }
2420
2421 PCMK__OUTPUT_ARGS("ticket-constraints", "xmlNode *")
2422 static int
2423 ticket_constraints_default(pcmk__output_t *out, va_list args)
2424 {
2425 xmlNode *constraint_xml = va_arg(args, xmlNode *);
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445 out->info(out, "Constraints XML:\n");
2446
2447 if (pcmk__xe_is(constraint_xml, PCMK__XE_XPATH_QUERY)) {
2448 xmlNode *child = pcmk__xe_first_child(constraint_xml, NULL, NULL, NULL);
2449
2450 do {
2451 GString *buf = g_string_sized_new(1024);
2452
2453 pcmk__xml_string(child, pcmk__xml_fmt_pretty, buf, 0);
2454 out->output_xml(out, PCMK_XE_CONSTRAINT, buf->str);
2455 g_string_free(buf, TRUE);
2456
2457 child = pcmk__xe_next(child);
2458 } while (child != NULL);
2459 } else {
2460 GString *buf = g_string_sized_new(1024);
2461
2462 pcmk__xml_string(constraint_xml, pcmk__xml_fmt_pretty, buf, 0);
2463 out->output_xml(out, PCMK_XE_CONSTRAINT, buf->str);
2464 g_string_free(buf, TRUE);
2465 }
2466
2467 return pcmk_rc_ok;
2468 }
2469
2470 static int
2471 add_ticket_element_with_constraints(xmlNode *node, void *userdata)
2472 {
2473 pcmk__output_t *out = (pcmk__output_t *) userdata;
2474 const char *ticket_id = crm_element_value(node, PCMK_XA_TICKET);
2475
2476 pcmk__output_xml_create_parent(out, PCMK_XE_TICKET,
2477 PCMK_XA_ID, ticket_id, NULL);
2478 pcmk__output_xml_create_parent(out, PCMK_XE_CONSTRAINTS, NULL);
2479 pcmk__output_xml_add_node_copy(out, node);
2480
2481
2482 pcmk__output_xml_pop_parent(out);
2483 pcmk__output_xml_pop_parent(out);
2484
2485 return pcmk_rc_ok;
2486 }
2487
2488 static int
2489 add_resource_element(xmlNode *node, void *userdata)
2490 {
2491 pcmk__output_t *out = (pcmk__output_t *) userdata;
2492 const char *rsc = crm_element_value(node, PCMK_XA_RSC);
2493
2494 pcmk__output_create_xml_node(out, PCMK_XE_RESOURCE,
2495 PCMK_XA_ID, rsc, NULL);
2496 return pcmk_rc_ok;
2497 }
2498
2499 PCMK__OUTPUT_ARGS("ticket-constraints", "xmlNode *")
2500 static int
2501 ticket_constraints_xml(pcmk__output_t *out, va_list args)
2502 {
2503 xmlNode *constraint_xml = va_arg(args, xmlNode *);
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515 pcmk__output_xml_create_parent(out, PCMK_XE_TICKETS, NULL);
2516
2517 if (pcmk__xe_is(constraint_xml, PCMK__XE_XPATH_QUERY)) {
2518
2519
2520
2521 pcmk__xe_foreach_child(constraint_xml, NULL, add_ticket_element_with_constraints, out);
2522
2523
2524 pcmk__output_xml_pop_parent(out);
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538 pcmk__output_xml_create_parent(out, PCMK_XE_RESOURCES, NULL);
2539 pcmk__xe_foreach_child(constraint_xml, NULL, add_resource_element, out);
2540 pcmk__output_xml_pop_parent(out);
2541
2542 } else {
2543
2544
2545
2546 add_ticket_element_with_constraints(constraint_xml, out);
2547 pcmk__output_xml_pop_parent(out);
2548
2549 pcmk__output_xml_create_parent(out, PCMK_XE_RESOURCES, NULL);
2550 add_resource_element(constraint_xml, out);
2551 pcmk__output_xml_pop_parent(out);
2552 }
2553
2554 return pcmk_rc_ok;
2555 }
2556
2557 PCMK__OUTPUT_ARGS("ticket-state", "xmlNode *")
2558 static int
2559 ticket_state_default(pcmk__output_t *out, va_list args)
2560 {
2561 xmlNode *state_xml = va_arg(args, xmlNode *);
2562
2563 GString *buf = g_string_sized_new(1024);
2564
2565 out->info(out, "State XML:\n");
2566 pcmk__xml_string(state_xml, pcmk__xml_fmt_pretty, buf, 0);
2567 out->output_xml(out, PCMK__XE_TICKET_STATE, buf->str);
2568
2569 g_string_free(buf, TRUE);
2570 return pcmk_rc_ok;
2571 }
2572
2573 static int
2574 add_ticket_element(xmlNode *node, void *userdata)
2575 {
2576 pcmk__output_t *out = (pcmk__output_t *) userdata;
2577 xmlNode *ticket_node = NULL;
2578
2579 ticket_node = pcmk__output_create_xml_node(out, PCMK_XE_TICKET, NULL);
2580 pcmk__xe_copy_attrs(ticket_node, node, pcmk__xaf_none);
2581 return pcmk_rc_ok;
2582 }
2583
2584 PCMK__OUTPUT_ARGS("ticket-state", "xmlNode *")
2585 static int
2586 ticket_state_xml(pcmk__output_t *out, va_list args)
2587 {
2588 xmlNode *state_xml = va_arg(args, xmlNode *);
2589
2590
2591
2592
2593
2594
2595
2596 pcmk__output_xml_create_parent(out, PCMK_XE_TICKETS, NULL);
2597
2598 if (state_xml->children != NULL) {
2599
2600
2601
2602 pcmk__xe_foreach_child(state_xml, PCMK__XE_TICKET_STATE, add_ticket_element, out);
2603
2604 } else {
2605 add_ticket_element(state_xml, out);
2606 }
2607
2608 pcmk__output_xml_pop_parent(out);
2609 return pcmk_rc_ok;
2610 }
2611
2612 static pcmk__message_entry_t fmt_functions[] = {
2613 { "attribute", "default", attribute_default },
2614 { "attribute", "xml", attribute_xml },
2615 { "cluster-status", "default", pcmk__cluster_status_text },
2616 { "cluster-status", "html", cluster_status_html },
2617 { "cluster-status", "xml", cluster_status_xml },
2618 { "crmadmin-node", "default", crmadmin_node },
2619 { "crmadmin-node", "text", crmadmin_node_text },
2620 { "crmadmin-node", "xml", crmadmin_node_xml },
2621 { "dc", "default", dc },
2622 { "dc", "text", dc_text },
2623 { "dc", "xml", dc_xml },
2624 { "digests", "default", digests_text },
2625 { "digests", "xml", digests_xml },
2626 { "health", "default", health },
2627 { "health", "text", health_text },
2628 { "health", "xml", health_xml },
2629 { "inject-attr", "default", inject_attr },
2630 { "inject-attr", "xml", inject_attr_xml },
2631 { "inject-cluster-action", "default", inject_cluster_action },
2632 { "inject-cluster-action", "xml", inject_cluster_action_xml },
2633 { "inject-fencing-action", "default", inject_fencing_action },
2634 { "inject-fencing-action", "xml", inject_fencing_action_xml },
2635 { "inject-modify-config", "default", inject_modify_config },
2636 { "inject-modify-config", "xml", inject_modify_config_xml },
2637 { "inject-modify-node", "default", inject_modify_node },
2638 { "inject-modify-node", "xml", inject_modify_node_xml },
2639 { "inject-modify-ticket", "default", inject_modify_ticket },
2640 { "inject-modify-ticket", "xml", inject_modify_ticket_xml },
2641 { "inject-pseudo-action", "default", inject_pseudo_action },
2642 { "inject-pseudo-action", "xml", inject_pseudo_action_xml },
2643 { "inject-rsc-action", "default", inject_rsc_action },
2644 { "inject-rsc-action", "xml", inject_rsc_action_xml },
2645 { "inject-spec", "default", inject_spec },
2646 { "inject-spec", "xml", inject_spec_xml },
2647 { "locations-and-colocations", "default", locations_and_colocations },
2648 { "locations-and-colocations", "xml", locations_and_colocations_xml },
2649 { "locations-list", "default", locations_list },
2650 { "locations-list", "xml", locations_list_xml },
2651 { "node-action", "default", node_action },
2652 { "node-action", "xml", node_action_xml },
2653 { "node-info", "default", node_info_default },
2654 { "node-info", "xml", node_info_xml },
2655 { "pacemakerd-health", "default", pacemakerd_health },
2656 { "pacemakerd-health", "html", pacemakerd_health_html },
2657 { "pacemakerd-health", "text", pacemakerd_health_text },
2658 { "pacemakerd-health", "xml", pacemakerd_health_xml },
2659 { "profile", "default", profile_default, },
2660 { "profile", "xml", profile_xml },
2661 { "result-code", PCMK_VALUE_NONE, result_code_none },
2662 { "result-code", "text", result_code_text },
2663 { "result-code", "xml", result_code_xml },
2664 { "rsc-action", "default", rsc_action_default },
2665 { "rsc-action-item", "default", rsc_action_item },
2666 { "rsc-action-item", "xml", rsc_action_item_xml },
2667 { "rsc-is-colocated-with-list", "default", rsc_is_colocated_with_list },
2668 { "rsc-is-colocated-with-list", "xml", rsc_is_colocated_with_list_xml },
2669 { "rscs-colocated-with-list", "default", rscs_colocated_with_list },
2670 { "rscs-colocated-with-list", "xml", rscs_colocated_with_list_xml },
2671 { "rule-check", "default", rule_check_default },
2672 { "rule-check", "xml", rule_check_xml },
2673 { "ticket-attribute", "default", ticket_attribute_default },
2674 { "ticket-attribute", "xml", ticket_attribute_xml },
2675 { "ticket-constraints", "default", ticket_constraints_default },
2676 { "ticket-constraints", "xml", ticket_constraints_xml },
2677 { "ticket-state", "default", ticket_state_default },
2678 { "ticket-state", "xml", ticket_state_xml },
2679
2680 { NULL, NULL, NULL }
2681 };
2682
2683 void
2684 pcmk__register_lib_messages(pcmk__output_t *out) {
2685 pcmk__register_messages(out, fmt_functions);
2686 }