#!/usr/bin/python import moira import sys import Queue def lenient_query(*query): try: results = moira.query(*query) except moira.MoiraException as e: msg = e[1] if msg == 'No records in database match query': results = [] else: raise return results def expand_closure(lst, owns=True, members=True, member_of=True, recursive=True, ): closure = set() include_type = 'list' if recursive: include_type = 'rlist' if owns: results = lenient_query('get_ace_use', include_type, lst) for result in results: if result['use_type'] == 'LIST': closure.add(result['use_name']) if members: results = lenient_query('get_members_of_list', lst) for result in results: if result['member_type'] == 'LIST': closure.add(result['member_name']) if member_of: results = lenient_query('get_lists_of_member', include_type, lst) for result in results: closure.add(result['list_name']) return closure def get_exclusions(lst): exclusions = set() results = lenient_query('get_members_of_list', lst) for result in results: if result['member_type'] == 'LIST': exclusions.add(result['member_name']) return exclusions def compute_closure(lists, exclude): closure = set() parent = {} the_queue = Queue.Queue() for lst in lists: the_queue.put(lst) for lst in lists: parent[lst] = None while not the_queue.empty(): lst = the_queue.get() if lst in closure: print "skipping %s" % (lst, ) continue closure.add(lst) try: new_lists = expand_closure(lst, member_of=False, recursive=False, ) except moira.MoiraException as e: msg = e[1] if msg == 'Insufficient permission to perform requested database access': new_lists = [] print >>sys.stderr, "List %s (parent %s) appears to be hidden; ignoring. (Queue length: %d; closure length: %d)" % (lst, parent[lst], the_queue.qsize(), len(closure), ) else: raise for new_list in new_lists: if new_list in closure: pass elif new_list in exclude: print "Excluding %s (parent %s)" % (new_list, lst) else: the_queue.put(new_list) parent[new_list] = lst print "%s (from %s)" % (new_list, lst) return closure if __name__ == '__main__': moira.connect() moira.auth('awdflu') # client name is awdflu --- Alex Dehnert file-lists-updater starter_list = sys.argv[1] exclude_list = sys.argv[2] exclude = get_exclusions(exclude_list) closure = compute_closure([starter_list], exclude) moira.disconnect() print "\n\n\n" for lst in closure: print lst print print "Count:", len(closure)