[ldap_locks] Mise en place des locks. Cf commentaires pour les détails.

* Malheureusement lc_ldap._create_entity et objet.create sont un peu
 sales, mais j'ai pas trouvé mieux.
 * L'historique contient désormais les secondes.
This commit is contained in:
Pierre-Elliott Bécue 2013-05-30 15:22:11 +02:00
parent 17efae121c
commit d6efff30de
7 changed files with 123 additions and 58 deletions

View file

@ -38,6 +38,8 @@ import os
import exceptions
import socket
import crans_utils
import collections
import subprocess
class LdapLockedByYou(exceptions.StandardError):
"""
@ -67,24 +69,37 @@ class LdapLockHolder:
"""
On crée la connexion, et on crée un dico vide.
"""
self.locks = {}
self.host = socket.gethostbyname()
self.locks = collections.defaultdict(dict, {})
self.host = socket.gethostname()
self.pid = os.getpid()
self.conn = conn
def __del__(self):
def purge(self, Id=None):
"""
On essaye de détruire tous les verrous hébergés par
l'objet mourant.
l'objet.
"""
for item, value in self.locks:
try:
self.removelock(item, value)
except:
pass
del self.conn
if Id == None:
for key, subdict in self.locks['default'].keys():
for item, value in subdict:
try:
self.removelock(item, value, key)
except:
pass
else:
for item, value in self.locks[Id].items():
try:
self.removelock(item, value, Id)
except:
pass
def addlock(self, item, value):
def __del__(self):
"""
En cas de destruction du lockholder
"""
self.purge()
def addlock(self, item, value, Id='default'):
"""
Applique un verrou sur "$item=$value,$LOCKS_DN",
si le précédent verrou était géré par la session
@ -97,21 +112,21 @@ class LdapLockHolder:
"""
try:
host, pid = self.getlock(item, value)
if host == self.host and pid == self.pid():
host, pid = self.getlock(item, value, Id)
if host == self.host and pid == self.pid:
raise LdapLockedByYou("La donnée %r=%r est lockée par vous-même." % (item, value))
elif host == self.host:
status = crans_utils.process_status(pid)
if status:
raise LdapLockedByOther("La donnée %r=%r est lockée par quelqu'un d'autre ou un processus." % (item, value))
else:
self.removelock(item, value)
self.removelock(item, value, Id, True)
else:
raise LdapLockedByOther("La donnée %r=%r est lockée par quelqu'un d'autre ou un processus." % (item, value))
except ldap.NO_SUCH_OBJECT:
pass
except LockFormatError:
self.removelock(item, value)
self.removelock(item, value, Id)
dn = "%s=%s,%s" % (item, value, LOCKS_DN)
lockid = "%s-%s" % (self.host, self.pid)
@ -121,38 +136,49 @@ class LdapLockHolder:
try:
self.conn.add_s(dn, modlist)
self.locks[item] = value
self.locks[Id][item] = value
except ldap.ALREADY_EXISTS:
status = crans_utils.process_status(pid)
if status:
raise LdapLockedByOther("La donnée %r=%r est lockée par quelqu'un d'autre ou un processus." % (item, value))
else:
self.removelock(item, value)
self.removelock(item, value, Id)
try:
self.conn.add_s(dn, modlist)
self.locks[item] = value
# 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))
def removelock(self, item, value):
def removelock(self, item, value, Id='default', force=False):
"""
Libère le lock "$item=$value,$LOCKS_DN".
"""
print "Deleting %s=%s,%s\n" % (item, value, LOCKS_DN)
if self.locks.get(item, "") == value:
self.locks.pop(item)
self.conn.delete_s("%s=%s,%s" % (item, value, LOCKS_DN))
if not force:
if self.locks[Id].get(item, "") == str(value):
_ = self.locks[Id].pop(item)
self.conn.delete_s("%s=%s,%s" % (item, value, LOCKS_DN))
else:
pass
else:
print "Lock %s=%s,%s does not exist on this session" % (item, value, LOCKS_DN)
try:
self.conn.delete_s("%s=%s,%s" % (item, value, LOCKS_DN))
except:
pass
def getlock(self, item, value):
def getlock(self, item, value, Id):
"""
Trouve le lock item=value, et renvoie le contenu de lockinfo
via un couple host, pid
"""
result = self.conn.search_s('%s=%s,%s' % (item, value, LOCKS_DN), 0)
if not result:
_ = self.locks[Id].pop(item)
return None, 0
try:
return result[0][1]['lockid'][0].split('-')
host, pid = result[0][1]['lockid'][0].split('-')
return host, int(pid)
except:
raise LockFormatError