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