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