This source file includes following definitions.
- rm_files
- clean_up_extra_schema_files
- write_extra_schema_file
- get_schema_files
- get_schema_files_complete
- remoted_request_cib_schema_files
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <ftw.h>
13 #include <unistd.h>
14 #include <sys/stat.h>
15
16 #include <crm/cib.h>
17 #include <crm/cib/cib_types.h>
18 #include <crm/cib/internal.h>
19 #include <crm/crm.h>
20 #include <crm/common/mainloop.h>
21 #include <crm/common/xml.h>
22
23 #include "pacemaker-execd.h"
24
25 static pid_t schema_fetch_pid = 0;
26
27 static int
28 rm_files(const char *pathname, const struct stat *sbuf, int type, struct FTW *ftwb)
29 {
30
31 if (ftwb->level == 0) {
32 return 0;
33 }
34
35 if (remove(pathname) != 0) {
36 int rc = errno;
37 crm_err("Could not remove %s: %s", pathname, pcmk_rc_str(rc));
38 return -1;
39 }
40
41 return 0;
42 }
43
44 static void
45 clean_up_extra_schema_files(void)
46 {
47 const char *remote_schema_dir = pcmk__remote_schema_dir();
48 int rc;
49
50
51 rc = mkdir(remote_schema_dir, 0755);
52
53 if (rc == 0) {
54
55 return;
56 }
57
58 if (errno == EEXIST) {
59
60
61
62
63 rc = nftw(remote_schema_dir, rm_files, 10, FTW_DEPTH|FTW_MOUNT|FTW_PHYS);
64
65 if (rc == 0) {
66
67 return;
68 }
69
70 if (errno == ENOTDIR) {
71
72 crm_err("%s already exists but is not a directory",
73 remote_schema_dir);
74 } else {
75 rc = errno;
76 crm_err("Could not clear directory %s: %s", remote_schema_dir,
77 pcmk_rc_str(rc));
78 }
79 } else {
80 rc = errno;
81 crm_err("Could not create directory for schemas: %s",
82 pcmk_rc_str(rc));
83 }
84 }
85
86 static void
87 write_extra_schema_file(xmlNode *xml, void *user_data)
88 {
89 const char *remote_schema_dir = pcmk__remote_schema_dir();
90 const char *file = NULL;
91 char *path = NULL;
92 int rc;
93
94 file = crm_element_value(xml, PCMK_XA_PATH);
95 if (file == NULL) {
96 crm_warn("No destination path given in schema request");
97 return;
98 }
99
100 path = crm_strdup_printf("%s/%s", remote_schema_dir, file);
101
102
103
104
105
106 for (xmlNode *child = xml->children; child != NULL; child = child->next) {
107 FILE *stream = NULL;
108
109 if (child->type != XML_CDATA_SECTION_NODE) {
110 continue;
111 }
112
113 stream = fopen(path, "w+");
114 if (stream == NULL) {
115 crm_warn("Could not write schema file %s: %s", path, strerror(errno));
116 } else {
117 rc = fprintf(stream, "%s", child->content);
118
119 if (rc < 0) {
120 crm_warn("Could not write schema file %s: %s", path, strerror(errno));
121 }
122
123 fclose(stream);
124 }
125
126 break;
127 }
128
129 free(path);
130 }
131
132 static void
133 get_schema_files(void)
134 {
135 int rc = pcmk_rc_ok;
136 cib_t *cib = NULL;
137 xmlNode *reply;
138
139 cib = cib_new();
140 if (cib == NULL) {
141 pcmk_common_cleanup();
142 _exit(CRM_EX_OSERR);
143 }
144
145 rc = cib->cmds->signon(cib, crm_system_name, cib_query);
146 rc = pcmk_legacy2rc(rc);
147 if (rc != pcmk_rc_ok) {
148 crm_err("Could not connect to the CIB manager: %s", pcmk_rc_str(rc));
149 pcmk_common_cleanup();
150 _exit(pcmk_rc2exitc(rc));
151 }
152
153 rc = cib->cmds->fetch_schemas(cib, &reply, pcmk__highest_schema_name(),
154 cib_sync_call);
155 if (rc != pcmk_ok) {
156 crm_err("Could not get schema files: %s", pcmk_strerror(rc));
157 rc = pcmk_legacy2rc(rc);
158
159 } else if (reply->children != NULL) {
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 pcmk__xpath_foreach_result(reply->doc, "//" PCMK__XE_FILE,
189 write_extra_schema_file, NULL);
190 }
191
192 pcmk__xml_free(reply);
193 cib__clean_up_connection(&cib);
194 pcmk_common_cleanup();
195 _exit(pcmk_rc2exitc(rc));
196 }
197
198
199
200
201 static void
202 get_schema_files_complete(mainloop_child_t *p, pid_t pid, int core, int signo, int exitcode)
203 {
204 const char *errmsg = "Could not load additional schema files";
205
206 if ((signo == 0) && (exitcode == 0)) {
207 const char *remote_schema_dir = pcmk__remote_schema_dir();
208
209
210
211
212 pcmk__load_schemas_from_dir(remote_schema_dir);
213 pcmk__sort_schemas();
214 crm_info("Fetching extra schema files completed successfully");
215
216 } else {
217 if (signo == 0) {
218 crm_err("%s: process %d exited %d", errmsg, (int) pid, exitcode);
219
220 } else {
221 crm_err("%s: process %d terminated with signal %d (%s)%s",
222 errmsg, (int) pid, signo, strsignal(signo),
223 (core? " and dumped core" : ""));
224 }
225
226
227
228
229
230
231
232 clean_up_extra_schema_files();
233 }
234 }
235
236 void
237 remoted_request_cib_schema_files(void)
238 {
239 pid_t pid;
240 int rc;
241
242
243
244
245
246 if (schema_fetch_pid != 0) {
247 if (mainloop_child_kill(schema_fetch_pid) == FALSE) {
248 crm_warn("Unable to kill pre-existing schema-fetch process");
249 return;
250 }
251
252 schema_fetch_pid = 0;
253 }
254
255
256
257
258
259
260
261
262
263 clean_up_extra_schema_files();
264 pcmk__schema_cleanup();
265 pcmk__schema_init();
266
267 crm_info("Fetching extra schema files from cluster");
268 pid = fork();
269
270 switch (pid) {
271 case -1: {
272 rc = errno;
273 crm_warn("Could not spawn process to get schema files: %s", pcmk_rc_str(rc));
274 break;
275 }
276
277 case 0:
278
279 get_schema_files();
280 break;
281
282 default:
283
284 schema_fetch_pid = pid;
285 mainloop_child_add_with_flags(pid, 5 * 60 * 1000, "schema-fetch", NULL,
286 mainloop_leave_pid_group,
287 get_schema_files_complete);
288 break;
289 }
290 }