]> andersk Git - moira.git/blobdiff - incremental/afs.c
Added user status information as argument #10 to the incremental program
[moira.git] / incremental / afs.c
index 28dffee30ae009b5b1eb2abe0e09bddc60d4bc1d..ac881bd590245b2264a5dc99c3f03da2b78aef96 100644 (file)
@@ -41,7 +41,8 @@ int do_quota();
 /* Support stub routines */
 int run_cmd();
 int add_user_lists();
-int get_members();
+int add_list_members();
+int check_user();
 int edit_group();
 int pr_try();
 int check_afs();
@@ -57,6 +58,15 @@ extern long pr_AddToGroup();
 extern long pr_RemoveUserFromGroup();
 
 static char tbl_buf[1024];
+static struct member {
+       int op;
+       char list[33];
+       char type[9];
+       char member[129];
+       struct member *next;
+} *member_head = 0;
+
+static int mr_connections=0;
 
 main(argc, argv)
 char **argv;
@@ -68,12 +78,13 @@ int argc;
     for (i = getdtablesize() - 1; i > 2; i--)
       close(i);
 
+    whoami = ((whoami = rindex(argv[0], '/')) ? whoami++ : argv[0]);
+
     table = argv[1];
     beforec = atoi(argv[2]);
     before = &argv[4];
     afterc = atoi(argv[3]);
     after = &argv[4 + beforec];
-    whoami = argv[0];
 
     setlinebuf(stdout);
 
@@ -92,7 +103,7 @@ int argc;
     }
     strcat(tbl_buf, ")");
 #ifdef DEBUG
-    printf("%s\n", tbl_buf);
+    com_err(whoami, 0, "%s", tbl_buf);
 #endif
 
     initialize_sms_error_table();
@@ -120,7 +131,6 @@ char **after;
 int afterc;
 {
     int astate, bstate, auid, buid, code;
-    char hostname[64];
     char *av[2];
 
     auid = buid = astate = bstate = 0;
@@ -143,6 +153,9 @@ int afterc;
 
     if (astate == bstate) {
        /* Only a modify has to be done */
+       com_err(whoami, 0, "Changing user %s (uid %d) to %s (uid %d)",
+              before[U_NAME], buid, after[U_NAME], auid);
+
        code = pr_try(pr_ChangeEntry, before[U_NAME], after[U_NAME], auid, "");
        if (code) {
            critical_alert("incremental",
@@ -153,6 +166,9 @@ int afterc;
        return;
     }
     if (bstate == 1) {
+       com_err(whoami, 0, "Deleting user %s (uid %d)",
+              before[U_NAME], buid);
+
        code = pr_try(pr_DeleteByID, buid);
        if (code && code != PRNOENT) {
            critical_alert("incremental",
@@ -162,6 +178,10 @@ int afterc;
        return;
     }
     if (astate == 1) {
+       com_err(whoami, 0, "%s user %s (uid %d)",
+              ((bstate != 0) ? "Reactivating" : "Creating"),
+              after[U_NAME], auid);
+       
        code = pr_try(pr_CreateUser, after[U_NAME], &auid);
        if (code) {
            critical_alert("incremental",
@@ -170,11 +190,9 @@ int afterc;
            return;
        }
 
-       if (beforec) {
+       if (bstate != 0) {
            /* Reactivating a user; get his group list */
-           gethostname(hostname, sizeof(hostname));
-           code = mr_connect(hostname);
-           if (!code) code = mr_auth("afs.incr");
+           code = moira_connect();
            if (code) {
                critical_alert("incremental",
                               "Error contacting Moira server to retrieve grouplist of user %s: %s",
@@ -189,7 +207,7 @@ int afterc;
                critical_alert("incremental",
                               "Couldn't retrieve membership of user %s: %s",
                               after[U_NAME], error_message(code));
-           mr_disconnect();
+           moira_disconnect();
        }
        return;
     }
@@ -205,7 +223,6 @@ int afterc;
     register int agid, bgid;
     int ahide, bhide;
     long code, id;
-    char hostname[64];
     char g1[PR_MAXNAMELEN], g2[PR_MAXNAMELEN];
     char *av[2];
 
@@ -229,6 +246,10 @@ int afterc;
            strcpy(g2, "system:");
            strcat(g1, before[L_NAME]);
            strcat(g2, after[L_NAME]);
+
+           com_err(whoami, 0, "Changing group %s (gid %d) to %s (gid %d)",
+                  before[L_NAME], bgid, after[L_NAME], agid);
+
            code = pr_try(pr_ChangeEntry, g1, g2, -agid, "");
            if (code) {
                critical_alert("incremental",
@@ -238,6 +259,9 @@ int afterc;
            }
        }
        if (ahide != bhide) {
+           com_err(whoami, 0, "Making group %s (gid %d) %s",
+                  after[L_NAME], agid,
+                  (ahide ? "hidden" : "visible"));
            code = pr_try(pr_SetFieldsEntry, -agid, PR_SF_ALLBITS,
                          (ahide ? PRP_STATUS_ANY : PRP_GROUP_DEFAULT) >>PRIVATE_SHIFT,
                          0 /*ngroups*/, 0 /*nusers*/);
@@ -250,6 +274,8 @@ int afterc;
        return;
     }
     if (bgid) {
+       com_err(whoami, 0, "Deleting group %s (gid %d)",
+              before[L_NAME], bgid);
        code = pr_try(pr_DeleteByID, -bgid);
        if (code && code != PRNOENT) {
            critical_alert("incremental",
@@ -263,6 +289,8 @@ int afterc;
        strcat(g1, after[L_NAME]);
        strcpy(g2, "system:administrators");
        id = -agid;
+       com_err(whoami, 0, "Creating %s group %s (gid %d)",
+              (ahide ? "hidden" : "visible"), after[L_NAME], agid);
        code = pr_try(pr_CreateGroup, g1, g2, &id);
        if (code) {
            critical_alert("incremental",
@@ -282,27 +310,37 @@ int afterc;
        }
 
        /* We need to make sure the group is properly populated */
-       if (beforec < L_ACTIVE || atoi(before[L_ACTIVE]) == 0) return;
+       if (beforec < L_ACTIVE) return;
 
-       gethostname(hostname, sizeof(hostname));
-       code = mr_connect(hostname);
-       if (!code) code = mr_auth("afs.incr");
+       code = moira_connect();
        if (code) {
            critical_alert("incremental",
                           "Error contacting Moira server to resolve %s: %s",
                           after[L_NAME], error_message(code));
            return;
        }
-       av[0] = "LIST";
-       av[1] = after[L_NAME];
-       get_members(2, av, after[L_NAME]);
-
-       mr_disconnect();
+       av[0] = after[L_NAME];
+       code = mr_query("get_end_members_of_list", 1, av,
+                       add_list_members, after[L_NAME]);
+       if (code)
+           critical_alert("incremental",
+                          "Couldn't retrieve full membership of list %s: %s",
+                          after[L_NAME], error_message(code));
+       moira_disconnect();
        return;
     }
 }
 
 
+    
+#define LM_EXTRA_ACTIVE          (LM_END)
+#define LM_EXTRA_PUBLIC   (LM_END+1)
+#define LM_EXTRA_HIDDEN   (LM_END+2)
+#define LM_EXTRA_MAILLIST (LM_END+3)
+#define LM_EXTRA_GROUP    (LM_END+4)
+#define LM_EXTRA_GID      (LM_END+5)
+#define LM_EXTRA_END      (LM_END+6)
+
 do_member(before, beforec, after, afterc)
 char **before;
 int beforec;
@@ -311,15 +349,27 @@ int afterc;
 {
     int code;
     char *p;
-    
-    if ((beforec < 4 || !atoi(before[LM_END])) &&
-       (afterc < 4 || !atoi(after[LM_END])))
-       return;
 
-    if (afterc) 
-       edit_group(1, after[LM_LIST], after[LM_TYPE], after[LM_MEMBER]);
-    if (beforec)
+    if (afterc) {
+       if (afterc < LM_EXTRA_END) {
+           return;
+       } else if (afterc < LM_EXTRA_END) {
+           if (!atoi(after[LM_EXTRA_GROUP])) return;
+       } else
+         if (!atoi(after[LM_EXTRA_ACTIVE]) && !atoi(after[LM_EXTRA_GROUP]))
+           return;
+       
+       edit_group(1, after[LM_LIST], after[LM_TYPE], after[LM_MEMBER]);
+    } else if (beforec) {
+       if (beforec < LM_EXTRA_END) {
+           return;
+       } else if (beforec < LM_EXTRA_END) {
+           if (!atoi(before[LM_EXTRA_GROUP])) return;
+       } else
+         if (!atoi(before[LM_EXTRA_ACTIVE]) && !atoi(before[LM_EXTRA_GROUP]))
+           return;
        edit_group(0, before[LM_LIST], before[LM_TYPE], before[LM_MEMBER]);
+    }
 }
 
 
@@ -351,37 +401,47 @@ int afterc;
        return;
     }
     
-    /* What do we do?  When do we use FS_CREATE?
-     *
-     * Currently, we use FS_CREATE to indicate that Moira should attempt
-     * to update the file servers (rename, creation, ownership change).
-     * 
-     * Howerver, at this time, we there is no back-end support to handle:
-     *   TYPE change       (eg. AFS -> ERR)
-     *   LOCKERTYPE change (eg. PROJECT -> COURSE)
-     *   PACK change       (eg. /afs/athena/foo -> /afs/athena/bar)
-     *   LABEL change      (eg. "foo" -> "bar")
-     *   Locker Deletion
-     */
-
     btype = !strcmp(before[FS_TYPE], "AFS");
     if (afterc < FS_CREATE) {
        if (btype)
            critical_alert("incremental",
-                          "Could not delete AFS filesystem %s: Operation not supported",
+                          "Cannot delete AFS filesystem %s: Operation not supported",
                           before[FS_NAME]);
        return;
-    } if (acreate && atype) {
-       if (btype) {
-           critical_alert("incremental",
-                          "Cannot change attributes of AFS filesystem %s: Operation not supported",
-                          after[FS_NAME]);
-       } else {
-           critical_alert("incremental",
-                          "Cannot convert %s to an AFS filesystem: Operation not supported",
-                          after[FS_NAME]);
-       }
     }
+
+    if (!acreate)
+       return;
+
+    /* Are we dealing with AFS lockers (could be type ERR lockers) */
+    if (!atype && !btype)
+       if (strcmp(before[FS_TYPE], "ERR") || strcmp(after[FS_TYPE], "ERR"))
+           return;
+                                                   
+    /* By now, we know we are simply changing AFS filesystem attributes.
+     * Operations supported:
+     *    Name change:  rename/remount
+     *    Path change:  remount
+     *    Type change:  ERR<-->AFS
+     */
+
+#if 0
+    if (strcmp(before[FS_OWNER], after[FS_OWNER]) ||
+       strcmp(before[FS_OWNERS], after[FS_OWNERS]))
+    {
+       critical_alert("incremental",
+                      "Cannot change ownership of filesystem %s: Operation not yet supported",
+                      after[FS_NAME]);
+    }
+#endif
+
+    sprintf(cmd, "%s/perl -I%s %s/afs_rename.pl %s %s %s %s %s %s %s %s %s %s",
+           BIN_DIR, BIN_DIR, BIN_DIR,
+           before[FS_NAME], before[FS_MACHINE], before[FS_TYPE],
+           before[FS_L_TYPE], before[FS_PACK],
+           after[FS_NAME], after[FS_MACHINE], after[FS_TYPE],
+           after[FS_L_TYPE], after[FS_PACK]);
+    run_cmd(cmd);
 }
 
 
@@ -429,29 +489,29 @@ add_user_lists(ac, av, user)
     char *av[];
     char *user;
 {
-    if (atoi(av[5]))
-       edit_group(1, av[0], "USER", user);
+    if (atoi(av[L_ACTIVE]) && atoi(av[L_GROUP]))       /* active group ? */
+       edit_group(1, av[L_NAME], "USER", user);
+    return 0;
 }
 
 
-get_members(ac, av, group)
+add_list_members(ac, av, group)
     int ac;
     char *av[];
     char *group;
 {
-    int code=0;
+    edit_group(1, group, av[0], av[1]);
+    return 0;
+}
 
-    if (strcmp(av[0], "LIST")) {
-       edit_group(1, group, av[0], av[1]);
-    } else {
-       code = mr_query("get_end_members_of_list", 1, &av[1],
-                       get_members, group);
-       if (code)
-           critical_alert("incremental",
-                          "Couldn't retrieve full membership of %s: %s",
-                          group, error_message(code));
-    }
-    return code;
+
+check_user(ac, av, ustate)
+    int ac;
+    char *av[];
+    int *ustate;
+{
+    *ustate = atoi(av[U_STATE]);
+    return 0;
 }
 
 
@@ -463,8 +523,9 @@ edit_group(op, group, type, member)
 {
     char *p = 0;
     char buf[PR_MAXNAMELEN];
-    int code;
+    int code, ustate;
     static char local_realm[REALM_SZ+1] = "";
+    struct member *m;
 
     /* The following KERBEROS code allows for the use of entities
      * user@foreign_cell.
@@ -478,19 +539,65 @@ edit_group(op, group, type, member)
     } else if (strcmp(type, "USER"))
        return;                                 /* invalid type */
 
+    /* Cannot risk doing another query during a callback */
+    /* We could do this simply for type USER, but eventually this may also
+     * dynamically add KERBEROS types to the prdb, and we will need to do
+     * a query to look up the uid of the null-instance user */
+    if (mr_connections) {
+       m = (struct member *)malloc(sizeof(struct member));
+       if (!m) {
+           critical_alert("incremental", "Out of memory");
+           exit(1);
+       }
+       m->op = op;
+       strcpy(m->list, group);
+       strcpy(m->type, type);
+       strcpy(m->member, member);
+       m->next = member_head;
+       member_head = m;
+       return;
+    }
+
     strcpy(buf, "system:");
     strcat(buf, group);
+    com_err(whoami, 0, "%s %s %s group %s",
+          (op ? "Adding" : "Removing"), member,
+          (op ? "to" : "from"), group);
+    code = 0;
     code=pr_try(op ? pr_AddToGroup : pr_RemoveUserFromGroup, member, buf);
     if (code) {
-       if (op==0 && code == PRNOENT) return;
-       if (op==1 && code == PRIDEXIST) return;
-       if (strcmp(type, "KERBEROS") || code != PRNOENT) {
-           critical_alert("incremental",
-                          "Couldn't %s %s %s %s: %s",
-                          op ? "add" : "remove", member,
-                          op ? "to" : "from", buf,
-                          error_message(code));
+       if (op==1 && code == PRIDEXIST) return; /* Already added */
+
+       if (code == PRNOENT) {                  /* Something is missing */
+           if (op==0) return;                  /* Already deleted */
+           if (!strcmp(type, "KERBEROS"))      /* Special instances; ok */
+               return;
+
+           /* Check whether the member being added is an active user */
+           code = moira_connect();
+           if (!code) code = mr_query("get_user_by_login", 1, &member,
+                                      check_user, &ustate);
+           if (code) {
+               critical_alert("incremental",
+                              "Error contacting Moira server to lookup user %s: %s",
+                              member, error_message(code));
+           }
+
+           /* We don't use moira_disconnect()
+            * because we may already be in the routine.
+            */
+           mr_disconnect();
+           mr_connections--;
+
+           if (!code && ustate!=1 && ustate!=2) return; /* inactive user */
+           code = PRNOENT;
        }
+
+       critical_alert("incremental",
+                      "Couldn't %s %s %s %s: %s",
+                      op ? "add" : "remove", member,
+                      op ? "to" : "from", buf,
+                      error_message(code));
     }
 }
 
@@ -507,16 +614,20 @@ long pr_try(fn, a1, a2, a3, a4, a5, a6, a7, a8)
 #endif
 
     check_afs();
-    
-    if (!initd) {
-       code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
-       if (code) {
-           critical_alert("incremental", "Couldn't initialize libprot: %s",
-                          error_message(code));
-           return;
-       }
+
+    if (initd) {
+       code=pr_Initialize(0, AFSCONF_CLIENTNAME, 0);
+    } else {
+       code = 0;
        initd = 1;
     }
+    if (!code) code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
+    if (code) {
+       critical_alert("incremental", "Couldn't initialize libprot: %s",
+                      error_message(code));
+       return;
+    }
+
     sleep(1);                                  /* give ptserver room */
 
     while (code = (*fn)(a1, a2, a3, a4, a5, a6, a7, a8)) {
@@ -570,3 +681,37 @@ check_afs()
        sleep(60);
     }
 }
+
+
+moira_connect()
+{
+    static char hostname[64];
+    long code;
+
+    if (!mr_connections++) {
+#ifdef DEBUG
+       code = mr_connect("moira");
+#else
+       gethostname(hostname, sizeof(hostname));
+       code = mr_connect(hostname);
+#endif
+       if (!code) code = mr_auth("afs.incr");
+       return code;    
+    }
+    return 0;
+}
+
+moira_disconnect()
+{
+    struct member *m;
+    
+    if (!--mr_connections) {
+       mr_disconnect();
+       while(m = member_head) {
+           edit_group(m->op, m->list, m->type, m->member);
+           member_head = m->next;
+           free(m);
+       }
+    }
+    return 0;
+}
This page took 0.052967 seconds and 4 git commands to generate.