[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 time
|
||||||
import fuse
|
import fuse
|
||||||
import errno
|
import errno
|
||||||
|
import pickle
|
||||||
|
import hashlib
|
||||||
import getpass
|
import getpass
|
||||||
|
|
||||||
from OpenSSL import crypto
|
from OpenSSL import crypto
|
||||||
|
@ -59,12 +61,61 @@ import gestion.secrets_new as secrets
|
||||||
fuse.fuse_python_api = (0, 2)
|
fuse.fuse_python_api = (0, 2)
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
LOG_FILENAME = 'ldapcertfs.log'
|
import logging.handlers
|
||||||
logging.basicConfig(filename=LOG_FILENAME,level=logging.WARNING)
|
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 = {}
|
||||||
CACHE_TIMEOUT = 60
|
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):
|
def set_to_cache(keys, value, now=None, null=False):
|
||||||
global CACHE
|
global CACHE
|
||||||
|
@ -116,6 +167,21 @@ class Item(object):
|
||||||
else:
|
else:
|
||||||
self.data = ''
|
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):
|
def read(self, offset, length):
|
||||||
return self.data[offset:offset+length]
|
return self.data[offset:offset+length]
|
||||||
|
|
||||||
|
@ -189,16 +255,16 @@ class LdapCertFS(fuse.Fuse):
|
||||||
try:
|
try:
|
||||||
self.conn = lc_ldap.shortcuts.lc_ldap_readonly()
|
self.conn = lc_ldap.shortcuts.lc_ldap_readonly()
|
||||||
if not rec:
|
if not rec:
|
||||||
logger.warning("[ldapcertfs] ldap down, retrying")
|
logger.warning("ldap down, retrying")
|
||||||
kwargs['rec'] = True
|
kwargs['rec'] = True
|
||||||
self.func_cache(func, *args, **kwargs)
|
self.func_cache(func, *args, **kwargs)
|
||||||
except Exception as e:
|
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
|
# Si le serveur est down on essaye de fournir un ancienne valeur du cache
|
||||||
try:
|
try:
|
||||||
return get_from_cache(serial, expire=-1)
|
return get_from_cache(serial, expire=-1)
|
||||||
except ValueError:
|
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 []
|
return []
|
||||||
|
|
||||||
def search_cache(self, filter, **kwargs):
|
def search_cache(self, filter, **kwargs):
|
||||||
|
@ -358,9 +424,20 @@ class LdapCertFS(fuse.Fuse):
|
||||||
elif machine_host and xid and file:
|
elif machine_host and xid and file:
|
||||||
self.make_file(xid, file)
|
self.make_file(xid, file)
|
||||||
set_to_cache(path, True)
|
set_to_cache(path, True)
|
||||||
|
set_to_static_cache(path, self._storage[path])
|
||||||
# --- Metadata -----------------------------------------------------------
|
# --- Metadata -----------------------------------------------------------
|
||||||
def getattr(self, path):
|
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:
|
if not path in self._storage:
|
||||||
return -errno.ENOENT
|
return -errno.ENOENT
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue