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
- 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__register_lib_messages
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/common/results.h>
12 #include <crm/msg_xml.h>
13 #include <crm/stonith-ng.h>
14 #include <crm/fencing/internal.h>
15 #include <crm/pengine/internal.h>
16 #include <libxml/tree.h>
17 #include <pacemaker-internal.h>
18
19 static char *
20 colocations_header(pe_resource_t *rsc, pcmk__colocation_t *cons,
21 gboolean dependents) {
22 char *score = NULL;
23 char *retval = NULL;
24
25 score = score2char(cons->score);
26 if (cons->role_rh > RSC_ROLE_STARTED) {
27 retval = crm_strdup_printf("%s (score=%s, %s role=%s, id=%s)",
28 rsc->id, score, dependents ? "needs" : "with",
29 role2text(cons->role_rh), cons->id);
30 } else {
31 retval = crm_strdup_printf("%s (score=%s, id=%s)",
32 rsc->id, score, cons->id);
33 }
34
35 free(score);
36 return retval;
37 }
38
39 static void
40 colocations_xml_node(pcmk__output_t *out, pe_resource_t *rsc,
41 pcmk__colocation_t *cons) {
42 char *score = NULL;
43 xmlNodePtr node = NULL;
44
45 score = score2char(cons->score);
46 node = pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_DEPEND,
47 "id", cons->id,
48 "rsc", cons->rsc_lh->id,
49 "with-rsc", cons->rsc_rh->id,
50 "score", score,
51 NULL);
52
53 if (cons->node_attribute) {
54 xmlSetProp(node, (pcmkXmlStr) "node-attribute", (pcmkXmlStr) cons->node_attribute);
55 }
56
57 if (cons->role_lh != RSC_ROLE_UNKNOWN) {
58 xmlSetProp(node, (pcmkXmlStr) "rsc-role", (pcmkXmlStr) role2text(cons->role_lh));
59 }
60
61 if (cons->role_rh != RSC_ROLE_UNKNOWN) {
62 xmlSetProp(node, (pcmkXmlStr) "with-rsc-role", (pcmkXmlStr) role2text(cons->role_rh));
63 }
64
65 free(score);
66 }
67
68 static int
69 do_locations_list_xml(pcmk__output_t *out, pe_resource_t *rsc, 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 pe__location_t *cons = lpc->data;
77
78 GList *lpc2 = NULL;
79
80 for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
81 pe_node_t *node = (pe_node_t *) lpc2->data;
82 char *score = score2char(node->weight);
83
84 if (add_header) {
85 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "locations");
86 }
87
88 pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_LOCATION,
89 "node", node->details->uname,
90 "rsc", rsc->id,
91 "id", cons->id,
92 "score", score,
93 NULL);
94 free(score);
95 }
96 }
97
98 if (add_header) {
99 PCMK__OUTPUT_LIST_FOOTER(out, rc);
100 }
101
102 return rc;
103 }
104
105 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
106 "pe_node_t *", "pe_node_t *", "pe_action_t *",
107 "pe_action_t *")
108 static int
109 rsc_action_item(pcmk__output_t *out, va_list args)
110 {
111 const char *change = va_arg(args, const char *);
112 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
113 pe_node_t *origin = va_arg(args, pe_node_t *);
114 pe_node_t *destination = va_arg(args, pe_node_t *);
115 pe_action_t *action = va_arg(args, pe_action_t *);
116 pe_action_t *source = va_arg(args, pe_action_t *);
117
118 int len = 0;
119 char *reason = NULL;
120 char *details = NULL;
121 bool same_host = FALSE;
122 bool same_role = FALSE;
123 bool need_role = FALSE;
124
125 static int rsc_width = 5;
126 static int detail_width = 5;
127
128 CRM_ASSERT(action);
129 CRM_ASSERT(destination != NULL || origin != NULL);
130
131 if(source == NULL) {
132 source = action;
133 }
134
135 len = strlen(rsc->id);
136 if(len > rsc_width) {
137 rsc_width = len + 2;
138 }
139
140 if ((rsc->role > RSC_ROLE_STARTED)
141 || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
142 need_role = TRUE;
143 }
144
145 if(origin != NULL && destination != NULL && origin->details == destination->details) {
146 same_host = TRUE;
147 }
148
149 if(rsc->role == rsc->next_role) {
150 same_role = TRUE;
151 }
152
153 if (need_role && (origin == NULL)) {
154
155 details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), destination->details->uname);
156
157 } else if (origin == NULL) {
158
159 details = crm_strdup_printf("%s", destination->details->uname);
160
161 } else if (need_role && (destination == NULL)) {
162
163 details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
164
165 } else if (destination == NULL) {
166
167 details = crm_strdup_printf("%s", origin->details->uname);
168
169 } else if (need_role && same_role && same_host) {
170
171 details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
172
173 } else if (same_role && same_host) {
174
175 details = crm_strdup_printf("%s", origin->details->uname);
176
177 } else if (need_role && same_role) {
178
179 details = crm_strdup_printf("%s -> %s %s", origin->details->uname, destination->details->uname, role2text(rsc->role));
180
181 } else if (same_role) {
182
183 details = crm_strdup_printf("%s -> %s", origin->details->uname, destination->details->uname);
184
185 } else if (same_host) {
186
187 details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), origin->details->uname);
188
189 } else {
190
191 details = crm_strdup_printf("%s %s -> %s %s", role2text(rsc->role), origin->details->uname, role2text(rsc->next_role), destination->details->uname);
192 }
193
194 len = strlen(details);
195 if(len > detail_width) {
196 detail_width = len;
197 }
198
199 if(source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
200 reason = crm_strdup_printf("due to %s (blocked)", source->reason);
201
202 } else if(source->reason) {
203 reason = crm_strdup_printf("due to %s", source->reason);
204
205 } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
206 reason = strdup("blocked");
207
208 }
209
210 out->list_item(out, NULL, "%-8s %-*s ( %*s )%s%s", change, rsc_width,
211 rsc->id, detail_width, details, reason ? " " : "", reason ? reason : "");
212
213 free(details);
214 free(reason);
215 return pcmk_rc_ok;
216 }
217
218 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
219 "pe_node_t *", "pe_node_t *", "pe_action_t *",
220 "pe_action_t *")
221 static int
222 rsc_action_item_xml(pcmk__output_t *out, va_list args)
223 {
224 const char *change = va_arg(args, const char *);
225 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
226 pe_node_t *origin = va_arg(args, pe_node_t *);
227 pe_node_t *destination = va_arg(args, pe_node_t *);
228 pe_action_t *action = va_arg(args, pe_action_t *);
229 pe_action_t *source = va_arg(args, pe_action_t *);
230
231 char *change_str = NULL;
232
233 bool same_host = FALSE;
234 bool same_role = FALSE;
235 bool need_role = FALSE;
236 xmlNode *xml = NULL;
237
238 CRM_ASSERT(action);
239 CRM_ASSERT(destination != NULL || origin != NULL);
240
241 if (source == NULL) {
242 source = action;
243 }
244
245 if ((rsc->role > RSC_ROLE_STARTED)
246 || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
247 need_role = TRUE;
248 }
249
250 if(origin != NULL && destination != NULL && origin->details == destination->details) {
251 same_host = TRUE;
252 }
253
254 if(rsc->role == rsc->next_role) {
255 same_role = TRUE;
256 }
257
258 change_str = g_ascii_strdown(change, -1);
259 xml = pcmk__output_create_xml_node(out, "rsc_action",
260 "action", change_str,
261 "resource", rsc->id,
262 NULL);
263 g_free(change_str);
264
265 if (need_role && (origin == NULL)) {
266
267 pcmk__xe_set_props(xml,
268 "role", role2text(rsc->role),
269 "next-role", role2text(rsc->next_role),
270 "dest", destination->details->uname,
271 NULL);
272
273 } else if (origin == NULL) {
274
275 crm_xml_add(xml, "node", destination->details->uname);
276
277 } else if (need_role && (destination == NULL)) {
278
279 pcmk__xe_set_props(xml,
280 "role", role2text(rsc->role),
281 "node", origin->details->uname,
282 NULL);
283
284 } else if (destination == NULL) {
285
286 crm_xml_add(xml, "node", origin->details->uname);
287
288 } else if (need_role && same_role && same_host) {
289
290 pcmk__xe_set_props(xml,
291 "role", role2text(rsc->role),
292 "source", origin->details->uname,
293 NULL);
294
295 } else if (same_role && same_host) {
296
297 crm_xml_add(xml, "source", origin->details->uname);
298
299 } else if (need_role && same_role) {
300
301 pcmk__xe_set_props(xml,
302 "source", origin->details->uname,
303 "dest", destination->details->uname,
304 "role", role2text(rsc->role),
305 NULL);
306
307 } else if (same_role) {
308
309 pcmk__xe_set_props(xml,
310 "source", origin->details->uname,
311 "dest", destination->details->uname,
312 NULL);
313
314 } else if (same_host) {
315
316 pcmk__xe_set_props(xml,
317 "role", role2text(rsc->role),
318 "next-role", role2text(rsc->next_role),
319 "source", origin->details->uname,
320 NULL);
321
322 } else {
323
324 pcmk__xe_set_props(xml,
325 "role", role2text(rsc->role),
326 "source", origin->details->uname,
327 "next-role", role2text(rsc->next_role),
328 "dest", destination->details->uname,
329 NULL);
330 }
331
332 if (source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
333 pcmk__xe_set_props(xml,
334 "reason", source->reason,
335 "blocked", "true",
336 NULL);
337
338 } else if(source->reason) {
339 crm_xml_add(xml, "reason", source->reason);
340
341 } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
342 crm_xml_add(xml, "blocked", "true");
343
344 }
345
346 return pcmk_rc_ok;
347 }
348
349 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
350 static int
351 rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
352 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
353 gboolean recursive = va_arg(args, gboolean);
354
355 int rc = pcmk_rc_no_output;
356
357 if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
358 return rc;
359 }
360
361 pe__set_resource_flags(rsc, pe_rsc_allocating);
362 for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
363 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
364 char *hdr = NULL;
365
366 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources %s is colocated with", rsc->id);
367
368 if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
369 out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_rh->id, cons->id);
370 continue;
371 }
372
373 hdr = colocations_header(cons->rsc_rh, cons, FALSE);
374 out->list_item(out, NULL, "%s", hdr);
375 free(hdr);
376
377
378 out->begin_list(out, NULL, NULL, NULL);
379
380 out->message(out, "locations-list", cons->rsc_rh);
381 if (recursive) {
382 out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
383 }
384
385 out->end_list(out);
386 }
387
388 PCMK__OUTPUT_LIST_FOOTER(out, rc);
389 return rc;
390 }
391
392 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
393 static int
394 rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
395 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
396 gboolean recursive = va_arg(args, gboolean);
397
398 int rc = pcmk_rc_no_output;
399
400 if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
401 return rc;
402 }
403
404 pe__set_resource_flags(rsc, pe_rsc_allocating);
405 for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
406 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
407
408 if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
409 colocations_xml_node(out, cons->rsc_rh, cons);
410 continue;
411 }
412
413 colocations_xml_node(out, cons->rsc_rh, cons);
414 do_locations_list_xml(out, cons->rsc_rh, false);
415
416 if (recursive) {
417 out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
418 }
419 }
420
421 return rc;
422 }
423
424 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
425 static int
426 rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
427 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
428 gboolean recursive = va_arg(args, gboolean);
429
430 int rc = pcmk_rc_no_output;
431
432 if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
433 return rc;
434 }
435
436 pe__set_resource_flags(rsc, pe_rsc_allocating);
437 for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
438 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
439 char *hdr = NULL;
440
441 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources colocated with %s", rsc->id);
442
443 if (pcmk_is_set(cons->rsc_lh->flags, pe_rsc_allocating)) {
444 out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_lh->id, cons->id);
445 continue;
446 }
447
448 hdr = colocations_header(cons->rsc_lh, cons, TRUE);
449 out->list_item(out, NULL, "%s", hdr);
450 free(hdr);
451
452
453 out->begin_list(out, NULL, NULL, NULL);
454
455 out->message(out, "locations-list", cons->rsc_lh);
456 if (recursive) {
457 out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
458 }
459
460 out->end_list(out);
461 }
462
463 PCMK__OUTPUT_LIST_FOOTER(out, rc);
464 return rc;
465 }
466
467 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
468 static int
469 rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
470 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
471 gboolean recursive = va_arg(args, gboolean);
472
473 int rc = pcmk_rc_no_output;
474
475 if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
476 return rc;
477 }
478
479 pe__set_resource_flags(rsc, pe_rsc_allocating);
480 for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
481 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
482
483 if (pcmk_is_set(cons->rsc_lh->flags, pe_rsc_allocating)) {
484 colocations_xml_node(out, cons->rsc_lh, cons);
485 continue;
486 }
487
488 colocations_xml_node(out, cons->rsc_lh, cons);
489 do_locations_list_xml(out, cons->rsc_lh, false);
490
491 if (recursive) {
492 out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
493 }
494 }
495
496 return rc;
497 }
498
499 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
500 static int
501 locations_list(pcmk__output_t *out, va_list args) {
502 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
503
504 GList *lpc = NULL;
505 GList *list = rsc->rsc_location;
506 int rc = pcmk_rc_no_output;
507
508 for (lpc = list; lpc != NULL; lpc = lpc->next) {
509 pe__location_t *cons = lpc->data;
510
511 GList *lpc2 = NULL;
512
513 for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
514 pe_node_t *node = (pe_node_t *) lpc2->data;
515 char *score = score2char(node->weight);
516
517 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Locations");
518 out->list_item(out, NULL, "Node %s (score=%s, id=%s, rsc=%s)",
519 node->details->uname, score, cons->id, rsc->id);
520 free(score);
521 }
522 }
523
524 PCMK__OUTPUT_LIST_FOOTER(out, rc);
525 return rc;
526 }
527
528 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
529 static int
530 locations_list_xml(pcmk__output_t *out, va_list args) {
531 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
532 return do_locations_list_xml(out, rsc, true);
533 }
534
535 PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
536 static int
537 stacks_and_constraints(pcmk__output_t *out, va_list args) {
538 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
539 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
540 gboolean recursive = va_arg(args, gboolean);
541
542 xmlNodePtr cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS,
543 data_set->input);
544
545 unpack_constraints(cib_constraints, data_set);
546
547
548 rsc = uber_parent(rsc);
549
550 out->message(out, "locations-list", rsc);
551
552 pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
553 out->message(out, "rscs-colocated-with-list", rsc, recursive);
554
555 pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
556 out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
557 return pcmk_rc_ok;
558 }
559
560 PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
561 static int
562 stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
563 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
564 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
565 gboolean recursive = va_arg(args, gboolean);
566
567 xmlNodePtr cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS,
568 data_set->input);
569
570 unpack_constraints(cib_constraints, data_set);
571
572
573 rsc = uber_parent(rsc);
574
575 pcmk__output_xml_create_parent(out, "constraints", NULL);
576 do_locations_list_xml(out, rsc, false);
577
578 pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
579 out->message(out, "rscs-colocated-with-list", rsc, recursive);
580
581 pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
582 out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
583
584 pcmk__output_xml_pop_parent(out);
585 return pcmk_rc_ok;
586 }
587
588 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
589 static int
590 health_text(pcmk__output_t *out, va_list args)
591 {
592 const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
593 const char *host_from = va_arg(args, const char *);
594 const char *fsa_state = va_arg(args, const char *);
595 const char *result = va_arg(args, const char *);
596
597 if (!out->is_quiet(out)) {
598 return out->info(out, "Controller on %s in state %s: %s", crm_str(host_from),
599 crm_str(fsa_state), crm_str(result));
600 } else if (fsa_state != NULL) {
601 pcmk__formatted_printf(out, "%s\n", fsa_state);
602 return pcmk_rc_ok;
603 }
604
605 return pcmk_rc_no_output;
606 }
607
608 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
609 static int
610 health_xml(pcmk__output_t *out, va_list args)
611 {
612 const char *sys_from = va_arg(args, const char *);
613 const char *host_from = va_arg(args, const char *);
614 const char *fsa_state = va_arg(args, const char *);
615 const char *result = va_arg(args, const char *);
616
617 pcmk__output_create_xml_node(out, crm_str(sys_from),
618 "node_name", crm_str(host_from),
619 "state", crm_str(fsa_state),
620 "result", crm_str(result),
621 NULL);
622 return pcmk_rc_ok;
623 }
624
625 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
626 static int
627 pacemakerd_health_text(pcmk__output_t *out, va_list args)
628 {
629 const char *sys_from = va_arg(args, const char *);
630 const char *state = va_arg(args, const char *);
631 const char *last_updated = va_arg(args, const char *);
632
633 if (!out->is_quiet(out)) {
634 return out->info(out, "Status of %s: '%s' %s %s", crm_str(sys_from),
635 crm_str(state), (!pcmk__str_empty(last_updated))?
636 "last updated":"", crm_str(last_updated));
637 } else {
638 pcmk__formatted_printf(out, "%s\n", crm_str(state));
639 return pcmk_rc_ok;
640 }
641
642 return pcmk_rc_no_output;
643 }
644
645 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
646 static int
647 pacemakerd_health_xml(pcmk__output_t *out, va_list args)
648 {
649 const char *sys_from = va_arg(args, const char *);
650 const char *state = va_arg(args, const char *);
651 const char *last_updated = va_arg(args, const char *);
652
653 pcmk__output_create_xml_node(out, crm_str(sys_from),
654 "state", crm_str(state),
655 "last_updated", crm_str(last_updated),
656 NULL);
657 return pcmk_rc_ok;
658 }
659
660 PCMK__OUTPUT_ARGS("dc", "const char *")
661 static int
662 dc_text(pcmk__output_t *out, va_list args)
663 {
664 const char *dc = va_arg(args, const char *);
665
666 if (!out->is_quiet(out)) {
667 return out->info(out, "Designated Controller is: %s", crm_str(dc));
668 } else if (dc != NULL) {
669 pcmk__formatted_printf(out, "%s\n", dc);
670 return pcmk_rc_ok;
671 }
672
673 return pcmk_rc_no_output;
674 }
675
676 PCMK__OUTPUT_ARGS("dc", "const char *")
677 static int
678 dc_xml(pcmk__output_t *out, va_list args)
679 {
680 const char *dc = va_arg(args, const char *);
681
682 pcmk__output_create_xml_node(out, "dc",
683 "node_name", crm_str(dc),
684 NULL);
685 return pcmk_rc_ok;
686 }
687
688 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "gboolean")
689 static int
690 crmadmin_node_text(pcmk__output_t *out, va_list args)
691 {
692 const char *type = va_arg(args, const char *);
693 const char *name = va_arg(args, const char *);
694 const char *id = va_arg(args, const char *);
695 gboolean BASH_EXPORT = va_arg(args, gboolean);
696
697 if (out->is_quiet(out)) {
698 pcmk__formatted_printf(out, "%s\n", crm_str(name));
699 return pcmk_rc_ok;
700 } else if (BASH_EXPORT) {
701 return out->info(out, "export %s=%s", crm_str(name), crm_str(id));
702 } else {
703 return out->info(out, "%s node: %s (%s)", type ? type : "cluster",
704 crm_str(name), crm_str(id));
705 }
706 }
707
708 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "gboolean")
709 static int
710 crmadmin_node_xml(pcmk__output_t *out, va_list args)
711 {
712 const char *type = va_arg(args, const char *);
713 const char *name = va_arg(args, const char *);
714 const char *id = va_arg(args, const char *);
715
716 pcmk__output_create_xml_node(out, "node",
717 "type", type ? type : "cluster",
718 "name", crm_str(name),
719 "id", crm_str(id),
720 NULL);
721 return pcmk_rc_ok;
722 }
723
724 PCMK__OUTPUT_ARGS("digests", "pe_resource_t *", "pe_node_t *", "const char *",
725 "guint", "op_digest_cache_t *")
726 static int
727 digests_text(pcmk__output_t *out, va_list args)
728 {
729 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
730 pe_node_t *node = va_arg(args, pe_node_t *);
731 const char *task = va_arg(args, const char *);
732 guint interval_ms = va_arg(args, guint);
733 op_digest_cache_t *digests = va_arg(args, op_digest_cache_t *);
734
735 char *action_desc = NULL;
736 const char *rsc_desc = "unknown resource";
737 const char *node_desc = "unknown node";
738
739 if (interval_ms != 0) {
740 action_desc = crm_strdup_printf("%ums-interval %s action", interval_ms,
741 ((task == NULL)? "unknown" : task));
742 } else if (pcmk__str_eq(task, "monitor", pcmk__str_none)) {
743 action_desc = strdup("probe action");
744 } else {
745 action_desc = crm_strdup_printf("%s action",
746 ((task == NULL)? "unknown" : task));
747 }
748 if ((rsc != NULL) && (rsc->id != NULL)) {
749 rsc_desc = rsc->id;
750 }
751 if ((node != NULL) && (node->details->uname != NULL)) {
752 node_desc = node->details->uname;
753 }
754 out->begin_list(out, NULL, NULL, "Digests for %s %s on %s",
755 rsc_desc, action_desc, node_desc);
756 free(action_desc);
757
758 if (digests == NULL) {
759 out->list_item(out, NULL, "none");
760 out->end_list(out);
761 return pcmk_rc_ok;
762 }
763 if (digests->digest_all_calc != NULL) {
764 out->list_item(out, NULL, "%s (all parameters)",
765 digests->digest_all_calc);
766 }
767 if (digests->digest_secure_calc != NULL) {
768 out->list_item(out, NULL, "%s (non-private parameters)",
769 digests->digest_secure_calc);
770 }
771 if (digests->digest_restart_calc != NULL) {
772 out->list_item(out, NULL, "%s (non-reloadable parameters)",
773 digests->digest_restart_calc);
774 }
775 out->end_list(out);
776 return pcmk_rc_ok;
777 }
778
779 static void
780 add_digest_xml(xmlNode *parent, const char *type, const char *digest,
781 xmlNode *digest_source)
782 {
783 if (digest != NULL) {
784 xmlNodePtr digest_xml = create_xml_node(parent, "digest");
785
786 crm_xml_add(digest_xml, "type", ((type == NULL)? "unspecified" : type));
787 crm_xml_add(digest_xml, "hash", digest);
788 if (digest_source != NULL) {
789 add_node_copy(digest_xml, digest_source);
790 }
791 }
792 }
793
794 PCMK__OUTPUT_ARGS("digests", "pe_resource_t *", "pe_node_t *", "const char *",
795 "guint", "op_digest_cache_t *")
796 static int
797 digests_xml(pcmk__output_t *out, va_list args)
798 {
799 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
800 pe_node_t *node = va_arg(args, pe_node_t *);
801 const char *task = va_arg(args, const char *);
802 guint interval_ms = va_arg(args, guint);
803 op_digest_cache_t *digests = va_arg(args, op_digest_cache_t *);
804
805 char *interval_s = crm_strdup_printf("%ums", interval_ms);
806 xmlNode *xml = NULL;
807
808 xml = pcmk__output_create_xml_node(out, "digests",
809 "resource", crm_str(rsc->id),
810 "node", crm_str(node->details->uname),
811 "task", crm_str(task),
812 "interval", interval_s,
813 NULL);
814 free(interval_s);
815 if (digests != NULL) {
816 add_digest_xml(xml, "all", digests->digest_all_calc,
817 digests->params_all);
818 add_digest_xml(xml, "nonprivate", digests->digest_secure_calc,
819 digests->params_secure);
820 add_digest_xml(xml, "nonreloadable", digests->digest_restart_calc,
821 digests->params_restart);
822 }
823 return pcmk_rc_ok;
824 }
825
826 #define STOP_SANITY_ASSERT(lineno) do { \
827 if(current && current->details->unclean) { \
828 \
829 } else if(stop == NULL) { \
830 crm_err("%s:%d: No stop action exists for %s", \
831 __func__, lineno, rsc->id); \
832 CRM_ASSERT(stop != NULL); \
833 } else if (pcmk_is_set(stop->flags, pe_action_optional)) { \
834 crm_err("%s:%d: Action %s is still optional", \
835 __func__, lineno, stop->uuid); \
836 CRM_ASSERT(!pcmk_is_set(stop->flags, pe_action_optional)); \
837 } \
838 } while(0)
839
840 PCMK__OUTPUT_ARGS("rsc-action", "pe_resource_t *", "pe_node_t *", "pe_node_t *",
841 "gboolean")
842 static int
843 rsc_action_default(pcmk__output_t *out, va_list args)
844 {
845 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
846 pe_node_t *current = va_arg(args, pe_node_t *);
847 pe_node_t *next = va_arg(args, pe_node_t *);
848 gboolean moving = va_arg(args, gboolean);
849
850 GList *possible_matches = NULL;
851 char *key = NULL;
852 int rc = pcmk_rc_no_output;
853
854 pe_node_t *start_node = NULL;
855 pe_action_t *start = NULL;
856 pe_action_t *stop = NULL;
857 pe_action_t *promote = NULL;
858 pe_action_t *demote = NULL;
859
860 if (!pcmk_is_set(rsc->flags, pe_rsc_managed)
861 || (current == NULL && next == NULL)) {
862 pe_rsc_info(rsc, "Leave %s\t(%s%s)",
863 rsc->id, role2text(rsc->role),
864 !pcmk_is_set(rsc->flags, pe_rsc_managed)? " unmanaged" : "");
865 return rc;
866 }
867
868 if (current != NULL && next != NULL && !pcmk__str_eq(current->details->id, next->details->id, pcmk__str_casei)) {
869 moving = TRUE;
870 }
871
872 possible_matches = pe__resource_actions(rsc, next, RSC_START, FALSE);
873 if (possible_matches) {
874 start = possible_matches->data;
875 g_list_free(possible_matches);
876 }
877
878 if ((start == NULL) || !pcmk_is_set(start->flags, pe_action_runnable)) {
879 start_node = NULL;
880 } else {
881 start_node = current;
882 }
883 possible_matches = pe__resource_actions(rsc, start_node, RSC_STOP, FALSE);
884 if (possible_matches) {
885 stop = possible_matches->data;
886 g_list_free(possible_matches);
887 }
888
889 possible_matches = pe__resource_actions(rsc, next, RSC_PROMOTE, FALSE);
890 if (possible_matches) {
891 promote = possible_matches->data;
892 g_list_free(possible_matches);
893 }
894
895 possible_matches = pe__resource_actions(rsc, next, RSC_DEMOTE, FALSE);
896 if (possible_matches) {
897 demote = possible_matches->data;
898 g_list_free(possible_matches);
899 }
900
901 if (rsc->role == rsc->next_role) {
902 pe_action_t *migrate_op = NULL;
903
904 possible_matches = pe__resource_actions(rsc, next, RSC_MIGRATED, FALSE);
905 if (possible_matches) {
906 migrate_op = possible_matches->data;
907 }
908
909 CRM_CHECK(next != NULL,);
910 if (next == NULL) {
911 } else if ((migrate_op != NULL) && (current != NULL)
912 && pcmk_is_set(migrate_op->flags, pe_action_runnable)) {
913 rc = out->message(out, "rsc-action-item", "Migrate", rsc, current,
914 next, start, NULL);
915
916 } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
917 rc = out->message(out, "rsc-action-item", "Reload", rsc, current,
918 next, start, NULL);
919
920 } else if (start == NULL || pcmk_is_set(start->flags, pe_action_optional)) {
921 if ((demote != NULL) && (promote != NULL)
922 && !pcmk_is_set(demote->flags, pe_action_optional)
923 && !pcmk_is_set(promote->flags, pe_action_optional)) {
924 rc = out->message(out, "rsc-action-item", "Re-promote", rsc,
925 current, next, promote, demote);
926 } else {
927 pe_rsc_info(rsc, "Leave %s\t(%s %s)", rsc->id,
928 role2text(rsc->role), next->details->uname);
929 }
930
931 } else if (!pcmk_is_set(start->flags, pe_action_runnable)) {
932 rc = out->message(out, "rsc-action-item", "Stop", rsc, current,
933 NULL, stop, (stop && stop->reason)? stop : start);
934 STOP_SANITY_ASSERT(__LINE__);
935
936 } else if (moving && current) {
937 rc = out->message(out, "rsc-action-item", pcmk_is_set(rsc->flags, pe_rsc_failed)? "Recover" : "Move",
938 rsc, current, next, stop, NULL);
939
940 } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
941 rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
942 NULL, stop, NULL);
943 STOP_SANITY_ASSERT(__LINE__);
944
945 } else {
946 rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
947 next, start, NULL);
948
949 }
950
951 g_list_free(possible_matches);
952 return rc;
953 }
954
955 if(stop
956 && (rsc->next_role == RSC_ROLE_STOPPED
957 || (start && !pcmk_is_set(start->flags, pe_action_runnable)))) {
958
959 GList *gIter = NULL;
960
961 key = stop_key(rsc);
962 for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
963 pe_node_t *node = (pe_node_t *) gIter->data;
964 pe_action_t *stop_op = NULL;
965
966 possible_matches = find_actions(rsc->actions, key, node);
967 if (possible_matches) {
968 stop_op = possible_matches->data;
969 g_list_free(possible_matches);
970 }
971
972 if (stop_op && (stop_op->flags & pe_action_runnable)) {
973 STOP_SANITY_ASSERT(__LINE__);
974 }
975
976 if (out->message(out, "rsc-action-item", "Stop", rsc, node, NULL,
977 stop_op, (stop_op && stop_op->reason)? stop_op : start) == pcmk_rc_ok) {
978 rc = pcmk_rc_ok;
979 }
980 }
981
982 free(key);
983
984 } else if ((stop != NULL)
985 && pcmk_all_flags_set(rsc->flags, pe_rsc_failed|pe_rsc_stop)) {
986
987 rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
988 next, stop, start);
989 STOP_SANITY_ASSERT(__LINE__);
990
991 } else if (moving) {
992 rc = out->message(out, "rsc-action-item", "Move", rsc, current, next,
993 stop, NULL);
994 STOP_SANITY_ASSERT(__LINE__);
995
996 } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
997 rc = out->message(out, "rsc-action-item", "Reload", rsc, current, next,
998 start, NULL);
999
1000 } else if (stop != NULL && !pcmk_is_set(stop->flags, pe_action_optional)) {
1001 rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1002 next, start, NULL);
1003 STOP_SANITY_ASSERT(__LINE__);
1004
1005 } else if (rsc->role == RSC_ROLE_PROMOTED) {
1006 CRM_LOG_ASSERT(current != NULL);
1007 rc = out->message(out, "rsc-action-item", "Demote", rsc, current,
1008 next, demote, NULL);
1009
1010 } else if (rsc->next_role == RSC_ROLE_PROMOTED) {
1011 CRM_LOG_ASSERT(next);
1012 rc = out->message(out, "rsc-action-item", "Promote", rsc, current,
1013 next, promote, NULL);
1014
1015 } else if (rsc->role == RSC_ROLE_STOPPED && rsc->next_role > RSC_ROLE_STOPPED) {
1016 rc = out->message(out, "rsc-action-item", "Start", rsc, current, next,
1017 start, NULL);
1018 }
1019
1020 return rc;
1021 }
1022
1023 PCMK__OUTPUT_ARGS("node-action", "char *", "char *", "char *")
1024 static int
1025 node_action(pcmk__output_t *out, va_list args)
1026 {
1027 char *task = va_arg(args, char *);
1028 char *node_name = va_arg(args, char *);
1029 char *reason = va_arg(args, char *);
1030
1031 if (task == NULL) {
1032 return pcmk_rc_no_output;
1033 } else if (reason) {
1034 out->list_item(out, NULL, "%s %s '%s'", task, node_name, reason);
1035 } else {
1036 crm_notice(" * %s %s\n", task, node_name);
1037 }
1038
1039 return pcmk_rc_ok;
1040 }
1041
1042 PCMK__OUTPUT_ARGS("node-action", "char *", "char *", "char *")
1043 static int
1044 node_action_xml(pcmk__output_t *out, va_list args)
1045 {
1046 char *task = va_arg(args, char *);
1047 char *node_name = va_arg(args, char *);
1048 char *reason = va_arg(args, char *);
1049
1050 if (task == NULL) {
1051 return pcmk_rc_no_output;
1052 } else if (reason) {
1053 pcmk__output_create_xml_node(out, "node_action",
1054 "task", task,
1055 "node", node_name,
1056 "reason", reason,
1057 NULL);
1058 } else {
1059 crm_notice(" * %s %s\n", task, node_name);
1060 }
1061
1062 return pcmk_rc_ok;
1063 }
1064
1065 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1066 static int
1067 inject_cluster_action(pcmk__output_t *out, va_list args)
1068 {
1069 const char *node = va_arg(args, const char *);
1070 const char *task = va_arg(args, const char *);
1071 xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1072
1073 if (out->is_quiet(out)) {
1074 return pcmk_rc_no_output;
1075 }
1076
1077 if(rsc) {
1078 out->list_item(out, NULL, "Cluster action: %s for %s on %s", task, ID(rsc), node);
1079 } else {
1080 out->list_item(out, NULL, "Cluster action: %s on %s", task, node);
1081 }
1082
1083 return pcmk_rc_ok;
1084 }
1085
1086 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1087 static int
1088 inject_cluster_action_xml(pcmk__output_t *out, va_list args)
1089 {
1090 const char *node = va_arg(args, const char *);
1091 const char *task = va_arg(args, const char *);
1092 xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1093
1094 xmlNodePtr xml_node = NULL;
1095
1096 if (out->is_quiet(out)) {
1097 return pcmk_rc_no_output;
1098 }
1099
1100 xml_node = pcmk__output_create_xml_node(out, "cluster_action",
1101 "task", task,
1102 "node", node,
1103 NULL);
1104
1105 if (rsc) {
1106 crm_xml_add(xml_node, "id", ID(rsc));
1107 }
1108
1109 return pcmk_rc_ok;
1110 }
1111
1112 PCMK__OUTPUT_ARGS("inject-fencing-action", "char *", "const char *")
1113 static int
1114 inject_fencing_action(pcmk__output_t *out, va_list args)
1115 {
1116 char *target = va_arg(args, char *);
1117 const char *op = va_arg(args, const char *);
1118
1119 if (out->is_quiet(out)) {
1120 return pcmk_rc_no_output;
1121 }
1122
1123 out->list_item(out, NULL, "Fencing %s (%s)", target, op);
1124 return pcmk_rc_ok;
1125 }
1126
1127 PCMK__OUTPUT_ARGS("inject-fencing-action", "char *", "const char *")
1128 static int
1129 inject_fencing_action_xml(pcmk__output_t *out, va_list args)
1130 {
1131 char *target = va_arg(args, char *);
1132 const char *op = va_arg(args, const char *);
1133
1134 if (out->is_quiet(out)) {
1135 return pcmk_rc_no_output;
1136 }
1137
1138 pcmk__output_create_xml_node(out, "fencing_action",
1139 "target", target,
1140 "op", op,
1141 NULL);
1142 return pcmk_rc_ok;
1143 }
1144
1145 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1146 static int
1147 inject_attr(pcmk__output_t *out, va_list args)
1148 {
1149 const char *name = va_arg(args, const char *);
1150 const char *value = va_arg(args, const char *);
1151 xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1152
1153 xmlChar *node_path = NULL;
1154
1155 if (out->is_quiet(out)) {
1156 return pcmk_rc_no_output;
1157 }
1158
1159 node_path = xmlGetNodePath(cib_node);
1160
1161 out->list_item(out, NULL, "Injecting attribute %s=%s into %s '%s'",
1162 name, value, node_path, ID(cib_node));
1163
1164 free(node_path);
1165 return pcmk_rc_ok;
1166 }
1167
1168 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1169 static int
1170 inject_attr_xml(pcmk__output_t *out, va_list args)
1171 {
1172 const char *name = va_arg(args, const char *);
1173 const char *value = va_arg(args, const char *);
1174 xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1175
1176 xmlChar *node_path = NULL;
1177
1178 if (out->is_quiet(out)) {
1179 return pcmk_rc_no_output;
1180 }
1181
1182 node_path = xmlGetNodePath(cib_node);
1183
1184 pcmk__output_create_xml_node(out, "inject_attr",
1185 "name", name,
1186 "value", value,
1187 "node_path", node_path,
1188 "cib_node", ID(cib_node),
1189 NULL);
1190 free(node_path);
1191 return pcmk_rc_ok;
1192 }
1193
1194 PCMK__OUTPUT_ARGS("inject-spec", "char *")
1195 static int
1196 inject_spec(pcmk__output_t *out, va_list args)
1197 {
1198 char *spec = va_arg(args, char *);
1199
1200 if (out->is_quiet(out)) {
1201 return pcmk_rc_no_output;
1202 }
1203
1204 out->list_item(out, NULL, "Injecting %s into the configuration", spec);
1205 return pcmk_rc_ok;
1206 }
1207
1208 PCMK__OUTPUT_ARGS("inject-spec", "char *")
1209 static int
1210 inject_spec_xml(pcmk__output_t *out, va_list args)
1211 {
1212 char *spec = va_arg(args, char *);
1213
1214 if (out->is_quiet(out)) {
1215 return pcmk_rc_no_output;
1216 }
1217
1218 pcmk__output_create_xml_node(out, "inject_spec",
1219 "spec", spec,
1220 NULL);
1221 return pcmk_rc_ok;
1222 }
1223
1224 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1225 static int
1226 inject_modify_config(pcmk__output_t *out, va_list args)
1227 {
1228 const char *quorum = va_arg(args, const char *);
1229 const char *watchdog = va_arg(args, const char *);
1230
1231 if (out->is_quiet(out)) {
1232 return pcmk_rc_no_output;
1233 }
1234
1235 out->begin_list(out, NULL, NULL, "Performing Requested Modifications");
1236
1237 if (quorum) {
1238 out->list_item(out, NULL, "Setting quorum: %s", quorum);
1239 }
1240
1241 if (watchdog) {
1242 out->list_item(out, NULL, "Setting watchdog: %s", watchdog);
1243 }
1244
1245 return pcmk_rc_ok;
1246 }
1247
1248 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1249 static int
1250 inject_modify_config_xml(pcmk__output_t *out, va_list args)
1251 {
1252 const char *quorum = va_arg(args, const char *);
1253 const char *watchdog = va_arg(args, const char *);
1254
1255 xmlNodePtr node = NULL;
1256
1257 if (out->is_quiet(out)) {
1258 return pcmk_rc_no_output;
1259 }
1260
1261 node = pcmk__output_xml_create_parent(out, "modifications", NULL);
1262
1263 if (quorum) {
1264 crm_xml_add(node, "quorum", quorum);
1265 }
1266
1267 if (watchdog) {
1268 crm_xml_add(node, "watchdog", watchdog);
1269 }
1270
1271 return pcmk_rc_ok;
1272 }
1273
1274 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "char *")
1275 static int
1276 inject_modify_node(pcmk__output_t *out, va_list args)
1277 {
1278 const char *action = va_arg(args, const char *);
1279 char *node = va_arg(args, char *);
1280
1281 if (out->is_quiet(out)) {
1282 return pcmk_rc_no_output;
1283 }
1284
1285 if (pcmk__str_eq(action, "Online", pcmk__str_none)) {
1286 out->list_item(out, NULL, "Bringing node %s online", node);
1287 return pcmk_rc_ok;
1288 } else if (pcmk__str_eq(action, "Offline", pcmk__str_none)) {
1289 out->list_item(out, NULL, "Taking node %s offline", node);
1290 return pcmk_rc_ok;
1291 } else if (pcmk__str_eq(action, "Failing", pcmk__str_none)) {
1292 out->list_item(out, NULL, "Failing node %s", node);
1293 return pcmk_rc_ok;
1294 }
1295
1296 return pcmk_rc_no_output;
1297 }
1298
1299 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "char *")
1300 static int
1301 inject_modify_node_xml(pcmk__output_t *out, va_list args)
1302 {
1303 const char *action = va_arg(args, const char *);
1304 char *node = va_arg(args, char *);
1305
1306 if (out->is_quiet(out)) {
1307 return pcmk_rc_no_output;
1308 }
1309
1310 pcmk__output_create_xml_node(out, "modify_node",
1311 "action", action,
1312 "node", node,
1313 NULL);
1314 return pcmk_rc_ok;
1315 }
1316
1317 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "char *")
1318 static int
1319 inject_modify_ticket(pcmk__output_t *out, va_list args)
1320 {
1321 const char *action = va_arg(args, const char *);
1322 char *ticket = va_arg(args, char *);
1323
1324 if (out->is_quiet(out)) {
1325 return pcmk_rc_no_output;
1326 }
1327
1328 if (pcmk__str_eq(action, "Standby", pcmk__str_none)) {
1329 out->list_item(out, NULL, "Making ticket %s standby", ticket);
1330 } else {
1331 out->list_item(out, NULL, "%s ticket %s", action, ticket);
1332 }
1333
1334 return pcmk_rc_ok;
1335 }
1336
1337 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "char *")
1338 static int
1339 inject_modify_ticket_xml(pcmk__output_t *out, va_list args)
1340 {
1341 const char *action = va_arg(args, const char *);
1342 char *ticket = va_arg(args, char *);
1343
1344 if (out->is_quiet(out)) {
1345 return pcmk_rc_no_output;
1346 }
1347
1348 pcmk__output_create_xml_node(out, "modify_ticket",
1349 "action", action,
1350 "ticket", ticket,
1351 NULL);
1352 return pcmk_rc_ok;
1353 }
1354
1355 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1356 static int
1357 inject_pseudo_action(pcmk__output_t *out, va_list args)
1358 {
1359 const char *node = va_arg(args, const char *);
1360 const char *task = va_arg(args, const char *);
1361
1362 if (out->is_quiet(out)) {
1363 return pcmk_rc_no_output;
1364 }
1365
1366 out->list_item(out, NULL, "Pseudo action: %s%s%s", task, node ? " on " : "",
1367 node ? node : "");
1368 return pcmk_rc_ok;
1369 }
1370
1371 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1372 static int
1373 inject_pseudo_action_xml(pcmk__output_t *out, va_list args)
1374 {
1375 const char *node = va_arg(args, const char *);
1376 const char *task = va_arg(args, const char *);
1377
1378 xmlNodePtr xml_node = NULL;
1379
1380 if (out->is_quiet(out)) {
1381 return pcmk_rc_no_output;
1382 }
1383
1384 xml_node = pcmk__output_create_xml_node(out, "pseudo_action",
1385 "task", task,
1386 NULL);
1387 if (node) {
1388 crm_xml_add(xml_node, "node", node);
1389 }
1390
1391 return pcmk_rc_ok;
1392 }
1393
1394 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *", "char *", "guint")
1395 static int
1396 inject_rsc_action(pcmk__output_t *out, va_list args)
1397 {
1398 const char *rsc = va_arg(args, const char *);
1399 const char *operation = va_arg(args, const char *);
1400 char *node = va_arg(args, char *);
1401 guint interval_ms = va_arg(args, guint);
1402
1403 if (out->is_quiet(out)) {
1404 return pcmk_rc_no_output;
1405 }
1406
1407 if (interval_ms) {
1408 out->list_item(out, NULL, "Resource action: %-15s %s=%u on %s",
1409 rsc, operation, interval_ms, node);
1410 } else {
1411 out->list_item(out, NULL, "Resource action: %-15s %s on %s",
1412 rsc, operation, node);
1413 }
1414
1415 return pcmk_rc_ok;
1416 }
1417
1418 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *", "char *", "guint")
1419 static int
1420 inject_rsc_action_xml(pcmk__output_t *out, va_list args)
1421 {
1422 const char *rsc = va_arg(args, const char *);
1423 const char *operation = va_arg(args, const char *);
1424 char *node = va_arg(args, char *);
1425 guint interval_ms = va_arg(args, guint);
1426
1427 xmlNodePtr xml_node = NULL;
1428
1429 if (out->is_quiet(out)) {
1430 return pcmk_rc_no_output;
1431 }
1432
1433 xml_node = pcmk__output_create_xml_node(out, "rsc_action",
1434 "resource", rsc,
1435 "op", operation,
1436 "node", node,
1437 NULL);
1438
1439 if (interval_ms) {
1440 char *interval_s = pcmk__itoa(interval_ms);
1441
1442 crm_xml_add(xml_node, "interval", interval_s);
1443 free(interval_s);
1444 }
1445
1446 return pcmk_rc_ok;
1447 }
1448
1449 static pcmk__message_entry_t fmt_functions[] = {
1450 { "crmadmin-node", "default", crmadmin_node_text },
1451 { "crmadmin-node", "xml", crmadmin_node_xml },
1452 { "dc", "default", dc_text },
1453 { "dc", "xml", dc_xml },
1454 { "digests", "default", digests_text },
1455 { "digests", "xml", digests_xml },
1456 { "health", "default", health_text },
1457 { "health", "xml", health_xml },
1458 { "inject-attr", "default", inject_attr },
1459 { "inject-attr", "xml", inject_attr_xml },
1460 { "inject-cluster-action", "default", inject_cluster_action },
1461 { "inject-cluster-action", "xml", inject_cluster_action_xml },
1462 { "inject-fencing-action", "default", inject_fencing_action },
1463 { "inject-fencing-action", "xml", inject_fencing_action_xml },
1464 { "inject-modify-config", "default", inject_modify_config },
1465 { "inject-modify-config", "xml", inject_modify_config_xml },
1466 { "inject-modify-node", "default", inject_modify_node },
1467 { "inject-modify-node", "xml", inject_modify_node_xml },
1468 { "inject-modify-ticket", "default", inject_modify_ticket },
1469 { "inject-modify-ticket", "xml", inject_modify_ticket_xml },
1470 { "inject-pseudo-action", "default", inject_pseudo_action },
1471 { "inject-pseudo-action", "xml", inject_pseudo_action_xml },
1472 { "inject-rsc-action", "default", inject_rsc_action },
1473 { "inject-rsc-action", "xml", inject_rsc_action_xml },
1474 { "inject-spec", "default", inject_spec },
1475 { "inject-spec", "xml", inject_spec_xml },
1476 { "locations-list", "default", locations_list },
1477 { "locations-list", "xml", locations_list_xml },
1478 { "node-action", "default", node_action },
1479 { "node-action", "xml", node_action_xml },
1480 { "pacemakerd-health", "default", pacemakerd_health_text },
1481 { "pacemakerd-health", "xml", pacemakerd_health_xml },
1482 { "rsc-action", "default", rsc_action_default },
1483 { "rsc-action-item", "default", rsc_action_item },
1484 { "rsc-action-item", "xml", rsc_action_item_xml },
1485 { "rsc-is-colocated-with-list", "default", rsc_is_colocated_with_list },
1486 { "rsc-is-colocated-with-list", "xml", rsc_is_colocated_with_list_xml },
1487 { "rscs-colocated-with-list", "default", rscs_colocated_with_list },
1488 { "rscs-colocated-with-list", "xml", rscs_colocated_with_list_xml },
1489 { "stacks-constraints", "default", stacks_and_constraints },
1490 { "stacks-constraints", "xml", stacks_and_constraints_xml },
1491
1492 { NULL, NULL, NULL }
1493 };
1494
1495 void
1496 pcmk__register_lib_messages(pcmk__output_t *out) {
1497 pcmk__register_messages(out, fmt_functions);
1498 }