]> andersk Git - moira.git/blame_incremental - dcm/dcm.pc
use CODE=ANSI_C option to proc
[moira.git] / dcm / dcm.pc
... / ...
CommitLineData
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
14static char rcsid_dcm_c[] = "$Header$";
15#endif lint
16
17#include <signal.h>
18#include <stdio.h>
19#include <string.h>
20#include <time.h>
21#include <unistd.h>
22#include <sys/param.h>
23#include <sys/wait.h>
24
25#include <com_err.h>
26#include <gdb.h>
27#include <moira.h>
28#include <moira_site.h>
29
30EXEC SQL INCLUDE sqlca;
31EXEC SQL WHENEVER SQLERROR DO dbmserr();
32
33#define SQL_NO_MATCH 1403
34#define SOFT_FAIL(x) (((x) == MR_NO_MEM) || ((x) == MR_CANT_CONNECT) || ((x) == MR_CCONFIG) || ((x) == MR_DEADLOCK) || ((x) == MR_BUSY) || ((x) == MR_ABORT))
35
36char whobuf[256], *whoami = whobuf, *db = "moira";
37extern CONNECTION conn;
38
39int main(int argc, char **argv)
40{
41 int i;
42 EXEC SQL BEGIN DECLARE SECTION;
43 char buf[16], *name;
44 int enable;
45 EXEC SQL END DECLARE SECTION;
46 struct save_queue *sq;
47 int status;
48
49 if (strchr(argv[0], '/'))
50 strcpy(whoami, strrchr(argv[0], '/') + 1);
51 else strcpy(whoami, argv[0]);
52 umask(7);
53
54 setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
55 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
56
57 initialize_sms_error_table();
58 initialize_krb_error_table();
59
60 /* if services were specified on the command line, do just those ones */
61 if (argc > 1)
62 {
63 for (i = 1; i < argc; i++)
64 {
65 if (generate_service(argv[i], 1))
66 do_hosts(argv[i]);
67 }
68 exit(0);
69 }
70
71 /* if DCM is not enabled, exit after logging */
72 if (!access(NODCMFILE, F_OK))
73 {
74 printf("/etc/nodcm exists -- exiting\n");
75 exit(1);
76 }
77
78 EXEC SQL CONNECT :db IDENTIFIED BY :db;
79
80 EXEC SQL SELECT value INTO :enable FROM numvalues WHERE name = 'dcm_enable';
81 if (enable == 0)
82 {
83 printf("dcm_enable not set -- exiting\n");
84 exit(1);
85 }
86
87 /* fetch list of services */
88 EXEC SQL DECLARE csr_svc CURSOR FOR SELECT LOWER(name) FROM servers
89 WHERE enable = 1 AND harderror = 0 AND update_int > 0;
90 EXEC SQL OPEN csr_svc;
91 sq = sq_create();
92 while (1)
93 {
94 EXEC SQL FETCH csr_svc INTO :buf;
95 if (sqlca.sqlcode)
96 break;
97
98 sq_save_data(sq, strdup(strtrim(buf)));
99 }
100 EXEC SQL CLOSE csr_svc;
101 /* we will repeatedly open and close the db since it seems to get
102 upset if you keep it open across a fork */
103 EXEC SQL COMMIT RELEASE;
104
105 /* Now run through list */
106 while (sq_get_data(sq, &name))
107 {
108 if (generate_service(name, 0))
109 {
110 switch (fork())
111 {
112 case -1:
113 fprintf(stderr, "dcm: could not fork for service %s -- exiting",
114 name);
115 exit(1);
116 case 0:
117 sprintf(strchr(whoami, '\0'), " (%s)", name);
118 do_hosts(name);
119 com_err(whoami, 0, "exiting");
120 exit(0);
121 default:
122 break;
123 }
124 }
125 }
126
127 /* wait for children */
128 while (waitpid(0, &status, 0) > 0)
129 ;
130 com_err(whoami, 0, "exiting");
131}
132
133int generate_service(char *name, int force)
134{
135 EXEC SQL BEGIN DECLARE SECTION;
136 int interval, dfcheck, status;
137 time_t now;
138 char *errmsg;
139 EXEC SQL END DECLARE SECTION;
140 char dfgen_prog[64], dfgen_cmd[128];
141 struct sigaction action, prevaction;
142 int waits;
143
144 EXEC SQL CONNECT :db IDENTIFIED BY :db;
145
146 EXEC SQL SELECT update_int, dfcheck INTO :interval, :dfcheck
147 FROM servers WHERE name = UPPER(:name);
148 if (sqlca.sqlcode == SQL_NO_MATCH)
149 {
150 com_err(whoami, 0, "No such service `%s'", name);
151 EXEC SQL COMMIT RELEASE;
152 return 0;
153 }
154
155 time(&now);
156
157 if ((interval * 60 + dfcheck < now) || force)
158 {
159 sprintf(dfgen_prog, "%s/%s.gen", BIN_DIR, name);
160 if (access(dfgen_prog, F_OK) != 0)
161 {
162 com_err(whoami, 0, "prog %s doesn't exist", dfgen_prog);
163 EXEC SQL COMMIT RELEASE;
164 return 0;
165 }
166 sprintf(dfgen_cmd, "exec %s %s/%s.out", dfgen_prog, DCM_DIR, name);
167 com_err(whoami, 0, "running %s", dfgen_prog);
168
169 EXEC SQL UPDATE servers SET inprogress = 1
170 WHERE name = UPPER(:name);
171
172 action.sa_flags = 0;
173 sigemptyset(&action.sa_mask);
174 action.sa_handler = SIG_DFL;
175 sigaction(SIGCHLD, &action, &prevaction);
176 waits = system(dfgen_cmd);
177 sigaction(SIGCHLD, &prevaction, NULL);
178 if (WIFSIGNALED(waits))
179 {
180 status = MR_COREDUMP;
181 com_err(whoami, status, " %s exited on signal %d",
182 dfgen_prog, WTERMSIG(waits));
183 }
184 else if (WEXITSTATUS(waits))
185 {
186 /* extract the process's exit value */
187 status = WEXITSTATUS(waits) + ERROR_TABLE_BASE_sms;
188 if (status != MR_NO_CHANGE)
189 com_err(whoami, status, "in %s", dfgen_prog);
190 }
191 else
192 status = MR_SUCCESS;
193
194 if (status == MR_SUCCESS)
195 {
196 EXEC SQL UPDATE servers SET dfgen = :now, dfcheck = :now,
197 inprogress = 0 WHERE name = UPPER(:name);
198 EXEC SQL COMMIT RELEASE;
199 return 1;
200 }
201 else if (status == MR_NO_CHANGE)
202 {
203 EXEC SQL UPDATE servers SET dfcheck = :now, inprogress = 0
204 WHERE name = UPPER(:name);
205 }
206 else if (SOFT_FAIL(status))
207 {
208 errmsg = error_message(status);
209 EXEC SQL UPDATE servers SET errmsg = :errmsg, inprogress = 0
210 WHERE name = UPPER(:name);
211 }
212 else /* HARD_FAIL(status) */
213 {
214 errmsg = error_message(status);
215 EXEC SQL UPDATE servers SET dfcheck = :now, harderror = :status,
216 errmsg = :errmsg, inprogress = 0 WHERE name = UPPER(:name);
217 critical_alert("DCM", "DCM building config files for %s: %s",
218 name, errmsg);
219 }
220 }
221 EXEC SQL COMMIT RELEASE;
222 return 0;
223}
224
225void do_hosts(char *service)
226{
227 EXEC SQL BEGIN DECLARE SECTION;
228 char type[16], host[73], target[64], script[128], *errmsg;
229 int status = 0, mid, dfgen, replicated;
230 time_t now;
231 EXEC SQL END DECLARE SECTION;
232
233 time(&now);
234 gdb_init();
235
236 EXEC SQL CONNECT :db IDENTIFIED BY :db;
237
238 EXEC SQL SELECT dfgen, type, target_file, script
239 INTO :dfgen, :type, :target, :script
240 FROM servers WHERE name = UPPER(:service);
241 replicated = !strncmp(type, "REPLICAT", 8);
242
243 EXEC SQL DECLARE csr_hst1 CURSOR FOR
244 SELECT m.name FROM machine m, serverhosts sh
245 WHERE sh.service = UPPER(:service)
246 AND sh.enable = 1 AND sh.hosterror = 0
247 AND sh.lts < :dfgen AND sh.mach_id = m.mach_id
248 FOR UPDATE OF sh.inprogress, sh.hosterror, sh.hosterrmsg;
249 EXEC SQL OPEN csr_hst1;
250
251 while (1)
252 {
253 EXEC SQL FETCH csr_hst1 INTO :host;
254 if (sqlca.sqlcode == SQL_NO_MATCH)
255 break;
256
257 com_err(whoami, 0, "sending %s data to %s", service, strtrim(host));
258 EXEC SQL UPDATE serverhosts SET inprogress = 1
259 WHERE CURRENT OF csr_hst1;
260 status = dcm_send_file(service, host, strtrim(target));
261 if (status)
262 {
263 errmsg = error_message(status);
264 EXEC SQL UPDATE serverhosts SET hosterrmsg = :errmsg,
265 inprogress = 0 WHERE CURRENT OF csr_hst1;
266 if (!SOFT_FAIL(status))
267 {
268 EXEC SQL UPDATE serverhosts SET hosterror = :status
269 WHERE CURRENT OF csr_hst1;
270 critical_alert("DCM", "DCM updating %s:%s: %s",
271 service, host, errmsg);
272 }
273
274 if (replicated)
275 break;
276 }
277 }
278 EXEC SQL CLOSE csr_hst1;
279
280 if (status == MR_SUCCESS || !replicated)
281 {
282 EXEC SQL DECLARE csr_hst2 CURSOR FOR
283 SELECT m.name FROM machine m, serverhosts sh
284 WHERE sh.service = UPPER(:service) AND sh.inprogress = 1
285 AND sh.mach_id = m.mach_id
286 FOR UPDATE OF sh.hosterror, sh.hosterrmsg, sh.inprogress;
287 EXEC SQL OPEN csr_hst2;
288
289 while (1)
290 {
291 EXEC SQL FETCH csr_hst2 INTO :host;
292 if (sqlca.sqlcode == SQL_NO_MATCH)
293 break;
294
295 com_err(whoami, 0, "executing instructions on %s", strtrim(host));
296 status = dcm_execute(service, host, strtrim(script));
297 if (status)
298 {
299 errmsg = error_message(status);
300 EXEC SQL UPDATE serverhosts SET hosterrmsg = :errmsg,
301 inprogress = 0 WHERE CURRENT OF csr_hst2;
302 if (!SOFT_FAIL(status))
303 {
304 EXEC SQL UPDATE serverhosts SET hosterror = :status
305 WHERE CURRENT OF csr_hst2;
306 critical_alert("DCM", "DCM updating %s:%s: %s",
307 service, host, errmsg);
308 }
309
310 if (replicated)
311 {
312 /* We're giving up, so clear the inprogress flag on
313 any hosts in this service we haven't gotten to yet */
314 EXEC SQL UPDATE serverhosts SET inprogress = 0
315 WHERE service = UPPER(:service);
316 break;
317 }
318 }
319 else
320 {
321 EXEC SQL UPDATE serverhosts SET inprogress = 0, lts = :now
322 WHERE CURRENT OF csr_hst2;
323 }
324 }
325 EXEC SQL CLOSE csr_hst2;
326 }
327
328 if (status && replicated)
329 {
330 EXEC SQL UPDATE servers SET harderror = :status, errmsg = :errmsg
331 WHERE name = UPPER(:service);
332 }
333
334 EXEC SQL COMMIT RELEASE;
335}
336
337int dcm_send_file(char *service, char *host, char *target)
338{
339 char addr[256], data[MAXPATHLEN];
340 int code;
341
342 sprintf(addr, "%s:moira_update", host);
343 conn = start_server_connection(addr, "");
344 if (!conn || (connection_status(conn) == CON_STOPPED))
345 {
346 com_err(whoami, connection_errno(conn), "can't connect to %s", addr);
347 return MR_CANT_CONNECT;
348 }
349
350 code = send_auth(host);
351 if (code)
352 {
353 com_err(whoami, code, "authenticating to %s", host);
354 goto done;
355 }
356
357 sprintf(data, "%s/%s.out", DCM_DIR, service);
358 code = send_file(data, target, 1);
359 if (code == MR_UNKNOWN_PROC)
360 code = send_file(data, target, 0);
361 if (code)
362 com_err(whoami, code, "sending data to %s", host);
363
364done:
365 send_quit();
366 sever_connection(conn);
367 return code;
368}
369
370int dcm_execute(char *service, char *host, char *script)
371{
372 char addr[256], inst[MAXPATHLEN];
373 int code;
374
375 sprintf(addr, "%s:moira_update", host);
376 conn = start_server_connection(addr, "");
377 if (!conn || (connection_status(conn) == CON_STOPPED))
378 {
379 com_err(whoami, connection_errno(conn), "can't connect to %s", addr);
380 return MR_CANT_CONNECT;
381 }
382
383 code = send_auth(host);
384 if (code)
385 {
386 com_err(whoami, code, "authenticating to %s", host);
387 goto done;
388 }
389
390 sprintf(inst, "/tmp/moira-update.XXXXXX");
391 mktemp(inst);
392 code = send_file(script, inst, 0);
393 if (code)
394 {
395 com_err(whoami, code, "sending instructions to %s", host);
396 goto done;
397 }
398
399 code = execute(inst);
400 if (code)
401 com_err(whoami, code, "executing instructions on %s", host);
402
403done:
404 send_quit();
405 sever_connection(conn);
406 return code;
407}
408
409void dbmserr(void)
410{
411 EXEC SQL BEGIN DECLARE SECTION;
412 char err_msg[256];
413 EXEC SQL END DECLARE SECTION;
414 int bufsize = 256, msglength = 0;
415
416 sqlglm(err_msg, &bufsize, &msglength);
417 err_msg[msglength] = '\0';
418 com_err(whoami, 0, "Encountered SQL error:\n%s", err_msg);
419 com_err(whoami, 0, "exiting");
420 exit(1);
421}
This page took 0.037549 seconds and 5 git commands to generate.