can be used to monitor accounts in /var/log/accounts - or to actually cleanup with...
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Wed, 20 May 2009 20:37:02 +0000 (20:37 +0000)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Wed, 20 May 2009 20:37:02 +0000 (20:37 +0000)
plc-orphan-accounts.py

index c2f9b59..b8ce321 100755 (executable)
@@ -1,9 +1,27 @@
 #!/usr/bin/env plcsh
-
+#
+# $Id$
+#
 # searches and displays any local orphan account (not attached to a site)
 # remote accounts with identical emails are displayed as well
 
+import sys
 import time
+import readline
+from optparse import OptionParser
+
+logdir="/var/log/accounts"
+
+def run_in_log (options):
+    monthstring=time.strftime("%Y-%m")
+    if not os.path.isdir(logdir):
+        os.mkdir(logdir)
+    logname="%s/orphans-%s.log"%(logdir,monthstring)
+    sys.stdout=open(logname,'a')
+    sys.stderr=sys.stdout
+    run(options)
+    sys.stderr.close()
+    sys.stdout.close()
 
 # sort filters look broken
 def sort_email (p1,p2):
@@ -24,6 +42,16 @@ def list_person (margin,p):
     else: print 'DIS',
     print p['email']
 
+date_keys=['date_created','last_updated']
+def details_person (p):
+    keys=p.keys()
+    keys.sort()
+    for key in keys:
+        print key,'->',
+        value=p[key]
+        if key in date_keys:    print time.asctime(time.gmtime(value))
+        else:                   print value
+
 def get_related(email):
     return GetPersons ({'email':email,'~peer_id':None})
 
@@ -34,33 +62,105 @@ def header (message):
     print 'Listing orphan accounts and any similar remote'
     print '--------------------'
 
-def main_orphans ():
+def delete_local (person,default_bool,options):
+    
+    # just in case
+    if person['peer_id'] != None:
+        print 'ERROR: cannot delete non-local person',person['email']
+        return
+
+    prompt = 'want to delete '+person['email']
+    if default_bool:    prompt += ' v(erbose)/[y]/n ? '
+    else:               prompt += ' v(erbose)y/[n] ? '
+
+    done=False
+
+    while not done:
+        done=True
+        try:
+            answer = raw_input(prompt).strip()
+        except EOFError :
+            print 'bailing out'
+            sys.exit(1)
+
+        if answer=='':
+            do_delete=default_bool
+        elif answer.lower()[0]=='y':
+            do_delete=True
+        elif answer.lower()[0]=='n':
+            do_delete=False
+        elif answer.lower()[0]=='v':
+            details_person(person)
+            done=False
+        else:
+            done=False
+    id=person['person_id']
+    email=person['email']
+    if options.dry_run:
+        if do_delete:                   print 'Would delete',id,'->',email
+        else:                           print 'Would preserve',id,'->',email
+    elif do_delete:
+        print 'Deleting',id,'->',email,
+        if DeletePerson(id) == 1:       print 'OK',id,'deleted'
+        else:                           print 'Deletion failed'
+
+def main_orphans (options):
     orphans = get_orphans()
     header ('Listing  %d  local accounts with no site - and similar remote accounts'%len(orphans))
-    index=1
-    for p in orphans:
-        list_person ("%3d"%index,p)
-        for related in get_related(p['email']):
-            list_person("dup",related)
+    index=0
+    for local in orphans:
         index+=1
+        list_person ("%3d"%index,local)
+        for related in get_related(local['email']):
+            list_person("dup",related)
+        if options.delete:
+            delete_default = not local['enabled']
+            delete_local(local,delete_default,options)
     
-def main_duplicates():
+def main_duplicates(options):
 
     header ('Listing all duplicate accounts')
     locals = GetPersons({'peer_id':None,'-SORT':'email'})
     locals.sort(sort_email)
-    index=1
+    index=0
     for local in locals:
         remotes=GetPersons({'email':local['email'],'~peer_id':None})
         if remotes:
+            index+=1
             list_person('%3d'%index,local)
             for remote in remotes:
                 list_person('dup',remote)
-        
-            index+=1
+            if options.delete:
+                delete_default = not local['enabled']
+                delete_local(local,delete_default,options)
+
+def run (options):
+    main_orphans(options)
+    main_duplicates(options)
+
 def main():
-    main_orphans()
-    main_duplicates()
 
+    usage="%prog [ -- options]"
+
+    parser = OptionParser(usage=usage)
+    parser.add_option("-l","--log", dest="log", action="store_true",default=False,
+                      help="write current status in /var/log/accounts")
+    parser.add_option("-d","--delete", dest="delete", action="store_true",default=False,
+                      help="interactively delete extraneous accounts")
+    parser.add_option("-n","--dry-run", dest="dry_run", action="store_true",default=False,
+                      help="go through the delete prompting but does not delete")
+
+    (options,args) = parser.parse_args()
+    if len(args)!=0:
+        parser.error("Unexpected arguments",args)
+
+    if options.dry_run: options.delete=True
+    
+    if options.log:
+        options.delete=False
+        run_in_log(options)
+    else:
+        run(options)
+    
 if __name__ == '__main__':
     main()