1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
/*
* Original copyright 2004 International Business Machines
* Later changes copyright 2008-2025 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 <stdio.h>
#include <libxml/tree.h> // xmlNode
#include <crm/common/xml.h>
#include <crm/common/cib.h>
#include <crm/common/cib_internal.h>
/*
* Functions to help find particular sections of the CIB
*/
// Map CIB element names to their parent elements and XPath searches
static struct {
const char *name; // Name of this CIB element
const char *parent; // CIB element that this element is a child of
const char *path; // XPath to find this CIB element
} cib_sections[] = {
{
// This first entry is also the default if a NULL is compared
PCMK_XE_CIB,
NULL,
"//" PCMK_XE_CIB
},
{
PCMK_XE_STATUS,
"/" PCMK_XE_CIB,
"//" PCMK_XE_CIB "/" PCMK_XE_STATUS
},
{
PCMK_XE_CONFIGURATION,
"/" PCMK_XE_CIB,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION
},
{
PCMK_XE_CRM_CONFIG,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_CRM_CONFIG
},
{
PCMK_XE_NODES,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_NODES
},
{
PCMK_XE_RESOURCES,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RESOURCES
},
{
PCMK_XE_CONSTRAINTS,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_CONSTRAINTS
},
{
PCMK_XE_OP_DEFAULTS,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_OP_DEFAULTS
},
{
PCMK_XE_RSC_DEFAULTS,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RSC_DEFAULTS
},
{
PCMK_XE_ACLS,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_ACLS
},
{
PCMK_XE_FENCING_TOPOLOGY,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_FENCING_TOPOLOGY
},
{
PCMK_XE_TAGS,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_TAGS
},
{
PCMK_XE_ALERTS,
"/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
"//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_ALERTS
},
{
PCMK__XE_ALL,
NULL,
"//" PCMK_XE_CIB
},
};
/*!
* \brief Get the relative XPath needed to find a specified CIB element name
*
* \param[in] element_name Name of CIB element
*
* \return XPath for finding \p element_name in CIB XML (or NULL if unknown)
* \note The return value is constant and should not be freed.
*/
const char *
pcmk_cib_xpath_for(const char *element_name)
{
for (int lpc = 0; lpc < PCMK__NELEM(cib_sections); lpc++) {
// A NULL element_name will match the first entry
if (pcmk__str_eq(element_name, cib_sections[lpc].name,
pcmk__str_null_matches)) {
return cib_sections[lpc].path;
}
}
return NULL;
}
/*!
* \internal
* \brief Get the absolute XPath needed to find a specified CIB element name
*
* \param[in] element Name of CIB element
*
* \return XPath for finding \p element in CIB XML (or \c NULL if unknown)
*/
const char *
pcmk__cib_abs_xpath_for(const char *element)
{
const char *xpath = pcmk_cib_xpath_for(element);
// XPaths returned by pcmk_cib_xpath_for() are relative (starting with "//")
return ((xpath != NULL)? (xpath + 1) : NULL);
}
/*!
* \brief Get the parent element name of a given CIB element name
*
* \param[in] element_name Name of CIB element
*
* \return Parent element of \p element_name (or NULL if none or unknown)
* \note The return value is constant and should not be freed.
*/
const char *
pcmk_cib_parent_name_for(const char *element_name)
{
for (int lpc = 0; lpc < PCMK__NELEM(cib_sections); lpc++) {
// A NULL element_name will match the first entry
if (pcmk__str_eq(element_name, cib_sections[lpc].name,
pcmk__str_null_matches)) {
return cib_sections[lpc].parent;
}
}
return NULL;
}
/*!
* \brief Find an element in the CIB
*
* \param[in,out] cib Top-level CIB XML to search
* \param[in] element_name Name of CIB element to search for
*
* \return XML element in \p cib corresponding to \p element_name
* (or \p cib itself if element is unknown or not found)
*/
xmlNode *
pcmk_find_cib_element(xmlNode *cib, const char *element_name)
{
return pcmk__xpath_find_one(cib->doc, pcmk_cib_xpath_for(element_name),
LOG_TRACE);
}
/*!
* \internal
* \brief Check that the feature set in the CIB is supported on this node
*
* \param[in] new_version PCMK_XA_CRM_FEATURE_SET attribute from the CIB
*/
int
pcmk__check_feature_set(const char *cib_version)
{
if (cib_version && compare_version(cib_version, CRM_FEATURE_SET) > 0) {
return EPROTONOSUPPORT;
}
return pcmk_rc_ok;
}
|