[ldap_locks] Renommage des erreurs ldap en erreur de Lock, factorisation, reformatage
This commit is contained in:
parent
320300d85c
commit
4f88ae824a
1 changed files with 52 additions and 54 deletions
106
ldap_locks.py
106
ldap_locks.py
|
@ -53,6 +53,12 @@ class LdapLockedByYou(LockError):
|
|||
"""
|
||||
pass
|
||||
|
||||
class LdapLockedByMySelf(LockError):
|
||||
"""
|
||||
Classe d'erreur pour les locks par l'idlock courant
|
||||
"""
|
||||
pass
|
||||
|
||||
class LdapLockedByOther(LockError):
|
||||
"""
|
||||
Erreur car le lock est occupé par un autre process.
|
||||
|
@ -65,6 +71,9 @@ class LockFormatError(LockError):
|
|||
"""
|
||||
pass
|
||||
|
||||
class LockNotFound(LockError):
|
||||
"""Le lock n'a pas été trouvé"""
|
||||
|
||||
LOCKS_DN = 'ou=lock,dc=crans,dc=org'
|
||||
|
||||
class LdapLockHolder:
|
||||
|
@ -75,36 +84,38 @@ class LdapLockHolder:
|
|||
"""
|
||||
On crée la connexion, et on crée un dico vide.
|
||||
"""
|
||||
self.locks = collections.defaultdict(dict, {})
|
||||
# On crée un Id => (item => set())
|
||||
self.locks = collections.defaultdict(lambda:collections.defaultdict(set))
|
||||
self.host = socket.gethostname()
|
||||
self.pid = os.getpid()
|
||||
self.conn = conn
|
||||
self.time = 600.0
|
||||
self.timeout = 600.0
|
||||
|
||||
def purge(self, Id=None):
|
||||
def newid(self):
|
||||
id = 'id_%s' % time.time()
|
||||
if id in self.locks:
|
||||
return self.newid()
|
||||
else:
|
||||
return id
|
||||
|
||||
def purge(self, Id, purgeAll=False):
|
||||
"""
|
||||
On essaye de détruire tous les verrous hébergés par
|
||||
l'objet.
|
||||
"""
|
||||
if Id == None:
|
||||
for key, subdict in self.locks['default'].items():
|
||||
for item, value in subdict.items():
|
||||
try:
|
||||
self.removelock(item, value, key)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
for item, value in self.locks[Id].items():
|
||||
try:
|
||||
if not purgeAll:
|
||||
for item, values in self.locks[Id].items():
|
||||
for value in values.copy():
|
||||
self.removelock(item, value, Id)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
for Id in self.locks:
|
||||
self.purge(Id)
|
||||
|
||||
def __del__(self):
|
||||
"""
|
||||
En cas de destruction du lockholder
|
||||
"""
|
||||
self.purge()
|
||||
self.purge(purgeAll=True)
|
||||
|
||||
def addlock(self, item, value, Id='default'):
|
||||
"""
|
||||
|
@ -119,27 +130,23 @@ class LdapLockHolder:
|
|||
"""
|
||||
try:
|
||||
host, pid, begin = self.getlock(item, value)
|
||||
if time.time() - begin >= self.time:
|
||||
time_left = self.timeout - (time.time() - begin)
|
||||
if time_left <= 0:
|
||||
self.removelock(item, value, Id, True)
|
||||
elif Id!='default' and str(value) in self.locks[Id][item]:
|
||||
raise LdapLockedByMySelf("La donnée %r=%r est lockée par vous-même pour encore %ds." % (item, value, time_left))
|
||||
elif host == self.host and pid == self.pid:
|
||||
time_left = self.time - (time.time() - begin)
|
||||
raise LdapLockedByYou("La donnée %r=%r est lockée par vous-même pour encore %ds." % (item, value, time_left))
|
||||
elif host == self.host:
|
||||
status = crans_utils.process_status(pid)
|
||||
if status:
|
||||
time_left = self.time - (time.time() - begin)
|
||||
raise LdapLockedByOther("La donnée %r=%r est lockée par un processus actif pour encore %ds." % (item, value, time_left))
|
||||
else:
|
||||
self.removelock(item, value, Id, True)
|
||||
else:
|
||||
time_left = self.time - (time.time() - begin)
|
||||
raise LdapLockedByOther("La donnée %r=%r est lockée depuis une autre machine pour encore %ds." % (item, value, time_left))
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
except LockNotFound:
|
||||
pass
|
||||
except LockFormatError:
|
||||
self.removelock(item, value, Id)
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
dn = "%s=%s,%s" % (item, value, LOCKS_DN)
|
||||
lockid = "%s-%s-%s" % (self.host, self.pid, time.time())
|
||||
|
@ -151,36 +158,28 @@ class LdapLockHolder:
|
|||
|
||||
try:
|
||||
self.conn.add_s(dn, modlist)
|
||||
self.locks[Id][item] = value
|
||||
self.locks[Id][item].add(str(value))
|
||||
except ldap.ALREADY_EXISTS:
|
||||
status = crans_utils.process_status(pid)
|
||||
if status:
|
||||
raise LdapLockedByOther("La donnée %r=%r est lockée par un processus actif." % (item, value))
|
||||
else:
|
||||
self.removelock(item, value, Id)
|
||||
try:
|
||||
self.conn.add_s(dn, modlist)
|
||||
|
||||
# Si on a un pointeur vers l'id de l'objet, on en tient compte
|
||||
self.locks[Id][item] = value
|
||||
except:
|
||||
raise StandardError("Quelque chose a planté durant la pose du lock %s=%s" % (item, value))
|
||||
# Quelqu'un à eu le lock avant nous, on réessaye
|
||||
# S'il a été libéré, banzai, sinon, ça lèvera une exception
|
||||
return self.addlock(item, value, Id)
|
||||
|
||||
def removelock(self, item, value, Id='default', force=False):
|
||||
"""
|
||||
Libère le lock "$item=$value,$LOCKS_DN".
|
||||
"""
|
||||
if not force:
|
||||
if self.locks[Id].get(item, "") == str(value):
|
||||
_ = self.locks[Id].pop(item)
|
||||
try:
|
||||
if force or str(value) in self.locks[Id][item]:
|
||||
self.conn.delete_s("%s=%s,%s" % (item, value, LOCKS_DN))
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
pass
|
||||
finally:
|
||||
try:
|
||||
self.conn.delete_s("%s=%s,%s" % (item, value, LOCKS_DN))
|
||||
except:
|
||||
self.locks[Id][item].remove(value)
|
||||
except KeyError:
|
||||
pass
|
||||
if not self.locks[Id][item]:
|
||||
self.locks[Id].pop(item)
|
||||
|
||||
def getlock(self, item, value):
|
||||
"""
|
||||
|
@ -188,13 +187,12 @@ class LdapLockHolder:
|
|||
via un triplet host, pid, begin
|
||||
"""
|
||||
|
||||
result = self.conn.search_s('%s=%s,%s' % (item, value, LOCKS_DN), 0)
|
||||
try:
|
||||
try:
|
||||
host, pid, begin = result[0][1]['lockid'][0].split('-')
|
||||
except:
|
||||
host, pid = result[0][1]['lockid'][0].split('-')
|
||||
begin = time.time()
|
||||
result = self.conn.search_s('%s=%s,%s' % (item, value, LOCKS_DN), 0)
|
||||
host, pid, begin = result[0][1]['lockid'][0].split('-')
|
||||
return host, int(pid), float(begin)
|
||||
except:
|
||||
raise LockFormatError
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
raise LockNotFound()
|
||||
except ValueError as e:
|
||||
self.removelock(item, value, Id, force=True)
|
||||
raise LockNotFound()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue