Exemple #1
0
 def __init__(self):
     super(Giedo, self).__init__(settings.GIEDO_SOCKET)
     self.log = logging.getLogger('giedo')
     self.last_sync_ts = 0
     self.daan, self.cilia, self.moniek, self.hans = None, None, None, None
     try:
         self.daan = WhimClient(settings.DAAN_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to daan")
     try:
         self.cilia = WhimClient(settings.CILIA_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to cilia")
     try:
         self.moniek = WhimClient(settings.MONIEK_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to moniek")
     try:
         self.hans = WhimClient(settings.HANS_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to hans")
     self.mirte = mirte.get_a_manager()
     self.threadPool = self.mirte.get_a('threadPool')
     self.operation_lock = threading.Lock()
     self.ss_actions = (
         ('postfix', self.daan, self._gen_postfix),
         ('postfix-slm', self.daan, self._gen_postfix_slm),
         ('mailman', self.hans, self._gen_mailman),
         ('unix', self.cilia, self._gen_unix),
         ('wiki', self.daan, self._gen_wiki),
         ('ldap', self.daan, self._gen_ldap),
         ('wolk', self.cilia, self._gen_wolk))
Exemple #2
0
 def __init__(self):
     super(Giedo, self).__init__(settings.GIEDO_SOCKET)
     self.l = logging.getLogger('giedo')
     self.last_sync_ts = 0
     self.daan, self.cilia = None, None
     try:
         self.daan = WhimClient(settings.DAAN_SOCKET)
     except:
         self.l.exception("Couldn't connect to daan")
     try:
         self.cilia = WhimClient(settings.CILIA_SOCKET)
     except:
         self.l.exception("Couldn't connect to cilia")
     self.mirte = mirte.get_a_manager()
     self.threadPool = self.mirte.get_a('threadPool')
     self.operation_lock = threading.Lock()
     self.push_changes_event = threading.Event()
     self.openvpn_lock = threading.Lock()
     self.threadPool.execute(self.run_change_pusher)
     if default_storage.exists("villanet.pem"):
         self.villanet_key = RSA.load_pub_key(default_storage.path(
             "villanet.pem"))
     self.ss_actions = (
               ('postfix', self.daan, self._gen_postfix),
               ('postfix-slm', self.daan, self._gen_postfix_slm),
               ('mailman', self.daan, self._gen_mailman),
               ('forum', self.daan, self._gen_forum),
               ('unix', self.cilia, self._gen_unix),
               ('wiki', self.daan, self._gen_wiki),
               ('ldap', self.daan, self._gen_ldap),
               ('wolk', self.cilia, self._gen_wolk),
               ('quassel', self.daan, self._gen_quassel))
     self.push_changes_event.set()
Exemple #3
0
 def __init__(self):
         super(Giedo, self).__init__(settings.GIEDO_SOCKET)
         self.daan = WhimClient(settings.DAAN_SOCKET)
         self.cilia = WhimClient(settings.CILIA_SOCKET)
         self.mirte = mirte.get_a_manager()
         self.threadPool = self.mirte.get_a('threadPool')
         self.operation_lock = threading.Lock()
         self.ss_actions = (
                       ('postfix', self.daan, self._gen_postfix),
                       ('mailman', self.daan, self._gen_mailman),
                       ('forum', self.daan, self._gen_forum),
                       ('unix', self.cilia, self._gen_unix),
                       ('wiki', self.daan, self._gen_wiki))
Exemple #4
0
 def __init__(self):
     super(Giedo, self).__init__(settings.GIEDO_SOCKET)
     self.daan = WhimClient(settings.DAAN_SOCKET)
     self.cilia = WhimClient(settings.CILIA_SOCKET)
     self.mirte = mirte.get_a_manager()
     self.threadPool = self.mirte.get_a("threadPool")
     self.operation_lock = threading.Lock()
     self.ss_actions = (
         ("postfix", self.daan, self._gen_postfix),
         ("mailman", self.daan, self._gen_mailman),
         ("forum", self.daan, self._gen_forum),
         ("unix", self.cilia, self._gen_unix),
         ("wiki", self.daan, self._gen_wiki),
     )
Exemple #5
0
 def __init__(self):
     super(Giedo, self).__init__(settings.GIEDO_SOCKET)
     self.log = logging.getLogger('giedo')
     self.last_sync_ts = 0
     self.daan, self.cilia, self.moniek, self.hans = None, None, None, None
     try:
         self.daan = WhimClient(settings.DAAN_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to daan")
     try:
         self.cilia = WhimClient(settings.CILIA_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to cilia")
     try:
         self.moniek = WhimClient(settings.MONIEK_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to moniek")
     try:
         self.hans = WhimClient(settings.HANS_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to hans")
     self.mirte = mirte.get_a_manager()
     self.threadPool = self.mirte.get_a('threadPool')
     self.operation_lock = threading.Lock()
     self.ss_actions = (('postfix', self.daan, self._gen_postfix),
                        ('postfix-slm', self.daan, self._gen_postfix_slm),
                        ('mailman', self.hans, self._gen_mailman),
                        ('unix', self.cilia, self._gen_unix),
                        ('wiki', self.daan, self._gen_wiki),
                        ('ldap', self.daan,
                         self._gen_ldap), ('wolk', self.cilia,
                                           self._gen_wolk))
Exemple #6
0
 def __init__(self):
     super(Giedo, self).__init__(settings.GIEDO_SOCKET)
     self.daan = WhimClient(settings.DAAN_SOCKET)
     self.cilia = WhimClient(settings.CILIA_SOCKET)
     self.mirte = mirte.get_a_manager()
     self.threadPool = self.mirte.get_a('threadPool')
     self.operation_lock = threading.Lock()
     self.push_changes_event = threading.Event()
     self.threadPool.execute(self.run_change_pusher)
     if default_storage.exists("villanet.pem"):
         self.villanet_key = RSA.load_pub_key(default_storage.path(
             "villanet.pem"))
     self.ss_actions = (
               ('postfix', self.daan, self._gen_postfix),
               ('mailman', self.daan, self._gen_mailman),
               ('forum', self.daan, self._gen_forum),
               ('unix', self.cilia, self._gen_unix),
               ('wiki', self.daan, self._gen_wiki))
     self.push_changes_event.set()
Exemple #7
0
 def __init__(self):
     super(Giedo, self).__init__(settings.GIEDO_SOCKET)
     self.last_sync_ts = 0
     self.daan = WhimClient(settings.DAAN_SOCKET)
     self.cilia = WhimClient(settings.CILIA_SOCKET)
     self.mirte = mirte.get_a_manager()
     self.threadPool = self.mirte.get_a('threadPool')
     self.operation_lock = threading.Lock()
     self.push_changes_event = threading.Event()
     self.threadPool.execute(self.run_change_pusher)
     if default_storage.exists("villanet.pem"):
         self.villanet_key = RSA.load_pub_key(
             default_storage.path("villanet.pem"))
     self.ss_actions = (('postfix', self.daan, self._gen_postfix),
                        ('postfix-slm', self.daan, self._gen_postfix_slm),
                        ('mailman', self.daan, self._gen_mailman),
                        ('forum', self.daan, self._gen_forum),
                        ('unix', self.cilia, self._gen_unix),
                        ('wiki', self.daan,
                         self._gen_wiki), ('ldap', self.daan,
                                           self._gen_ldap))
     self.push_changes_event.set()
Exemple #8
0
 def __init__(self):
     super(Giedo, self).__init__()
     self.log = logging.getLogger('giedo')
     self.last_sync_ts = 0
     self.daan, self.cilia, self.moniek, self.hans = None, None, None, None
     try:
         self.daan = daan_pb2_grpc.DaanStub(
             grpc.insecure_channel('unix:' + settings.DAAN_SOCKET))
     except Exception:
         self.log.exception("Couldn't connect to daan")
     try:
         self.cilia = WhimClient(settings.CILIA_SOCKET)
     except Exception:
         self.log.exception("Couldn't connect to cilia")
     try:
         self.moniek = moniek_pb2_grpc.MoniekStub(
             grpc.insecure_channel('unix:' + settings.MONIEK_SOCKET))
     except Exception:
         self.log.exception("Couldn't connect to moniek")
     try:
         self.hans = hans_pb2_grpc.HansStub(
             grpc.insecure_channel('unix:' + settings.HANS_SOCKET))
     except Exception:
         self.log.exception("Couldn't connect to hans")
     self.mirte = mirte.get_a_manager()
     self.threadPool = self.mirte.get_a('threadPool')
     self.operation_lock = threading.Lock()
     self.ss_actions = (('postfix', self.daan.SetPostfixMap,
                         self._gen_postfix),
                        ('postfix-slm', self.daan.SetPostfixSenderLoginMap,
                         self._gen_postfix_slm),
                        ('mailman', self.hans.ApplyChanges,
                         self._gen_mailman), ('unix', self.cilia.send,
                                              self._gen_unix),
                        ('wiki', self.daan.ApplyWikiChanges,
                         self._gen_wiki),
                        ('ldap', self.daan.ApplyLDAPChanges,
                         self._gen_ldap), ('wolk', self.cilia.send,
                                           self._gen_wolk))
Exemple #9
0
class Giedo(WhimDaemon):

    def __init__(self):
        super(Giedo, self).__init__(settings.GIEDO_SOCKET)
        self.log = logging.getLogger('giedo')
        self.last_sync_ts = 0
        self.daan, self.cilia, self.moniek, self.hans = None, None, None, None
        try:
            self.daan = WhimClient(settings.DAAN_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to daan")
        try:
            self.cilia = WhimClient(settings.CILIA_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to cilia")
        try:
            self.moniek = WhimClient(settings.MONIEK_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to moniek")
        try:
            self.hans = WhimClient(settings.HANS_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to hans")
        self.mirte = mirte.get_a_manager()
        self.threadPool = self.mirte.get_a('threadPool')
        self.operation_lock = threading.Lock()
        self.ss_actions = (
            ('postfix', self.daan, self._gen_postfix),
            ('postfix-slm', self.daan, self._gen_postfix_slm),
            ('mailman', self.hans, self._gen_mailman),
            ('unix', self.cilia, self._gen_unix),
            ('wiki', self.daan, self._gen_wiki),
            ('ldap', self.daan, self._gen_ldap),
            ('wolk', self.cilia, self._gen_wolk))

    def pre_mainloop(self):
        super(Giedo, self).pre_mainloop()
        self.notify_systemd()

    def _gen_wolk(self):
        return {'type': 'wolk',
                'changes': generate_wolk_changes(self)}

    def _gen_ldap(self):
        return {'type': 'ldap',
                'changes': generate_ldap_changes(self)}

    def _gen_postfix_slm(self):
        return {'type': 'postfix-slm',
                'map': generate_postfix_slm_map(self)}

    def _gen_postfix(self):
        return {'type': 'postfix',
                'map': generate_postfix_map(self)}

    def _gen_mailman(self):
        return {'type': 'maillist-apply-changes',
                'changes': generate_mailman_changes(self)}

    def _gen_wiki(self):
        return {'type': 'wiki',
                'changes': generate_wiki_changes(self)}

    def _gen_unix(self):
        return {'type': 'unix',
                'map': generate_unix_map(self)}

    def sync(self):
        update_db_start = time.time()
        update_db(self)
        logging.info("update_db %s" % (time.time() - update_db_start))
        todo = [len(self.ss_actions)]
        todo_lock = threading.Lock()
        todo_event = threading.Event()

        def _sync_action(func, name, daemon, action):
            try:
                func(name, daemon, action)
            except Exception:
                logging.exception('uncaught exception in %s (daemon %s)' %
                                  (name, daemon))
            with todo_lock:
                todo[0] -= 1
                if todo[0] == 0:
                    todo_event.set()

        def _entry(name, daemon, action):
            start = time.time()
            msg = action()
            elapsed = time.time() - start
            logging.info("generate %s %.4f" % (name, elapsed))
            start = time.time()
            daemon.send(msg)
            elapsed = time.time() - start
            logging.info("send %s %.4f (%s to go)" %
                         (name, elapsed, todo[0] - 1))

        for action in self.ss_actions:
            self.threadPool.execute(_sync_action, _entry, *action)
        todo_event.wait()
        self.last_sync_ts = time.time()

    def handle(self, d):
        if d['type'] == 'sync':
            with self.operation_lock:
                return self.sync()
        elif d['type'] == 'setpass':
            with self.operation_lock:
                u = Es.by_name(d['user'])
                if u is None:
                    return {'error': 'no such user'}
                u = u.as_user()
                if not u.check_password(d['oldpass']):
                    return {'error': 'wrong old password'}
                u.set_password(d['newpass'])
                d2 = {'type': 'setpass',
                      'user': d['user'],
                      'pass': d['newpass']}
                self.daan.send(d2)
                self.cilia.send(d2)
                return {'success': True}
        elif d['type'] == 'ping':
            return {'pong': True}
        elif d['type'] == 'fotoadmin-scan-userdirs':
            return self.cilia.send(d)
        elif d['type'] == 'fotoadmin-move-fotos':
            with self.operation_lock:
                ret = self.daan.send(d)
                if 'success' not in ret:
                    return ret
                ret = scan_fotos()
                if 'success' not in ret:
                    return ret
                return self.cilia.send({
                    'type': 'fotoadmin-remove-moved-fotos',
                    'store': d['store'],
                    'user': d['user'],
                    'dir': d['dir']})
        elif d['type'] == 'fotoadmin-scan-fotos':
            with self.operation_lock:
                return scan_fotos()
        elif d['type'] == 'update-site-agenda':
            with self.operation_lock:
                return update_site_agenda(self)
        elif d['type'] in ['fotoadmin-create-event']:
            with self.operation_lock:
                return self.daan.send(d)
        elif d['type'] == 'last-synced?':
            return self.last_sync_ts
        elif d['type'] in ('fin-get-account',
                           'fin-get-debitors',
                           'fin-check-names',
                           'fin-get-gnucash-object',
                           'fin-get-years',
                           'fin-get-errors'):
            try:
                return self.moniek.send(d)
            except IOError as e:
                return {'error': 'IOError: ' + e.args[0]}
        elif d['type'] in ('maillist-get-moderated-lists',
                           'maillist-activate-moderation',
                           'maillist-get-moderator-cookie',
                           'maillist-deactivate-moderation'):
            return self.hans.send(d)
        else:
            logging.warn("Unknown command: %s" % d['type'])
Exemple #10
0
class Giedo(WhimDaemon):
    def __init__(self):
        super(Giedo, self).__init__(settings.GIEDO_SOCKET)
        self.last_sync_ts = 0
        self.daan = WhimClient(settings.DAAN_SOCKET)
        self.cilia = WhimClient(settings.CILIA_SOCKET)
        self.mirte = mirte.get_a_manager()
        self.threadPool = self.mirte.get_a('threadPool')
        self.operation_lock = threading.Lock()
        self.push_changes_event = threading.Event()
        self.threadPool.execute(self.run_change_pusher)
        if default_storage.exists("villanet.pem"):
            self.villanet_key = RSA.load_pub_key(
                default_storage.path("villanet.pem"))
        self.ss_actions = (('postfix', self.daan, self._gen_postfix),
                           ('postfix-slm', self.daan, self._gen_postfix_slm),
                           ('mailman', self.daan, self._gen_mailman),
                           ('forum', self.daan, self._gen_forum),
                           ('unix', self.cilia, self._gen_unix),
                           ('wiki', self.daan,
                            self._gen_wiki), ('ldap', self.daan,
                                              self._gen_ldap))
        self.push_changes_event.set()

    def _gen_ldap(self):
        return {'type': 'ldap', 'changes': generate_ldap_changes(self)}

    def _gen_postfix_slm(self):
        return {'type': 'postfix-slm', 'map': generate_postfix_slm_map(self)}

    def _gen_postfix(self):
        return {'type': 'postfix', 'map': generate_postfix_map(self)}

    def _gen_mailman(self):
        return {'type': 'mailman', 'changes': generate_mailman_changes(self)}

    def _gen_wiki(self):
        return {'type': 'wiki', 'changes': generate_wiki_changes(self)}

    def _gen_forum(self):
        return {'type': 'forum', 'changes': generate_forum_changes(self)}

    def _gen_unix(self):
        return {'type': 'unix', 'map': generate_unix_map(self)}

    def _sync_villanet(self):
        ret = self.villanet_request({'action': 'listUsers'})
        if not ret[0]:
            return
        ret = json.loads(ret[1])
        users = dict()
        ulut = dict()
        for u in Es.users():
            ulut[u._id] = str(u.name)
        member_relations_grouped = dict()
        for rel in Es.query_relations(_with=Es.by_name('leden'), until=now()):
            if rel['who'] not in member_relations_grouped:
                member_relations_grouped[rel['who']] = []
            member_relations_grouped[rel['who']].append(rel)
        for user_id, relations in member_relations_grouped.items():
            latest = max(relations, key=lambda x: x['until'])
            users[ulut[user_id]] = latest['until'].strftime('%Y-%m-%d')
        vn = set(ret.keys())
        kn = set(users.keys())
        dt_max = settings.DT_MAX.strftime('%Y-%m-%d')
        for name in kn - vn:
            data = {
                'username': name,
                'password': self.villanet_encrypt_password(pseudo_randstr(16)),
            }
            if users[name] != dt_max:
                data['till'] = users[name]
            pc = Es.PushChange({
                'system': 'villanet',
                'action': 'addUser',
                'data': data
            })
            pc.save()
        for name in vn - kn:
            logging.info("Stray user %s" % name)
        for name in vn & kn:
            remote = (ret[name]['till'][:10]
                      if ret[name]['till'] is not None else '')
            local = users[name] if users[name] != dt_max else ''
            if remote != local:
                pc = Es.PushChange({
                    'system': 'villanet',
                    'action': 'changeUser',
                    'data': {
                        'username': name,
                        'till': local
                    }
                })
                pc.save()
        self.push_changes_event.set()

    def sync(self):
        update_db_start = time.time()
        update_db(self)
        logging.info("update_db %s" % (time.time() - update_db_start))
        todo = [len(self.ss_actions)]
        todo_lock = threading.Lock()
        todo_event = threading.Event()

        def _sync_action(func, *args):
            try:
                func(*args)
            except Exception as e:
                logging.exception("Uncaught exception")
            with todo_lock:
                todo[0] -= 1
                if todo[0] == 0:
                    todo_event.set()

        def _entry(name, daemon, action):
            start = time.time()
            msg = action()
            elapsed = time.time() - start
            logging.info("generate %s %s" % (name, elapsed))
            start = time.time()
            daemon.send(msg)
            elapsed = time.time() - start
            logging.info("send %s %s" % (name, elapsed))

        todo[0] += 1
        self.threadPool.execute(_sync_action, self._sync_villanet)
        for act in self.ss_actions:
            self.threadPool.execute(_sync_action, _entry, *act)
        todo_event.wait()
        self.last_sync_ts = time.time()

    def handle(self, d):
        if d['type'] == 'sync':
            with self.operation_lock:
                return self.sync()
        elif d['type'] == 'setpass':
            with self.operation_lock:
                u = Es.by_name(d['user'])
                if u is None:
                    return {'error': 'no such user'}
                u = u.as_user()
                if not u.check_password(d['oldpass']):
                    return {'error': 'wrong old password'}
                u.set_password(d['newpass'])
                d2 = {
                    'type': 'setpass',
                    'user': d['user'],
                    'pass': d['newpass']
                }
                self.daan.send(d2)
                self.cilia.send(d2)
                return {'success': True}
        elif d['type'] == 'set-villanet-password':
            with self.operation_lock:
                u = Es.by_name(d['user'])
                if u is None:
                    return {'error': 'no such user'}
                u = u.as_user()
                if not u.check_password(d['oldpass']):
                    return {'error': 'wrong current password'}
                pc = Es.PushChange({
                    'system': 'villanet',
                    'action': 'changeUser',
                    'data': {
                        'username': d['user'],
                        'password':
                        self.villanet_encrypt_password(d['newpass'])
                    }
                })
                pc.save()
                self.push_changes_event.set()
                return {'success': True}
        elif d['type'] == 'fotoadmin-move-fotos':
            with self.operation_lock:
                # TODO should this block Giedo?
                ret = self.daan.send(d)
                if 'success' not in ret:
                    return ret
                return self.cilia.send({
                    'type': 'fotoadmin-remove-moved-fotos',
                    'user': d['user'],
                    'dir': d['dir']
                })
        elif d['type'] == 'openvpn_create':
            with self.operation_lock:
                # XXX hoeft niet onder de operation_lock?
                u = Es.by_name(d['user'])
                if u is None:
                    return {'error': 'no such user'}
                u = u.as_user()
                if d['want'] == 'exe':
                    create_openvpn_installer(self, u)
                else:
                    create_openvpn_zip(self, u)
        elif d['type'] == 'update-site-agenda':
            with self.operation_lock:
                return update_site_agenda(self)
        elif d['type'] in [
                'update-knsite', 'update-knfotos', 'fotoadmin-create-event'
        ]:
            with self.operation_lock:
                return self.daan.send(d)
        elif d['type'] == 'last-synced?':
            return self.last_sync_ts
        else:
            logging.warn("Unknown command: %s" % d['type'])

    def villanet_encrypt_password(self, password):
        ctx = self.villanet_key.public_encrypt(password, RSA.pkcs1_padding)
        return ctx.encode('base64').replace("\n", '')

    def run_change_pusher(self):
        while True:
            self.push_changes_event.wait()
            self.push_changes_event.clear()
            for pc in Es.pcol.find():
                if pc['system'] == 'villanet':
                    if settings.VILLANET_SECRET_API_KEY == '':
                        logging.warn("VILLANET_SECRET_API_KEY not set")
                        continue
                    params = pc['data']
                    params['action'] = pc['action']
                    ret = self.villanet_request(params)
                    if not ret[0]:
                        continue
                else:
                    logging.warn("Unknown PushChange system %s " %
                                 pc['system'])
                Es.pcol.remove({'_id': pc['_id']})

    def villanet_request(self, params):
        params['apikey'] = settings.VILLANET_SECRET_API_KEY
        url = "http://www.vvs-nijmegen.nl/knapi.php?" + urlencode(params)
        ret = urllib2.urlopen(url, timeout=1).read()
        ret = ret.strip()
        if ret[:4] == 'OK: ':
            return (True, ret[4:])
        else:
            return (False, ret)
Exemple #11
0
class Giedo(giedo_pb2_grpc.GiedoServicer):
    def __init__(self):
        super(Giedo, self).__init__()
        self.log = logging.getLogger('giedo')
        self.last_sync_ts = 0
        self.daan, self.cilia, self.moniek, self.hans = None, None, None, None
        try:
            self.daan = daan_pb2_grpc.DaanStub(
                grpc.insecure_channel('unix:' + settings.DAAN_SOCKET))
        except Exception:
            self.log.exception("Couldn't connect to daan")
        try:
            self.cilia = WhimClient(settings.CILIA_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to cilia")
        try:
            self.moniek = moniek_pb2_grpc.MoniekStub(
                grpc.insecure_channel('unix:' + settings.MONIEK_SOCKET))
        except Exception:
            self.log.exception("Couldn't connect to moniek")
        try:
            self.hans = hans_pb2_grpc.HansStub(
                grpc.insecure_channel('unix:' + settings.HANS_SOCKET))
        except Exception:
            self.log.exception("Couldn't connect to hans")
        self.mirte = mirte.get_a_manager()
        self.threadPool = self.mirte.get_a('threadPool')
        self.operation_lock = threading.Lock()
        self.ss_actions = (('postfix', self.daan.SetPostfixMap,
                            self._gen_postfix),
                           ('postfix-slm', self.daan.SetPostfixSenderLoginMap,
                            self._gen_postfix_slm),
                           ('mailman', self.hans.ApplyChanges,
                            self._gen_mailman), ('unix', self.cilia.send,
                                                 self._gen_unix),
                           ('wiki', self.daan.ApplyWikiChanges,
                            self._gen_wiki),
                           ('ldap', self.daan.ApplyLDAPChanges,
                            self._gen_ldap), ('wolk', self.cilia.send,
                                              self._gen_wolk))

    def _gen_wolk(self):
        return {'type': 'wolk', 'changes': generate_wolk_changes(self)}

    def _gen_ldap(self):
        return generate_ldap_changes()

    def _gen_postfix_slm(self):
        return generate_postfix_slm_map()

    def _gen_postfix(self):
        return generate_postfix_map()

    def _gen_mailman(self):
        return generate_mailman_changes(self.hans)

    def _gen_wiki(self):
        return generate_wiki_changes()

    def _gen_unix(self):
        return {'type': 'unix', 'map': generate_unix_map(self)}

    def sync(self):
        update_db_start = time.time()
        update_db(self)
        logging.info("update_db %s" % (time.time() - update_db_start))
        todo = [len(self.ss_actions)]
        todo_lock = threading.Lock()
        todo_event = threading.Event()

        def _sync_action(func, name, daemon, action):
            try:
                func(name, daemon, action)
            except Exception:
                logging.exception('uncaught exception in %s (daemon %s)' %
                                  (name, daemon))
            with todo_lock:
                todo[0] -= 1
                if todo[0] == 0:
                    todo_event.set()

        def _entry(name, send, action):
            start = time.time()
            msg = action()
            elapsed = time.time() - start
            logging.info("generate %s %.4f" % (name, elapsed))
            start = time.time()
            send(msg)
            elapsed = time.time() - start
            logging.info("send %s %.4f (%s to go)" %
                         (name, elapsed, todo[0] - 1))

        for action in self.ss_actions:
            self.threadPool.execute(_sync_action, _entry, *action)
        todo_event.wait()
        self.last_sync_ts = time.time()

    def sync_locked(self):
        with self.operation_lock:
            self.sync()

    def SyncBlocking(self, request, context):
        self.sync_locked()
        return common_pb2.Empty()

    def SyncAsync(self, request, context):
        self.threadPool.execute(self.sync_locked)
        return common_pb2.Empty()

    def LastSynced(self, request, context):
        return giedo_pb2.LastSyncedResult(time=self.last_sync_ts)

    def SetPassword(self, request, context):
        with self.operation_lock:
            u = Es.by_name(request.user)
            if u is None:
                context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
                context.set_details('no such user')
                return common_pb2.Empty()
            u = u.as_user()
            if not u.check_password(request.oldpass):
                context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
                context.set_details('wrong old password')
                return common_pb2.Empty()
            u.set_password(request.newpass)
            self.daan.SetLDAPPassword(
                daan_pb2.LDAPNewPassword(user=request.user.encode(),
                                         password=request.newpass.encode()))
            self.cilia.send({
                'type': 'setpass',
                'user': request.user,
                'pass': request.newpass
            })
        return common_pb2.Empty()

    def FotoadminScanUserdirs(self, request, context):
        resp = giedo_pb2.FotoadminUserdirs()
        for path, displayName in self.cilia.send(
            {'type': 'fotoadmin-scan-userdirs'}):
            resp.userdirs.append(
                giedo_pb2.FotoadminUserdir(path=path, displayName=displayName))
        return resp

    def FotoadminCreateEvent(self, request, context):
        with self.operation_lock:
            try:
                self.daan.FotoadminCreateEvent(request)
            except grpc.RpcError as e:
                context.set_code(e.code())
                context.set_details(e.details())
        return common_pb2.Empty()

    def FotoadminMoveFotos(self, request, context):
        with self.operation_lock:
            self.daan.FotoadminMoveFotos(request)
            scan_fotos()
            ret = self.cilia.send({
                'type': 'fotoadmin-remove-moved-fotos',
                'store': request.store,
                'user': request.user,
                'dir': request.dir
            })
            if 'success' not in ret:
                context.set_code(grpc.StatusCode.PERMISSION_DENIED)
                context.set_details(ret['error'])
        return common_pb2.Empty()

    def ScanFotos(self, request, context):
        with self.operation_lock:
            scan_fotos()
        return common_pb2.Empty()

    def UpdateSiteAgenda(self, request, context):
        with self.operation_lock:
            ret = update_site_agenda()
            if 'success' not in ret:
                context.set_code(grpc.StatusCode.UNKNOWN)
                context.set_details(ret['error'])
        return common_pb2.Empty()

    def FinGetAccount(self, request, context):
        return self.moniek.FinGetAccount(request)

    def FinGetDebitors(self, request, context):
        return self.moniek.FinGetDebitors(request)

    def FinCheckNames(self, request, context):
        return self.moniek.FinCheckNames(request)

    def FinGetGnuCashObject(self, request, context):
        return self.moniek.FinGetGnuCashObject(request)

    def FinGetYears(self, request, context):
        return self.moniek.FinGetYears(request)

    def FinGetErrors(self, request, context):
        return self.moniek.FinGetErrors(request)
Exemple #12
0
class Giedo(WhimDaemon):
    def __init__(self):
        super(Giedo, self).__init__(settings.GIEDO_SOCKET)
        self.daan = WhimClient(settings.DAAN_SOCKET)
        self.cilia = WhimClient(settings.CILIA_SOCKET)
        self.mirte = mirte.get_a_manager()
        self.threadPool = self.mirte.get_a("threadPool")
        self.operation_lock = threading.Lock()
        self.ss_actions = (
            ("postfix", self.daan, self._gen_postfix),
            ("mailman", self.daan, self._gen_mailman),
            ("forum", self.daan, self._gen_forum),
            ("unix", self.cilia, self._gen_unix),
            ("wiki", self.daan, self._gen_wiki),
        )

    def _gen_postfix(self):
        return {"type": "postfix", "map": generate_postfix_map(self)}

    def _gen_mailman(self):
        return {"type": "mailman", "changes": generate_mailman_changes(self)}

    def _gen_wiki(self):
        return {"type": "wiki", "changes": generate_wiki_changes(self)}

    def _gen_forum(self):
        return {"type": "forum", "changes": generate_forum_changes(self)}

    def _gen_unix(self):
        return {"type": "unix", "map": generate_unix_map(self)}

    def sync(self):
        update_db_start = time.time()
        update_db(self)
        logging.info("update_db %s" % (time.time() - update_db_start))
        todo = [len(self.ss_actions)]
        todo_lock = threading.Lock()
        todo_event = threading.Event()

        def _entry(name, daemon, action):
            start = time.time()
            msg = action()
            elapsed = time.time() - start
            logging.info("generate %s %s" % (name, elapsed))
            start = time.time()
            daemon.send(msg)
            elapsed = time.time() - start
            logging.info("send %s %s" % (name, elapsed))
            with todo_lock:
                todo[0] -= 1
                if todo[0] == 0:
                    todo_event.set()

        for act in self.ss_actions:
            self.threadPool.execute(_entry, *act)
        todo_event.wait()

    def handle(self, d):
        with self.operation_lock:
            if d["type"] == "sync":
                return self.sync()
            elif d["type"] == "setpass":
                u = Es.by_name(d["user"])
                if u is None:
                    return {"error": "no such user"}
                u = u.as_user()
                if not u.check_password(d["oldpass"]):
                    return {"error": "wrong old password"}
                u.set_password(d["newpass"])
                d2 = {"type": "setpass", "user": d["user"], "pass": d["newpass"]}
                self.daan.send(d2)
                self.cilia.send(d2)
                return {"success": True}
            elif d["type"] == "fotoadmin-move-fotos":
                # TODO should this block Giedo?
                ret = self.daan.send(d)
                if "success" not in ret:
                    return ret
                return self.cilia.send({"type": "fotoadmin-remove-moved-fotos", "user": d["user"], "dir": d["dir"]})
            elif d["type"] == "openvpn_create":
                # XXX hoeft niet onder de operation_lock
                u = Es.by_name(d["user"])
                if u is None:
                    return {"error": "no such user"}
                u = u.as_user()
                if d["want"] == "exe":
                    create_openvpn_installer(self, u)
                else:
                    create_openvpn_zip(self, u)
            elif d["type"] == "update-site-agenda":
                return update_site_agenda(self)
            elif d["type"] in ["update-knsite", "update-knfotos", "fotoadmin-create-event"]:
                return self.daan.send(d)
            else:
                print "Unknown command: %s" % d["type"]
Exemple #13
0
class Giedo(WhimDaemon):
    def __init__(self):
        super(Giedo, self).__init__(settings.GIEDO_SOCKET)
        self.daan = WhimClient(settings.DAAN_SOCKET)
        self.cilia = WhimClient(settings.CILIA_SOCKET)
        self.mirte = mirte.get_a_manager()
        self.threadPool = self.mirte.get_a('threadPool')
        self.operation_lock = threading.Lock()
        self.push_changes_event = threading.Event()
        self.threadPool.execute(self.run_change_pusher)
        if default_storage.exists("villanet.pem"):
            self.villanet_key = RSA.load_pub_key(default_storage.path(
                "villanet.pem"))
        self.ss_actions = (
                  ('postfix', self.daan, self._gen_postfix),
                  ('mailman', self.daan, self._gen_mailman),
                  ('forum', self.daan, self._gen_forum),
                  ('unix', self.cilia, self._gen_unix),
                  ('wiki', self.daan, self._gen_wiki))
        self.push_changes_event.set()


    def _gen_postfix(self):
        return {'type': 'postfix',
            'map': generate_postfix_map(self)}
    def _gen_mailman(self):
        return {'type': 'mailman',
            'changes': generate_mailman_changes(
                        self)}
    def _gen_wiki(self):
        return {'type': 'wiki',
            'changes': generate_wiki_changes(self)}
    def _gen_forum(self):
        return {'type': 'forum',
            'changes': generate_forum_changes(self)}
    def _gen_unix(self):
        return  {'type': 'unix',
             'map': generate_unix_map(self)}

    def _sync_villanet(self):
        ret = self.villanet_request({'action': 'listUsers'})
        if not ret[0]:
            return
        ret = json.loads(ret[1])
        users = dict()
        ulut = dict()
        for u in Es.users():
            ulut[u._id] = str(u.name)
        member_relations_grouped = dict()
        for rel in Es.query_relations(_with=Es.by_name('leden'), until=now()):
            if rel['who'] not in member_relations_grouped:
                member_relations_grouped[rel['who']] = []
            member_relations_grouped[rel['who']].append(rel)
        for user_id, relations in member_relations_grouped.items():
            latest = max(relations, key=lambda x: x['until'])
            users[ulut[user_id]] = latest['until'].strftime('%Y-%m-%d')
        vn = set(ret.keys())
        kn = set(users.keys())
        dt_max = settings.DT_MAX.strftime('%Y-%m-%d')
        for name in kn - vn:
            data = {
                    'username': name,
                    'password': self.villanet_encrypt_password(
                        pseudo_randstr(16)),
                }
            if users[name] != dt_max:
                data['till'] = users[name]
            pc = Es.PushChange({'system': 'villanet', 'action': 'addUser',
                'data': data})
            pc.save()
        for name in vn - kn:
            logging.info("Stray user %s" % name)
        for name in vn & kn:
            remote = (ret[name]['till'][:10] if ret[name]['till'] is not None
                    else '')
            local = users[name] if users[name] != dt_max else ''
            if remote != local:
                pc = Es.PushChange({'system': 'villanet',
                    'action': 'changeUser', 'data': {
                        'username': name,
                        'till': local
                        }})
                pc.save()
        self.push_changes_event.set()

    def sync(self):
        update_db_start = time.time()
        update_db(self)
        logging.info("update_db %s" % (time.time() - update_db_start))
        todo = [len(self.ss_actions)]
        todo_lock = threading.Lock()
        todo_event = threading.Event()

        def _sync_action(func, *args):
            func(*args)
            with todo_lock:
                todo[0] -= 1
                if todo[0] == 0:
                    todo_event.set()

        def _entry(name, daemon, action):
            start = time.time()
            msg = action()
            elapsed = time.time() - start
            logging.info("generate %s %s" % (name, elapsed))
            start = time.time()
            daemon.send(msg)
            elapsed = time.time() - start
            logging.info("send %s %s" % (name, elapsed))

        todo[0] += 1
        self.threadPool.execute(_sync_action, self._sync_villanet)
        for act in self.ss_actions:
            self.threadPool.execute(_sync_action, _entry, *act)
        todo_event.wait()

    def handle(self, d):
        with self.operation_lock:
            if d['type'] == 'sync':
                return self.sync()
            elif d['type'] == 'setpass':
                u = Es.by_name(d['user'])
                if u is None:
                    return {'error': 'no such user'}
                u = u.as_user()
                if not u.check_password(d['oldpass']):
                    return {'error': 'wrong old password'}
                u.set_password(d['newpass'])
                d2 = {'type': 'setpass',
                      'user': d['user'],
                      'pass': d['newpass']}
                self.daan.send(d2)
                self.cilia.send(d2)
                return {'success': True}
            elif d['type'] == 'set-villanet-password':
                u = Es.by_name(d['user'])
                if u is None:
                    return {'error': 'no such user'}
                u = u.as_user()
                if not u.check_password(d['oldpass']):
                    return {'error': 'wrong current password'}
                pc = Es.PushChange({'system': 'villanet',
                    'action': 'changeUser', 'data': {
                        'username': d['user'],
                        'password': self.villanet_encrypt_password(d['newpass'])
                            }})
                pc.save()
                self.push_changes_event.set()
                return {'success': True}
            elif d['type'] == 'fotoadmin-move-fotos':
                # TODO should this block Giedo?
                ret = self.daan.send(d)
                if 'success' not in ret:
                    return ret
                return self.cilia.send({
                    'type': 'fotoadmin-remove-moved-fotos',
                    'user': d['user'],
                    'dir': d['dir']})
            elif d['type'] == 'openvpn_create':
                # XXX hoeft niet onder de operation_lock
                u = Es.by_name(d['user'])
                if u is None:
                    return {'error': 'no such user'}
                u = u.as_user()
                if d['want'] == 'exe':
                    create_openvpn_installer(self, u)
                else:
                    create_openvpn_zip(self, u)
            elif d['type'] == 'update-site-agenda':
                return update_site_agenda(self)
            elif d['type'] in ['update-knsite', 'update-knfotos',
                    'fotoadmin-create-event']:
                return self.daan.send(d)
            else:
                logging.warn("Unknown command: %s" % d['type'])

    def villanet_encrypt_password(self, password):
        ctx = self.villanet_key.public_encrypt(password, RSA.pkcs1_padding)
        return ctx.encode('base64').replace("\n", '')

    def run_change_pusher(self):
        while True:
            self.push_changes_event.wait()
            self.push_changes_event.clear()
            for pc in Es.pcol.find():
                if pc['system'] == 'villanet':
                    if settings.VILLANET_SECRET_API_KEY == '':
                        logging.warn("VILLANET_SECRET_API_KEY not set")
                        continue
                    params = pc['data']
                    params['action'] = pc['action']
                    ret = self.villanet_request(params)
                    if not ret[0]:
                        continue
                else:
                    logging.warn("Unknown PushChange system %s " % pc['system'])
                Es.pcol.remove({'_id': pc['_id']})

    def villanet_request(self, params):
        params['apikey'] = settings.VILLANET_SECRET_API_KEY
        url = "http://www.vvs-nijmegen.nl/knapi.php?"+ urlencode(params)
        ret = urllib2.urlopen(url).read()
        ret = ret.strip()
        if ret[:4] == 'OK: ':
            return (True, ret[4:])
        else:
            return (False, ret)
Exemple #14
0
class Giedo(WhimDaemon):
        def __init__(self):
                super(Giedo, self).__init__(settings.GIEDO_SOCKET)
                self.daan = WhimClient(settings.DAAN_SOCKET)
                self.cilia = WhimClient(settings.CILIA_SOCKET)
                self.mirte = mirte.get_a_manager()
                self.threadPool = self.mirte.get_a('threadPool')
                self.operation_lock = threading.Lock()
                self.ss_actions = (
                              ('postfix', self.daan, self._gen_postfix),
                              ('mailman', self.daan, self._gen_mailman),
                              ('forum', self.daan, self._gen_forum),
                              ('unix', self.cilia, self._gen_unix),
                              ('wiki', self.daan, self._gen_wiki))


        def _gen_postfix(self):
                return {'type': 'postfix',
                        'map': generate_postfix_map(self)}
        def _gen_mailman(self):
                return {'type': 'mailman',
                        'changes': generate_mailman_changes(
                                                self)}
        def _gen_wiki(self):
                return {'type': 'wiki',
                        'changes': generate_wiki_changes(self)}
        def _gen_forum(self):
                return {'type': 'forum',
                        'changes': generate_forum_changes(self)}
        def _gen_unix(self):
                return  {'type': 'unix',
                         'map': generate_unix_map(self)}

        def sync(self):
                update_db_start = time.time()
                update_db(self)
                logging.info("update_db %s" % (time.time() - update_db_start))
                todo = [len(self.ss_actions)]
                todo_lock = threading.Lock()
                todo_event = threading.Event()
                def _entry(name, daemon, action):
                        start = time.time()
                        msg = action()
                        elapsed = time.time() - start
                        logging.info("generate %s %s" % (name, elapsed))
                        start = time.time()
                        daemon.send(msg)
                        elapsed = time.time() - start
                        logging.info("send %s %s" % (name, elapsed))
                        with todo_lock:
                                todo[0] -= 1
                                if todo[0] == 0:
                                        todo_event.set()
                for act in self.ss_actions:
                        self.threadPool.execute(_entry, *act)
                todo_event.wait()

        def handle(self, d):
                with self.operation_lock:
                        if d['type'] == 'sync':
                                return self.sync()
                        elif d['type'] == 'setpass':
                                u = Es.by_name(d['user'])
                                if u is None:
                                        return {'error': 'no such user'}
                                u = u.as_user()
                                if not u.check_password(d['oldpass']):
                                        return {'error': 'wrong old password'}
                                u.set_password(d['newpass'])
                                d2 = {'type': 'setpass',
                                      'user': d['user'],
                                      'pass': d['newpass']}
                                self.daan.send(d2)
                                self.cilia.send(d2)
                                return {'success': True}
Exemple #15
0
def get_giedo_connection():
    global __GIEDO
    if __GIEDO is None:
        __GIEDO = WhimClient(settings.GIEDO_SOCKET)
    return __GIEDO
Exemple #16
0
class Giedo(WhimDaemon):
    def __init__(self):
        super(Giedo, self).__init__(settings.GIEDO_SOCKET)
        self.log = logging.getLogger('giedo')
        self.last_sync_ts = 0
        self.daan, self.cilia, self.moniek, self.hans = None, None, None, None
        try:
            self.daan = WhimClient(settings.DAAN_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to daan")
        try:
            self.cilia = WhimClient(settings.CILIA_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to cilia")
        try:
            self.moniek = WhimClient(settings.MONIEK_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to moniek")
        try:
            self.hans = WhimClient(settings.HANS_SOCKET)
        except Exception:
            self.log.exception("Couldn't connect to hans")
        self.mirte = mirte.get_a_manager()
        self.threadPool = self.mirte.get_a('threadPool')
        self.operation_lock = threading.Lock()
        self.ss_actions = (('postfix', self.daan, self._gen_postfix),
                           ('postfix-slm', self.daan, self._gen_postfix_slm),
                           ('mailman', self.hans, self._gen_mailman),
                           ('unix', self.cilia, self._gen_unix),
                           ('wiki', self.daan, self._gen_wiki),
                           ('ldap', self.daan,
                            self._gen_ldap), ('wolk', self.cilia,
                                              self._gen_wolk))

    def pre_mainloop(self):
        super(Giedo, self).pre_mainloop()
        self.notify_systemd()

    def _gen_wolk(self):
        return {'type': 'wolk', 'changes': generate_wolk_changes(self)}

    def _gen_ldap(self):
        return {'type': 'ldap', 'changes': generate_ldap_changes(self)}

    def _gen_postfix_slm(self):
        return {'type': 'postfix-slm', 'map': generate_postfix_slm_map(self)}

    def _gen_postfix(self):
        return {'type': 'postfix', 'map': generate_postfix_map(self)}

    def _gen_mailman(self):
        return {
            'type': 'maillist-apply-changes',
            'changes': generate_mailman_changes(self)
        }

    def _gen_wiki(self):
        return {'type': 'wiki', 'changes': generate_wiki_changes(self)}

    def _gen_unix(self):
        return {'type': 'unix', 'map': generate_unix_map(self)}

    def sync(self):
        update_db_start = time.time()
        update_db(self)
        logging.info("update_db %s" % (time.time() - update_db_start))
        todo = [len(self.ss_actions)]
        todo_lock = threading.Lock()
        todo_event = threading.Event()

        def _sync_action(func, name, daemon, action):
            try:
                func(name, daemon, action)
            except Exception:
                logging.exception('uncaught exception in %s (daemon %s)' %
                                  (name, daemon))
            with todo_lock:
                todo[0] -= 1
                if todo[0] == 0:
                    todo_event.set()

        def _entry(name, daemon, action):
            start = time.time()
            msg = action()
            elapsed = time.time() - start
            logging.info("generate %s %.4f" % (name, elapsed))
            start = time.time()
            daemon.send(msg)
            elapsed = time.time() - start
            logging.info("send %s %.4f (%s to go)" %
                         (name, elapsed, todo[0] - 1))

        for action in self.ss_actions:
            self.threadPool.execute(_sync_action, _entry, *action)
        todo_event.wait()
        self.last_sync_ts = time.time()

    def handle(self, d):
        if d['type'] == 'sync':
            with self.operation_lock:
                return self.sync()
        elif d['type'] == 'setpass':
            with self.operation_lock:
                u = Es.by_name(d['user'])
                if u is None:
                    return {'error': 'no such user'}
                u = u.as_user()
                if not u.check_password(d['oldpass']):
                    return {'error': 'wrong old password'}
                u.set_password(d['newpass'])
                d2 = {
                    'type': 'setpass',
                    'user': d['user'],
                    'pass': d['newpass']
                }
                self.daan.send(d2)
                self.cilia.send(d2)
                return {'success': True}
        elif d['type'] == 'ping':
            return {'pong': True}
        elif d['type'] == 'fotoadmin-scan-userdirs':
            return self.cilia.send(d)
        elif d['type'] == 'fotoadmin-move-fotos':
            with self.operation_lock:
                ret = self.daan.send(d)
                if 'success' not in ret:
                    return ret
                ret = scan_fotos()
                if 'success' not in ret:
                    return ret
                return self.cilia.send({
                    'type': 'fotoadmin-remove-moved-fotos',
                    'store': d['store'],
                    'user': d['user'],
                    'dir': d['dir']
                })
        elif d['type'] == 'fotoadmin-scan-fotos':
            with self.operation_lock:
                return scan_fotos()
        elif d['type'] == 'update-site-agenda':
            with self.operation_lock:
                return update_site_agenda(self)
        elif d['type'] in ['fotoadmin-create-event']:
            with self.operation_lock:
                return self.daan.send(d)
        elif d['type'] == 'last-synced?':
            return self.last_sync_ts
        elif d['type'] in ('fin-get-account', 'fin-get-debitors',
                           'fin-check-names', 'fin-get-gnucash-object',
                           'fin-get-years', 'fin-get-errors'):
            try:
                return self.moniek.send(d)
            except IOError as e:
                return {'error': 'IOError: ' + e.args[0]}
        elif d['type'] in ('maillist-get-moderated-lists',
                           'maillist-activate-moderation',
                           'maillist-get-moderator-cookie',
                           'maillist-deactivate-moderation'):
            return self.hans.send(d)
        else:
            logging.warn("Unknown command: %s" % d['type'])