diff --git a/utils/ldapcertfs.py b/utils/ldapcertfs.py index f4b0ea35..231e0457 100755 --- a/utils/ldapcertfs.py +++ b/utils/ldapcertfs.py @@ -44,6 +44,7 @@ import os import sys import ssl import stat +import ldap import time import fuse import errno @@ -59,7 +60,7 @@ fuse.fuse_python_api = (0, 2) import logging LOG_FILENAME = 'ldapcertfs.log' -logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG) +logging.basicConfig(filename=LOG_FILENAME,level=logging.WARNING) CACHE = {} @@ -81,7 +82,7 @@ def get_from_cache(key, now=None, expire=CACHE_TIMEOUT): now = time.time() if key in CACHE: (ts, v) = CACHE[key] - if now - ts < expire: + if now - ts < expire or expire < 0: return v else: raise ValueError("Expired") @@ -172,13 +173,39 @@ class LdapCertFS(fuse.Fuse): self._storage = {} self.passphrase = {} - def search_cache(self, filter, **kwargs): + def _func_cache(self, func, *args, **kwargs): + rec = kwargs.pop('rec', False) + kwargs_l = ["%s=%s" % kv for kv in kwargs.items()] + kwargs_l.sort() + serial = "%s(%s,%s)" % (func.__name__, ", ".join(args), ", ".join(kwargs_l)) try: - return get_from_cache(filter) + return get_from_cache(serial) except ValueError: - objects = self.conn.search(filter, **kwargs) - set_to_cache(filter, objects) - return objects + try: + objects = func(*args, **kwargs) + set_to_cache(serial, objects) + return objects + except ldap.SERVER_DOWN: + try: + self.conn = lc_ldap.shortcuts.lc_ldap_readonly() + if not rec: + logger.warning("[ldapcertfs] ldap down, retrying") + kwargs['rec'] = rec + self.func_cache(func, *args, **kwargs) + except Exception as e: + logger.error("[ldapcertfs] uncaught exception %r" % e) + # Si le serveur est down on essaye de fournir un ancienne valeur du cache + try: + return get_from_cache(serial, expire=-1) + except ValueError: + logger.critical("[ldapcertfs] fail to return a valid result, I will probably crash next to this") + return [] + + def search_cache(self, filter, **kwargs): + return self._func_cache(self.conn.search, filter, **kwargs) + + def get_local_machines(self): + return self._func_cache(self.conn.get_local_machines) def make_root(self): self._storage['/'] = Item(0755 | stat.S_IFDIR, self.uid, self.gid) @@ -187,7 +214,7 @@ class LdapCertFS(fuse.Fuse): elif self.ldap_filter: machines = self.search_cache("(&(%s)(mid=*))" % self.ldap_filter, sizelimit=8000) else: - machines = self.conn.get_local_machines() + machines = self.get_local_machines() for machine in machines: if not machine.certificats(): continue