[gest_crans_lc] Découpage dans plusieurs fichiers
Héritage multiple banzai \o/
This commit is contained in:
parent
5d477cc1ac
commit
2d04dedf7b
10 changed files with 3209 additions and 3014 deletions
359
gestion/dialog/machine.py
Normal file
359
gestion/dialog/machine.py
Normal file
|
@ -0,0 +1,359 @@
|
|||
#!/bin/bash /usr/scripts/python.sh
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
u"""
|
||||
Copyright (C) Valentin Samir
|
||||
Licence : GPLv3
|
||||
|
||||
"""
|
||||
import sys
|
||||
if '/usr/scripts' not in sys.path:
|
||||
sys.path.append('/usr/scripts')
|
||||
|
||||
import lc_ldap.objets as objets
|
||||
import lc_ldap.attributs as attributs
|
||||
|
||||
import certificat
|
||||
import blacklist
|
||||
from CPS import TailCall, tailcaller, Continue
|
||||
|
||||
class Dialog(certificat.Dialog, blacklist.Dialog):
|
||||
def machine_information(self, cont, machine=None, objectClass=None, proprio=None, realm=None, fields_values=None):
|
||||
"""
|
||||
Permet de modifier une machine si elle est fournit par le paramètre machine
|
||||
sinon, crée une machine à partir de proprio, objectClass et realm.
|
||||
Si on ne fait qu'éditer une machine, proprio, objectClass et realm sont ignoré
|
||||
D'une machinère générale, il faudrait mettre ici tous les attributs single value
|
||||
et les multivalué que l'on peut simplement représenter de façon textuelle avec
|
||||
un séparateur.
|
||||
Pour le moment il y a :
|
||||
* host
|
||||
* macAddress
|
||||
* ipHostNumber
|
||||
* port(TCP|UDP)(in|out)
|
||||
"""
|
||||
a = attributs
|
||||
# Quel sont les attributs ldap dont on veut afficher et la taille du champs d'édition correspondant
|
||||
to_display = [(a.host, 30), (a.macAddress, 17), (a.ipHostNumber, 15),
|
||||
(a.portTCPout, 50), (a.portTCPin, 50), (a.portUDPout, 50),
|
||||
(a.portUDPin, 50)
|
||||
]
|
||||
|
||||
# Quel séparateur on utilise pour les champs multivalué
|
||||
separateur = ' '
|
||||
|
||||
def box():
|
||||
if machine:
|
||||
attrs = dict((k,[str(a) for a in at]) for k,at in machine.items())
|
||||
else:
|
||||
attrs = {}
|
||||
|
||||
fields = [("%s :" % a.legend, separateur.join(attrs.get(a.ldap_name, [a.default] if a.default else [])), l+1, l) for a,l in to_display]
|
||||
|
||||
return self.dialog.form(
|
||||
text="",
|
||||
timeout=self.timeout,
|
||||
height=0, width=0, form_height=0,
|
||||
fields=fields_values if fields_values else fields,
|
||||
title="Paramètres machine",
|
||||
backtitle="Gestion des machines du Crans")
|
||||
|
||||
def check_host(host, objectClass):
|
||||
# Si c'est une machine wifi, host doit finir par wifi.crans.org
|
||||
if "machineWifi" == objectClass or 'borneWifi' == objectClass:
|
||||
hostend = ".wifi.crans.org"
|
||||
# Si c'est une machine wifi, host doit finir par crans.org
|
||||
elif "machineFixe" == objectClass:
|
||||
hostend = ".crans.org"
|
||||
# Si l'object class est machineCrans, pas de vérification
|
||||
elif "machineCrans" == objectClass:
|
||||
return host
|
||||
# Sinon, libre à chachun d'ajouter d'autres objectClass ou de filtrer
|
||||
# plus finement fonction des droits de self.conn.droits
|
||||
else:
|
||||
raise ValueError("La machine n'est ni une machine fixe, ni une machine wifi mais %s ?!?" % objectClass)
|
||||
|
||||
if not host.endswith(hostend) and not '.' in host:
|
||||
host = "%s.wifi.crans.org" % host
|
||||
elif host.endswith(hostend) and '.' in host[:-len(hostend)]:
|
||||
raise ValueError("Nom d'hôte invalide, devrait finir par %s et être sans point dans la première partie" % hostend)
|
||||
elif not host.endswith(hostend) and '.' in host:
|
||||
raise ValueError("Nom d'hôte invalide, devrait finir par %s et être sans point dans la première partie" % hostend)
|
||||
|
||||
return host
|
||||
|
||||
def modif_machine(machine, attrs):
|
||||
with self.conn.search(dn=machine.dn, scope=0, mode='rw')[0] as machine:
|
||||
for (key, values) in attrs.items():
|
||||
machine[key]=values
|
||||
machine.validate_changes()
|
||||
machine.history_gen()
|
||||
machine.save()
|
||||
return machine
|
||||
|
||||
def create_machine(proprio, realm, attrs):
|
||||
# Dans ce cas, on a besoin d'un proprio et d'un realm pour déterminer le rid
|
||||
if proprio is None or realm is None:
|
||||
raise EnvironmentError("On essaye de créer une machine mais proprio ou realm vaut None")
|
||||
ldif = {
|
||||
'macAddress': ['%s' % attrs['macAddress']],
|
||||
'host': ['%s' % attrs['host']]
|
||||
}
|
||||
with self.conn.newMachine(proprio.dn, realm, ldif) as machine:
|
||||
for (key, values) in attrs.items():
|
||||
machine[key]=values
|
||||
if attributs.ipsec in machine.attribs:
|
||||
machine[attributs.ipsec.ldap_name]=attributs.ipsec.default
|
||||
machine.validate_changes()
|
||||
if self.confirm_item(machine, "Voulez vous vraiement créer cette machine ?"):
|
||||
machine.create()
|
||||
self.display_item(machine, "La machine à bien été créée", ipsec=True)
|
||||
return machine
|
||||
else:
|
||||
raise Continue(cont)
|
||||
|
||||
def todo(to_display, tags, objectClass, machine, proprio, realm, separateur, cont):
|
||||
attrs = {}
|
||||
# On traite les valeurs reçues
|
||||
for ((a,l),values) in zip(to_display, tags):
|
||||
values = unicode(values, 'utf-8')
|
||||
# Si le champs n'est pas single value, on utilise separateur pour découper
|
||||
# et on ne garde que les valeurs non vides
|
||||
if not a.singlevalue:
|
||||
values = [v for v in values.split(separateur) if v]
|
||||
# Pour host, on fait quelques vérification de syntaxe
|
||||
if a.ldap_name == 'host':
|
||||
attrs[a.ldap_name]=check_host(values, objectClass)
|
||||
else:
|
||||
attrs[a.ldap_name]=values
|
||||
# Soit on édite une machine existante
|
||||
if machine:
|
||||
machine = modif_machine(machine, attrs)
|
||||
# Soit on crée une nouvelle machine
|
||||
else:
|
||||
machine = create_machine(proprio, realm, attrs)
|
||||
raise Continue(cont(machine=machine))
|
||||
|
||||
|
||||
if machine:
|
||||
objectClass = machine["objectClass"][0]
|
||||
|
||||
(code, tags) = self.handle_dialog(cont, box)
|
||||
|
||||
# On prépare les fiels à afficher à l'utilisateur si une erreure à lieu
|
||||
# pendant le traitement des donnée (on n'éfface pas ce qui a déjà été entré
|
||||
# c'est au cableur de corriger ou d'annuler
|
||||
fields_values = [("%s :" % a.legend, values, l) for ((a,l),values) in zip(to_display, tags)]
|
||||
retry_cont = TailCall(self.machine_information, machine=machine, cont=cont, objectClass=objectClass, proprio=proprio, realm=realm, fields_values=fields_values)
|
||||
|
||||
return self.handle_dialog_result(
|
||||
code=code,
|
||||
output=tags,
|
||||
cancel_cont=cont,
|
||||
error_cont=retry_cont,
|
||||
codes_todo=[([self.dialog.DIALOG_OK], todo, [to_display, tags, objectClass, machine, proprio, realm, separateur, cont])]
|
||||
)
|
||||
|
||||
def modif_machine_blacklist(self, machine, cont):
|
||||
"""Raccourci vers edit_blacklist spécifique aux machines"""
|
||||
return self.edit_blacklist(obj=machine, title="Éditions des blacklist de la machine %s" % machine['host'][0], update_obj='machine', cont=cont)
|
||||
|
||||
|
||||
|
||||
def modif_machine_attributs(self, machine, attr, cont):
|
||||
"""Juste un raccourci vers edit_attributs spécifique aux machines"""
|
||||
return self.edit_attributs(obj=machine, update_obj='machine', attr=attr, title="Modification de la machine %s" % machine['host'][0], cont=cont)
|
||||
|
||||
def modif_adherent_attributs(self, adherent, attr, cont):
|
||||
"""Juste un raccourci vers edit_attributs spécifique aux adherents"""
|
||||
return self.edit_attributs(obj=adherent, update_obj='adherent', attr=attr, title="Modification de %s %s" % (adherent['prenom'][0], adherent['nom'][0]), cont=cont)
|
||||
|
||||
|
||||
def modif_machine_boolean(self, machine, cont):
|
||||
"""Juste un raccourci vers edit_boolean_attributs spécifique aux machines"""
|
||||
a = attributs
|
||||
attribs = [a.dnsIpv6]
|
||||
return self.edit_boolean_attributs(
|
||||
obj=machine,
|
||||
attribs=attribs,
|
||||
title="Édition des attributs booléen de la machine %s" % machine['host'][0],
|
||||
update_obj='machine',
|
||||
cont=cont)
|
||||
|
||||
|
||||
|
||||
def modif_machine(self, cont, machine=None, tag=None):
|
||||
"""
|
||||
Permet d'éditer une machine. Si fournie en paramètre on éditer en place,
|
||||
sinon, on en cherche une dans la base ldap
|
||||
"""
|
||||
if machine is None:
|
||||
machine = self.select(["machineFixe", "machineWifi", "machineCrans", "borneWifi"], "Recherche d'une machine pour modification", cont=cont)
|
||||
a = attributs
|
||||
menu_droits = {
|
||||
'Information' : [a.parent, a.cableur, a.nounou],
|
||||
'Autre': [a.parent, a.cableur, a.nounou],
|
||||
'Blackliste':[a.cableur, a.nounou],
|
||||
'Certificat': [a.parent, a.cableur, a.nounou],
|
||||
'Exemption' : [a.nounou],
|
||||
'Alias' : [a.parent, a.cableur, a.nounou],
|
||||
'Remarques' : [a.cableur, a.nounou],
|
||||
'SshKey' : [a.parent, a.nounou],
|
||||
'Supprimer' : [a.parent, a.cableur, a.nounou],
|
||||
}
|
||||
menu = {
|
||||
'Information' : {'text' : "Modifier le nom de machine, l'IP, adresse MAC", "callback":self.machine_information},
|
||||
'Autre' : {'text' : "Modifier les attribut booléen comme dsnIpv6", "callback":self.modif_machine_boolean},
|
||||
'Blackliste' : {'text': 'Modifier les blacklist de la machine', 'callback':self.modif_machine_blacklist},
|
||||
'Certificat' : {'text': 'Modifier les certificats de la machine', 'callback':self.modif_machine_certificat},
|
||||
'Exemption' : {'text':"Modifier la liste d'exemption d'upload de la machine", 'attribut':attributs.exempt},
|
||||
'Alias' : {'text': 'Créer ou supprimer un alias de la machine', 'attribut':attributs.hostAlias},
|
||||
'Remarques' : {'text':'Ajouter ou supprimer une remarque de la machine', 'attribut':attributs.info},
|
||||
'SshKey' : {'text':'Ajouter ou supprimer une clef ssh pour la machine', 'attribut':attributs.sshFingerprint},
|
||||
'Supprimer' : {'text':'Supprimer la machine', 'callback':self.delete_machine},
|
||||
}
|
||||
menu_order = ['Information', 'Blackliste', 'Certificat', 'Alias', 'Exemption', 'SshKey', 'Autre', 'Remarques', 'Supprimer']
|
||||
def box(default_item=None):
|
||||
return self.dialog.menu(
|
||||
"Que souhaitez vous modifier ?",
|
||||
width=0,
|
||||
height=0,
|
||||
menu_height=0,
|
||||
timeout=self.timeout,
|
||||
item_help=0,
|
||||
default_item=str(default_item),
|
||||
title="Modification de %s" % machine['host'][0],
|
||||
scrollbar=True,
|
||||
cancel_label="Retour",
|
||||
backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login,
|
||||
choices=[(key, menu[key]['text']) for key in menu_order if self.has_right(menu_droits[key], machine)])
|
||||
|
||||
def todo(tag, menu, machine, cont_ret):
|
||||
if not tag in menu_order:
|
||||
raise Continue(cont_ret)
|
||||
else:
|
||||
if 'callback' in menu[tag]:
|
||||
raise Continue(TailCall(menu[tag]['callback'], machine=machine, cont=cont_ret))
|
||||
elif 'attribut' in menu[tag]:
|
||||
raise Continue(TailCall(self.modif_machine_attributs, machine=machine, cont=cont_ret, attr=menu[tag]['attribut'].ldap_name))
|
||||
else:
|
||||
raise EnvironmentError("Il n'y a ni champ 'attribut' ni 'callback' pour le tag %s" % tag)
|
||||
|
||||
(code, tag) = self.handle_dialog(cont, box, tag)
|
||||
cont_ret = TailCall(self.modif_machine, cont=cont, machine=machine, tag=tag)
|
||||
|
||||
return self.handle_dialog_result(
|
||||
code=code,
|
||||
output=tag,
|
||||
cancel_cont=cont(machine=machine),
|
||||
error_cont=cont_ret,
|
||||
codes_todo=[([self.dialog.DIALOG_OK], todo, [tag, menu, machine, cont_ret])]
|
||||
)
|
||||
|
||||
def create_machine_proprio(self, cont, proprio, tag=None):
|
||||
"""Permet d'ajouter une machine à un proprio (adherent, club ou AssociationCrans)"""
|
||||
a = attributs
|
||||
menu_droits = {
|
||||
'Fixe' : [a.soi, a.cableur, a.nounou],
|
||||
'Wifi' : [a.soi, a.cableur, a.nounou],
|
||||
}
|
||||
menu = {
|
||||
'Fixe' : {'text' : "Machine filaire", 'objectClass':'machineFixe', 'realm':'adherents'},
|
||||
'Wifi' : {'text': 'Machine sans fil', 'objectClass':'machineWifi', 'realm':'wifi-adh'},
|
||||
}
|
||||
menu_order = ['Fixe', 'Wifi']
|
||||
if isinstance(proprio, objets.AssociationCrans):
|
||||
menu_droits.update({
|
||||
'Fixe' : [a.nounou],
|
||||
'Wifi' : [a.nounou],
|
||||
'Adm' : [a.nounou],
|
||||
})
|
||||
menu.update({
|
||||
'Fixe' : {'text' : "Ajouter un serveur sur le vlan adherent", 'objectClass':'machineCrans', 'realm':'serveurs'},
|
||||
'Wifi' : {'text': 'Ajouter une borne WiFi sur le vlan wifi', 'objectClass':'borneWifi', 'realm':'bornes'},
|
||||
'Adm' : {'text' : "Ajouter un serveur sur le vlan adm", "objectClass":"machineCrans", 'realm':'adm'},
|
||||
})
|
||||
menu_order.append('Adm')
|
||||
def box(default_item=None):
|
||||
return self.dialog.menu(
|
||||
"Type de Machine ?",
|
||||
width=0,
|
||||
height=0,
|
||||
menu_height=0,
|
||||
item_help=0,
|
||||
timeout=self.timeout,
|
||||
default_item=str(default_item),
|
||||
title="Création de machines",
|
||||
scrollbar=True,
|
||||
cancel_label="Retour",
|
||||
backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login,
|
||||
choices=[(key, menu[key]['text']) for key in menu_order if self.has_right(menu_droits[key], proprio)])
|
||||
|
||||
def todo(tag, menu, proprio, self_cont, cont):
|
||||
if not tag in menu_order:
|
||||
raise Continue(self_cont)
|
||||
else:
|
||||
return self.machine_information(
|
||||
cont=cont,
|
||||
machine=None,
|
||||
objectClass=menu[tag]['objectClass'],
|
||||
proprio=proprio,
|
||||
realm=menu[tag]['realm']
|
||||
)
|
||||
|
||||
(code, tag) = self.handle_dialog(cont, box, tag)
|
||||
cont = cont(proprio=None) if isinstance(proprio, objets.AssociationCrans) else cont(proprio=proprio)
|
||||
self_cont = TailCall(self.create_machine_proprio, cont=cont, proprio=proprio, tag=tag)
|
||||
|
||||
return self.handle_dialog_result(
|
||||
code=code,
|
||||
output=tag,
|
||||
cancel_cont=cont,
|
||||
error_cont=self_cont,
|
||||
codes_todo=[([self.dialog.DIALOG_OK], todo, [tag, menu, proprio, self_cont, cont])]
|
||||
)
|
||||
|
||||
def create_machine_adherent(self, cont, adherent=None):
|
||||
"""
|
||||
Permet d'ajouter une machine à un adhérent.
|
||||
On affiche un menu pour choisir le type de machine (juste filaire et wifi pour le moment)
|
||||
"""
|
||||
if adherent is None:
|
||||
adherent = self.select(["adherent"], "Recherche d'un adhérent pour lui ajouter une machine", cont=cont)
|
||||
return self.create_machine_proprio(cont=cont, proprio=adherent)
|
||||
|
||||
def create_machine_club(self, cont, club=None):
|
||||
"""
|
||||
Permet d'ajouter une machine à un club.
|
||||
On affiche un menu pour choisir le type de machine (juste filaire et wifi pour le moment)
|
||||
"""
|
||||
if club is None:
|
||||
club = self.select(["club"], "Recherche d'un club pour lui ajouter une machine", cont=cont)
|
||||
return self.create_machine_proprio(cont=cont, proprio=club)
|
||||
|
||||
def create_machine_crans(self, cont):
|
||||
"""Permet l'ajout d'une machine à l'association"""
|
||||
associationCrans = self.conn.search(dn="ou=data,dc=crans,dc=org", scope=0)[0]
|
||||
return self.create_machine_proprio(cont=cont, proprio=associationCrans)
|
||||
def delete_machine(self, cont, machine=None):
|
||||
"""Permet la suppression d'une machine de la base ldap"""
|
||||
if machine is None:
|
||||
machine = self.select(["machineFixe", "machineWifi", "machineCrans", "borneWifi"], "Recherche d'une machine pour supression", cont=cont)
|
||||
|
||||
def todo(machine):
|
||||
if self.confirm_item(item=machine, title="Voulez vous vraiement supprimer la machine ?", defaultno=True):
|
||||
with self.conn.search(dn=machine.dn, scope=0, mode='rw')[0] as machine:
|
||||
machine.delete()
|
||||
self.dialog.msgbox("La machine a bien été supprimée", timeout=self.timeout, title="Suppression d'une machine")
|
||||
raise Continue(cont(machine=None))
|
||||
else:
|
||||
raise Continue(cont)
|
||||
|
||||
return self.handle_dialog_result(
|
||||
code=self.dialog.DIALOG_OK,
|
||||
output="",
|
||||
cancel_cont=cont,
|
||||
error_cont=cont,
|
||||
codes_todo=[([self.dialog.DIALOG_OK], todo, [machine])]
|
||||
)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue