This source file includes following definitions.
- xml_show_patchset_header
- xml_show_patchset_v1_recursive
- xml_show_patchset_v1
- xml_show_patchset_v2
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- pcmk__register_patchset_messages
- xml_log_patchset
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/common/xml.h>
13
14 #include "crmcommon_private.h"
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 static int
41 xml_show_patchset_header(pcmk__output_t *out, const xmlNode *patchset)
42 {
43 int rc = pcmk_rc_no_output;
44 int add[] = { 0, 0, 0 };
45 int del[] = { 0, 0, 0 };
46
47 xml_patch_versions(patchset, add, del);
48
49 if ((add[0] != del[0]) || (add[1] != del[1]) || (add[2] != del[2])) {
50 const char *fmt = crm_element_value(patchset, PCMK_XA_FORMAT);
51 const char *digest = crm_element_value(patchset, PCMK__XA_DIGEST);
52
53 out->info(out, "Diff: --- %d.%d.%d %s", del[0], del[1], del[2], fmt);
54 rc = out->info(out, "Diff: +++ %d.%d.%d %s",
55 add[0], add[1], add[2], digest);
56
57 } else if ((add[0] != 0) || (add[1] != 0) || (add[2] != 0)) {
58 rc = out->info(out, "Local-only Change: %d.%d.%d",
59 add[0], add[1], add[2]);
60 }
61
62 return rc;
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 static int
80 xml_show_patchset_v1_recursive(pcmk__output_t *out, const char *prefix,
81 const xmlNode *data, int depth, uint32_t options)
82 {
83 if ((data->children == NULL)
84 || (crm_element_value(data, PCMK__XA_CRM_DIFF_MARKER) != NULL)) {
85
86
87 options &= ~pcmk__xml_fmt_diff_short;
88
89 if (pcmk_is_set(options, pcmk__xml_fmt_diff_plus)) {
90 prefix = PCMK__XML_PREFIX_CREATED;
91 } else {
92 prefix = PCMK__XML_PREFIX_DELETED;
93 }
94 }
95
96 if (pcmk_is_set(options, pcmk__xml_fmt_diff_short)) {
97 int rc = pcmk_rc_no_output;
98
99
100 for (const xmlNode *child = pcmk__xml_first_child(data); child != NULL;
101 child = pcmk__xml_next(child)) {
102 int temp_rc = xml_show_patchset_v1_recursive(out, prefix, child,
103 depth + 1, options);
104 rc = pcmk__output_select_rc(rc, temp_rc);
105 }
106 return rc;
107 }
108
109 return pcmk__xml_show(out, prefix, data, depth,
110 options
111 |pcmk__xml_fmt_open
112 |pcmk__xml_fmt_children
113 |pcmk__xml_fmt_close);
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 static int
132 xml_show_patchset_v1(pcmk__output_t *out, const xmlNode *patchset,
133 uint32_t options)
134 {
135 const xmlNode *removed = NULL;
136 const xmlNode *added = NULL;
137 const xmlNode *child = NULL;
138 bool is_first = true;
139 int rc = xml_show_patchset_header(out, patchset);
140
141
142
143
144
145
146 removed = pcmk__xe_first_child(patchset, PCMK__XE_DIFF_REMOVED, NULL, NULL);
147 for (child = pcmk__xml_first_child(removed); child != NULL;
148 child = pcmk__xml_next(child)) {
149 int temp_rc = xml_show_patchset_v1_recursive(out, "- ", child, 0,
150 options
151 |pcmk__xml_fmt_diff_minus);
152 rc = pcmk__output_select_rc(rc, temp_rc);
153
154 if (is_first) {
155 is_first = false;
156 } else {
157 rc = pcmk__output_select_rc(rc, out->info(out, " --- "));
158 }
159 }
160
161 is_first = true;
162 added = pcmk__xe_first_child(patchset, PCMK__XE_DIFF_ADDED, NULL, NULL);
163 for (child = pcmk__xml_first_child(added); child != NULL;
164 child = pcmk__xml_next(child)) {
165 int temp_rc = xml_show_patchset_v1_recursive(out, "+ ", child, 0,
166 options
167 |pcmk__xml_fmt_diff_plus);
168 rc = pcmk__output_select_rc(rc, temp_rc);
169
170 if (is_first) {
171 is_first = false;
172 } else {
173 rc = pcmk__output_select_rc(rc, out->info(out, " +++ "));
174 }
175 }
176
177 return rc;
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 static int
195 xml_show_patchset_v2(pcmk__output_t *out, const xmlNode *patchset)
196 {
197 int rc = xml_show_patchset_header(out, patchset);
198 int temp_rc = pcmk_rc_no_output;
199
200 for (const xmlNode *change = pcmk__xe_first_child(patchset, NULL, NULL,
201 NULL);
202 change != NULL; change = pcmk__xe_next(change)) {
203
204 const char *op = crm_element_value(change, PCMK_XA_OPERATION);
205 const char *xpath = crm_element_value(change, PCMK_XA_PATH);
206
207 if (op == NULL) {
208 continue;
209 }
210
211 if (strcmp(op, PCMK_VALUE_CREATE) == 0) {
212 char *prefix = crm_strdup_printf(PCMK__XML_PREFIX_CREATED " %s: ",
213 xpath);
214
215 temp_rc = pcmk__xml_show(out, prefix, change->children, 0,
216 pcmk__xml_fmt_pretty|pcmk__xml_fmt_open);
217 rc = pcmk__output_select_rc(rc, temp_rc);
218
219
220 for (char *ch = prefix + 2; *ch != '\0'; ch++) {
221 *ch = ' ';
222 }
223
224 temp_rc = pcmk__xml_show(out, prefix, change->children, 0,
225 pcmk__xml_fmt_pretty
226 |pcmk__xml_fmt_children
227 |pcmk__xml_fmt_close);
228 rc = pcmk__output_select_rc(rc, temp_rc);
229 free(prefix);
230
231 } else if (strcmp(op, PCMK_VALUE_MOVE) == 0) {
232 const char *position = crm_element_value(change, PCMK_XE_POSITION);
233
234 temp_rc = out->info(out,
235 PCMK__XML_PREFIX_MOVED " %s moved to offset %s",
236 xpath, position);
237 rc = pcmk__output_select_rc(rc, temp_rc);
238
239 } else if (strcmp(op, PCMK_VALUE_MODIFY) == 0) {
240 xmlNode *clist = pcmk__xe_first_child(change, PCMK_XE_CHANGE_LIST,
241 NULL, NULL);
242 GString *buffer_set = NULL;
243 GString *buffer_unset = NULL;
244
245 for (const xmlNode *child = pcmk__xe_first_child(clist, NULL, NULL,
246 NULL);
247 child != NULL; child = pcmk__xe_next(child)) {
248
249 const char *name = crm_element_value(child, PCMK_XA_NAME);
250
251 op = crm_element_value(child, PCMK_XA_OPERATION);
252 if (op == NULL) {
253 continue;
254 }
255
256 if (strcmp(op, "set") == 0) {
257 const char *value = crm_element_value(child, PCMK_XA_VALUE);
258
259 pcmk__add_separated_word(&buffer_set, 256, "@", ", ");
260 pcmk__g_strcat(buffer_set, name, "=", value, NULL);
261
262 } else if (strcmp(op, "unset") == 0) {
263 pcmk__add_separated_word(&buffer_unset, 256, "@", ", ");
264 g_string_append(buffer_unset, name);
265 }
266 }
267
268 if (buffer_set != NULL) {
269 temp_rc = out->info(out, "+ %s: %s", xpath, buffer_set->str);
270 rc = pcmk__output_select_rc(rc, temp_rc);
271 g_string_free(buffer_set, TRUE);
272 }
273
274 if (buffer_unset != NULL) {
275 temp_rc = out->info(out, "-- %s: %s",
276 xpath, buffer_unset->str);
277 rc = pcmk__output_select_rc(rc, temp_rc);
278 g_string_free(buffer_unset, TRUE);
279 }
280
281 } else if (strcmp(op, PCMK_VALUE_DELETE) == 0) {
282 int position = -1;
283
284 crm_element_value_int(change, PCMK_XE_POSITION, &position);
285 if (position >= 0) {
286 temp_rc = out->info(out, "-- %s (%d)", xpath, position);
287 } else {
288 temp_rc = out->info(out, "-- %s", xpath);
289 }
290 rc = pcmk__output_select_rc(rc, temp_rc);
291 }
292 }
293
294 return rc;
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312 PCMK__OUTPUT_ARGS("xml-patchset", "const xmlNode *")
313 static int
314 xml_patchset_default(pcmk__output_t *out, va_list args)
315 {
316 const xmlNode *patchset = va_arg(args, const xmlNode *);
317
318 int format = 1;
319
320 if (patchset == NULL) {
321 crm_trace("Empty patch");
322 return pcmk_rc_no_output;
323 }
324
325 crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
326 switch (format) {
327 case 1:
328 return xml_show_patchset_v1(out, patchset, pcmk__xml_fmt_pretty);
329 case 2:
330 return xml_show_patchset_v2(out, patchset);
331 default:
332 crm_err("Unknown patch format: %d", format);
333 return pcmk_rc_bad_xml_patch;
334 }
335 }
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 PCMK__OUTPUT_ARGS("xml-patchset", "const xmlNode *")
353 static int
354 xml_patchset_log(pcmk__output_t *out, va_list args)
355 {
356 static struct qb_log_callsite *patchset_cs = NULL;
357
358 const xmlNode *patchset = va_arg(args, const xmlNode *);
359
360 uint8_t log_level = pcmk__output_get_log_level(out);
361 int format = 1;
362
363 if (log_level == LOG_NEVER) {
364 return pcmk_rc_no_output;
365 }
366
367 if (patchset == NULL) {
368 crm_trace("Empty patch");
369 return pcmk_rc_no_output;
370 }
371
372 if (patchset_cs == NULL) {
373 patchset_cs = qb_log_callsite_get(__func__, __FILE__, "xml-patchset",
374 log_level, __LINE__,
375 crm_trace_nonlog);
376 }
377
378 if (!crm_is_callsite_active(patchset_cs, log_level, crm_trace_nonlog)) {
379
380 return pcmk_rc_no_output;
381 }
382
383 crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
384 switch (format) {
385 case 1:
386 if (log_level < LOG_DEBUG) {
387 return xml_show_patchset_v1(out, patchset,
388 pcmk__xml_fmt_pretty
389 |pcmk__xml_fmt_diff_short);
390 }
391 return xml_show_patchset_v1(out, patchset, pcmk__xml_fmt_pretty);
392 case 2:
393 return xml_show_patchset_v2(out, patchset);
394 default:
395 crm_err("Unknown patch format: %d", format);
396 return pcmk_rc_bad_xml_patch;
397 }
398 }
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415 PCMK__OUTPUT_ARGS("xml-patchset", "const xmlNode *")
416 static int
417 xml_patchset_xml(pcmk__output_t *out, va_list args)
418 {
419 const xmlNode *patchset = va_arg(args, const xmlNode *);
420
421 if (patchset != NULL) {
422 GString *buf = g_string_sized_new(1024);
423
424 pcmk__xml_string(patchset, pcmk__xml_fmt_pretty|pcmk__xml_fmt_text, buf,
425 0);
426
427 out->output_xml(out, PCMK_XE_XML_PATCHSET, buf->str);
428 g_string_free(buf, TRUE);
429 return pcmk_rc_ok;
430 }
431 crm_trace("Empty patch");
432 return pcmk_rc_no_output;
433 }
434
435 static pcmk__message_entry_t fmt_functions[] = {
436 { "xml-patchset", "default", xml_patchset_default },
437 { "xml-patchset", "log", xml_patchset_log },
438 { "xml-patchset", "xml", xml_patchset_xml },
439
440 { NULL, NULL, NULL }
441 };
442
443
444
445
446
447
448
449 void
450 pcmk__register_patchset_messages(pcmk__output_t *out) {
451 pcmk__register_messages(out, fmt_functions);
452 }
453
454
455
456
457 #include <crm/common/xml_compat.h>
458
459 void
460 xml_log_patchset(uint8_t log_level, const char *function,
461 const xmlNode *patchset)
462 {
463
464
465
466
467
468
469
470
471 static struct qb_log_callsite *patchset_cs = NULL;
472
473 pcmk__output_t *out = NULL;
474 int format = 1;
475 int rc = pcmk_rc_no_output;
476
477 switch (log_level) {
478 case LOG_NEVER:
479 return;
480 case LOG_STDOUT:
481 CRM_CHECK(pcmk__text_output_new(&out, NULL) == pcmk_rc_ok, return);
482 break;
483 default:
484 if (patchset_cs == NULL) {
485 patchset_cs = qb_log_callsite_get(__func__, __FILE__,
486 "xml-patchset", log_level,
487 __LINE__, crm_trace_nonlog);
488 }
489 if (!crm_is_callsite_active(patchset_cs, log_level,
490 crm_trace_nonlog)) {
491 return;
492 }
493 CRM_CHECK(pcmk__log_output_new(&out) == pcmk_rc_ok, return);
494 pcmk__output_set_log_level(out, log_level);
495 break;
496 }
497
498 if (patchset == NULL) {
499
500 crm_trace("Empty patch");
501 goto done;
502 }
503
504 crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
505 switch (format) {
506 case 1:
507 if (log_level < LOG_DEBUG) {
508 rc = xml_show_patchset_v1(out, patchset,
509 pcmk__xml_fmt_pretty
510 |pcmk__xml_fmt_diff_short);
511 } else {
512 rc = xml_show_patchset_v1(out, patchset, pcmk__xml_fmt_pretty);
513 }
514 break;
515 case 2:
516 rc = xml_show_patchset_v2(out, patchset);
517 break;
518 default:
519 crm_err("Unknown patch format: %d", format);
520 rc = pcmk_rc_bad_xml_patch;
521 break;
522 }
523
524 done:
525 out->finish(out, pcmk_rc2exitc(rc), true, NULL);
526 pcmk__output_free(out);
527 }
528
529
530