]> andersk Git - moira.git/blob - incremental/afs.c
Added some "retry" code upon failed prdb updates.
[moira.git] / incremental / afs.c
1 /* $Header$
2  *
3  * Do AFS incremental updates
4  *
5  * Copyright (C) 1989,1992 by the Massachusetts Institute of Technology
6  * for copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <sys/types.h>
11 #include <sys/file.h>
12 #include <strings.h>
13
14 #include <krb.h>
15 #include <moira.h>
16 #include <moira_site.h>
17
18 #include <afs/param.h>
19 #include <afs/cellconfig.h>
20 #include <afs/venus.h>
21 #include <afs/ptclient.h>
22 #include <afs/pterror.h>
23
24 #define STOP_FILE "/moira/afs/noafs"
25 #define TRY_PR 2
26
27 #define file_exists(file) (access((file), F_OK) == 0)
28
29 char *whoami;
30
31 main(argc, argv)
32 char **argv;
33 int argc;
34 {
35     int beforec, afterc, i;
36     char *table, **before, **after;
37     char buf[1024];
38
39     for (i = getdtablesize() - 1; i > 2; i--)
40       close(i);
41
42     table = argv[1];
43     beforec = atoi(argv[2]);
44     before = &argv[4];
45     afterc = atoi(argv[3]);
46     after = &argv[4 + beforec];
47     whoami = argv[0];
48
49     strcpy(buf, table);
50     strcat(buf, " (");
51     for (i = 0; i < beforec; i++) {
52         if (i > 0)
53           strcat(buf, ",");
54         strcat(buf, before[i]);
55     }
56     strcat(buf, ")->(");
57     for (i = 0; i < afterc; i++) {
58         if (i > 0)
59           strcat(buf, ",");
60         strcat(buf, after[i]);
61     }
62     strcat(buf, ")");
63 #ifdef DEBUG
64     printf("%s\n", buf);
65 #endif
66
67     initialize_sms_error_table();
68     initialize_krb_error_table();
69
70     for (i=0; file_exists(STOP_FILE); i++) {
71         if (i > 30) {
72             critical_alert("incremental",
73                            "AFS incremental failed (%s exists): %s",
74                            STOP_FILE, buf);
75             exit(1);
76         }
77         sleep(60);
78     }
79
80     if (!strcmp(table, "users")) {
81         do_user(before, beforec, after, afterc);
82     } else if (!strcmp(table, "list")) {
83         do_list(before, beforec, after, afterc);
84     } else if (!strcmp(table, "members")) {
85         do_member(before, beforec, after, afterc);
86     } else if (!strcmp(table, "filesys")) {
87         do_filesys(before, beforec, after, afterc);
88     } else if (!strcmp(table, "quota")) {
89         do_quota(before, beforec, after, afterc);
90     }
91     exit(0);
92 }
93
94
95 do_cmd(cmd)
96 char *cmd;
97 {
98     int success = 0, tries = 0;
99
100     while (success == 0 && tries < 2) {
101         if (tries++)
102             sleep(90);
103         com_err(whoami, 0, "Executing command: %s", cmd);
104         if (system(cmd) == 0)
105             success++;
106     }
107     if (!success)
108         critical_alert("incremental", "failed command: %s", cmd);
109 }
110
111
112 add_user_lists(ac, av, user)
113     int ac;
114     char *av[];
115     char *user;
116 {
117     if (atoi(av[5])) {
118         sleep(1);                               /* give ptserver some time */
119         edit_group(1, av[0], "USER", user);
120     }
121 }
122
123
124 do_user(before, beforec, after, afterc)
125 char **before;
126 int beforec;
127 char **after;
128 int afterc;
129 {
130     int astate, bstate, auid, buid, code, tries;
131     char hostname[64];
132     char *av[2];
133
134     auid = buid = astate = bstate = 0;
135     if (afterc > U_STATE) astate = atoi(after[U_STATE]);
136     if (beforec > U_STATE) bstate = atoi(before[U_STATE]);
137     if (afterc > U_UID) auid = atoi(after[U_UID]);
138     if (beforec > U_UID) buid = atoi(before[U_UID]);
139
140     /* We consider "half-registered" users to be active */
141     if (astate == 2) astate = 1;
142     if (bstate == 2) bstate = 1;
143
144     if (astate != 1 && bstate != 1)             /* inactive user */
145         return;
146
147     if (astate == bstate && auid == buid && 
148         !strcmp(before[U_NAME], after[U_NAME]))
149         /* No AFS related attributes have changed */
150         return;
151
152     code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
153     if (code) {
154         critical_alert("incremental", "Couldn't initialize libprot: %s",
155                        error_message(code));
156         return;
157     }
158     
159     if (astate == bstate) {
160         /* Only a modify has to be done */
161         tries = 0;
162         while (code=pr_ChangeEntry(before[U_NAME], after[U_NAME], auid, "")) {
163             if (++tries > TRY_PR)
164                 break;
165             if (code == UNOQUORUM) { sleep(90); continue; }
166             sleep(2);
167         }
168         if (code) {
169             critical_alert("incremental",
170                            "Couldn't change user %s (id %d) to %s (id %d): %s",
171                            before[U_NAME], buid, after[U_NAME], auid,
172                            error_message(code));
173         }
174         return;
175     }
176     if (bstate == 1) {
177         tries = 0;
178         while (code = pr_DeleteByID(buid)) {
179             if (++tries > TRY_PR)
180                 break;
181             if (code == UNOQUORUM) { sleep(90); continue; }
182             sleep(2);
183         }
184         if (code && code != PRNOENT) {
185             critical_alert("incremental",
186                            "Couldn't delete user %s (id %d): %s",
187                            before[U_NAME], buid, error_message(code));
188         }
189         return;
190     }
191     if (astate == 1) {
192         tries = 0;
193         while (code = pr_CreateUser(after[U_NAME], &auid)) {
194             if (++tries > TRY_PR)
195                 break;
196             if (code == UNOQUORUM) { sleep(90); continue; }
197             sleep(2);
198         }
199         if (code) {
200             critical_alert("incremental",
201                            "Couldn't create user %s (id %d): %s",
202                            after[U_NAME], auid, error_message(code));
203             return;
204         }
205
206         if (beforec) {
207             /* Reactivating a user; get his group list */
208             gethostname(hostname, sizeof(hostname));
209             code = mr_connect(hostname);
210             if (!code) code = mr_auth("afs.incr");
211             if (code) {
212                 critical_alert("incremental",
213                                "Error contacting Moira server to retrieve grouplist of user %s: %s",
214                                after[U_NAME], error_message(code));
215                 return;
216             }
217             av[0] = "ruser";
218             av[1] = after[U_NAME];
219             code = mr_query("get_lists_of_member", 2, av,
220                             add_user_lists, after[U_NAME]);
221             if (code)
222                 critical_alert("incremental",
223                                "Couldn't retrieve membership of user %s: %s",
224                                after[U_NAME], error_message(code));
225             mr_disconnect();
226         }
227         return;
228     }
229 }
230
231
232
233 do_list(before, beforec, after, afterc)
234 char **before;
235 int beforec;
236 char **after;
237 int afterc;
238 {
239     register int agid, bgid;
240     int ahide, bhide, tries;
241     long code, id;
242     char hostname[64];
243     char g1[PR_MAXNAMELEN], g2[PR_MAXNAMELEN];
244     char *av[2];
245
246     agid = bgid = 0;
247     if (beforec > L_GID && atoi(before[L_ACTIVE]) && atoi(before[L_GROUP])) {
248         bgid = atoi(before[L_GID]);
249         bhide = atoi(before[L_HIDDEN]);
250     }
251     if (afterc > L_GID && atoi(after[L_ACTIVE]) && atoi(after[L_GROUP])) {
252         agid = atoi(after[L_GID]);
253         ahide = atoi(after[L_HIDDEN]);
254     }
255
256     if (agid == 0 && bgid == 0)                 /* Not active groups */
257         return;
258
259     code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
260     if (code) {
261         critical_alert("incremental", "Couldn't initialize libprot: %s",
262                        error_message(code));
263         return;
264     }
265
266     if (agid && bgid) {
267         if (strcmp(after[L_NAME], before[L_NAME])) {
268             /* Only a modify is required */
269             strcpy(g1, "system:");
270             strcpy(g2, "system:");
271             strcat(g1, before[L_NAME]);
272             strcat(g2, after[L_NAME]);
273             tries = 0;
274             while (code = pr_ChangeEntry(g1, g2, -agid, "")) {
275                 if (++tries > TRY_PR)
276                     break;
277                 if (code == UNOQUORUM) { sleep(90); continue; }
278                 sleep(2);
279             }
280             if (code) {
281                 critical_alert("incremental",
282                                "Couldn't change group %s (id %d) to %s (id %d): %s",
283                                before[L_NAME], -bgid, after[L_NAME], -agid,
284                                error_message(code));
285             }
286         }
287         if (ahide != bhide) {
288             tries = 0;
289             while (code = pr_SetFieldsEntry
290                    (-agid, PR_SF_ALLBITS,
291                     (ahide ?PRP_STATUS_ANY :PRP_GROUP_DEFAULT)>>PRIVATE_SHIFT,
292                     0 /*ngroups*/, 0 /*nusers*/)) {
293                 if (++tries > TRY_PR)
294                     break;
295                 if (code == UNOQUORUM) { sleep(90); continue; }
296                 sleep(2);
297             }
298             if (code) {
299                 critical_alert("incremental",
300                                "Couldn't set flags of group %s: %s",
301                                after[L_NAME], error_message(code));
302             }
303         }
304         return;
305     }
306     if (bgid) {
307         tries = 0;
308         while (code = pr_DeleteByID(-bgid)) {
309             if (++tries > TRY_PR)
310                 break;
311             if (code == UNOQUORUM) { sleep(90); continue; }
312             sleep(2);
313         }
314         if (code && code != PRNOENT) {
315             critical_alert("incremental",
316                            "Couldn't delete group %s (id %d): %s",
317                            before[L_NAME], -bgid, error_message(code));
318         }
319         return;
320     }
321     if (agid) {
322         strcpy(g1, "system:");
323         strcat(g1, after[L_NAME]);
324         strcpy(g2, "system:administrators");
325         id = -agid;
326         tries = 0;
327         while (code = pr_CreateGroup(g1, g2, &id)) {
328             if (++tries > TRY_PR)
329                 break;
330             if (code == UNOQUORUM) { sleep(90); continue; }
331             sleep(2);
332         }
333         if (code) {
334             critical_alert("incremental",
335                            "Couldn't create group %s (id %d): %s",
336                            after[L_NAME], id, error_message(code));
337             return;
338         }
339         if (ahide) {
340             tries = 0;
341             while (code = pr_SetFieldsEntry
342                    (-agid, PR_SF_ALLBITS,
343                     (ahide ?PRP_STATUS_ANY :PRP_GROUP_DEFAULT)>>PRIVATE_SHIFT,
344                     0 /*ngroups*/, 0 /*nusers*/)) {
345                 if (++tries > TRY_PR)
346                     break;
347                 if (code == UNOQUORUM) { sleep(90); continue; }
348                 sleep(2);
349             }
350             if (code) {
351                 critical_alert("incremental",
352                                "Couldn't set flags of group %s: %s",
353                                after[L_NAME], error_message(code));
354             }
355         }
356
357         sleep(1);                               /* give ptserver some time */
358
359         /* We need to make sure the group is properly populated */
360         if (beforec < L_ACTIVE || atoi(before[L_ACTIVE]) == 0) return;
361
362         gethostname(hostname, sizeof(hostname));
363         code = mr_connect(hostname);
364         if (!code) code = mr_auth("afs.incr");
365         if (code) {
366             critical_alert("incremental",
367                            "Error contacting Moira server to resolve %s: %s",
368                            after[L_NAME], error_message(code));
369             return;
370         }
371         av[0] = "LIST";
372         av[1] = after[L_NAME];
373         get_members(2, av, after[L_NAME]);
374
375         mr_disconnect();
376         return;
377     }
378 }
379
380
381 do_member(before, beforec, after, afterc)
382 char **before;
383 int beforec;
384 char **after;
385 int afterc;
386 {
387     int code;
388     char *p;
389     
390     if ((beforec < 4 || !atoi(before[LM_END])) &&
391         (afterc < 4 || !atoi(after[LM_END])))
392         return;
393
394     code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
395     if (code) {
396         critical_alert("incremental", "Couldn't initialize libprot: %s",
397                        error_message(code));
398         return;
399     }
400
401     if (afterc) 
402         edit_group(1, after[LM_LIST], after[LM_TYPE], after[LM_MEMBER]);
403     if (beforec)
404         edit_group(0, before[LM_LIST], before[LM_TYPE], before[LM_MEMBER]);
405 }
406
407
408 get_members(ac, av, group)
409     int ac;
410     char *av[];
411     char *group;
412 {
413     int code=0;
414
415     if (strcmp(av[0], "LIST")) {
416         sleep(1);                               /* give ptserver some time */
417         edit_group(1, group, av[0], av[1]);
418     } else {
419         code = mr_query("get_end_members_of_list", 1, &av[1],
420                         get_members, group);
421         if (code)
422             critical_alert("incremental",
423                            "Couldn't retrieve full membership of %s: %s",
424                            group, error_message(code));
425     }
426     return code;
427 }
428
429
430 edit_group(op, group, type, member)
431     int op;
432     char *group;
433     char *type;
434     char *member;
435 {
436     char *p = 0;
437     char buf[PR_MAXNAMELEN];
438     int (*fn)();
439     int code;
440     int tries = 0;
441     static char local_realm[REALM_SZ+1] = "";
442     extern long pr_AddToGroup(), pr_RemoveUserFromGroup();
443
444     fn = op ? pr_AddToGroup : pr_RemoveUserFromGroup;
445     
446     /* The following KERBEROS code allows for the use of entities
447      * user@foreign_cell.
448      */
449     if (!local_realm[0])
450         krb_get_lrealm(local_realm, 1);
451     if (!strcmp(type, "KERBEROS")) {
452         p = index(member, '@');
453         if (p && !strcasecmp(p+1, local_realm))
454             *p = 0;
455     } else if (strcmp(type, "USER"))
456         return;                                 /* invalid type */
457
458     strcpy(buf, "system:");
459     strcat(buf, group);
460     sleep(1);                                   /* give ptserver some time */
461     while (code = (*fn)(member, buf)) {
462         if (++tries > TRY_PR)
463             break;
464         if (code == UNOQUORUM) { sleep(90); continue; }
465         sleep(2);
466     }
467     if (code) {
468         if (op==0 && code == PRNOENT) return;
469         if (op==1 && code == PRIDEXIST) return;
470         if (strcmp(type, "KERBEROS") || code != PRNOENT) {
471             critical_alert("incremental",
472                            "Couldn't %s %s %s %s: %s",
473                            op ? "add" : "remove", member,
474                            op ? "to" : "from", buf,
475                            error_message(code));
476         }
477     }
478     if (p) *p = '@';
479 }
480
481
482 do_filesys(before, beforec, after, afterc)
483 char **before;
484 int beforec;
485 char **after;
486 int afterc;
487 {
488     char cmd[1024];
489     
490     if (beforec < FS_CREATE) {
491         if (afterc < FS_CREATE || atoi(after[FS_CREATE])==0 ||
492             strcmp(after[FS_TYPE], "AFS"))
493             return;
494
495         /* new locker creation */
496         sprintf(cmd, "%s/perl -I%s %s/afs_create.pl %s %s %s %s %s %s",
497                 BIN_DIR, BIN_DIR, BIN_DIR,
498                 after[FS_NAME], after[FS_L_TYPE], after[FS_MACHINE],
499                 after[FS_PACK], after[FS_OWNER], after[FS_OWNERS]);
500         do_cmd(cmd);
501         return;
502     }
503
504     /* What do we do?  When do we use FS_CREATE?
505      * 
506      * TYPE change:  AFS->ERR, ERR->AFS: rename/unmount/remount
507      * LOCKERTYPE change: rename/remount
508      * PACK change: remount
509      * LABEL change: rename/remount
510      * Deletion: rename/unmount
511      */
512     if (afterc < FS_CREATE) {
513         if (!strcmp(before[FS_TYPE], "AFS"))
514             critical_alert("incremental",
515                            "Could not delete AFS filesystem %s: Operation not supported\n",
516                            before[FS_NAME]);
517         return;
518     }
519
520     if (!strcmp(after[FS_TYPE], "AFS")) {
521         if (strcmp(before[FS_TYPE], "AFS")) {
522             critical_alert("incremental",
523                            "Cannot convert %s to an AFS filesystem: Operation not supported\n",
524                            after[FS_NAME]);
525         } else {
526             critical_alert("incremental",
527                            "Cannot change attributes of AFS filesystem %s: Operation not supported\n",
528                            after[FS_NAME]);
529         }
530         return;
531     }
532 }
533
534
535 do_quota(before, beforec, after, afterc)
536 char **before;
537 int beforec;
538 char **after;
539 int afterc;
540 {
541     char cmd[1024];
542
543     if (afterc < Q_DIRECTORY || strcmp("ANY", after[Q_TYPE]) ||
544         strncmp("/afs/", after[Q_DIRECTORY], 5))
545         return;
546
547     sprintf(cmd, "%s/perl -I%s %s/afs_quota.pl %s %s",
548             BIN_DIR, BIN_DIR, BIN_DIR,
549             after[Q_DIRECTORY], after[Q_QUOTA]);
550     do_cmd(cmd);
551     return;
552 }
This page took 0.132591 seconds and 5 git commands to generate.