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