rblanche: avoid crashing on deactivated users
[user/alex/software/my-snippets.git] / rblanche.py
1 #!/usr/bin/python
2 import optparse
3 import sys
4
5 import moira
6
7 def get_members_of_list(lst):
8     return moira.query('get_members_of_list', lst)
9
10 class RBlanche(object):
11     def __init__(self, chpoboxing=False, ):
12         self.reset_caches()
13         self.chpoboxing = chpoboxing
14
15     def reset_caches(self, ):
16         self.cache = {}
17         self.chpobox = {}
18
19     def expand(self, lst):
20         if lst in self.cache: return self.cache[lst]
21         try:
22             members = get_members_of_list(lst)
23         except moira.MoiraException, e:
24             code, message = e
25             if message == "Insufficient permission to perform requested database access":
26                 self.cache[lst] = [{'member_type': 'ERR', 'member_name':'** Error: no permissions to look up this list **'}]
27                 return self.cache[lst]
28             else: raise
29         for member in members:
30             if member['member_type'] == 'LIST':
31                 member['members'] = self.expand(member['member_name'])
32         self.cache[lst] = members
33         return members
34
35     def get_and_format_pobox(self, user):
36         try:
37             result = moira.query('get_pobox', user)[0]
38         except moira.MoiraException, e:
39             return "%8s ** moira error: %s **" % (user, e)
40         if result['type'] == 'SMTP':
41             fmt = '-> %s'
42         elif result['type'] == 'SPLIT':
43             fmt = '=> %s'
44         elif result['type'] in ('EXCHANGE', 'IMAP', 'POP', ''):
45             fmt = '  (%s)'
46         else:
47             raise ValueError("Unknown pobox type %s" % (result['type'], ))
48         text = ('%8s ' + fmt) % (result['login'], result['address'], )
49         return text
50
51     def format_user(self, user):
52         text = user
53         if self.chpoboxing:
54             if user not in self.chpobox:
55                 self.chpobox[user] = self.get_and_format_pobox(user)
56             text = self.chpobox[user]
57         return text
58
59     def print_tree(self, path, lst_tree):
60         for member in lst_tree:
61             if 'members' in member:
62                 path.append(member['member_name'])
63                 self.print_tree(path, member['members'])
64                 path.pop()
65             else:
66                 if member['member_type'] == "USER":
67                     text = self.format_user(member['member_name'])
68                 elif member['member_type'] == "ERR":
69                     text = member['member_name']
70                 else:
71                     text = "%s:%s" % (member['member_type'], member['member_name'], )
72                 print ":  ".join(path+[text])
73
74     def rblanche(self, lst):
75         result = self.expand(lst)
76         self.print_tree([lst], result)
77
78 def parse_args():
79     parser = optparse.OptionParser(usage='usage: %prog [--auth=yes|no|try] [-cd] list')
80     parser.add_option('--auth', dest='auth', default=None,
81                 help='authenticate to the moira server? (yes, no, or try)'
82     )
83     parser.add_option('-c', '--chpobox',
84                 dest='chpoboxing', action='store_true', default=False,
85                 help='check mail forwarding for each user',
86     )
87     options, args = parser.parse_args()
88
89     if len(args) != 1:
90         parser.error("incorrect number of arguments")
91
92     if options.auth:
93         if options.auth == 'yes': options.auth = True
94         elif options.auth == 'try': options.auth = None
95         elif options.auth == 'no': options.auth = False
96         else:
97             parser.error("--auth takes yes, no, and try (default; auth if possible)")
98
99     return options, args
100
101 if __name__ == '__main__':
102     options, args = parse_args()
103     moira.connect()
104     if options.auth:
105         moira.auth('rblnchpy')
106     elif options.auth is None:
107         try:
108             moira.auth('rblnchpy')
109         except moira.MoiraException:
110             print >>sys.stderr, "Warning: Failed to authenticate to moira"
111     rblanche = RBlanche(chpoboxing=options.chpoboxing)
112     rblanche.rblanche(args[0])