pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_verify.c
Go to the documentation of this file.
1/*
2 * Copyright 2023-2025 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#include <crm_internal.h>
11#include <crm/cib/internal.h>
12#include <crm/common/output.h>
13#include <crm/common/results.h>
15#include <pacemaker-internal.h>
16#include <pacemaker.h>
17
18#include <stdint.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <unistd.h>
22
24
25int
26pcmk__parse_cib(pcmk__output_t *out, const char *cib_source, xmlNodePtr *cib_object)
27{
28 // @COMPAT Take an enum for cib_source instead of trying to figure it out?
29 const char *first = cib_source;
30
31 if (cib_source == NULL) {
32 return cib__signon_query(out, NULL, cib_object);
33 }
34
35 while (isspace(*first)) {
36 first++;
37 }
38
39 if (*first == '<') {
40 *cib_object = pcmk__xml_parse(cib_source);
41 } else {
42 *cib_object = pcmk__xml_read(cib_source);
43 }
44
45 return (*cib_object == NULL)? pcmk_rc_unpack_error : pcmk_rc_ok;
46}
47
48int
50 xmlNode **cib_object)
51{
52 /* @TODO The scheduler argument is needed only for pcmk__config_has_error
53 * and pcmk__config_has_warning. When we reset the scheduler, we reset those
54 * global variables. Otherwise, we could drop the argument and create our
55 * own scheduler object locally. Then we could be confident that it has no
56 * relevant state.
57 *
58 * We should improve this, possibly with an "enum pcmk__fail_type" pointer
59 * argument or similar.
60 */
61 int rc = pcmk_rc_ok;
62 xmlNode *status = NULL;
63
64 pcmk__assert((cib_object != NULL) && (*cib_object != NULL));
65
66 /* Without the CIB element, we can't get a schema to validate against, so
67 * report that separately from validation
68 */
69 if (!pcmk__xe_is(*cib_object, PCMK_XE_CIB)) {
70 out->err(out,
71 "Input is not a CIB (outermost element is %s not "
72 PCMK_XE_CIB ")",
73 pcmk__s((const char *) (*cib_object)->name, "unrecognizable"));
75 goto verify_done;
76 }
77
78 status = pcmk_find_cib_element(*cib_object, PCMK_XE_STATUS);
79 if (status == NULL) {
80 pcmk__xe_create(*cib_object, PCMK_XE_STATUS);
81 }
82
83 if (!pcmk__validate_xml(*cib_object, NULL,
84 (xmlRelaxNGValidityErrorFunc) out->err, out)) {
87 goto verify_done;
88 }
89
90 rc = pcmk__update_configured_schema(cib_object, false);
91 if (rc != pcmk_rc_ok) {
93 out->err(out, "The cluster will NOT be able to use this configuration.\n"
94 "Please manually update the configuration to conform to the %s syntax.",
96 goto verify_done;
97 }
98
99 /* Process the configuration to set pcmk__config_has_error and
100 * pcmk__config_has_warning.
101 *
102 * @TODO Some parts of the configuration are unpacked only when needed (for
103 * example, action configuration), so we aren't necessarily checking those.
104 */
105 if (*cib_object != NULL) {
106 scheduler->input = *cib_object;
107
109 if (status == NULL) {
110 // No status available, so do minimal checks
112 }
114
115 scheduler->input = NULL;
116 }
117
118verify_done:
121 pcmk__config_err("CIB did not pass schema validation");
122 } else if (pcmk__config_has_warning) {
124 }
125 return rc;
126}
127
128int
129pcmk_verify(xmlNodePtr *xml, const char *cib_source)
130{
132 pcmk__output_t *out = NULL;
133 int rc = pcmk_rc_ok;
134
135 xmlNode *cib_object = NULL;
136
137 rc = pcmk__xml_output_new(&out, xml);
138 if (rc != pcmk_rc_ok) {
139 return rc;
140 }
141
144
145 rc = pcmk__parse_cib(out, cib_source, &cib_object);
146 if (rc != pcmk_rc_ok) {
147 out->err(out, "Verification failed: %s", pcmk_rc_str(rc));
148 goto done;
149 }
150
152 if (scheduler == NULL) {
153 rc = errno;
154 out->err(out, "Couldn't allocate scheduler data: %s", pcmk_rc_str(rc));
155 goto done;
156 }
157
158 scheduler->priv->out = out;
159 rc = pcmk__verify(scheduler, out, &cib_object);
160
161done:
164 pcmk__xml_free(cib_object);
165 return rc;
166}
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
Definition cib_utils.c:863
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
Definition cib.c:172
#define pcmk__config_err(fmt...)
bool pcmk__config_has_error
Definition utils.c:43
bool pcmk__config_has_warning
Definition utils.c:44
pcmk_scheduler_t * scheduler
Control output from tools.
void pcmk__xml_output_finish(pcmk__output_t *out, crm_exit_t exit_status, xmlNodePtr *xml)
Definition output.c:273
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
Definition output.c:246
High Level API.
int pcmk__verify(pcmk_scheduler_t *scheduler, pcmk__output_t *out, xmlNode **cib_object)
Definition pcmk_verify.c:49
int pcmk_verify(xmlNodePtr *xml, const char *cib_source)
Verify that a CIB is error-free or output errors and warnings.
int pcmk__parse_cib(pcmk__output_t *out, const char *cib_source, xmlNodePtr *cib_object)
Definition pcmk_verify.c:26
void pcmk__register_lib_messages(pcmk__output_t *out)
void pcmk__schedule_actions(pcmk_scheduler_t *scheduler)
void pe__register_messages(pcmk__output_t *out)
Definition pe_output.c:3482
Function and executable result codes.
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:617
@ pcmk_rc_ok
Definition results.h:159
@ pcmk_rc_schema_validation
Definition results.h:138
@ pcmk_rc_unpack_error
Definition results.h:122
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
Definition results.c:820
#define pcmk__assert(expr)
Scheduler API.
void pcmk_free_scheduler(pcmk_scheduler_t *scheduler)
Free scheduler data.
Definition scheduler.c:193
pcmk_scheduler_t * pcmk_new_scheduler(void)
Create a new object to hold scheduler data.
Definition scheduler.c:32
#define pcmk__set_scheduler_flags(scheduler, flags_to_set)
@ pcmk__sched_no_counts
@ pcmk__sched_validate_only
bool pcmk__validate_xml(xmlNode *xml_blob, const char *validation, xmlRelaxNGValidityErrorFunc error_handler, void *error_handler_context)
Definition schemas.c:825
const char * pcmk__highest_schema_name(void)
Definition schemas.c:101
int pcmk__update_configured_schema(xmlNode **xml, bool to_logs)
Update XML from its configured schema to the latest major series.
Definition schemas.c:1257
This structure contains everything that makes up a single output formatter.
int int void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
pcmk__scheduler_private_t * priv
Definition scheduler.h:99
xmlNode * input
Definition scheduler.h:81
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
void pcmk__xml_free(xmlNode *xml)
Definition xml.c:816
xmlNode * pcmk__xml_read(const char *filename)
Definition xml_io.c:101
xmlNode * pcmk__xml_parse(const char *input)
Definition xml_io.c:167
#define PCMK_XE_CIB
Definition xml_names.h:79
#define PCMK_XE_STATUS
Definition xml_names.h:204