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 struct stat sb;
49 int rc;
50
51 rc = stat(remote_schema_dir, &sb);
52
53 if (rc == -1) {
54 if (errno == ENOENT) {
55
56 if (mkdir(remote_schema_dir, 0755) != 0) {
57 rc = errno;
58 crm_err("Could not create directory for schemas: %s",
59 pcmk_rc_str(rc));
60 }
61
62 } else {
63 rc = errno;
64 crm_err("Could not create directory for schemas: %s",
65 pcmk_rc_str(rc));
66 }
67
68 } else if (!S_ISDIR(sb.st_mode)) {
69
70
71
72 crm_err("%s already exists but is not a directory", remote_schema_dir);
73
74 } else {
75
76
77
78 rc = nftw(remote_schema_dir, rm_files, 10, FTW_DEPTH|FTW_MOUNT|FTW_PHYS);
79
80 if (rc != 0) {
81 crm_err("Could not remove %s: %s", remote_schema_dir, pcmk_rc_str(rc));
82 }
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 crm_foreach_xpath_result(reply, "//" PCMK_XA_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 }