This source file includes following definitions.
- pcmk__parse_cib
- pcmk__verify
- pcmk_verify
1
2
3
4
5
6
7
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>
14 #include <crm/common/scheduler.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
23 #include "libpacemaker_private.h"
24
25 int
26 pcmk__parse_cib(pcmk__output_t *out, const char *cib_source, xmlNodePtr *cib_object)
27 {
28
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
48 int
49 pcmk__verify(pcmk_scheduler_t *scheduler, pcmk__output_t *out,
50 xmlNode **cib_object)
51 {
52
53
54
55
56
57
58
59
60
61 int rc = pcmk_rc_ok;
62 xmlNode *status = NULL;
63
64 pcmk__assert((cib_object != NULL) && (*cib_object != NULL));
65
66
67
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"));
74 rc = pcmk_rc_schema_validation;
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)) {
85 pcmk__config_has_error = true;
86 rc = pcmk_rc_schema_validation;
87 goto verify_done;
88 }
89
90 rc = pcmk__update_configured_schema(cib_object, false);
91 if (rc != pcmk_rc_ok) {
92 pcmk__config_has_error = true;
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.",
95 pcmk__highest_schema_name());
96 goto verify_done;
97 }
98
99
100
101
102
103
104
105 if (*cib_object != NULL) {
106 scheduler->input = *cib_object;
107
108 pcmk__set_scheduler_flags(scheduler, pcmk__sched_no_counts);
109 if (status == NULL) {
110
111 pcmk__set_scheduler_flags(scheduler, pcmk__sched_validate_only);
112 }
113 pcmk__schedule_actions(scheduler);
114
115 scheduler->input = NULL;
116 }
117
118 verify_done:
119 if (pcmk__config_has_error) {
120 rc = pcmk_rc_schema_validation;
121 pcmk__config_err("CIB did not pass schema validation");
122 } else if (pcmk__config_has_warning) {
123 rc = pcmk_rc_schema_validation;
124 }
125 return rc;
126 }
127
128 int
129 pcmk_verify(xmlNodePtr *xml, const char *cib_source)
130 {
131 pcmk_scheduler_t *scheduler = NULL;
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
142 pe__register_messages(out);
143 pcmk__register_lib_messages(out);
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
151 scheduler = pcmk_new_scheduler();
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
161 done:
162 pcmk_free_scheduler(scheduler);
163 pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
164 pcmk__xml_free(cib_object);
165 return rc;
166 }