Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/include/crm/common/xml_compat.h b/include/crm/common/xml_compat.h
index aa507320f6..921ece7111 100644
--- a/include/crm/common/xml_compat.h
+++ b/include/crm/common/xml_compat.h
@@ -1,87 +1,84 @@
/*
* Copyright 2004-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef PCMK__CRM_COMMON_XML_COMPAT__H
#define PCMK__CRM_COMMON_XML_COMPAT__H
#include <glib.h> // gboolean
#include <libxml/tree.h> // xmlNode
#include <crm/common/nvpair.h> // crm_xml_add()
#include <crm/common/xml_names.h> // PCMK_XE_CLONE
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file
* \brief Deprecated Pacemaker XML API
* \ingroup core
* \deprecated Do not include this header directly. The XML APIs in this
* header, and the header itself, will be removed in a future
* release.
*/
//! \deprecated Do not use (will be removed in a future release)
#define XML_PARANOIA_CHECKS 0
//! \deprecated This function will be removed in a future release
xmlDoc *getDocPtr(xmlNode *node);
//! \deprecated This function will be removed in a future release
xmlNode *find_entity(xmlNode *parent, const char *node_name, const char *id);
//! \deprecated This function will be removed in a future release
char *xml_get_path(const xmlNode *xml);
//! \deprecated This function will be removed in a future release
void xml_log_changes(uint8_t level, const char *function, const xmlNode *xml);
-//! \deprecated This function will be removed in a future release
-void xml_log_patchset(uint8_t level, const char *function, const xmlNode *xml);
-
// NOTE: sbd (as of at least 1.5.2) uses this
//! \deprecated Use name member directly
static inline const char *
crm_element_name(const xmlNode *xml)
{
return (xml == NULL)? NULL : (const char *) xml->name;
}
// NOTE: sbd (as of at least 1.5.2) uses this
//! \deprecated Do not use Pacemaker for general-purpose XML manipulation
xmlNode *copy_xml(xmlNode *src_node);
// NOTE: sbd (as of at least 1.5.2) uses this
//! \deprecated Do not use
gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs);
// NOTE: sbd (as of at least 1.5.2) uses this
//! \deprecated Call \c crm_log_init() or \c crm_log_cli_init() instead
void crm_xml_init(void);
//! \deprecated Exit with \c crm_exit() instead
void crm_xml_cleanup(void);
//! \deprecated Do not use Pacemaker for general-purpose XML manipulation
void pcmk_free_xml_subtree(xmlNode *xml);
// NOTE: sbd (as of at least 1.5.2) uses this
//! \deprecated Do not use Pacemaker for general-purpose XML manipulation
void free_xml(xmlNode *child);
//! \deprecated Do not use Pacemaker for general-purpose XML manipulation
xmlNode *expand_idref(xmlNode *input, xmlNode *top);
#ifdef __cplusplus
}
#endif
#endif // PCMK__CRM_COMMON_XML_COMPAT__H
diff --git a/lib/common/patchset_display.c b/lib/common/patchset_display.c
index 1351c86071..0855c6e829 100644
--- a/lib/common/patchset_display.c
+++ b/lib/common/patchset_display.c
@@ -1,530 +1,452 @@
/*
* Copyright 2004-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <crm/common/xml.h>
#include "crmcommon_private.h"
/*!
* \internal
* \brief Output an XML patchset header
*
* This function parses a header from an XML patchset (an \p XML_ATTR_DIFF
* element and its children).
*
* All header lines contain three integers separated by dots, of the form
* <tt>{0}.{1}.{2}</tt>:
* * \p {0}: \c PCMK_XA_ADMIN_EPOCH
* * \p {1}: \c PCMK_XA_EPOCH
* * \p {2}: \c PCMK_XA_NUM_UPDATES
*
* Lines containing \p "---" describe removals and end with the patch format
* number. Lines containing \p "+++" describe additions and end with the patch
* digest.
*
* \param[in,out] out Output object
* \param[in] patchset XML patchset to output
*
* \return Standard Pacemaker return code
*
* \note This function produces output only for text-like formats.
*/
static int
xml_show_patchset_header(pcmk__output_t *out, const xmlNode *patchset)
{
int rc = pcmk_rc_no_output;
int add[] = { 0, 0, 0 };
int del[] = { 0, 0, 0 };
xml_patch_versions(patchset, add, del);
if ((add[0] != del[0]) || (add[1] != del[1]) || (add[2] != del[2])) {
const char *fmt = crm_element_value(patchset, PCMK_XA_FORMAT);
const char *digest = crm_element_value(patchset, PCMK__XA_DIGEST);
out->info(out, "Diff: --- %d.%d.%d %s", del[0], del[1], del[2], fmt);
rc = out->info(out, "Diff: +++ %d.%d.%d %s",
add[0], add[1], add[2], digest);
} else if ((add[0] != 0) || (add[1] != 0) || (add[2] != 0)) {
rc = out->info(out, "Local-only Change: %d.%d.%d",
add[0], add[1], add[2]);
}
return rc;
}
/*!
* \internal
* \brief Output a user-friendly form of XML additions or removals
*
* \param[in,out] out Output object
* \param[in] prefix String to prepend to every line of output
* \param[in] data XML node to output
* \param[in] depth Current indentation level
* \param[in] options Group of \p pcmk__xml_fmt_options flags
*
* \return Standard Pacemaker return code
*
* \note This function produces output only for text-like formats.
*/
static int
xml_show_patchset_v1_recursive(pcmk__output_t *out, const char *prefix,
const xmlNode *data, int depth, uint32_t options)
{
if ((data->children == NULL)
|| (crm_element_value(data, PCMK__XA_CRM_DIFF_MARKER) != NULL)) {
// Found a change; clear the pcmk__xml_fmt_diff_short option if set
options &= ~pcmk__xml_fmt_diff_short;
if (pcmk_is_set(options, pcmk__xml_fmt_diff_plus)) {
prefix = PCMK__XML_PREFIX_CREATED;
} else { // pcmk_is_set(options, pcmk__xml_fmt_diff_minus)
prefix = PCMK__XML_PREFIX_DELETED;
}
}
if (pcmk_is_set(options, pcmk__xml_fmt_diff_short)) {
int rc = pcmk_rc_no_output;
// Keep looking for the actual change
for (const xmlNode *child = pcmk__xml_first_child(data); child != NULL;
child = pcmk__xml_next(child)) {
int temp_rc = xml_show_patchset_v1_recursive(out, prefix, child,
depth + 1, options);
rc = pcmk__output_select_rc(rc, temp_rc);
}
return rc;
}
return pcmk__xml_show(out, prefix, data, depth,
options
|pcmk__xml_fmt_open
|pcmk__xml_fmt_children
|pcmk__xml_fmt_close);
}
/*!
* \internal
* \brief Output a user-friendly form of an XML patchset (format 1)
*
* This function parses an XML patchset (an \p XML_ATTR_DIFF element and its
* children) into a user-friendly combined diff output.
*
* \param[in,out] out Output object
* \param[in] patchset XML patchset to output
* \param[in] options Group of \p pcmk__xml_fmt_options flags
*
* \return Standard Pacemaker return code
*
* \note This function produces output only for text-like formats.
*/
static int
xml_show_patchset_v1(pcmk__output_t *out, const xmlNode *patchset,
uint32_t options)
{
const xmlNode *removed = NULL;
const xmlNode *added = NULL;
const xmlNode *child = NULL;
bool is_first = true;
int rc = xml_show_patchset_header(out, patchset);
/* It's not clear whether "- " or "+ " ever does *not* get overridden by
* PCMK__XML_PREFIX_DELETED or PCMK__XML_PREFIX_CREATED in practice.
* However, v1 patchsets can only exist during rolling upgrades from
* Pacemaker 1.1.11, so not worth worrying about.
*/
removed = pcmk__xe_first_child(patchset, PCMK__XE_DIFF_REMOVED, NULL, NULL);
for (child = pcmk__xml_first_child(removed); child != NULL;
child = pcmk__xml_next(child)) {
int temp_rc = xml_show_patchset_v1_recursive(out, "- ", child, 0,
options
|pcmk__xml_fmt_diff_minus);
rc = pcmk__output_select_rc(rc, temp_rc);
if (is_first) {
is_first = false;
} else {
rc = pcmk__output_select_rc(rc, out->info(out, " --- "));
}
}
is_first = true;
added = pcmk__xe_first_child(patchset, PCMK__XE_DIFF_ADDED, NULL, NULL);
for (child = pcmk__xml_first_child(added); child != NULL;
child = pcmk__xml_next(child)) {
int temp_rc = xml_show_patchset_v1_recursive(out, "+ ", child, 0,
options
|pcmk__xml_fmt_diff_plus);
rc = pcmk__output_select_rc(rc, temp_rc);
if (is_first) {
is_first = false;
} else {
rc = pcmk__output_select_rc(rc, out->info(out, " +++ "));
}
}
return rc;
}
/*!
* \internal
* \brief Output a user-friendly form of an XML patchset (format 2)
*
* This function parses an XML patchset (an \p XML_ATTR_DIFF element and its
* children) into a user-friendly combined diff output.
*
* \param[in,out] out Output object
* \param[in] patchset XML patchset to output
*
* \return Standard Pacemaker return code
*
* \note This function produces output only for text-like formats.
*/
static int
xml_show_patchset_v2(pcmk__output_t *out, const xmlNode *patchset)
{
int rc = xml_show_patchset_header(out, patchset);
int temp_rc = pcmk_rc_no_output;
for (const xmlNode *change = pcmk__xe_first_child(patchset, NULL, NULL,
NULL);
change != NULL; change = pcmk__xe_next(change)) {
const char *op = crm_element_value(change, PCMK_XA_OPERATION);
const char *xpath = crm_element_value(change, PCMK_XA_PATH);
if (op == NULL) {
continue;
}
if (strcmp(op, PCMK_VALUE_CREATE) == 0) {
char *prefix = crm_strdup_printf(PCMK__XML_PREFIX_CREATED " %s: ",
xpath);
temp_rc = pcmk__xml_show(out, prefix, change->children, 0,
pcmk__xml_fmt_pretty|pcmk__xml_fmt_open);
rc = pcmk__output_select_rc(rc, temp_rc);
// Overwrite all except the first two characters with spaces
for (char *ch = prefix + 2; *ch != '\0'; ch++) {
*ch = ' ';
}
temp_rc = pcmk__xml_show(out, prefix, change->children, 0,
pcmk__xml_fmt_pretty
|pcmk__xml_fmt_children
|pcmk__xml_fmt_close);
rc = pcmk__output_select_rc(rc, temp_rc);
free(prefix);
} else if (strcmp(op, PCMK_VALUE_MOVE) == 0) {
const char *position = crm_element_value(change, PCMK_XE_POSITION);
temp_rc = out->info(out,
PCMK__XML_PREFIX_MOVED " %s moved to offset %s",
xpath, position);
rc = pcmk__output_select_rc(rc, temp_rc);
} else if (strcmp(op, PCMK_VALUE_MODIFY) == 0) {
xmlNode *clist = pcmk__xe_first_child(change, PCMK_XE_CHANGE_LIST,
NULL, NULL);
GString *buffer_set = NULL;
GString *buffer_unset = NULL;
for (const xmlNode *child = pcmk__xe_first_child(clist, NULL, NULL,
NULL);
child != NULL; child = pcmk__xe_next(child)) {
const char *name = crm_element_value(child, PCMK_XA_NAME);
op = crm_element_value(child, PCMK_XA_OPERATION);
if (op == NULL) {
continue;
}
if (strcmp(op, "set") == 0) {
const char *value = crm_element_value(child, PCMK_XA_VALUE);
pcmk__add_separated_word(&buffer_set, 256, "@", ", ");
pcmk__g_strcat(buffer_set, name, "=", value, NULL);
} else if (strcmp(op, "unset") == 0) {
pcmk__add_separated_word(&buffer_unset, 256, "@", ", ");
g_string_append(buffer_unset, name);
}
}
if (buffer_set != NULL) {
temp_rc = out->info(out, "+ %s: %s", xpath, buffer_set->str);
rc = pcmk__output_select_rc(rc, temp_rc);
g_string_free(buffer_set, TRUE);
}
if (buffer_unset != NULL) {
temp_rc = out->info(out, "-- %s: %s",
xpath, buffer_unset->str);
rc = pcmk__output_select_rc(rc, temp_rc);
g_string_free(buffer_unset, TRUE);
}
} else if (strcmp(op, PCMK_VALUE_DELETE) == 0) {
int position = -1;
crm_element_value_int(change, PCMK_XE_POSITION, &position);
if (position >= 0) {
temp_rc = out->info(out, "-- %s (%d)", xpath, position);
} else {
temp_rc = out->info(out, "-- %s", xpath);
}
rc = pcmk__output_select_rc(rc, temp_rc);
}
}
return rc;
}
/*!
* \internal
* \brief Output a user-friendly form of an XML patchset
*
* This function parses an XML patchset (an \p XML_ATTR_DIFF element and its
* children) into a user-friendly combined diff output.
*
* \param[in,out] out Output object
* \param[in] args Message-specific arguments
*
* \return Standard Pacemaker return code
*
* \note \p args should contain the following:
* -# XML patchset
*/
PCMK__OUTPUT_ARGS("xml-patchset", "const xmlNode *")
static int
xml_patchset_default(pcmk__output_t *out, va_list args)
{
const xmlNode *patchset = va_arg(args, const xmlNode *);
int format = 1;
if (patchset == NULL) {
crm_trace("Empty patch");
return pcmk_rc_no_output;
}
crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
switch (format) {
case 1:
return xml_show_patchset_v1(out, patchset, pcmk__xml_fmt_pretty);
case 2:
return xml_show_patchset_v2(out, patchset);
default:
crm_err("Unknown patch format: %d", format);
return pcmk_rc_bad_xml_patch;
}
}
/*!
* \internal
* \brief Output a user-friendly form of an XML patchset
*
* This function parses an XML patchset (an \p XML_ATTR_DIFF element and its
* children) into a user-friendly combined diff output.
*
* \param[in,out] out Output object
* \param[in] args Message-specific arguments
*
* \return Standard Pacemaker return code
*
* \note \p args should contain the following:
* -# XML patchset
*/
PCMK__OUTPUT_ARGS("xml-patchset", "const xmlNode *")
static int
xml_patchset_log(pcmk__output_t *out, va_list args)
{
static struct qb_log_callsite *patchset_cs = NULL;
const xmlNode *patchset = va_arg(args, const xmlNode *);
uint8_t log_level = pcmk__output_get_log_level(out);
int format = 1;
if (log_level == LOG_NEVER) {
return pcmk_rc_no_output;
}
if (patchset == NULL) {
crm_trace("Empty patch");
return pcmk_rc_no_output;
}
if (patchset_cs == NULL) {
patchset_cs = qb_log_callsite_get(__func__, __FILE__, "xml-patchset",
log_level, __LINE__,
crm_trace_nonlog);
}
if (!crm_is_callsite_active(patchset_cs, log_level, crm_trace_nonlog)) {
// Nothing would be logged, so skip all the work
return pcmk_rc_no_output;
}
crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
switch (format) {
case 1:
if (log_level < LOG_DEBUG) {
return xml_show_patchset_v1(out, patchset,
pcmk__xml_fmt_pretty
|pcmk__xml_fmt_diff_short);
}
return xml_show_patchset_v1(out, patchset, pcmk__xml_fmt_pretty);
case 2:
return xml_show_patchset_v2(out, patchset);
default:
crm_err("Unknown patch format: %d", format);
return pcmk_rc_bad_xml_patch;
}
}
/*!
* \internal
* \brief Output an XML patchset
*
* This function outputs an XML patchset (an \p XML_ATTR_DIFF element and its
* children) without modification, as a CDATA block.
*
* \param[in,out] out Output object
* \param[in] args Message-specific arguments
*
* \return Standard Pacemaker return code
*
* \note \p args should contain the following:
* -# XML patchset
*/
PCMK__OUTPUT_ARGS("xml-patchset", "const xmlNode *")
static int
xml_patchset_xml(pcmk__output_t *out, va_list args)
{
const xmlNode *patchset = va_arg(args, const xmlNode *);
if (patchset != NULL) {
GString *buf = g_string_sized_new(1024);
pcmk__xml_string(patchset, pcmk__xml_fmt_pretty|pcmk__xml_fmt_text, buf,
0);
out->output_xml(out, PCMK_XE_XML_PATCHSET, buf->str);
g_string_free(buf, TRUE);
return pcmk_rc_ok;
}
crm_trace("Empty patch");
return pcmk_rc_no_output;
}
static pcmk__message_entry_t fmt_functions[] = {
{ "xml-patchset", "default", xml_patchset_default },
{ "xml-patchset", "log", xml_patchset_log },
{ "xml-patchset", "xml", xml_patchset_xml },
{ NULL, NULL, NULL }
};
/*!
* \internal
* \brief Register the formatting functions for XML patchsets
*
* \param[in,out] out Output object
*/
void
pcmk__register_patchset_messages(pcmk__output_t *out) {
pcmk__register_messages(out, fmt_functions);
}
-
-// Deprecated functions kept only for backward API compatibility
-// LCOV_EXCL_START
-
-#include <crm/common/xml_compat.h>
-
-void
-xml_log_patchset(uint8_t log_level, const char *function,
- const xmlNode *patchset)
-{
- /* This function has some duplication relative to the message functions.
- * This way, we can maintain the const xmlNode * in the signature. The
- * message functions must be non-const. They have to support XML output
- * objects, which must make a copy of a the patchset, requiring a non-const
- * function call.
- *
- * In contrast, this legacy function doesn't need to support XML output.
- */
- static struct qb_log_callsite *patchset_cs = NULL;
-
- pcmk__output_t *out = NULL;
- int format = 1;
- int rc = pcmk_rc_no_output;
-
- switch (log_level) {
- case LOG_NEVER:
- return;
- case LOG_STDOUT:
- CRM_CHECK(pcmk__text_output_new(&out, NULL) == pcmk_rc_ok, return);
- break;
- default:
- if (patchset_cs == NULL) {
- patchset_cs = qb_log_callsite_get(__func__, __FILE__,
- "xml-patchset", log_level,
- __LINE__, crm_trace_nonlog);
- }
- if (!crm_is_callsite_active(patchset_cs, log_level,
- crm_trace_nonlog)) {
- return;
- }
- CRM_CHECK(pcmk__log_output_new(&out) == pcmk_rc_ok, return);
- pcmk__output_set_log_level(out, log_level);
- break;
- }
-
- if (patchset == NULL) {
- // Should come after the LOG_NEVER check
- crm_trace("Empty patch");
- goto done;
- }
-
- crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
- switch (format) {
- case 1:
- if (log_level < LOG_DEBUG) {
- rc = xml_show_patchset_v1(out, patchset,
- pcmk__xml_fmt_pretty
- |pcmk__xml_fmt_diff_short);
- } else { // Note: LOG_STDOUT > LOG_DEBUG
- rc = xml_show_patchset_v1(out, patchset, pcmk__xml_fmt_pretty);
- }
- break;
- case 2:
- rc = xml_show_patchset_v2(out, patchset);
- break;
- default:
- crm_err("Unknown patch format: %d", format);
- rc = pcmk_rc_bad_xml_patch;
- break;
- }
-
-done:
- out->finish(out, pcmk_rc2exitc(rc), true, NULL);
- pcmk__output_free(out);
-}
-
-// LCOV_EXCL_STOP
-// End deprecated API

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 10, 2:52 AM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2009793
Default Alt Text
(21 KB)

Event Timeline