[lc_ldap, services] On ajoute ce qui faut à la base de service pour que generete régénère la conf
C'est un début, ça vise surtout à être compatible avec ce qui est existant.
This commit is contained in:
parent
ed140bf4b5
commit
1d61048828
2 changed files with 251 additions and 0 deletions
|
@ -59,6 +59,7 @@ import config
|
|||
import crans_utils
|
||||
import attributs
|
||||
import ldap_locks
|
||||
import services
|
||||
|
||||
uri = 'ldap://ldap.adm.crans.org/'
|
||||
base_dn = 'ou=data,dc=crans,dc=org'
|
||||
|
@ -578,6 +579,7 @@ class CransLdapObject(object):
|
|||
modlist = addModlist(cldif_to_ldif(self._modifs))
|
||||
# Requête LDAP de création de l'objet
|
||||
self.conn.add_s(self.dn, modlist)
|
||||
services.services_to_restart(self.conn, {}, self._modifs)
|
||||
|
||||
def bury(self, comm, login):
|
||||
self.history_add(login, u"destruction (%s)" % comm)
|
||||
|
@ -601,6 +603,7 @@ class CransLdapObject(object):
|
|||
raise EnvironmentError("Vous n'avez pas le droit de supprimer %s." % self.dn)
|
||||
self.bury(comm, login)
|
||||
self.conn.delete_s(self.dn)
|
||||
services.services_to_restart(self.conn, self.attrs, {})
|
||||
|
||||
def save(self):
|
||||
"""Sauvegarde dans la base les modifications apportées à l'objet.
|
||||
|
@ -624,6 +627,9 @@ class CransLdapObject(object):
|
|||
except:
|
||||
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)
|
||||
|
||||
# Vérification des modifications
|
||||
self.attrs = attributs.AttrsDict(self.conn, self.conn.search_s(self.dn, 0)[0][1], Parent=self)
|
||||
differences = []
|
||||
|
@ -886,6 +892,7 @@ class proprio(CransLdapObject):
|
|||
machine.delete(comm, login)
|
||||
self.bury(comm, login)
|
||||
self.conn.delete_s(self.dn)
|
||||
services.services_to_restart(self.conn, self.attrs, {})
|
||||
|
||||
class machine(CransLdapObject):
|
||||
u""" Une machine """
|
||||
|
|
244
services.py
Normal file
244
services.py
Normal file
|
@ -0,0 +1,244 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import ldap
|
||||
import lc_ldap
|
||||
import attributs
|
||||
|
||||
services_dn = 'ou=services,dc=crans,dc=org'
|
||||
|
||||
# liste des attributs dont dépend un service
|
||||
services_to_attrs = {}
|
||||
services_to_attrs['macip'] = [ attributs.ipHostNumber, attributs.ip6HostNumber, attributs.macAddress, attributs.paiement, attributs.carteEtudiant ]
|
||||
services_to_attrs['dns'] = [ attributs.ipHostNumber, attributs.ip6HostNumber, attributs.sshFingerprint, attributs.host, attributs.hostAlias, attributs.dnsIpv6 ]
|
||||
services_to_attrs['blacklist'] = [ attributs.blacklist, attributs.chbre, attributs.mailInvalide ] + services_to_attrs['macip']
|
||||
services_to_attrs['ports'] = [ attributs.portUDPout, attributs.portUDPin, attributs.portTCPout, attributs.portTCPin ]
|
||||
services_to_attrs['droits'] = [ attributs.droits ]
|
||||
services_to_attrs['mail_ajout_droits'] = [ attributs.droits ]
|
||||
services_to_attrs['dhcp'] = services_to_attrs['macip']
|
||||
#services_to_attrs['home'] = [ attributs.homeDirectory ] ## Vérifier que ça ne fasse pas de caca
|
||||
|
||||
services_to_attrs['del_user'] = []
|
||||
services_to_attrs['mail_bienvenue'] = []
|
||||
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), lc_ldap.machine) and ([str(x)] if isinstance(x, attributs.ipHostNumber) else [ str(ip) for ip in x.parent['ipHostNumber'] ]) or [ str(ip) for m in x.parent.machines() for ip in m['ipHostNumber']]
|
||||
## 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['ipHostNumber'] ]
|
||||
services_to_args['home']=lambda x: u'cransAccount' in [ str(o) for o in x.parent['objectClass']] and [ "%s,%s,%s" % (x.parent['homeDirectory'][0],x.parent['uidNumber'][0],x.parent['uid'][0]) ] or [ "%s,%s,%s,%s" % (x.parent['homeDirectory'][0],x.parent['uidNumber'][0],x.parent['uid'][0],x.parent['mail'][0]) ]
|
||||
services_to_args['mail_ajout_droits'] = lambda x: "%s:%s" % (x.parent['uid'][0], x)
|
||||
|
||||
# Quand redémarrer le service (par defaut 0)
|
||||
services_to_time={}
|
||||
services_to_time['blacklist']=lambda x: isinstance(x, attributs.blacklist) and (0 if x.value['debut'] == '-' else x.value['debut']) or 0
|
||||
|
||||
attrs_to_services = {}
|
||||
for (key, values) in services_to_attrs.items():
|
||||
for value in values:
|
||||
attrs_to_services[value] = attrs_to_services.get(value, []) + [key]
|
||||
|
||||
# Identique à celle dans ldap_crans.py
|
||||
def preattr(val):
|
||||
"""
|
||||
val est :
|
||||
* un entier
|
||||
* une chaîne
|
||||
* une liste avec un seul entier ou une seule chaîne
|
||||
|
||||
Retourne [ len(str(val).strip), str(val).strip en utf-8 ]
|
||||
"""
|
||||
|
||||
if isinstance(val, list) and len(val) == 1:
|
||||
return preattr(val[0])
|
||||
|
||||
elif isinstance(val, str) or isinstance(val, int):
|
||||
val = str(val).strip()
|
||||
# On passe tout en utf-8 pour ne pas avoir de problèmes
|
||||
# d'accents dans la base
|
||||
return [len(val), val]
|
||||
elif isinstance(val, unicode):
|
||||
val = val.strip()
|
||||
return [len(val), val.encode('utf-8')]
|
||||
else:
|
||||
raise TypeError(type(val))
|
||||
|
||||
# Presque identique à celle dans ldap_crans.py
|
||||
def service_to_restart(conn, new=None, args=[], start=0):
|
||||
"""
|
||||
start indique la date (en secondes depuis epoch) à partir du
|
||||
moment où cette action sera effectuée.
|
||||
|
||||
Si new = None retourne la liste des services à redémarrer.
|
||||
|
||||
Si new est fourni, mais ne commence pas par '-', on ajoute
|
||||
le service à la liste avec les arguments args (args doit être
|
||||
une liste).
|
||||
|
||||
Si new commence par '-', on supprime le service si son start
|
||||
est dans le futur.
|
||||
|
||||
Si new commence par '--', on supprime le service sans condition.
|
||||
"""
|
||||
if new: new = preattr(new)[1]
|
||||
|
||||
# Quels services sont déjà à redémarrer ?
|
||||
serv = {} # { service: [ arguments ] }
|
||||
serv_dates = {} # { service: [ dates de restart ] }
|
||||
services = []
|
||||
for s in conn.search_s(services_dn, 1, 'objectClass=service'):
|
||||
s = s[1]
|
||||
serv[s['cn'][0]] = s.get('args', [])
|
||||
serv_dates[s['cn'][0]] = s.get('start', [])
|
||||
services.append(Service(s['cn'][0], s.get('args', []), s.get('start', [])))
|
||||
|
||||
# Retourne la liste des services à redémarrer
|
||||
if not new: return services
|
||||
|
||||
# Effacement d'un service
|
||||
if new[0] == '-':
|
||||
if new[1] == '-':
|
||||
# Double -- on enlève quelque soit la date
|
||||
remove_dn = 'cn=%s,%s' % (new[2:], services_dn)
|
||||
else:
|
||||
# On enlève uniquement si la date est passée
|
||||
remove_dn = 'cn=%s,%s' % (new[1:], services_dn)
|
||||
if not serv.has_key(new[1:]):
|
||||
# Existe pas => rien à faire
|
||||
return
|
||||
keep_date = []
|
||||
for date in serv_dates[new[1:]]:
|
||||
if time.time() < int(date):
|
||||
keep_date.append(date)
|
||||
if keep_date:
|
||||
mods = [{'start': serv_dates[new[1:]]}, { 'start': keep_date }]
|
||||
conn.modify_s(remove_dn, ldap.modlist.modifyModlist(*mods))
|
||||
remove_dn = None
|
||||
|
||||
if remove_dn:
|
||||
# Suppression
|
||||
try: conn.delete_s(remove_dn)
|
||||
except: pass
|
||||
# Si n'existe pas => Erreur mais le résultat est là.
|
||||
return
|
||||
|
||||
serv_dn = 'cn=%s,%s' % (new, services_dn)
|
||||
|
||||
# Conversion avant stockage dans la base
|
||||
if isinstance(args, basestring):
|
||||
args = [args]
|
||||
args = map(lambda x:preattr(x)[1], args)
|
||||
try:
|
||||
start = [int(start)]
|
||||
except TypeError:
|
||||
pass
|
||||
start = map(lambda x:preattr(x)[1], start)
|
||||
|
||||
if new in serv.keys():
|
||||
modlist = []
|
||||
|
||||
new_args = []
|
||||
# Nouveaux arguments ?
|
||||
for arg in args:
|
||||
if arg not in serv[new]:
|
||||
new_args.append(arg)
|
||||
if new_args:
|
||||
modlist += ldap.modlist.modifyModlist({'args': serv[new]},
|
||||
{'args': serv[new] + new_args})
|
||||
|
||||
new_date = []
|
||||
# Nouvelle date ?
|
||||
for date in start:
|
||||
if date not in serv_dates[new]:
|
||||
new_date.append(date)
|
||||
if new_date:
|
||||
modlist += ldap.modlist.modifyModlist({'start': serv_dates[new]},
|
||||
{'start': serv_dates[new] + new_date})
|
||||
|
||||
if modlist:
|
||||
try:
|
||||
conn.modify_s(serv_dn, modlist)
|
||||
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||
# Pas grave
|
||||
pass
|
||||
# else rien à faire
|
||||
else:
|
||||
# Entrée non présente -> ajout
|
||||
modlist = ldap.modlist.addModlist({ 'objectClass': 'service',
|
||||
'cn': new,
|
||||
'args': args,
|
||||
'start': start })
|
||||
try:
|
||||
conn.add_s(serv_dn, modlist)
|
||||
except ldap.ALREADY_EXISTS:
|
||||
# Existe déja => rien à faire
|
||||
pass
|
||||
|
||||
def services_to_restart(conn, old_attrs={}, new_attrs={}):
|
||||
"""Détermine quels sont les services à reconfigurer"""
|
||||
old_attrs = dict((attributs.CRANS_ATTRIBUTES[key], value) for key,value in old_attrs.items())
|
||||
new_attrs = dict((attributs.CRANS_ATTRIBUTES[key], value) for key,value in new_attrs.items())
|
||||
|
||||
created_attr = [ attr for name in new_attrs.keys() if not name in old_attrs.keys() for attr in new_attrs[name]]
|
||||
deleted_attr = [ attr for name in old_attrs.keys() if not name in new_attrs.keys() for attr in old_attrs[name]]
|
||||
updated_attr = [ (old_attrs[name], new_attrs[name],
|
||||
[ i for i in old_attrs[name] if i.value not in [ j.value for j in new_attrs[name]]],
|
||||
[ i for i in new_attrs[name] if i.value not in [ j.value for j in old_attrs[name]]],
|
||||
) for name in set(new_attrs.keys()).intersection(old_attrs.keys()) if old_attrs[name][-1].value != new_attrs[name][-1].value ]
|
||||
updated_attr_new = [ i for j in updated_attr for i in j[3]]
|
||||
updated_attr_old = [ i for j in updated_attr for i in j[2]]
|
||||
|
||||
services_to_restart = {}
|
||||
for attr in [ attr for l in [created_attr, deleted_attr, updated_attr_new] for attr in l]:
|
||||
for service in attrs_to_services.get(attr.__class__, []):
|
||||
services_to_restart[service] = services_to_restart.get(service, []) + [attr]
|
||||
|
||||
for service in services_to_restart.keys():
|
||||
for attr in services_to_restart[service]:
|
||||
start = 0
|
||||
arg = []
|
||||
if service in services_to_args.keys():
|
||||
arg.extend(services_to_args[service](attr))
|
||||
if attr in updated_attr_new:
|
||||
arg.extend(services_to_args[service](updated_attr_old[updated_attr_new.index(attr)]))
|
||||
if service in services_to_time.keys():
|
||||
start = services_to_time[service](attr)
|
||||
#print "%s,%s,%s" % (service, arg, start)
|
||||
service_to_restart(conn, service, arg, start)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Identique à la classe dans ldap_crans.py
|
||||
class Service:
|
||||
""" Définit un service à redémarrer """
|
||||
def __init__(self, nom, args=[], start=[]):
|
||||
"""
|
||||
Nom du service
|
||||
Liste des arguments
|
||||
Liste d'horaires de démarrages
|
||||
"""
|
||||
|
||||
self.nom = nom
|
||||
self.args = args
|
||||
self.start = map(int, start)
|
||||
|
||||
def __unicode__(self):
|
||||
starting = self.start
|
||||
starting.sort()
|
||||
dates = u' et '.join(map(lambda t: t < time.time() and \
|
||||
u"maintenant" or time.strftime(date_format,
|
||||
time.localtime(t)),
|
||||
self.start))
|
||||
dates = u" à partir d%s %s" % (dates.startswith(u"maintenant") and u"e" or u"u",
|
||||
dates)
|
||||
return (u"%s(%s)%s" % (self.nom,
|
||||
u','.join([i.decode("UTF-8") for i in self.args]),
|
||||
dates)).replace(u" et maintenant", u"")
|
||||
|
||||
def __str__(self):
|
||||
return self.__unicode__().encode("utf-8", "ignore")
|
Loading…
Add table
Add a link
Reference in a new issue