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