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