pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
xml_internal.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-2023 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #ifndef PCMK__XML_INTERNAL__H
11 # define PCMK__XML_INTERNAL__H
12 
13 /*
14  * Internal-only wrappers for and extensions to libxml2 (libxslt)
15  */
16 
17 # include <stdlib.h>
18 # include <stdio.h>
19 # include <string.h>
20 
21 # include <crm/crm.h> /* transitively imports qblog.h */
23 
24 
68 #define PCMK__XML_LOG_BASE(priority, dechunk, postemit, prefix, fmt, ap) \
69 do { \
70  if (!(dechunk) && (prefix) == NULL) { /* quick pass */ \
71  qb_log_from_external_source_va(__func__, __FILE__, (fmt), \
72  (priority), __LINE__, 0, (ap)); \
73  (void) (postemit); \
74  } else { \
75  int CXLB_len = 0; \
76  char *CXLB_buf = NULL; \
77  static int CXLB_buffer_len = 0; \
78  static char *CXLB_buffer = NULL; \
79  static uint8_t CXLB_priority = 0; \
80  \
81  CXLB_len = vasprintf(&CXLB_buf, (fmt), (ap)); \
82  \
83  if (CXLB_len <= 0 || CXLB_buf[CXLB_len - 1] == '\n' || !(dechunk)) { \
84  if (CXLB_len < 0) { \
85  CXLB_buf = (char *) "LOG CORRUPTION HAZARD"; /*we don't modify*/\
86  CXLB_priority = QB_MIN(CXLB_priority, LOG_ERR); \
87  } else if (CXLB_len > 0 /* && (dechunk) */ \
88  && CXLB_buf[CXLB_len - 1] == '\n') { \
89  CXLB_buf[CXLB_len - 1] = '\0'; \
90  } \
91  if (CXLB_buffer) { \
92  qb_log_from_external_source(__func__, __FILE__, "%s%s%s", \
93  CXLB_priority, __LINE__, 0, \
94  (prefix) != NULL ? (prefix) : "", \
95  CXLB_buffer, CXLB_buf); \
96  free(CXLB_buffer); \
97  } else { \
98  qb_log_from_external_source(__func__, __FILE__, "%s%s", \
99  (priority), __LINE__, 0, \
100  (prefix) != NULL ? (prefix) : "", \
101  CXLB_buf); \
102  } \
103  if (CXLB_len < 0) { \
104  CXLB_buf = NULL; /* restore temporary override */ \
105  } \
106  CXLB_buffer = NULL; \
107  CXLB_buffer_len = 0; \
108  (void) (postemit); \
109  \
110  } else if (CXLB_buffer == NULL) { \
111  CXLB_buffer_len = CXLB_len; \
112  CXLB_buffer = CXLB_buf; \
113  CXLB_buf = NULL; \
114  CXLB_priority = (priority); /* remember as a running severest */ \
115  \
116  } else { \
117  CXLB_buffer = realloc(CXLB_buffer, 1 + CXLB_buffer_len + CXLB_len); \
118  memcpy(CXLB_buffer + CXLB_buffer_len, CXLB_buf, CXLB_len); \
119  CXLB_buffer_len += CXLB_len; \
120  CXLB_buffer[CXLB_buffer_len] = '\0'; \
121  CXLB_priority = QB_MIN(CXLB_priority, (priority)); /* severest? */ \
122  } \
123  free(CXLB_buf); \
124  } \
125 } while (0)
126 
127 /*
128  * \enum pcmk__xml_fmt_options
129  * \brief Bit flags to control format in XML logs and dumps
130  */
134 
137 
139  pcmk__xml_fmt_full = (1 << 2),
140 
142  pcmk__xml_fmt_open = (1 << 3),
143 
146 
149 
150  // @COMPAT Remove when log_data_element() is removed
152  pcmk__xml_fmt_text = (1 << 6),
153 
154  // @COMPAT Remove when v1 patchsets are removed
157 
158  // @COMPAT Remove when v1 patchsets are removed
161 
162  // @COMPAT Remove when v1 patchsets are removed
165 };
166 
167 int pcmk__xml_show(pcmk__output_t *out, const char *prefix, const xmlNode *data,
168  int depth, uint32_t options);
169 int pcmk__xml_show_changes(pcmk__output_t *out, const xmlNode *xml);
170 
171 /* XML search strings for guest, remote and pacemaker_remote nodes */
172 
173 /* search string to find CIB resources entries for cluster nodes */
174 #define PCMK__XP_MEMBER_NODE_CONFIG \
175  "//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \
176  "/" XML_CIB_TAG_NODE "[not(@type) or @type='member']"
177 
178 /* search string to find CIB resources entries for guest nodes */
179 #define PCMK__XP_GUEST_NODE_CONFIG \
180  "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \
181  "//" XML_TAG_META_SETS "//" XML_CIB_TAG_NVPAIR \
182  "[@name='" XML_RSC_ATTR_REMOTE_NODE "']"
183 
184 /* search string to find CIB resources entries for remote nodes */
185 #define PCMK__XP_REMOTE_NODE_CONFIG \
186  "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \
187  "[@type='remote'][@provider='pacemaker']"
188 
189 /* search string to find CIB node status entries for pacemaker_remote nodes */
190 #define PCMK__XP_REMOTE_NODE_STATUS \
191  "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE \
192  "[@" XML_NODE_IS_REMOTE "='true']"
193 
199 };
200 
201 void pcmk__strip_xml_text(xmlNode *xml);
202 const char *pcmk__xe_add_last_written(xmlNode *xe);
203 
204 xmlNode *pcmk__xe_match(const xmlNode *parent, const char *node_name,
205  const char *attr_n, const char *attr_v);
206 
207 void pcmk__xe_remove_matching_attrs(xmlNode *element,
208  bool (*match)(xmlAttrPtr, void *),
209  void *user_data);
210 
211 GString *pcmk__element_xpath(const xmlNode *xml);
212 
221 char *
223 
234  const char *filespec);
235 
244 static inline xmlNode *
245 pcmk__xml_first_child(const xmlNode *parent)
246 {
247  xmlNode *child = (parent? parent->children : NULL);
248 
249  while (child && (child->type == XML_TEXT_NODE)) {
250  child = child->next;
251  }
252  return child;
253 }
254 
263 static inline xmlNode *
264 pcmk__xml_next(const xmlNode *child)
265 {
266  xmlNode *next = (child? child->next : NULL);
267 
268  while (next && (next->type == XML_TEXT_NODE)) {
269  next = next->next;
270  }
271  return next;
272 }
273 
282 static inline xmlNode *
283 pcmk__xe_first_child(const xmlNode *parent)
284 {
285  xmlNode *child = (parent? parent->children : NULL);
286 
287  while (child && (child->type != XML_ELEMENT_NODE)) {
288  child = child->next;
289  }
290  return child;
291 }
292 
301 static inline xmlNode *
302 pcmk__xe_next(const xmlNode *child)
303 {
304  xmlNode *next = child? child->next : NULL;
305 
306  while (next && (next->type != XML_ELEMENT_NODE)) {
307  next = next->next;
308  }
309  return next;
310 }
311 
320 void
321 pcmk__xe_set_propv(xmlNodePtr node, va_list pairs);
322 
333 void
334 pcmk__xe_set_props(xmlNodePtr node, ...)
335 G_GNUC_NULL_TERMINATED;
336 
345 static inline xmlAttr *
346 pcmk__xe_first_attr(const xmlNode *xe)
347 {
348  return (xe == NULL)? NULL : xe->properties;
349 }
350 
360 char *
361 pcmk__xpath_node_id(const char *xpath, const char *node);
362 
363 /* internal XML-related utilities */
364 
366  pcmk__xf_none = 0x0000,
367  pcmk__xf_dirty = 0x0001,
371 
374  pcmk__xf_skip = 0x0040,
375  pcmk__xf_moved = 0x0080,
376 
381 
384  pcmk__xf_lazy = 0x4000,
385 };
386 
387 void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag);
388 
409 int
410 pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name,
411  int (*handler)(xmlNode *xml, void *userdata),
412  void *userdata);
413 
414 #endif // PCMK__XML_INTERNAL__H
char * pcmk__xml_artefact_root(enum pcmk__xml_artefact_ns ns)
Definition: xml.c:2627
A dumping ground.
char data[0]
Definition: cpg.c:55
xmlNode * pcmk__xe_match(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:454
const char * pcmk__xe_add_last_written(xmlNode *xe)
Definition: xml.c:1077
Exclude certain XML attributes (for calculating digests)
Definition: xml_internal.h:133
Include the opening tag of an XML element, and include XML comments.
Definition: xml_internal.h:142
void pcmk__xe_set_propv(xmlNodePtr node, va_list pairs)
Definition: xml.c:2677
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Definition: xml.c:77
char * pcmk__xpath_node_id(const char *xpath, const char *node)
Definition: xpath.c:315
Include indentation and newlines.
Definition: xml_internal.h:136
Log a created XML subtree.
Definition: xml_internal.h:156
Formatted output for pacemaker tools.
void pcmk__strip_xml_text(xmlNode *xml)
Definition: xml.c:979
Include the children of an XML element.
Definition: xml_internal.h:145
void pcmk__xe_remove_matching_attrs(xmlNode *element, bool(*match)(xmlAttrPtr, void *), void *user_data)
Definition: xml.c:618
Include full XML subtree (with any text), using libxml serialization.
Definition: xml_internal.h:139
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
Definition: xml.c:2695
xml_private_flags
Definition: xml_internal.h:365
pcmk__xml_artefact_ns
Definition: xml_internal.h:194
Log a removed XML subtree.
Definition: xml_internal.h:160
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
Definition: xml.c:2704
int pcmk__xml_show(pcmk__output_t *out, const char *prefix, const xmlNode *data, int depth, uint32_t options)
Definition: xml_display.c:229
Include the closing tag of an XML element.
Definition: xml_internal.h:148
int pcmk__xml_show_changes(pcmk__output_t *out, const xmlNode *xml)
Definition: xml_display.c:370
This structure contains everything that makes up a single output formatter.
Include XML text nodes.
Definition: xml_internal.h:152
Log a minimal version of an XML diff (only showing the changes)
Definition: xml_internal.h:164
GString * pcmk__element_xpath(const xmlNode *xml)
Definition: xpath.c:281
const char * parent
Definition: cib.c:25
char * pcmk__xml_artefact_path(enum pcmk__xml_artefact_ns ns, const char *filespec)
Definition: xml.c:2655
pcmk__xml_fmt_options
Definition: xml_internal.h:131