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