]>
Commit | Line | Data |
---|---|---|
846841f4 | 1 | /* |
2ce085d2 | 2 | * The Data Control Manager for MOIRA. |
846841f4 | 3 | * |
4 | * Copyright 1987, 1988 by the Massachusetts Institute of Technology. | |
5 | * For copying and distribution information, see the file | |
6 | * "mit-copyright.h". | |
7 | * | |
8 | * $Source$ | |
9 | * $Author$ | |
10 | * $Header$ | |
11 | */ | |
12 | ||
13 | #ifndef lint | |
14 | static char rcsid_dcm_c[] = "$Header$"; | |
15 | #endif lint | |
16 | ||
17 | #include <stdio.h> | |
18 | #include <update.h> | |
19 | #include <sys/file.h> | |
20 | #include <sys/time.h> | |
21 | #include <sys/wait.h> | |
15fa49b5 | 22 | #include <sys/stat.h> |
23 | #include <fcntl.h> | |
a1a0dadf | 24 | #include <signal.h> |
846841f4 | 25 | #include <ctype.h> |
2ce085d2 | 26 | #include <moira.h> |
27 | #include <moira_site.h> | |
846841f4 | 28 | #include "dcm.h" |
29 | #include "mit-copyright.h" | |
15fa49b5 | 30 | #include <unistd.h> |
846841f4 | 31 | |
32 | extern char *ctime(); | |
33 | extern char *getenv(); | |
34 | extern int log_flags; | |
35 | extern char *error_message(); | |
36 | char *itoa(); | |
37 | int gqval(); | |
38 | long time(); | |
39 | ||
40 | ||
41 | /* declared global so that we can get the current time from different places. */ | |
42 | struct timeval tv; | |
43 | ||
44 | ||
45 | main(argc, argv) | |
46 | int argc; | |
47 | char *argv[]; | |
48 | { | |
49 | int i; | |
50 | char **arg = argv; | |
51 | char *qargv[3]; | |
fe83b772 | 52 | char *s; |
846841f4 | 53 | int status; |
54 | ||
55 | whoami = argv[0]; | |
fe83b772 | 56 | s = getenv("DEBUG"); |
57 | dbg = s ? atoi(s) : 0; | |
846841f4 | 58 | umask(UMASK); |
59 | log_flags = 0; | |
15fa49b5 | 60 | |
61 | setvbuf(stderr, NULL, _IOLBF, BUFSIZ); | |
62 | setvbuf(stdout, NULL, _IOLBF, BUFSIZ); | |
846841f4 | 63 | |
64 | while(++arg - argv < argc) { | |
65 | if (**arg == '-') | |
66 | switch((*arg)[1]) { | |
67 | case 'd': | |
68 | dbg = atoi((*arg)[2]? *arg+2: *++arg); | |
69 | break; | |
70 | } | |
71 | } | |
72 | set_com_err_hook(dcm_com_err_hook); | |
73 | ||
74 | /* if /etc/nodcm exists, punt quietly. */ | |
185f76ce | 75 | if (!access(NODCMFILE, F_OK)) { |
846841f4 | 76 | exit(1); |
77 | } | |
78 | ||
2ce085d2 | 79 | if (status = mr_connect("")) { |
80 | com_err(whoami, status, " on mr_connect"); | |
846841f4 | 81 | leave("connect failed"); |
82 | } | |
83 | ||
2ce085d2 | 84 | if (status = mr_auth("dcm")) { |
846841f4 | 85 | com_err(whoami, status, " on \"authenticate\""); |
86 | leave("auth failed"); | |
87 | } | |
88 | ||
89 | /* if DCM is not enabled, exit after logging */ | |
90 | qargv[0] = "dcm_enable"; | |
2ce085d2 | 91 | if (status = mr_query("get_value", 1, qargv, gqval, &i)) { |
846841f4 | 92 | com_err(whoami, status, " check dcm_enable"); |
93 | leave("query failed"); | |
94 | } | |
95 | if (i == 0) { | |
96 | errno = 0; | |
97 | leave("dcm_enable not set"); | |
98 | } | |
99 | ||
100 | /* do it! */ | |
846841f4 | 101 | do_services(); |
102 | errno = 0; | |
103 | leave(""); | |
104 | } | |
105 | ||
106 | ||
107 | /* Used by the get_value query when checking for dcm_enable. */ | |
108 | ||
109 | gqval(argc, argv, hint) | |
110 | int argc; | |
111 | char **argv; | |
112 | int *hint; | |
113 | { | |
114 | *hint = atoi(argv[0]); | |
115 | return(UPCALL_STOP); | |
116 | } | |
117 | ||
118 | ||
119 | /* Used by qualified_get_server to make a list of servers to check */ | |
120 | ||
121 | qgetsv(argc, argv, sq) | |
122 | int argc; | |
123 | char **argv; | |
124 | struct save_queue *sq; | |
125 | { | |
126 | sq_save_data(sq, strsave(argv[0])); | |
127 | return(UPCALL_CONT); | |
128 | } | |
129 | ||
130 | ||
131 | /* Used by get_server_info to record all of the returned information */ | |
132 | ||
133 | getsvinfo(argc, argv, sserv) | |
134 | int argc; | |
135 | char **argv; | |
136 | struct service *sserv; | |
137 | { | |
138 | sserv->service = strsave(argv[0]); | |
139 | sserv->interval = atoi(argv[1]); | |
140 | sserv->target = strsave(argv[2]); | |
141 | sserv->script = strsave(argv[3]); | |
142 | sserv->dfgen = atoi(argv[4]); | |
143 | sserv->dfcheck = atoi(argv[5]); | |
144 | sserv->type = strsave(argv[6]); | |
145 | sserv->enable = atoi(argv[7]); | |
146 | sserv->inprogress = atoi(argv[8]); | |
147 | sserv->harderror = atoi(argv[9]); | |
148 | sserv->errmsg = strsave(argv[10]); | |
149 | return(UPCALL_STOP); | |
150 | } | |
151 | ||
152 | ||
153 | /* Scan the services and process any that need it. */ | |
154 | ||
155 | do_services() | |
156 | { | |
157 | char *qargv[6]; | |
158 | struct save_queue *sq, *sq_create(); | |
159 | char *service, dfgen_prog[64], dfgen_cmd[128]; | |
160 | struct service svc; | |
a1a0dadf | 161 | int status, lock_fd, ex, (*cstat)(); |
846841f4 | 162 | struct timezone tz; |
163 | register char *p; | |
15fa49b5 | 164 | int waits; |
165 | struct sigaction action, prevaction; | |
846841f4 | 166 | |
167 | if (dbg & DBG_VERBOSE) | |
168 | com_err(whoami, 0, "starting pass over services"); | |
169 | ||
170 | qargv[0] = "true"; | |
171 | qargv[1] = "dontcare"; | |
172 | qargv[2] = "false"; | |
173 | sq = sq_create(); | |
2ce085d2 | 174 | if (status = mr_query_with_retry("qualified_get_server", 3, qargv, |
0967ae03 | 175 | qgetsv, sq)) { |
846841f4 | 176 | com_err(whoami, status, " getting services"); |
177 | leave("query failed"); | |
178 | } | |
179 | while (sq_get_data(sq, &service)) { | |
180 | for (p = service; *p; p++) | |
181 | if (isupper(*p)) | |
182 | *p = tolower(*p); | |
183 | com_err(whoami, 0, "checking %s...", service); | |
184 | qargv[0] = service; | |
185f76ce | 185 | sprintf(dfgen_prog, "%s/%s.gen", BIN_DIR, service); |
846841f4 | 186 | if (!file_exists(dfgen_prog)) { |
187 | com_err(whoami, 0, "prog %s doesn't exist\n", dfgen_prog); | |
188 | free(service); | |
189 | continue; | |
190 | } | |
185f76ce | 191 | sprintf(dfgen_cmd, "exec %s %s/%s.out", |
192 | dfgen_prog, DCM_DIR, service); | |
846841f4 | 193 | gettimeofday(&tv, &tz); |
2ce085d2 | 194 | if (status = mr_query_with_retry("get_server_info", 1, qargv, |
0967ae03 | 195 | getsvinfo, &svc)) { |
4e5690ff | 196 | com_err(whoami, status, " getting service %s info, skipping to next service", service); |
197 | continue; | |
846841f4 | 198 | } |
199 | svc.service = strsave(service); | |
200 | qargv[0] = strsave(service); | |
201 | qargv[1] = itoa(svc.dfgen); | |
202 | qargv[2] = itoa(svc.dfcheck); | |
203 | qargv[3] = strsave("0"); | |
204 | qargv[4] = itoa(svc.harderror); | |
205 | qargv[5] = strsave(svc.errmsg); | |
206 | if (svc.interval != 0) { | |
207 | if (svc.interval * 60 + svc.dfcheck < tv.tv_sec) { | |
185f76ce | 208 | lock_fd = maybe_lock_update("@db@", service, 1); |
846841f4 | 209 | if (lock_fd < 0) |
210 | goto free_service; | |
211 | free(qargv[3]); | |
212 | free(qargv[4]); | |
213 | free(qargv[5]); | |
214 | qargv[3] = strsave("1"); | |
215 | qargv[4] = strsave("0"); | |
216 | qargv[5] = strsave(""); | |
2ce085d2 | 217 | status = mr_query_with_retry("set_server_internal_flags", 6, |
0967ae03 | 218 | qargv, scream, NULL); |
2ce085d2 | 219 | if (status != MR_SUCCESS) { |
846841f4 | 220 | com_err(whoami, status, " setting server state"); |
221 | goto free_service; | |
222 | } | |
223 | ||
224 | com_err(whoami, status, " running %s", dfgen_prog); | |
15fa49b5 | 225 | |
226 | action.sa_flags = 0; | |
227 | sigemptyset(&action.sa_mask); | |
228 | action.sa_handler = SIG_DFL; | |
229 | sigaction(SIGCHLD, &action, &prevaction); | |
230 | waits = system(dfgen_cmd); | |
231 | sigaction(SIGCHLD, &prevaction, NULL); | |
232 | if (WIFSIGNALED(waits)) { | |
95d47b7a | 233 | status = MR_COREDUMP; |
c9c95b8a | 234 | com_err(whoami, status, " %s exited on signal %d", |
15fa49b5 | 235 | dfgen_prog, WTERMSIG(waits)); |
236 | } else if (WEXITSTATUS(waits)) { | |
c9c95b8a | 237 | /* extract the process's exit value */ |
15fa49b5 | 238 | status = WEXITSTATUS(waits) + ERROR_TABLE_BASE_sms; |
846841f4 | 239 | com_err(whoami, status, " %s exited", dfgen_prog); |
240 | } | |
15fa49b5 | 241 | |
846841f4 | 242 | if (SOFT_FAIL(status)) { |
243 | free(qargv[5]); | |
244 | qargv[5] = strsave(error_message(status)); | |
2ce085d2 | 245 | } else if (status == MR_NO_CHANGE) { |
846841f4 | 246 | free(qargv[2]); |
247 | qargv[2] = itoa(tv.tv_sec); | |
248 | svc.dfcheck = tv.tv_sec; | |
2ce085d2 | 249 | } else if (status == MR_SUCCESS) { |
846841f4 | 250 | free(qargv[1]); |
251 | free(qargv[2]); | |
252 | qargv[1] = itoa(tv.tv_sec); | |
253 | qargv[2] = strsave(qargv[1]); | |
254 | svc.dfcheck = svc.dfgen = tv.tv_sec; | |
255 | } else { /* HARD_FAIL(status) */ | |
256 | free(qargv[2]); | |
257 | free(qargv[4]); | |
258 | free(qargv[5]); | |
259 | qargv[2] = itoa(tv.tv_sec); | |
260 | svc.dfcheck = tv.tv_sec; | |
261 | qargv[4] = itoa(status); | |
262 | qargv[5] = strsave(error_message(status)); | |
263 | critical_alert("DCM","DCM building config files for %s: %s", | |
264 | service, qargv[5]); | |
265 | } | |
266 | free_service: | |
267 | free(qargv[3]); | |
268 | qargv[3] = strsave("0"); | |
2ce085d2 | 269 | status = mr_query_with_retry("set_server_internal_flags", 6, |
0967ae03 | 270 | qargv, scream, NULL); |
271 | if (status) | |
272 | com_err(whoami, status, " setting service state"); | |
846841f4 | 273 | close(lock_fd); |
274 | free(qargv[0]); | |
275 | free(qargv[1]); | |
276 | free(qargv[2]); | |
277 | free(qargv[3]); | |
278 | free(qargv[4]); | |
279 | free(qargv[5]); | |
280 | } | |
281 | if (!strcmp(svc.type, "REPLICAT")) | |
282 | ex = 1; | |
283 | else | |
284 | ex = 0; | |
185f76ce | 285 | lock_fd = maybe_lock_update("@db@", service, ex); |
846841f4 | 286 | if (lock_fd >= 0) { |
287 | do_hosts(&svc); | |
288 | close(lock_fd); | |
289 | } | |
290 | } | |
291 | free(svc.service); | |
292 | free(svc.target); | |
293 | free(svc.script); | |
294 | free(svc.type); | |
295 | free(svc.errmsg); | |
296 | free(service); | |
297 | } | |
298 | sq_destroy(sq); | |
299 | } | |
300 | ||
301 | ||
302 | /* Used by qualified_get_server_host to make a list of hosts to check */ | |
303 | ||
304 | qgethost(argc, argv, sq) | |
305 | int argc; | |
306 | char **argv; | |
307 | struct save_queue *sq; | |
308 | { | |
309 | sq_save_data(sq, strsave(argv[1])); | |
310 | return(UPCALL_CONT); | |
311 | } | |
312 | ||
313 | ||
314 | /* Used by get_server_host_info to store all of the info about a host */ | |
315 | ||
316 | gethostinfo(argc, argv, shost) | |
317 | int argc; | |
318 | char **argv; | |
319 | struct svrhost *shost; | |
320 | { | |
321 | shost->service = strsave(argv[0]); | |
322 | shost->machine = strsave(argv[1]); | |
323 | shost->enable = atoi(argv[2]); | |
324 | shost->override = atoi(argv[3]); | |
325 | shost->success = atoi(argv[4]); | |
326 | shost->inprogress = atoi(argv[5]); | |
327 | shost->hosterror = atoi(argv[6]); | |
328 | shost->errmsg = strsave(argv[7]); | |
329 | shost->lasttry = atoi(argv[8]); | |
330 | shost->lastsuccess = atoi(argv[9]); | |
331 | shost->value1 = atoi(argv[10]); | |
332 | shost->value2 = atoi(argv[11]); | |
333 | shost->value3 = strsave(argv[12]); | |
334 | return(UPCALL_STOP); | |
335 | } | |
336 | ||
337 | ||
338 | /* Scans all of the hosts for a particular service, and processes them. */ | |
339 | ||
340 | do_hosts(svc) | |
341 | struct service *svc; | |
342 | { | |
343 | char *argv[9], *machine; | |
344 | int status, lock_fd; | |
345 | struct save_queue *sq; | |
346 | struct svrhost shost; | |
347 | ||
348 | sq = sq_create(); | |
349 | argv[0] = svc->service; | |
350 | argv[1] = "TRUE"; | |
351 | argv[2] = argv[3] = argv[4] = "DONTCARE"; | |
352 | argv[5] = "FALSE"; | |
2ce085d2 | 353 | status = mr_query_with_retry("qualified_get_server_host", 6, argv, |
0967ae03 | 354 | qgethost, sq); |
2ce085d2 | 355 | if (status == MR_NO_MATCH) { |
846841f4 | 356 | return; |
357 | } else if (status) { | |
358 | com_err(whoami, status, " getting server_hosts for %s", svc->service); | |
359 | return; | |
360 | } | |
361 | while (sq_get_data(sq, &machine)) { | |
362 | if (dbg & DBG_TRACE) | |
363 | com_err(whoami, 0, "checking %s...", machine); | |
364 | argv[1] = machine; | |
2ce085d2 | 365 | status = mr_query_with_retry("get_server_host_info", 2, argv, |
0967ae03 | 366 | gethostinfo, &shost); |
846841f4 | 367 | if (status) { |
368 | com_err(whoami,status, " getting server_host_info for %s", machine); | |
369 | goto free_mach; | |
370 | } | |
371 | if (!shost.enable || shost.hosterror || | |
4112693b | 372 | (shost.success && !shost.override && |
6899dfbe | 373 | shost.lastsuccess >= svc->dfgen)) { |
846841f4 | 374 | if (dbg & DBG_TRACE) |
375 | com_err(whoami, 0, "not updating %s:%s", svc->service, machine); | |
376 | goto free_mach; | |
377 | } | |
062079b1 | 378 | |
185f76ce | 379 | lock_fd = maybe_lock_update(machine, svc->service, 1); |
062079b1 | 380 | if (lock_fd < 0) |
381 | goto free_mach; | |
382 | argv[0] = svc->service; | |
383 | argv[1] = machine; | |
384 | argv[2] = argv[3] = argv[5] = "0"; | |
385 | argv[4] = "1"; | |
386 | argv[6] = strsave(""); | |
387 | argv[7] = itoa(tv.tv_sec); | |
388 | argv[8] = itoa(shost.lastsuccess); | |
2ce085d2 | 389 | status = mr_query_with_retry("set_server_host_internal", 9, argv, |
0967ae03 | 390 | scream, NULL); |
2ce085d2 | 391 | if (status != MR_SUCCESS) { |
062079b1 | 392 | com_err(whoami,status," while setting internal state for %s:%s", |
393 | svc->service, machine); | |
394 | goto free_mach; | |
395 | } | |
2ce085d2 | 396 | status = mr_update_server(svc->service, machine, svc->target, |
062079b1 | 397 | svc->script); |
2ce085d2 | 398 | if (status == MR_SUCCESS) { |
67852ff1 | 399 | argv[2] = argv[4] = "0"; |
062079b1 | 400 | argv[3] = "1"; |
401 | free(argv[8]); | |
402 | argv[8] = itoa(tv.tv_sec); | |
403 | } else if (SOFT_FAIL(status)) { | |
67852ff1 | 404 | argv[4] = "0"; |
062079b1 | 405 | free(argv[6]); |
406 | argv[6] = strsave(error_message(status)); | |
407 | } else { /* HARD_FAIL */ | |
408 | argv[2] = itoa(shost.override); | |
67852ff1 | 409 | argv[4] = "0"; |
062079b1 | 410 | argv[5] = itoa(status); |
411 | free(argv[6]); | |
412 | argv[6] = strsave(error_message(status)); | |
413 | critical_alert("DCM", "DCM updating %s:%s: %s", | |
414 | machine, svc->service, argv[6]); | |
415 | if (!strcmp(svc->type, "REPLICAT")) { | |
416 | char *qargv[6]; | |
417 | ||
418 | svc->harderror = status; | |
419 | svc->errmsg = strsave(argv[6]); | |
420 | qargv[0] = strsave(svc->service); | |
421 | qargv[1] = itoa(svc->dfgen); | |
422 | qargv[2] = itoa(svc->dfcheck); | |
423 | qargv[3] = strsave("0"); | |
424 | qargv[4] = itoa(svc->harderror); | |
425 | qargv[5] = strsave(svc->errmsg); | |
2ce085d2 | 426 | status = mr_query_with_retry("set_server_internal_flags", |
0967ae03 | 427 | 6, qargv, scream, NULL); |
428 | if (status) | |
429 | com_err(whoami, status, " setting service state again"); | |
062079b1 | 430 | free(qargv[0]); |
431 | free(qargv[1]); | |
432 | free(qargv[2]); | |
433 | free(qargv[3]); | |
434 | free(qargv[4]); | |
435 | free(qargv[5]); | |
436 | close(lock_fd); | |
2ce085d2 | 437 | status = mr_query_with_retry("set_server_host_internal", |
0967ae03 | 438 | 9, argv,scream,NULL); |
67852ff1 | 439 | free(argv[2]); |
440 | free(argv[5]); | |
0967ae03 | 441 | if (status) |
442 | com_err(whoami, status, " setting host state again"); | |
062079b1 | 443 | return(-1); |
846841f4 | 444 | } |
846841f4 | 445 | } |
062079b1 | 446 | close(lock_fd); |
2ce085d2 | 447 | status = mr_query_with_retry("set_server_host_internal", 9, argv, |
0967ae03 | 448 | scream, NULL); |
449 | if (status) | |
450 | com_err(whoami, status, " setting host state again"); | |
67852ff1 | 451 | /* free(argv[2]); |
452 | free(argv[5]); */ | |
846841f4 | 453 | free_mach: |
454 | free(machine); | |
455 | close(lock_fd); | |
456 | } | |
457 | return(0); | |
458 | } |