pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
xml_internal.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-2024 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__CRM_COMMON_XML_INTERNAL__H
11 #define PCMK__CRM_COMMON_XML_INTERNAL__H
12 
13 /*
14  * Internal-only wrappers for and extensions to libxml2 (libxslt)
15  */
16 
17 #include <stdlib.h>
18 #include <stdint.h> // uint32_t
19 #include <stdio.h>
20 
21 #include <crm/crm.h> /* transitively imports qblog.h */
23 #include <crm/common/xml_names.h> // PCMK_XA_ID, PCMK_XE_CLONE
24 
25 // This file is a wrapper for other xml_*_internal.h headers
31 
32 #include <libxml/relaxng.h>
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
81 #define PCMK__XML_LOG_BASE(priority, dechunk, postemit, prefix, fmt, ap) \
82 do { \
83  if (!(dechunk) && (prefix) == NULL) { /* quick pass */ \
84  qb_log_from_external_source_va(__func__, __FILE__, (fmt), \
85  (priority), __LINE__, 0, (ap)); \
86  (void) (postemit); \
87  } else { \
88  int CXLB_len = 0; \
89  char *CXLB_buf = NULL; \
90  static int CXLB_buffer_len = 0; \
91  static char *CXLB_buffer = NULL; \
92  static uint8_t CXLB_priority = 0; \
93  \
94  CXLB_len = vasprintf(&CXLB_buf, (fmt), (ap)); \
95  \
96  if (CXLB_len <= 0 || CXLB_buf[CXLB_len - 1] == '\n' || !(dechunk)) { \
97  if (CXLB_len < 0) { \
98  CXLB_buf = (char *) "LOG CORRUPTION HAZARD"; /*we don't modify*/\
99  CXLB_priority = QB_MIN(CXLB_priority, LOG_ERR); \
100  } else if (CXLB_len > 0 /* && (dechunk) */ \
101  && CXLB_buf[CXLB_len - 1] == '\n') { \
102  CXLB_buf[CXLB_len - 1] = '\0'; \
103  } \
104  if (CXLB_buffer) { \
105  qb_log_from_external_source(__func__, __FILE__, "%s%s%s", \
106  CXLB_priority, __LINE__, 0, \
107  (prefix) != NULL ? (prefix) : "", \
108  CXLB_buffer, CXLB_buf); \
109  free(CXLB_buffer); \
110  } else { \
111  qb_log_from_external_source(__func__, __FILE__, "%s%s", \
112  (priority), __LINE__, 0, \
113  (prefix) != NULL ? (prefix) : "", \
114  CXLB_buf); \
115  } \
116  if (CXLB_len < 0) { \
117  CXLB_buf = NULL; /* restore temporary override */ \
118  } \
119  CXLB_buffer = NULL; \
120  CXLB_buffer_len = 0; \
121  (void) (postemit); \
122  \
123  } else if (CXLB_buffer == NULL) { \
124  CXLB_buffer_len = CXLB_len; \
125  CXLB_buffer = CXLB_buf; \
126  CXLB_buf = NULL; \
127  CXLB_priority = (priority); /* remember as a running severest */ \
128  \
129  } else { \
130  CXLB_buffer = realloc(CXLB_buffer, 1 + CXLB_buffer_len + CXLB_len); \
131  memcpy(CXLB_buffer + CXLB_buffer_len, CXLB_buf, CXLB_len); \
132  CXLB_buffer_len += CXLB_len; \
133  CXLB_buffer[CXLB_buffer_len] = '\0'; \
134  CXLB_priority = QB_MIN(CXLB_priority, (priority)); /* severest? */ \
135  } \
136  free(CXLB_buf); \
137  } \
138 } while (0)
139 
140 /*
141  * \enum pcmk__xml_fmt_options
142  * \brief Bit flags to control format in XML logs and dumps
143  */
147 
150 
152  pcmk__xml_fmt_open = (1 << 3),
153 
156 
159 
160  // @COMPAT Can we start including text nodes unconditionally?
162  pcmk__xml_fmt_text = (1 << 6),
163 };
164 
165 void pcmk__xml_init(void);
166 void pcmk__xml_cleanup(void);
167 
168 int pcmk__xml_show(pcmk__output_t *out, const char *prefix, const xmlNode *data,
169  int depth, uint32_t options);
170 int pcmk__xml_show_changes(pcmk__output_t *out, const xmlNode *xml);
171 
172 /* XML search strings for guest, remote and pacemaker_remote nodes */
173 
174 /* search string to find CIB resources entries for cluster nodes */
175 #define PCMK__XP_MEMBER_NODE_CONFIG \
176  "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_NODES \
177  "/" PCMK_XE_NODE \
178  "[not(@" PCMK_XA_TYPE ") or @" PCMK_XA_TYPE "='" PCMK_VALUE_MEMBER "']"
179 
180 /* search string to find CIB resources entries for guest nodes */
181 #define PCMK__XP_GUEST_NODE_CONFIG \
182  "//" PCMK_XE_CIB "//" PCMK_XE_CONFIGURATION "//" PCMK_XE_PRIMITIVE \
183  "//" PCMK_XE_META_ATTRIBUTES "//" PCMK_XE_NVPAIR \
184  "[@" PCMK_XA_NAME "='" PCMK_META_REMOTE_NODE "']"
185 
186 /* search string to find CIB resources entries for remote nodes */
187 #define PCMK__XP_REMOTE_NODE_CONFIG \
188  "//" PCMK_XE_CIB "//" PCMK_XE_CONFIGURATION "//" PCMK_XE_PRIMITIVE \
189  "[@" PCMK_XA_TYPE "='" PCMK_VALUE_REMOTE "']" \
190  "[@" PCMK_XA_PROVIDER "='pacemaker']"
191 
192 /* search string to find CIB node status entries for pacemaker_remote nodes */
193 #define PCMK__XP_REMOTE_NODE_STATUS \
194  "//" PCMK_XE_CIB "//" PCMK_XE_STATUS "//" PCMK__XE_NODE_STATE \
195  "[@" PCMK_XA_REMOTE_NODE "='" PCMK_VALUE_TRUE "']"
196 
202 };
203 
204 void pcmk__strip_xml_text(xmlNode *xml);
205 
206 GString *pcmk__element_xpath(const xmlNode *xml);
207 
260 
268 
269  /* @COMPAT Drop escaping of at least '\n' and '\t' for
270  * pcmk__xml_escape_attr_pretty when openstack-info, openstack-floating-ip,
271  * and openstack-virtual-ip resource agents no longer depend on it.
272  *
273  * At time of writing, openstack-info may set a multiline value for the
274  * openstack_ports node attribute. The other two agents query the value and
275  * require it to be on one line with no spaces.
276  */
285 };
286 
287 bool pcmk__xml_needs_escape(const char *text, enum pcmk__xml_escape_type type);
288 char *pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type);
289 
298 char *
300 
311  const char *filespec);
312 
321 static inline xmlNode *
322 pcmk__xml_first_child(const xmlNode *parent)
323 {
324  xmlNode *child = (parent? parent->children : NULL);
325 
326  while (child && (child->type == XML_TEXT_NODE)) {
327  child = child->next;
328  }
329  return child;
330 }
331 
340 static inline xmlNode *
341 pcmk__xml_next(const xmlNode *child)
342 {
343  xmlNode *next = (child? child->next : NULL);
344 
345  while (next && (next->type == XML_TEXT_NODE)) {
346  next = next->next;
347  }
348  return next;
349 }
350 
351 void pcmk__xml_free(xmlNode *xml);
352 void pcmk__xml_free_doc(xmlDoc *doc);
353 xmlNode *pcmk__xml_copy(xmlNode *parent, xmlNode *src);
354 
363 
366 
372 };
373 
374 void pcmk__xml_sanitize_id(char *id);
375 
385 char *
386 pcmk__xpath_node_id(const char *xpath, const char *node);
387 
398 void
400  const char *name);
401 
402 /* internal XML-related utilities */
403 
405  pcmk__xf_none = 0x0000,
406  pcmk__xf_dirty = 0x0001,
410 
413  pcmk__xf_skip = 0x0040,
414  pcmk__xf_moved = 0x0080,
415 
420 
423  pcmk__xf_lazy = 0x4000,
424 };
425 
426 void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag);
427 
428 bool pcmk__xml_tree_foreach(xmlNode *xml, bool (*fn)(xmlNode *, void *),
429  void *user_data);
430 
431 static inline const char *
432 pcmk__xml_attr_value(const xmlAttr *attr)
433 {
434  return ((attr == NULL) || (attr->children == NULL))? NULL
435  : (const char *) attr->children->content;
436 }
437 
449 bool pcmk__cib_element_in_patchset(const xmlNode *patchset,
450  const char *element);
451 
452 #ifdef __cplusplus
453 }
454 #endif
455 
456 #endif // PCMK__CRM_COMMON_XML_INTERNAL__H
char * pcmk__xml_artefact_root(enum pcmk__xml_artefact_ns ns)
Definition: xml.c:1463
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition: xml.c:805
A dumping ground.
char * pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type)
Definition: xml.c:964
char data[0]
Definition: cpg.c:58
const char * name
Definition: cib.c:26
enum pcmk_ipc_server type
Definition: cpg.c:51
bool pcmk__xml_needs_escape(const char *text, enum pcmk__xml_escape_type type)
Definition: xml.c:882
void pcmk__xml_init(void)
Definition: xml.c:1430
Exclude certain XML attributes (for calculating digests)
Definition: xml_internal.h:146
Include the opening tag of an XML element, and include XML comments.
Definition: xml_internal.h:152
pcmk__xa_flags
Definition: xml_internal.h:360
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Definition: xml.c:96
char * pcmk__xpath_node_id(const char *xpath, const char *node)
Definition: xpath.c:290
Include indentation and newlines.
Definition: xml_internal.h:149
void pcmk__xml_free(xmlNode *xml)
Definition: xml.c:789
Formatted output for pacemaker tools.
void pcmk__strip_xml_text(xmlNode *xml)
Definition: xml.c:843
void pcmk__xml_cleanup(void)
Definition: xml.c:1456
pcmk__xml_escape_type
Definition: xml_internal.h:252
Include the children of an XML element.
Definition: xml_internal.h:155
Flag has no effect.
Definition: xml_internal.h:362
xml_private_flags
Definition: xml_internal.h:404
Defined string constants for XML element and attribute names.
pcmk__xml_artefact_ns
Definition: xml_internal.h:197
int pcmk__xml_show(pcmk__output_t *out, const char *prefix, const xmlNode *data, int depth, uint32_t options)
Definition: xml_display.c:221
Include the closing tag of an XML element.
Definition: xml_internal.h:158
int pcmk__xml_show_changes(pcmk__output_t *out, const xmlNode *xml)
Definition: xml_display.c:362
This structure contains everything that makes up a single output formatter.
Include XML text nodes.
Definition: xml_internal.h:162
void pcmk__xml_free_doc(xmlDoc *doc)
Definition: xml.c:495
bool pcmk__xml_tree_foreach(xmlNode *xml, bool(*fn)(xmlNode *, void *), void *user_data)
Definition: xml.c:47
GString * pcmk__element_xpath(const xmlNode *xml)
Definition: xpath.c:256
void pcmk__warn_multiple_name_matches(pcmk__output_t *out, xmlNode *search, const char *name)
Definition: xpath.c:332
bool pcmk__cib_element_in_patchset(const xmlNode *patchset, const char *element)
Definition: patchset.c:827
void pcmk__xml_sanitize_id(char *id)
Definition: xml.c:654
const char * parent
Definition: cib.c:27
char * pcmk__xml_artefact_path(enum pcmk__xml_artefact_ns ns, const char *filespec)
Definition: xml.c:1520
pcmk__xml_fmt_options
Definition: xml_internal.h:144
Don&#39;t overwrite existing values.
Definition: xml_internal.h:365