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