This source file includes following definitions.
- add_possible_values_default
- add_option_metadata_default
- PCMK__OUTPUT_ARGS
- add_desc_xml
- add_possible_values_xml
- map_legacy_option_type
- add_option_metadata_xml
- PCMK__OUTPUT_ARGS
- pcmk__register_option_messages
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <glib.h>
13
14 #include "crmcommon_private.h"
15
16
17
18
19
20
21
22
23 static void
24 add_possible_values_default(pcmk__output_t *out,
25 const pcmk__cluster_option_t *option)
26 {
27 const char *id = _("Possible values");
28 GString *buf = g_string_sized_new(256);
29
30 CRM_ASSERT(option->type != NULL);
31
32 if (pcmk_is_set(option->flags, pcmk__opt_generated)) {
33 id = _("Possible values (generated by Pacemaker)");
34 }
35
36 if ((option->values != NULL) && (strcmp(option->type, "select") == 0)) {
37 const char *delim = ", ";
38 bool found_default = (option->default_value == NULL);
39 char *str = pcmk__str_copy(option->values);
40
41 for (const char *value = strtok(str, delim); value != NULL;
42 value = strtok(NULL, delim)) {
43
44 if (buf->len > 0) {
45 g_string_append(buf, delim);
46 }
47 g_string_append_c(buf, '"');
48 g_string_append(buf, value);
49 g_string_append_c(buf, '"');
50
51 if (!found_default && (strcmp(value, option->default_value) == 0)) {
52 found_default = true;
53 g_string_append(buf, _(" (default)"));
54 }
55 }
56 free(str);
57
58 } else if (option->default_value != NULL) {
59 pcmk__g_strcat(buf,
60 option->type, _(" (default: \""), option->default_value,
61 "\")", NULL);
62
63 } else {
64 pcmk__g_strcat(buf, option->type, _(" (no default)"), NULL);
65 }
66
67 out->list_item(out, id, "%s", buf->str);
68 g_string_free(buf, TRUE);
69 }
70
71
72
73
74
75
76
77
78 static void
79 add_option_metadata_default(pcmk__output_t *out,
80 const pcmk__cluster_option_t *option)
81 {
82 const char *desc_short = option->description_short;
83 const char *desc_long = option->description_long;
84
85 CRM_ASSERT((desc_short != NULL) || (desc_long != NULL));
86
87 if (desc_short == NULL) {
88 desc_short = desc_long;
89 desc_long = NULL;
90 }
91
92 out->list_item(out, option->name, "%s", _(desc_short));
93
94 out->begin_list(out, NULL, NULL, NULL);
95
96 if (desc_long != NULL) {
97 out->list_item(out, NULL, "%s", _(desc_long));
98 }
99 add_possible_values_default(out, option);
100 out->end_list(out);
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 PCMK__OUTPUT_ARGS("option-list", "const char *", "const char *", "const char *",
124 "uint32_t", "const pcmk__cluster_option_t *", "bool")
125 static int
126 option_list_default(pcmk__output_t *out, va_list args)
127 {
128 const char *name G_GNUC_UNUSED = va_arg(args, const char *);
129 const char *desc_short = va_arg(args, const char *);
130 const char *desc_long = va_arg(args, const char *);
131 const uint32_t filter = va_arg(args, uint32_t);
132 const pcmk__cluster_option_t *option_list =
133 va_arg(args, pcmk__cluster_option_t *);
134 const bool all = (bool) va_arg(args, int);
135
136 const bool show_deprecated = all
137 || pcmk_is_set(filter, pcmk__opt_deprecated);
138 const bool show_advanced = all || pcmk_is_set(filter, pcmk__opt_advanced);
139 bool old_fancy = false;
140
141 GSList *deprecated = NULL;
142 GSList *advanced = NULL;
143
144 CRM_ASSERT((out != NULL) && (desc_short != NULL) && (desc_long != NULL)
145 && (option_list != NULL));
146
147 old_fancy = pcmk__output_text_get_fancy(out);
148 pcmk__output_text_set_fancy(out, true);
149
150 out->info(out, "%s", _(desc_short));
151 out->spacer(out);
152 out->info(out, "%s", _(desc_long));
153 out->begin_list(out, NULL, NULL, NULL);
154
155 for (const pcmk__cluster_option_t *option = option_list;
156 option->name != NULL; option++) {
157
158
159 if (pcmk_all_flags_set(option->flags, filter)) {
160 if (pcmk_is_set(option->flags, pcmk__opt_deprecated)) {
161 if (show_deprecated) {
162 deprecated = g_slist_prepend(deprecated, (gpointer) option);
163 }
164
165 } else if (pcmk_is_set(option->flags, pcmk__opt_advanced)) {
166 if (show_advanced) {
167 advanced = g_slist_prepend(advanced, (gpointer) option);
168 }
169
170 } else {
171 out->spacer(out);
172 add_option_metadata_default(out, option);
173 }
174 }
175 }
176
177 if (advanced != NULL) {
178 advanced = g_slist_reverse(advanced);
179
180 out->spacer(out);
181 out->begin_list(out, NULL, NULL, _("ADVANCED OPTIONS"));
182 for (const GSList *iter = advanced; iter != NULL; iter = iter->next) {
183 const pcmk__cluster_option_t *option = iter->data;
184
185 out->spacer(out);
186 add_option_metadata_default(out, option);
187 }
188 out->end_list(out);
189 g_slist_free(advanced);
190 }
191
192 if (deprecated != NULL) {
193 deprecated = g_slist_reverse(deprecated);
194
195 out->spacer(out);
196 out->begin_list(out, NULL, NULL,
197 _("DEPRECATED OPTIONS (will be removed in a future "
198 "release)"));
199 for (const GSList *iter = deprecated; iter != NULL; iter = iter->next) {
200 const pcmk__cluster_option_t *option = iter->data;
201
202 out->spacer(out);
203 add_option_metadata_default(out, option);
204 }
205 out->end_list(out);
206 g_slist_free(deprecated);
207 }
208
209 out->end_list(out);
210 pcmk__output_text_set_fancy(out, old_fancy);
211 return pcmk_rc_ok;
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225
226 static void
227 add_desc_xml(pcmk__output_t *out, bool for_long, const char *desc)
228 {
229 const char *tag = (for_long? PCMK_XE_LONGDESC : PCMK_XE_SHORTDESC);
230 xmlNode *node = pcmk__output_create_xml_text_node(out, tag, desc);
231
232 crm_xml_add(node, PCMK_XA_LANG, PCMK__VALUE_EN);
233
234 #ifdef ENABLE_NLS
235 {
236 static const char *locale = NULL;
237
238 if (strcmp(desc, _(desc)) == 0) {
239 return;
240 }
241
242 if (locale == NULL) {
243 locale = strtok(setlocale(LC_ALL, NULL), "_");
244 }
245 node = pcmk__output_create_xml_text_node(out, tag, _(desc));
246 crm_xml_add(node, PCMK_XA_LANG, locale);
247 }
248 #endif
249 }
250
251
252
253
254
255
256
257
258
259
260 static void
261 add_possible_values_xml(pcmk__output_t *out,
262 const pcmk__cluster_option_t *option)
263 {
264 if ((option->values != NULL) && (strcmp(option->type, "select") == 0)) {
265 const char *delim = ", ";
266 char *str = pcmk__str_copy(option->values);
267 const char *ptr = strtok(str, delim);
268
269 while (ptr != NULL) {
270 pcmk__output_create_xml_node(out, PCMK_XE_OPTION,
271 PCMK_XA_VALUE, ptr,
272 NULL);
273 ptr = strtok(NULL, delim);
274 }
275 free(str);
276 }
277 }
278
279
280
281
282
283
284
285
286
287 static const char *
288 map_legacy_option_type(const char *type)
289 {
290
291 if (pcmk__str_any_of(type, PCMK_VALUE_DURATION, PCMK_VALUE_TIMEOUT, NULL)) {
292 return PCMK__VALUE_TIME;
293
294 } else if (pcmk__str_any_of(type,
295 PCMK_VALUE_NONNEGATIVE_INTEGER,
296 PCMK_VALUE_SCORE, NULL)) {
297 return PCMK_VALUE_INTEGER;
298
299 } else if (pcmk__str_eq(type, PCMK_VALUE_VERSION, pcmk__str_none)) {
300 return PCMK_VALUE_STRING;
301
302 } else {
303 return type;
304 }
305 }
306
307
308
309
310
311
312
313
314 static void
315 add_option_metadata_xml(pcmk__output_t *out,
316 const pcmk__cluster_option_t *option)
317 {
318 const char *type = option->type;
319 const char *desc_long = option->description_long;
320 const char *desc_short = option->description_short;
321 const bool advanced = pcmk_is_set(option->flags, pcmk__opt_advanced);
322 const bool deprecated = pcmk_is_set(option->flags, pcmk__opt_deprecated);
323 const bool generated = pcmk_is_set(option->flags, pcmk__opt_generated);
324
325
326
327 const char *advanced_s = advanced? "1" : "0";
328 const char *generated_s = generated? "1" : "0";
329
330
331 const bool legacy = pcmk__output_get_legacy_xml(out);
332 char *desc_long_legacy = NULL;
333 GString *desc_short_legacy = NULL;
334
335
336 CRM_ASSERT(type != NULL);
337
338
339 CRM_ASSERT((desc_long != NULL) || (desc_short != NULL));
340
341 if (desc_long == NULL) {
342 desc_long = desc_short;
343 } else if (desc_short == NULL) {
344 desc_short = desc_long;
345 }
346
347 if (legacy) {
348
349 type = map_legacy_option_type(type);
350
351 if (option->values != NULL) {
352 desc_long_legacy = crm_strdup_printf("%s Allowed values: %s",
353 desc_long, option->values);
354 desc_long = desc_long_legacy;
355 }
356
357 if (deprecated || advanced) {
358 const size_t init_sz = 1023;
359
360 if (desc_long != option->description_long) {
361
362
363
364
365 desc_short = "";
366 } else {
367 desc_short = pcmk__s(option->description_short, "");
368 }
369
370 if (deprecated) {
371 pcmk__add_separated_word(&desc_short_legacy, init_sz,
372 "*** Deprecated ***", NULL);
373 }
374 if (advanced) {
375 pcmk__add_separated_word(&desc_short_legacy, init_sz,
376 "*** Advanced Use Only ***", NULL);
377 }
378 pcmk__add_separated_word(&desc_short_legacy, 0, desc_short, NULL);
379
380 desc_short = desc_short_legacy->str;
381 }
382
383
384
385
386
387 advanced_s = NULL;
388 generated_s = NULL;
389 }
390
391 pcmk__output_xml_create_parent(out, PCMK_XE_PARAMETER,
392 PCMK_XA_NAME, option->name,
393 PCMK_XA_ADVANCED, advanced_s,
394 PCMK_XA_GENERATED, generated_s,
395 NULL);
396
397 if (deprecated && !legacy) {
398
399 pcmk__output_create_xml_node(out, PCMK_XE_DEPRECATED, NULL);
400 }
401 add_desc_xml(out, true, desc_long);
402 add_desc_xml(out, false, desc_short);
403
404 pcmk__output_xml_create_parent(out, PCMK_XE_CONTENT,
405 PCMK_XA_TYPE, type,
406 PCMK_XA_DEFAULT, option->default_value,
407 NULL);
408
409 add_possible_values_xml(out, option);
410
411 pcmk__output_xml_pop_parent(out);
412 pcmk__output_xml_pop_parent(out);
413
414 free(desc_long_legacy);
415 if (desc_short_legacy != NULL) {
416 g_string_free(desc_short_legacy, TRUE);
417 }
418 }
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 PCMK__OUTPUT_ARGS("option-list", "const char *", "const char *", "const char *",
439 "uint32_t", "const pcmk__cluster_option_t *", "bool")
440 static int
441 option_list_xml(pcmk__output_t *out, va_list args)
442 {
443 const char *name = va_arg(args, const char *);
444 const char *desc_short = va_arg(args, const char *);
445 const char *desc_long = va_arg(args, const char *);
446 const uint32_t filter = va_arg(args, uint32_t);
447 const pcmk__cluster_option_t *option_list =
448 va_arg(args, pcmk__cluster_option_t *);
449
450 CRM_ASSERT((out != NULL) && (name != NULL) && (desc_short != NULL)
451 && (desc_long != NULL) && (option_list != NULL));
452
453 pcmk__output_xml_create_parent(out, PCMK_XE_RESOURCE_AGENT,
454 PCMK_XA_NAME, name,
455 PCMK_XA_VERSION, PACEMAKER_VERSION,
456 NULL);
457
458 pcmk__output_create_xml_text_node(out, PCMK_XE_VERSION, PCMK_OCF_VERSION);
459 add_desc_xml(out, true, desc_long);
460 add_desc_xml(out, false, desc_short);
461
462 pcmk__output_xml_create_parent(out, PCMK_XE_PARAMETERS, NULL);
463
464 for (const pcmk__cluster_option_t *option = option_list;
465 option->name != NULL; option++) {
466
467 if (pcmk_all_flags_set(option->flags, filter)) {
468 add_option_metadata_xml(out, option);
469 }
470 }
471
472 pcmk__output_xml_pop_parent(out);
473 pcmk__output_xml_pop_parent(out);
474 return pcmk_rc_ok;
475 }
476
477 static pcmk__message_entry_t fmt_functions[] = {
478 { "option-list", "default", option_list_default },
479 { "option-list", "xml", option_list_xml },
480
481 { NULL, NULL, NULL }
482 };
483
484
485
486
487
488
489
490 void
491 pcmk__register_option_messages(pcmk__output_t *out) {
492 pcmk__register_messages(out, fmt_functions);
493 }