]> andersk Git - moira.git/blame - dcm/dcm.pc
Change `SMS' to `Moira' where possible.
[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
5eaef520 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))
2a2a3914 35
5eaef520 36char whobuf[256], *whoami = whobuf, *db = "moira";
2a2a3914 37extern CONNECTION conn;
38
5eaef520 39int main(int argc, char **argv)
2a2a3914 40{
5eaef520 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]);
2a2a3914 67 }
5eaef520 68 exit(0);
2a2a3914 69 }
70
5eaef520 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);
2a2a3914 76 }
5eaef520 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);
2a2a3914 85 }
5eaef520 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)));
2a2a3914 99 }
5eaef520 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;
2a2a3914 123 }
124 }
125 }
5eaef520 126
127 /* wait for children */
128 while (waitpid(0, &status, 0) > 0)
129 ;
130 com_err(whoami, 0, "exiting");
2a2a3914 131}
132
133int generate_service(char *name, int force)
134{
5eaef520 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;
2a2a3914 153 }
5eaef520 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;
2a2a3914 165 }
5eaef520 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);
2a2a3914 219 }
220 }
5eaef520 221 EXEC SQL COMMIT RELEASE;
222 return 0;
2a2a3914 223}
224
225void do_hosts(char *service)
226{
5eaef520 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);
2a2a3914 272 }
5eaef520 273
274 if (replicated)
275 break;
2a2a3914 276 }
277 }
5eaef520 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);
2a2a3914 308 }
5eaef520 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;
2a2a3914 317 }
5eaef520 318 }
319 else
320 {
321 EXEC SQL UPDATE serverhosts SET inprogress = 0, lts = :now
322 WHERE CURRENT OF csr_hst2;
2a2a3914 323 }
324 }
5eaef520 325 EXEC SQL CLOSE csr_hst2;
2a2a3914 326 }
327
5eaef520 328 if (status && replicated)
329 {
330 EXEC SQL UPDATE servers SET harderror = :status, errmsg = :errmsg
331 WHERE name = UPPER(:service);
2a2a3914 332 }
333
5eaef520 334 EXEC SQL COMMIT RELEASE;
2a2a3914 335}
336
337int dcm_send_file(char *service, char *host, char *target)
338{
5eaef520 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;
2a2a3914 348 }
349
5eaef520 350 code = send_auth(host);
351 if (code)
352 {
353 com_err(whoami, code, "authenticating to %s", host);
354 goto done;
2a2a3914 355 }
356
5eaef520 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);
2a2a3914 363
364done:
5eaef520 365 send_quit();
366 sever_connection(conn);
367 return code;
2a2a3914 368}
369
370int dcm_execute(char *service, char *host, char *script)
371{
5eaef520 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;
2a2a3914 381 }
382
5eaef520 383 code = send_auth(host);
384 if (code)
385 {
386 com_err(whoami, code, "authenticating to %s", host);
387 goto done;
2a2a3914 388 }
389
5eaef520 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;
2a2a3914 397 }
398
5eaef520 399 code = execute(inst);
400 if (code)
401 com_err(whoami, code, "executing instructions on %s", host);
2a2a3914 402
403done:
5eaef520 404 send_quit();
405 sever_connection(conn);
406 return code;
407}
2a2a3914 408
409void dbmserr(void)
410{
5eaef520 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);
2a2a3914 421}
This page took 0.107201 seconds and 5 git commands to generate.