From e18e5222b712c26e18eb846c9f5efe789a528367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Elliott=20B=C3=A9cue?= Date: Thu, 13 Jun 2013 20:34:59 +0200 Subject: [PATCH] =?UTF-8?q?[Oops]=20J'ai=20oubli=C3=A9=20de=20commiter=20u?= =?UTF-8?q?n=20de=20mes=20d=C3=A9bugs.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- attributs.py | 3 +-- crans_utils.py | 2 +- lc_ldap.py | 22 ++++++++++++++++++---- ldap_locks.py | 45 ++++++++++++++++++++++++++++----------------- objets.py | 10 +++++----- 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/attributs.py b/attributs.py index c1c0d43..760d07c 100644 --- a/attributs.py +++ b/attributs.py @@ -556,8 +556,7 @@ class chbre(Attr): ldap_name = "chbre" def parse_value(self, chambre): - if self.parent != None: - if u'club' in [str(o) for o in self.parent['objectClass']]: + if self.parent != None and u'club' in [str(o) for o in self.parent['objectClass']]: if chambre in annuaires_pg.locaux_clubs(): self.value = chambre else: diff --git a/crans_utils.py b/crans_utils.py index 52e16d2..a487484 100644 --- a/crans_utils.py +++ b/crans_utils.py @@ -51,7 +51,7 @@ def find_rid_plage(rid): if isinstance(plages, list): for begin, end in plages: if begin <= rid <= end: - return tp, (begin, end) + return tp, config.rid_primaires[tp][0] else: (begin, end) = plages if begin <= rid <= end: diff --git a/lc_ldap.py b/lc_ldap.py index 0c1319c..a76841e 100644 --- a/lc_ldap.py +++ b/lc_ldap.py @@ -172,7 +172,7 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object): :py:class:`CransLdapObject`. On utilise la feature de ``sizelimit`` de ``python-ldap``""" if not isinstance(filterstr, unicode): - cranslib.deprecated.usage("search ne devrait utiliser que des unicode comme filtre(%r)" % filterstr, level=3) + cranslib.deprecated.usage("search ne devrait utiliser que des unicode comme filtre(%r)" % filterstr, level=2) filterstr = filterstr.decode('utf-8') ldap_res = self.search_ext_s(dn, scope, filterstr.encode('utf-8'), sizelimit=sizelimit) ret = [] @@ -314,7 +314,14 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object): for attribut in attribs: if attribut.unique: self.lockholder.addlock(key, str(attribut)) - return objets.new_cransldapobject(self, dn, 'rw', uldif) + try: + return objets.new_cransldapobject(self, dn, 'rw', uldif) + except ldap_locks.LockError: + for key, values in uldif.iteritems(): + attribs = [attributs.attrify(val, key, self) for val in values] + for attribut in attribs: + self.lockholder.removelock(key, str(attribut)) + raise def _find_id(self, attr, plage=None): '''Trouve un id libre. Si une plage est fournie, cherche @@ -342,8 +349,15 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object): raise EnvironmentError('Aucun %s libre dans la plage [%d, %d]' % (attr, plage[0], i)) else: - i = nonfree[-1]+1 - self.lockholder.addlock(attr, str(i)) + i = nonfree[-1] + 1 + while True: + try: + self.lockholder.addlock(attr, str(i)) + break + except ldap_locks.LockError: + i += 1 + except Exception: + raise return i def _check_parent(self, objdn): diff --git a/ldap_locks.py b/ldap_locks.py index f709739..7335d9a 100644 --- a/ldap_locks.py +++ b/ldap_locks.py @@ -40,20 +40,27 @@ import socket import crans_utils import collections import subprocess +import time -class LdapLockedByYou(exceptions.StandardError): +class LockError(exceptions.StandardError): + """ + Erreur standard de lock + """ + pass + +class LdapLockedByYou(LockError): """ Classe d'erreur pour les locks par le process courant """ pass -class LdapLockedByOther(exceptions.StandardError): +class LdapLockedByOther(LockError): """ Erreur car le lock est occupé par un autre process. """ pass -class LockFormatError(exceptions.StandardError): +class LockFormatError(LockError): """ L'objet lock qu'on a récupéré n'est pas tel qu'on le voudrait """ @@ -110,26 +117,29 @@ class LdapLockHolder: Sinon, on ne peut pas override le lock, et on laisse tomber. """ - try: - host, pid = self.getlock(item, value, Id) - if host == self.host and pid == self.pid: + host, pid, begin = self.getlock(item, value) + if time.time() - begin >= 600.0: + self.removelock(item, value, Id, True) + elif 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)) + raise LdapLockedByOther("La donnée %r=%r est lockée par un processus actif." % (item, value)) else: 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)) + raise LdapLockedByOther("La donnée %r=%r est lockée depuis une autre machine." % (item, value)) except ldap.NO_SUCH_OBJECT: pass except LockFormatError: self.removelock(item, value, Id) + except Exception: + raise dn = "%s=%s,%s" % (item, value, LOCKS_DN) - lockid = "%s-%s" % (self.host, self.pid) + lockid = "%s-%s-%s" % (self.host, self.pid, time.time()) modlist = ldap.modlist.addModlist({'objectClass' : 'lock', 'lockid' : lockid, item : value}) @@ -140,7 +150,7 @@ class LdapLockHolder: 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)) + raise LdapLockedByOther("La donnée %r=%r est lockée par un processus actif." % (item, value)) else: self.removelock(item, value, Id) try: @@ -167,18 +177,19 @@ class LdapLockHolder: except: pass - def getlock(self, item, value, Id): + def getlock(self, item, value): """ Trouve le lock item=value, et renvoie le contenu de lockinfo - via un couple host, pid + via un triplet host, pid, begin """ 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: - host, pid = result[0][1]['lockid'][0].split('-') - return host, int(pid) + try: + host, pid, begin = result[0][1]['lockid'][0].split('-') + except: + host, pid = result[0][1]['lockid'][0].split('-') + begin = time.time() + return host, int(pid), float(begin) except: raise LockFormatError diff --git a/objets.py b/objets.py index c70f9ae..40d6e20 100644 --- a/objets.py +++ b/objets.py @@ -565,7 +565,7 @@ class proprio(CransLdapObject): def machines(self): """Renvoie la liste des machines""" if self._machines is None: - self._machines = self.conn.search('mid=*', dn = self.dn, scope = 1, mode=self.mode) + self._machines = self.conn.search(u'mid=*', dn = self.dn, scope = 1, mode=self.mode) for m in self._machines: m._proprio = self return self._machines @@ -622,14 +622,14 @@ class machine(CransLdapObject): def _post_creation(self): """Fonction qui effectue quelques tâches lorsque la création est faite""" - if self._proprio: - if self._proprio._machines: + if self._proprio is not None: + if self._proprio._machines is not None: self._proprio._machines.append(self) def _post_deletion(self): """Fonction qui effectue quelques tâches lorsque l'on veut effacer""" - if self._proprio: - if self._proprio._machines: + if self._proprio is not None: + if self._proprio._machines is not None: self._proprio._machines.remove(self) class AssociationCrans(proprio):