]> andersk Git - moira.git/blame - dcm/dcm.pc
new status for GigE private subnets.
[moira.git] / dcm / dcm.pc
CommitLineData
7ac48069 1/* $Id$
2a2a3914 2 *
7ac48069 3 * The Data Control Manager for Moira.
2a2a3914 4 *
7ac48069 5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology.
6 * For copying and distribution information, see the file
7 * <mit-copyright.h>.
2a2a3914 8 */
9
7ac48069 10#include <mit-copyright.h>
11#include <moira.h>
12#include <moira_site.h>
dfaf9b68 13#include <moira_schema.h>
7ac48069 14#include "update.h"
15
16#include <sys/param.h>
17#include <sys/stat.h>
18#include <sys/wait.h>
2a2a3914 19
85330553 20#include <errno.h>
2a2a3914 21#include <signal.h>
22#include <stdio.h>
7ac48069 23#include <stdlib.h>
2a2a3914 24#include <string.h>
2a2a3914 25#include <unistd.h>
2a2a3914 26
2a2a3914 27EXEC SQL INCLUDE sqlca;
7ac48069 28void sqlglm(char *, unsigned int *, unsigned int *);
29
30RCSID("$Header$");
31
32int generate_service(char *name, int force);
33void do_hosts(char *service);
8afdb7c2 34int dcm_send_file(char *service, int type, char *host, char *target);
7ac48069 35int dcm_execute(char *service, char *host, char *script);
36void dbmserr(void);
37
2a2a3914 38#define SQL_NO_MATCH 1403
5eaef520 39#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 40
5eaef520 41char whobuf[256], *whoami = whobuf, *db = "moira";
2a2a3914 42
8afdb7c2 43enum { UNIQUE, DISTRIBUTED, REPLICATED };
44
5eaef520 45int main(int argc, char **argv)
2a2a3914 46{
5eaef520 47 int i;
48 EXEC SQL BEGIN DECLARE SECTION;
dfaf9b68 49 char buf[SERVERS_NAME_SIZE], *name;
5eaef520 50 int enable;
51 EXEC SQL END DECLARE SECTION;
52 struct save_queue *sq;
53 int status;
54
55 if (strchr(argv[0], '/'))
56 strcpy(whoami, strrchr(argv[0], '/') + 1);
57 else strcpy(whoami, argv[0]);
58 umask(7);
59
60 setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
61 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
62
63 initialize_sms_error_table();
64 initialize_krb_error_table();
65
66 /* if services were specified on the command line, do just those ones */
67 if (argc > 1)
68 {
69 for (i = 1; i < argc; i++)
70 {
71 if (generate_service(argv[i], 1))
72 do_hosts(argv[i]);
2a2a3914 73 }
5eaef520 74 exit(0);
2a2a3914 75 }
76
5eaef520 77 /* if DCM is not enabled, exit after logging */
78 if (!access(NODCMFILE, F_OK))
79 {
80 printf("/etc/nodcm exists -- exiting\n");
81 exit(1);
2a2a3914 82 }
5eaef520 83
ff20de45 84 EXEC SQL WHENEVER SQLERROR DO dbmserr();
85
5eaef520 86 EXEC SQL CONNECT :db IDENTIFIED BY :db;
87
88 EXEC SQL SELECT value INTO :enable FROM numvalues WHERE name = 'dcm_enable';
89 if (enable == 0)
90 {
91 printf("dcm_enable not set -- exiting\n");
92 exit(1);
2a2a3914 93 }
5eaef520 94
95 /* fetch list of services */
96 EXEC SQL DECLARE csr_svc CURSOR FOR SELECT LOWER(name) FROM servers
97 WHERE enable = 1 AND harderror = 0 AND update_int > 0;
98 EXEC SQL OPEN csr_svc;
99 sq = sq_create();
100 while (1)
101 {
102 EXEC SQL FETCH csr_svc INTO :buf;
103 if (sqlca.sqlcode)
104 break;
105
106 sq_save_data(sq, strdup(strtrim(buf)));
2a2a3914 107 }
5eaef520 108 EXEC SQL CLOSE csr_svc;
109 /* we will repeatedly open and close the db since it seems to get
110 upset if you keep it open across a fork */
111 EXEC SQL COMMIT RELEASE;
112
113 /* Now run through list */
114 while (sq_get_data(sq, &name))
115 {
116 if (generate_service(name, 0))
117 {
118 switch (fork())
119 {
120 case -1:
ff20de45 121 com_err(whoami, errno, "forking for service %s -- exiting",
5eaef520 122 name);
123 exit(1);
124 case 0:
ff20de45 125 sprintf(strchr(whoami, '\0'), " (%s:%ld)", name, (long)getpid());
5eaef520 126 do_hosts(name);
127 com_err(whoami, 0, "exiting");
128 exit(0);
129 default:
130 break;
2a2a3914 131 }
132 }
133 }
5eaef520 134
ff20de45 135 com_err(whoami, 0, "All files generated. Waiting for children to exit");
5eaef520 136 while (waitpid(0, &status, 0) > 0)
137 ;
138 com_err(whoami, 0, "exiting");
7ac48069 139 exit(0);
2a2a3914 140}
141
142int generate_service(char *name, int force)
143{
5eaef520 144 EXEC SQL BEGIN DECLARE SECTION;
145 int interval, dfcheck, status;
146 time_t now;
7ac48069 147 const char *errmsg;
5eaef520 148 EXEC SQL END DECLARE SECTION;
dfaf9b68 149 char dfgen_prog[MAXPATHLEN], dfgen_cmd[2 * MAXPATHLEN];
5eaef520 150 struct sigaction action, prevaction;
151 int waits;
152
153 EXEC SQL CONNECT :db IDENTIFIED BY :db;
154
dfaf9b68 155 EXEC SQL SELECT update_int, dfcheck INTO :interval, :dfcheck
5eaef520 156 FROM servers WHERE name = UPPER(:name);
157 if (sqlca.sqlcode == SQL_NO_MATCH)
158 {
159 com_err(whoami, 0, "No such service `%s'", name);
160 EXEC SQL COMMIT RELEASE;
161 return 0;
2a2a3914 162 }
5eaef520 163
164 time(&now);
165
166 if ((interval * 60 + dfcheck < now) || force)
167 {
168 sprintf(dfgen_prog, "%s/%s.gen", BIN_DIR, name);
169 if (access(dfgen_prog, F_OK) != 0)
170 {
171 com_err(whoami, 0, "prog %s doesn't exist", dfgen_prog);
172 EXEC SQL COMMIT RELEASE;
173 return 0;
2a2a3914 174 }
5eaef520 175 sprintf(dfgen_cmd, "exec %s %s/%s.out", dfgen_prog, DCM_DIR, name);
176 com_err(whoami, 0, "running %s", dfgen_prog);
177
ff20de45 178 EXEC SQL WHENEVER SQLERROR GOTO gen_cleanup;
179
5eaef520 180 EXEC SQL UPDATE servers SET inprogress = 1
181 WHERE name = UPPER(:name);
ff20de45 182 EXEC SQL COMMIT;
5eaef520 183
184 action.sa_flags = 0;
185 sigemptyset(&action.sa_mask);
186 action.sa_handler = SIG_DFL;
187 sigaction(SIGCHLD, &action, &prevaction);
188 waits = system(dfgen_cmd);
189 sigaction(SIGCHLD, &prevaction, NULL);
190 if (WIFSIGNALED(waits))
191 {
192 status = MR_COREDUMP;
193 com_err(whoami, status, " %s exited on signal %d",
194 dfgen_prog, WTERMSIG(waits));
195 }
196 else if (WEXITSTATUS(waits))
197 {
198 /* extract the process's exit value */
199 status = WEXITSTATUS(waits) + ERROR_TABLE_BASE_sms;
200 if (status != MR_NO_CHANGE)
201 com_err(whoami, status, "in %s", dfgen_prog);
202 }
203 else
204 status = MR_SUCCESS;
205
206 if (status == MR_SUCCESS)
207 {
208 EXEC SQL UPDATE servers SET dfgen = :now, dfcheck = :now,
209 inprogress = 0 WHERE name = UPPER(:name);
210 EXEC SQL COMMIT RELEASE;
211 return 1;
212 }
213 else if (status == MR_NO_CHANGE)
214 {
215 EXEC SQL UPDATE servers SET dfcheck = :now, inprogress = 0
216 WHERE name = UPPER(:name);
217 }
218 else if (SOFT_FAIL(status))
219 {
220 errmsg = error_message(status);
221 EXEC SQL UPDATE servers SET errmsg = :errmsg, inprogress = 0
222 WHERE name = UPPER(:name);
223 }
224 else /* HARD_FAIL(status) */
225 {
226 errmsg = error_message(status);
ff20de45 227 EXEC SQL UPDATE servers SET harderror = :status, errmsg = :errmsg,
228 inprogress = 0 WHERE name = UPPER(:name);
5eaef520 229 critical_alert("DCM", "DCM building config files for %s: %s",
230 name, errmsg);
2a2a3914 231 }
232 }
5eaef520 233 EXEC SQL COMMIT RELEASE;
234 return 0;
ff20de45 235
236gen_cleanup:
237 EXEC SQL WHENEVER SQLERROR DO dbmserr();
238 EXEC SQL UPDATE servers SET inprogress = 0, harderror = MR_INTERNAL,
239 errmsg = 'DBMS Internal Error' WHERE name = UPPER(:name);
240 dbmserr();
2a2a3914 241}
242
243void do_hosts(char *service)
244{
5eaef520 245 EXEC SQL BEGIN DECLARE SECTION;
8afdb7c2 246 char server_type[SERVERS_TYPE_SIZE], host[MACHINE_NAME_SIZE], *name;
dfaf9b68 247 char target[SERVERS_TARGET_FILE_SIZE], script[SERVERS_SCRIPT_SIZE];
7ac48069 248 const char *errmsg;
8afdb7c2 249 int status = 0, dfgen, type, mid;
5eaef520 250 time_t now;
251 EXEC SQL END DECLARE SECTION;
dae7c89e 252 struct save_queue *sq;
5eaef520 253
254 time(&now);
85330553 255 mr_init();
5eaef520 256
257 EXEC SQL CONNECT :db IDENTIFIED BY :db;
258
259 EXEC SQL SELECT dfgen, type, target_file, script
8afdb7c2 260 INTO :dfgen, :server_type, :target, :script
5eaef520 261 FROM servers WHERE name = UPPER(:service);
8afdb7c2 262 if (!strncmp(strtrim(server_type), "REPLICAT", 8))
263 type = REPLICATED;
264 else if (!strncmp(server_type, "DISTRIB", 8))
265 type = DISTRIBUTED;
266 else
267 type = UNIQUE;
ff20de45 268 strtrim(target);
269 strtrim(script);
5eaef520 270
271 EXEC SQL DECLARE csr_hst1 CURSOR FOR
ff20de45 272 SELECT m.name, m.mach_id FROM machine m, serverhosts sh
5eaef520 273 WHERE sh.service = UPPER(:service)
274 AND sh.enable = 1 AND sh.hosterror = 0
ff20de45 275 AND sh.lts < :dfgen AND sh.mach_id = m.mach_id;
5eaef520 276 EXEC SQL OPEN csr_hst1;
ff20de45 277 sq = sq_create();
5eaef520 278 while (1)
279 {
ff20de45 280 EXEC SQL FETCH csr_hst1 INTO :host, mid;
5eaef520 281 if (sqlca.sqlcode == SQL_NO_MATCH)
282 break;
283
ff20de45 284 sq_save_data(sq, strdup(strtrim(host)));
285 sq_save_data(sq, (void *)mid);
286 }
287 EXEC SQL CLOSE csr_hst1;
288
289 EXEC SQL WHENEVER SQLERROR GOTO host_cleanup;
290 while (sq_get_data(sq, &name))
291 {
292 sq_get_data(sq, &mid);
293 com_err(whoami, 0, "sending %s data to %s", service, name);
5eaef520 294 EXEC SQL UPDATE serverhosts SET inprogress = 1
ff20de45 295 WHERE service = UPPER(:service) AND mach_id = :mid;
296 EXEC SQL COMMIT;
8afdb7c2 297 status = dcm_send_file(service, type, name, target);
5eaef520 298 if (status)
299 {
300 errmsg = error_message(status);
301 EXEC SQL UPDATE serverhosts SET hosterrmsg = :errmsg,
ff20de45 302 inprogress = 0, success = 0, ltt = :now
dae7c89e 303 WHERE service = UPPER(:service) AND mach_id = :mid;
5eaef520 304 if (!SOFT_FAIL(status))
305 {
306 EXEC SQL UPDATE serverhosts SET hosterror = :status
dae7c89e 307 WHERE service = UPPER(:service) AND mach_id = :mid;
5eaef520 308 critical_alert("DCM", "DCM updating %s:%s: %s",
ff20de45 309 service, name, errmsg);
2a2a3914 310 }
ff20de45 311 EXEC SQL COMMIT;
5eaef520 312
8afdb7c2 313 if (type == REPLICATED)
5eaef520 314 break;
2a2a3914 315 }
316 }
ff20de45 317 sq_destroy(sq);
5eaef520 318
8afdb7c2 319 if (status == MR_SUCCESS || type != REPLICATED)
5eaef520 320 {
321 EXEC SQL DECLARE csr_hst2 CURSOR FOR
ff20de45 322 SELECT m.name, m.mach_id FROM machine m, serverhosts sh
5eaef520 323 WHERE sh.service = UPPER(:service) AND sh.inprogress = 1
d6ea2c57 324 AND sh.enable = 1 AND sh.hosterror = 0 AND sh.mach_id = m.mach_id;
5eaef520 325 EXEC SQL OPEN csr_hst2;
ff20de45 326 sq = sq_create();
5eaef520 327
328 while (1)
329 {
ff20de45 330 EXEC SQL FETCH csr_hst2 INTO :host, :mid;
5eaef520 331 if (sqlca.sqlcode == SQL_NO_MATCH)
332 break;
333
ff20de45 334 sq_save_data(sq, strdup(strtrim(host)));
335 sq_save_data(sq, (void *)mid);
336 }
337 EXEC SQL CLOSE csr_hst2;
338
339 while (sq_get_data(sq, &name))
340 {
341 sq_get_data(sq, &mid);
342
343 com_err(whoami, 0, "executing instructions on %s", name);
344 status = dcm_execute(service, name, script);
5eaef520 345 if (status)
346 {
347 errmsg = error_message(status);
348 EXEC SQL UPDATE serverhosts SET hosterrmsg = :errmsg,
ff20de45 349 inprogress = 0, success = 0, ltt = :now
350 WHERE service = UPPER(:service) AND mach_id = :mid;
5eaef520 351 if (!SOFT_FAIL(status))
352 {
353 EXEC SQL UPDATE serverhosts SET hosterror = :status
ff20de45 354 WHERE service = UPPER(:service) AND mach_id = :mid;
5eaef520 355 critical_alert("DCM", "DCM updating %s:%s: %s",
f272b0e1 356 service, name, errmsg);
2a2a3914 357 }
5eaef520 358
8afdb7c2 359 if (type == REPLICATED)
719f0386 360 break;
5eaef520 361 }
362 else
363 {
ff20de45 364 EXEC SQL UPDATE serverhosts SET inprogress = 0, ltt = :now,
365 lts = :now, success = 1 WHERE service = UPPER(:service)
366 AND mach_id = :mid;
2a2a3914 367 }
ff20de45 368 EXEC SQL COMMIT;
2a2a3914 369 }
5eaef520 370 EXEC SQL CLOSE csr_hst2;
2a2a3914 371 }
372
719f0386 373 if (type == REPLICATED)
374 {
375 /* Clear inprogress flag on any hosts we started but didn't
376 * finish.
377 */
378 EXEC SQL UPDATE serverhosts SET inprogress = 0
379 WHERE service = UPPER(:service);
380 }
381
ff20de45 382 EXEC SQL WHENEVER SQLERROR DO dbmserr();
8afdb7c2 383 if (status && !SOFT_FAIL(status) && type == REPLICATED)
5eaef520 384 {
385 EXEC SQL UPDATE servers SET harderror = :status, errmsg = :errmsg
386 WHERE name = UPPER(:service);
2a2a3914 387 }
388
5eaef520 389 EXEC SQL COMMIT RELEASE;
ff20de45 390 return;
391
392host_cleanup:
393 EXEC SQL UPDATE serverhosts SET inprogress = 0, success = 0, ltt = :now,
394 hosterror = MR_INTERNAL, hosterrmsg = 'DBMS Internal Error'
395 WHERE service = UPPER(:service) AND mach_id = :mid;
8afdb7c2 396 if (type == REPLICATED)
ff20de45 397 {
398 EXEC SQL UPDATE servers SET harderror = MR_INTERNAL,
399 errmsg = 'DBMS Internal Error' WHERE name = UPPER(:service);
400 }
2a2a3914 401}
402
8afdb7c2 403int dcm_send_file(char *service, int type, char *host, char *target)
2a2a3914 404{
85330553 405 char data[MAXPATHLEN];
406 int code, conn;
5eaef520 407
85330553 408 conn = mr_connect_internal(host, "moira_update");
409 if (!conn)
5eaef520 410 {
85330553 411 com_err(whoami, errno, "can't connect to %s", host);
5eaef520 412 return MR_CANT_CONNECT;
2a2a3914 413 }
414
96c29960 415 code = mr_send_auth(conn, host);
5eaef520 416 if (code)
417 {
418 com_err(whoami, code, "authenticating to %s", host);
419 goto done;
2a2a3914 420 }
421
8afdb7c2 422 if (type == DISTRIBUTED)
423 sprintf(data, "%s/%s/%s", DCM_DIR, service, host);
424 else
425 sprintf(data, "%s/%s.out", DCM_DIR, service);
96c29960 426 code = mr_send_file(conn, data, target, 0);
5eaef520 427 if (code)
428 com_err(whoami, code, "sending data to %s", host);
2a2a3914 429
430done:
96c29960 431 mr_send_quit(conn);
85330553 432 close(conn);
5eaef520 433 return code;
2a2a3914 434}
435
436int dcm_execute(char *service, char *host, char *script)
437{
85330553 438 char inst[MAXPATHLEN];
439 int code, conn;
5eaef520 440
85330553 441 conn = mr_connect_internal(host, "moira_update");
442 if (!conn)
5eaef520 443 {
85330553 444 com_err(whoami, errno, "can't connect to %s", host);
5eaef520 445 return MR_CANT_CONNECT;
2a2a3914 446 }
447
96c29960 448 code = mr_send_auth(conn, host);
5eaef520 449 if (code)
450 {
451 com_err(whoami, code, "authenticating to %s", host);
452 goto done;
2a2a3914 453 }
454
5eaef520 455 sprintf(inst, "/tmp/moira-update.XXXXXX");
456 mktemp(inst);
96c29960 457 code = mr_send_file(conn, script, inst, 0);
5eaef520 458 if (code)
459 {
460 com_err(whoami, code, "sending instructions to %s", host);
461 goto done;
2a2a3914 462 }
463
96c29960 464 code = mr_execute(conn, inst);
5eaef520 465 if (code)
466 com_err(whoami, code, "executing instructions on %s", host);
2a2a3914 467
468done:
96c29960 469 mr_send_quit(conn);
85330553 470 close(conn);
5eaef520 471 return code;
472}
2a2a3914 473
474void dbmserr(void)
475{
5eaef520 476 EXEC SQL BEGIN DECLARE SECTION;
477 char err_msg[256];
478 EXEC SQL END DECLARE SECTION;
479 int bufsize = 256, msglength = 0;
480
481 sqlglm(err_msg, &bufsize, &msglength);
482 err_msg[msglength] = '\0';
483 com_err(whoami, 0, "Encountered SQL error:\n%s", err_msg);
484 com_err(whoami, 0, "exiting");
485 exit(1);
2a2a3914 486}
This page took 0.132574 seconds and 5 git commands to generate.