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 _exit(ENOTCONN);
142 }
143
144 rc = cib->cmds->signon(cib, crm_system_name, cib_query);
145 if (rc != pcmk_ok) {
146 crm_err("Could not connect to the CIB manager: %s", pcmk_strerror(rc));
147 _exit(pcmk_rc2exitc(rc));
148 }
149
150 rc = cib->cmds->fetch_schemas(cib, &reply, pcmk__highest_schema_name(),
151 cib_sync_call);
152 if (rc != pcmk_ok) {
153 crm_err("Could not get schema files: %s", pcmk_strerror(rc));
154 rc = pcmk_legacy2rc(rc);
155
156 } else if (reply->children != NULL) {
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 crm_foreach_xpath_result(reply, "//" PCMK_XA_FILE,
186 write_extra_schema_file, NULL);
187 }
188
189 free_xml(reply);
190 cib__clean_up_connection(&cib);
191 _exit(pcmk_rc2exitc(rc));
192 }
193
194
195
196
197 static void
198 get_schema_files_complete(mainloop_child_t *p, pid_t pid, int core, int signo, int exitcode)
199 {
200 const char *errmsg = "Could not load additional schema files";
201
202 if ((signo == 0) && (exitcode == 0)) {
203 const char *remote_schema_dir = pcmk__remote_schema_dir();
204
205
206
207
208 pcmk__load_schemas_from_dir(remote_schema_dir);
209 pcmk__sort_schemas();
210 crm_info("Fetching extra schema files completed successfully");
211
212 } else {
213 if (signo == 0) {
214 crm_err("%s: process %d exited %d", errmsg, (int) pid, exitcode);
215
216 } else {
217 crm_err("%s: process %d terminated with signal %d (%s)%s",
218 errmsg, (int) pid, signo, strsignal(signo),
219 (core? " and dumped core" : ""));
220 }
221
222
223
224
225
226
227
228 clean_up_extra_schema_files();
229 }
230 }
231
232 void
233 remoted_request_cib_schema_files(void)
234 {
235 pid_t pid;
236 int rc;
237
238
239
240
241
242 if (schema_fetch_pid != 0) {
243 if (mainloop_child_kill(schema_fetch_pid) == FALSE) {
244 crm_warn("Unable to kill pre-existing schema-fetch process");
245 return;
246 }
247
248 schema_fetch_pid = 0;
249 }
250
251
252
253
254
255
256
257
258
259 clean_up_extra_schema_files();
260 crm_schema_cleanup();
261 crm_schema_init();
262
263 crm_info("Fetching extra schema files from cluster");
264 pid = fork();
265
266 switch (pid) {
267 case -1: {
268 rc = errno;
269 crm_warn("Could not spawn process to get schema files: %s", pcmk_rc_str(rc));
270 break;
271 }
272
273 case 0:
274
275 get_schema_files();
276 break;
277
278 default:
279
280 schema_fetch_pid = pid;
281 mainloop_child_add_with_flags(pid, 5 * 60 * 1000, "schema-fetch", NULL,
282 mainloop_leave_pid_group,
283 get_schema_files_complete);
284 break;
285 }
286 }