[global] On diminue le risque de lock résiduel, et on corrige une faille des fonctions new[A-Z]*

* En cas d'erreur au create ou au save, on supprime les locks malgré tout
    * Les fonctions new* modifiaient directement le dico qu'on leur passait en
    argument, on fait désormais une copie de celui-ci, de façon à ce que test.py
    n'instancie pas toujours le même objet en croyant instancier des objets
    différents à chaque fois
    * Cela permet de trouver une typo dans services.py
    * crans_utils a été un peu corrigé.
This commit is contained in:
Pierre-Elliott Bécue 2013-05-30 18:44:15 +02:00
parent e0bce3f7d3
commit 616acdbb7a
6 changed files with 52 additions and 21 deletions

View file

@ -664,7 +664,6 @@ class macAddress(Attr):
def parse_value(self, mac):
self.value = format_mac(mac)
# XXX self.parent['ip6HostNumber'] = cequ'ilfaut
def __unicode__(self):
return unicode(self.value).lower()
@ -700,7 +699,10 @@ class ip6HostNumber(Attr):
ldap_name = "ip6HostNumber"
def parse_value(self, ip6):
if self.parent != None:
ip = ip6_of_mac(str(self.parent['macAddress'][0]), int(str(self.parent['rid'][0])))
else:
ip = ip6
self.value = netaddr.ip.IPAddress(ip)
def __unicode__(self):

View file

@ -136,7 +136,7 @@ def ip6_of_mac(mac, rid):
if net != "special":
return netaddr.IPAddress(netaddr.IPNetwork(config.prefix[net][0]).first + int(euid64v6, 16))
else:
return config.ipv6_machines_speciales[rid]
return netaddr.IPAddress(config.ipv6_machines_speciales[rid])
def strip_accents(a):
""" Supression des accents de la chaîne fournie"""

View file

@ -47,6 +47,7 @@ import attributs
import objets
import ldap_locks
import variables
import copy
import itertools
## import de /usr/scripts/
@ -218,10 +219,13 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object):
_, adherents = self.allMachinesAdherents(mode)
return adherents
def newMachine(self, parent, realm, uldif, login=None):
def newMachine(self, parent, realm, mldif, login=None):
"""Crée une nouvelle machine: ``realm`` peut être:
fil, fil-v6, wifi, wifi-v6, adm, gratuit, personnel-ens, special
mldif est un uldif pour la machine
--Partiellement implémenté"""
# On ne veut pas modifier mldif directement
uldif = copy.deepcopy(mldif)
if login is None:
login = self.current_login
#adm, serveurs, bornes, wifi, adherents, gratuit ou personnel-ens"""
@ -239,7 +243,7 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object):
uldif['objectClass'] = [u'machineWifi']
assert isinstance(owner, objets.adherent) or isinstance(owner, objets.club)
elif realm in ["adherents", "adherents-v6", "personnel-ens"]:
elif realm in ["adherents", "fil-v6", "personnel-ens"]:
uldif['objectClass'] = [u'machineFixe']
assert isinstance(owner, objets.adherent) or isinstance(owner, objets.club)
@ -249,7 +253,7 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object):
# On récupère la plage des mids
plage = itertools.chain(*[xrange(a,b+1) for (a,b) in config.rid_primaires[realm]])
# On récupère le premier id libre dans la plages s'il n'est pas
# déjà précisé dans le ldiff
# déjà précisé dans le ldif
rid = uldif.setdefault('rid', [unicode(self._find_id('rid', plage)) ])
# La machine peut-elle avoir une ipv4 ?
@ -262,14 +266,14 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object):
# Tout doit disparaître !!
machine = self._create_entity('mid=%s,%s' % (uldif['mid'][0], parent), uldif)
machine.history_add(login, u"inscription")
if machine.may_be(variables.created, self.droits + self._check_parent(machine.dn)):
return machine
else:
raise EnvironmentError("Vous n'avez pas le droit de créer cette machine.")
def newAdherent(self, uldif):
def newAdherent(self, aldif):
"""Crée un nouvel adhérent"""
uldif = copy.deepcopy(aldif)
aid = uldif.setdefault('aid', [ unicode(self._find_id('aid')) ])
uldif['objectClass'] = [u'adherent']
adherent = self._create_entity('aid=%s,%s' % (aid[0], variables.base_dn), uldif)
@ -278,8 +282,9 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object):
else:
raise EnvironmentError("Vous n'avez pas le droit de créer cet adhérent.")
def newClub(self, uldif):
def newClub(self, cldif):
"""Crée un nouveau club"""
uldif = copy.deepcopy(cldif)
cid = uldif.setdefault('cid', [ unicode(self._find_id('cid')) ])
uldif['objectClass'] = [u'club']
club = self._create_entity('cid=%s,%s' % (cid[0], variables.base_dn), uldif)
@ -288,9 +293,10 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object):
else:
raise EnvironmentError("Vous n'avez pas le droit de créer cet adhérent.")
def newFacture(self, uldif):
def newFacture(self, fldif):
"""Crée une nouvelle facture
--Non implémenté !"""
uldif = copy.deepcopy(fldif)
raise NotImplementedError()
def _create_entity(self, dn, uldif):

View file

@ -44,6 +44,7 @@ import re
import datetime
import time
import ldap
import traceback
from ldap.modlist import addModlist, modifyModlist
## import locaux
@ -189,25 +190,37 @@ class CransLdapObject(object):
faite"""
pass
def create(self):
def create(self, login=None):
"""Crée l'objet dans la base ldap, cette méthode vise à faire en sorte que
l'objet se crée lui-même, si celui qui essaye de le modifier a les droits
de le faire."""
if login is None:
login = self.conn.current_login
self._check_optionnal(comment="créez")
self.history_add(login, u"Inscription")
# Création de la requête LDAP
modlist = addModlist(self._modifs.to_ldif())
# Requête LDAP de création de l'objet
try:
self.conn.add_s(self.dn, modlist)
except Exception:
print traceback.format_exc()
return
# On nettoie les locks
for key, values in self._modifs.to_ldif().iteritems():
for value in values:
self.conn.lockholder.removelock(key, value)
self.conn.lockholder.purge(id(self))
# Services à relancer
services.services_to_restart(self.conn, {}, self._modifs)
self._post_creation()
# Vérifications après insertion.
self.check_modifs()
def bury(self, comm, login):
"""Sauvegarde l'objet dans un fichier dans le cimetière."""
self.history_add(login, u"destruction (%s)" % comm)
@ -251,25 +264,33 @@ class CransLdapObject(object):
try:
self.conn.modify_s(self.dn, modlist)
except:
# On nettoie les locks
self.conn.lockholder.purge(id(self))
self._modifs = self.attrs
raise EnvironmentError("Impossible de modifier l'objet, peut-être n'existe-t-il pas ?")
# On programme le redémarrage des services
services.services_to_restart(self.conn, self.attrs, self._modifs)
# On nettoie les locks
self.conn.lockholder.purge(id(self))
# Vérification des modifications.
self.check_modifs()
def check_modifs(self):
"""
Fonction qui vérifie que les modifications se sont bien
passées.
"""
# Vérification des modifications
old_ldif = self.conn.search_s(self.dn, ldap.SCOPE_BASE)[0][1]
old_uldif = lc_ldap.ldif_to_uldif(old_ldif)
old_uldif = lc_ldap.ldif_to_uldif(self.conn.search_s(self.dn, ldap.SCOPE_BASE)[0][1])
self.attrs = attributs.AttrsDict(self.conn, old_uldif, Parent=self)
differences = []
# On fait les différences entre les deux dicos
for attr in set(self.attrs.keys()).union(set(self._modifs.keys())):
exp_vals = set([unicode(i) for i in self.attrs.get(attr, [])])
new_vals = set([unicode(i) for i in self._modifs.get(attr, [])])
exp_vals = set([str(i) for i in self.attrs.get(attr, [])])
new_vals = set([str(i) for i in self._modifs.get(attr, [])])
if exp_vals != new_vals:
differences.append({"missing": exp_vals - new_vals, "having": new_vals - exp_vals})
print differences[-1]
if differences:
raise EnvironmentError("Les modifications apportées à l'objet %s n'ont pas été correctement sauvegardées\n%s" % (self.dn, differences))

View file

@ -31,7 +31,7 @@ services_to_attrs['mail_modif'] = []
# génération des arguments du service à redémarrer (par defaut [])
services_to_args={}
services_to_args['macip']=lambda x: issubclass(type(x.parent), objets.machine) and ([str(x)] if isinstance(x, attributs.ipHostNumber) else [ str(ip) for ip in x.parent.get('ipHostNumber',[]) ]) or ([ str(ip) for m in x.parent.machines() for ip in m.get('ipHostNumber',[])] if issubclass(type(x.parent), lc_ldap.proprio) else [])
services_to_args['macip']=lambda x: issubclass(type(x.parent), objets.machine) and ([str(x)] if isinstance(x, attributs.ipHostNumber) else [ str(ip) for ip in x.parent.get('ipHostNumber',[]) ]) or ([ str(ip) for m in x.parent.machines() for ip in m.get('ipHostNumber',[])] if issubclass(type(x.parent), objets.proprio) else [])
## Inutile pour blackliste pour le moment
#services_to_args['blacklist']=lambda x: issubclass(type(x.parent), lc_ldap.machine) and [ str(ip) for m in x.parent.proprio().machines() for ip in m['ipHostNumber'] ] or [ str(ip) for m in x.parent.machines() for ip in m['ipHostNumber'] ]
services_to_args['port']=lambda x: [str(x)] if isinstance(x, attributs.ipHostNumber) or isinstance(x, attributs.ip6HostNumber) else [ str(ip) for ip in x.parent.get('ipHostNumber',[]) ]

View file

@ -51,9 +51,10 @@ machine_ldif = {
borne_ldif = {
'macAddress' : [randomMAC()],
'host' : ["autotest-%s.crans.org" % randomStr() ],
'canal' : ["11"],
'host' : [u"autotest-%s.crans.org" % randomStr() ],
'canal' : [u"11"],
'puissance' : [u"52"],
'hotspot' : [u'FALSE'],
}
club_ldif = {
@ -132,6 +133,7 @@ def tests_machines(parent_dn, realm_list, ipsec=False):
try:
machine = conn.search('mid=%s' % machine['mid'][0], mode='rw')[0]
machine.delete()
del(machine)
except Exception as error:
print ERREUR
if show_traceback: print traceback.format_exc()