[ldapcertfs] fallback sur un cache local si des erreurs ldap surviennent
This commit is contained in:
parent
b209f8f4f0
commit
08f4d259b7
1 changed files with 83 additions and 6 deletions
|
@ -48,6 +48,8 @@ import ldap
|
|||
import time
|
||||
import fuse
|
||||
import errno
|
||||
import pickle
|
||||
import hashlib
|
||||
import getpass
|
||||
|
||||
from OpenSSL import crypto
|
||||
|
@ -59,12 +61,61 @@ import gestion.secrets_new as secrets
|
|||
fuse.fuse_python_api = (0, 2)
|
||||
|
||||
import logging
|
||||
LOG_FILENAME = 'ldapcertfs.log'
|
||||
logging.basicConfig(filename=LOG_FILENAME,level=logging.WARNING)
|
||||
import logging.handlers
|
||||
logger = logging.getLogger('ldapcertfs')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
formatter = logging.Formatter('%(name)s: [%(levelname)s] %(message)s')
|
||||
handler = logging.handlers.SysLogHandler(address = '/dev/log')
|
||||
try:
|
||||
handler.addFormatter(formatter)
|
||||
except AttributeError:
|
||||
handler.formatter = formatter
|
||||
logger.addHandler(handler)
|
||||
|
||||
|
||||
CACHE = {}
|
||||
CACHE_TIMEOUT = 60
|
||||
CACHE_DIR = "/var/lib/ldapcertfs/"
|
||||
CACHE_STATIC_UPDATE = 3600
|
||||
CACHE_STATIC_EXPIRE = 3600 * 24 * 30
|
||||
LAST_CLEAN = 0
|
||||
|
||||
try:
|
||||
os.mkdir(CACHE_DIR, 0700)
|
||||
except OSError as e:
|
||||
if e.errno != 17: # File exists
|
||||
raise
|
||||
os.chmod(CACHE_DIR, 0700)
|
||||
|
||||
def clean_static_cache(storage={}):
|
||||
global LAST_CLEAN
|
||||
if time.time() - LAST_CLEAN > CACHE_STATIC_UPDATE:
|
||||
LAST_CLEAN = time.time()
|
||||
for file in os.listdir(CACHE_DIR):
|
||||
path = os.path.join(CACHE_DIR, file)
|
||||
if time.time() - os.path.getmtime(path) > CACHE_STATIC_EXPIRE and not path in storage:
|
||||
os.remove(path)
|
||||
|
||||
clean_static_cache()
|
||||
|
||||
def get_from_static_cache(key):
|
||||
path = os.path.join(CACHE_DIR, hashlib.md5(key).hexdigest())
|
||||
if os.path.isfile(path):
|
||||
with open(path) as f:
|
||||
return (os.path.getmtime(path), pickle.load(f))
|
||||
else:
|
||||
raise ValueError("Not Found")
|
||||
|
||||
def set_to_static_cache(key, value):
|
||||
try:
|
||||
(mtime, old_value) = get_from_static_cache(key)
|
||||
except ValueError:
|
||||
old_value = None
|
||||
if old_value != value:
|
||||
path = os.path.join(CACHE_DIR, hashlib.md5(key).hexdigest())
|
||||
with open(path, 'w+') as f:
|
||||
pickle.dump(value, f)
|
||||
os.chmod(path, 0600)
|
||||
|
||||
def set_to_cache(keys, value, now=None, null=False):
|
||||
global CACHE
|
||||
|
@ -116,6 +167,21 @@ class Item(object):
|
|||
else:
|
||||
self.data = ''
|
||||
|
||||
def __eq__(self, obj):
|
||||
if isinstance(obj, Item):
|
||||
return self.dev == obj.dev and \
|
||||
self.mode == obj.mode and \
|
||||
self.uid == obj.uid and \
|
||||
self.gid == obj.gid and \
|
||||
self.xattr == obj.xattr and \
|
||||
self.data == obj.data and \
|
||||
abs(self.mtime - obj.mtime) < CACHE_STATIC_UPDATE
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, obj):
|
||||
return not self == obj
|
||||
|
||||
def read(self, offset, length):
|
||||
return self.data[offset:offset+length]
|
||||
|
||||
|
@ -189,16 +255,16 @@ class LdapCertFS(fuse.Fuse):
|
|||
try:
|
||||
self.conn = lc_ldap.shortcuts.lc_ldap_readonly()
|
||||
if not rec:
|
||||
logger.warning("[ldapcertfs] ldap down, retrying")
|
||||
logger.warning("ldap down, retrying")
|
||||
kwargs['rec'] = True
|
||||
self.func_cache(func, *args, **kwargs)
|
||||
except Exception as e:
|
||||
logger.error("[ldapcertfs] uncaught exception %r" % e)
|
||||
logger.error("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")
|
||||
logger.critical("fail to return a valid result, I will probably crash next to this")
|
||||
return []
|
||||
|
||||
def search_cache(self, filter, **kwargs):
|
||||
|
@ -358,9 +424,20 @@ class LdapCertFS(fuse.Fuse):
|
|||
elif machine_host and xid and file:
|
||||
self.make_file(xid, file)
|
||||
set_to_cache(path, True)
|
||||
set_to_static_cache(path, self._storage[path])
|
||||
# --- Metadata -----------------------------------------------------------
|
||||
def getattr(self, path):
|
||||
self.build_path(path)
|
||||
try:
|
||||
self.build_path(path)
|
||||
clean_static_cache(self._storage)
|
||||
except Exception as e:
|
||||
logger.warning("Erreur : %s\n%s" % (e, traceback.format_exc()))
|
||||
if not path in self._storage:
|
||||
try:
|
||||
(ts, v) = get_from_static_cache(path)
|
||||
self._storage[path] = v
|
||||
except ValueError:
|
||||
pass
|
||||
if not path in self._storage:
|
||||
return -errno.ENOENT
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue