8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-27 07:02:26 +00:00

Deplace les checks dans les models + liaison entre ip_type et ip_list ranges

This commit is contained in:
Gabriel Detraz 2017-07-21 05:06:53 +02:00 committed by root
parent bbe687c29b
commit d5d4e2192b
5 changed files with 204 additions and 134 deletions

View file

@ -74,7 +74,7 @@ class AddInterfaceForm(EditInterfaceForm):
self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4" self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4"
if not infra: if not infra:
self.fields['type'].queryset = MachineType.objects.filter(ip_type__in=IpType.objects.filter(need_infra=False)) self.fields['type'].queryset = MachineType.objects.filter(ip_type__in=IpType.objects.filter(need_infra=False))
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True).filter(ip_type__in=IpType.objects.filter(need_infra=False)).filter(need_infra=False) self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True).filter(ip_type__in=IpType.objects.filter(need_infra=False))
else: else:
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True) self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True)
@ -92,7 +92,7 @@ class BaseEditInterfaceForm(EditInterfaceForm):
self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4" self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4"
if not infra: if not infra:
self.fields['type'].queryset = MachineType.objects.filter(ip_type__in=IpType.objects.filter(need_infra=False)) self.fields['type'].queryset = MachineType.objects.filter(ip_type__in=IpType.objects.filter(need_infra=False))
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True).filter(ip_type__in=IpType.objects.filter(need_infra=False)).filter(need_infra=False) self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True).filter(ip_type__in=IpType.objects.filter(need_infra=False))
else: else:
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True) self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True)
@ -152,14 +152,13 @@ class IpTypeForm(ModelForm):
super(IpTypeForm, self).__init__(*args, **kwargs) super(IpTypeForm, self).__init__(*args, **kwargs)
self.fields['type'].label = 'Type ip à ajouter' self.fields['type'].label = 'Type ip à ajouter'
class DelIpTypeForm(ModelForm): class EditIpTypeForm(IpTypeForm):
class Meta(IpTypeForm.Meta):
fields = ['extension','type','need_infra']
class DelIpTypeForm(forms.Form):
iptypes = forms.ModelMultipleChoiceField(queryset=IpType.objects.all(), label="Types d'ip actuelles", widget=forms.CheckboxSelectMultiple) iptypes = forms.ModelMultipleChoiceField(queryset=IpType.objects.all(), label="Types d'ip actuelles", widget=forms.CheckboxSelectMultiple)
class Meta:
exclude = ['type','extension','need_infra','domaine_ip','domaine_range']
model = IpType
class ExtensionForm(ModelForm): class ExtensionForm(ModelForm):
class Meta: class Meta:
model = Extension model = Extension

View file

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-07-21 01:50
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('machines', '0042_ns_ns'),
]
operations = [
migrations.RemoveField(
model_name='iplist',
name='need_infra',
),
migrations.AlterField(
model_name='iplist',
name='ip_type',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='machines.IpType'),
),
]

View file

@ -21,13 +21,14 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from django.db import models from django.db import models
from django.db.models.signals import post_save, post_delete from django.db.models.signals import post_save, pre_delete, post_delete
from django.dispatch import receiver from django.dispatch import receiver
from django.forms import ValidationError from django.forms import ValidationError
from macaddress.fields import MACAddressField
from netaddr import mac_bare, EUI
from django.core.validators import MinValueValidator,MaxValueValidator
from django.utils.functional import cached_property from django.utils.functional import cached_property
from macaddress.fields import MACAddressField
from netaddr import mac_bare, EUI, IPSet, IPNetwork
from django.core.validators import MinValueValidator,MaxValueValidator
import re
from re2o.settings import MAIN_EXTENSION from re2o.settings import MAIN_EXTENSION
@ -59,6 +60,48 @@ class IpType(models.Model):
domaine_ip = models.GenericIPAddressField(protocol='IPv4') domaine_ip = models.GenericIPAddressField(protocol='IPv4')
domaine_range = models.IntegerField(validators=[MinValueValidator(8), MaxValueValidator(32)]) domaine_range = models.IntegerField(validators=[MinValueValidator(8), MaxValueValidator(32)])
@cached_property
def network(self):
return str(self.domaine_ip) + '/' + str(self.domaine_range)
@cached_property
def ip_network(self):
return IPNetwork(self.network)
@cached_property
def ip_set(self):
return IPSet(self.ip_network)
@cached_property
def ip_set_as_str(self):
return [str(x) for x in self.ip_set]
@cached_property
def ip_objects(self):
return IpList.objects.filter(ipv4__in=self.ip_set_as_str)
def gen_ip_range(self):
# Creation du range d'ip dans les objets iplist
for ip in self.ip_network.iter_hosts():
obj, created = IpList.objects.get_or_create(ip_type=self, ipv4=str(ip))
def del_ip_range(self):
if Interface.objects.filter(ipv4__in=self.ip_objects):
raise ValidationError("Une ou plusieurs ip du range sont affectées, impossible de supprimer le range")
for ip in self.ip_objects():
ip.delete()
def clean(self):
# On check que les / ne se recoupent pas
for element in IpType.objects.all():
if not self.ip_set.isdisjoint(element.ip_set):
raise ValidationError("Le range indiqué n'est pas disjoint des ranges existants")
return
def save(self, *args, **kwargs):
self.clean()
super(IpType, self).save(*args, **kwargs)
def __str__(self): def __str__(self):
return self.type return self.type
@ -133,10 +176,18 @@ class Domain(models.Model):
unique_together = ("name", "extension") unique_together = ("name", "extension")
def clean(self): def clean(self):
""" Validation du nom de domaine, extensions dans type de machine, prefixe pas plus long que 63 caractères """
if self.interface_parent and self.cname: if self.interface_parent and self.cname:
raise ValidationError("On ne peut créer à la fois A et CNAME") raise ValidationError("On ne peut créer à la fois A et CNAME")
if self.cname==self: if self.cname==self:
raise ValidationError("On ne peut créer un cname sur lui même") raise ValidationError("On ne peut créer un cname sur lui même")
HOSTNAME_LABEL_PATTERN = re.compile("(?!-)[A-Z\d-]+(?<!-)$", re.IGNORECASE)
dns = self.name.lower()
if len(dns) > 63:
raise ValidationError("Le nom de domaine %s est trop long (maximum de 63 caractères)." % dns)
if not HOSTNAME_LABEL_PATTERN.match(dns):
raise ValidationError("Ce nom de domaine %s contient des carractères interdits." % dns)
return
def __str__(self): def __str__(self):
return str(self.name) + str(self.extension) return str(self.name) + str(self.extension)
@ -145,8 +196,20 @@ class IpList(models.Model):
PRETTY_NAME = "Addresses ipv4" PRETTY_NAME = "Addresses ipv4"
ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True) ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True)
ip_type = models.ForeignKey('IpType', on_delete=models.PROTECT) ip_type = models.ForeignKey('IpType', on_delete=models.CASCADE)
need_infra = models.BooleanField(default=False)
@cached_property
def need_infra(self):
return self.ip_type.need_infra
def clean(self):
if not str(self.ipv4) in self.ip_type.ip_set_as_str:
raise ValidationError("L'ipv4 et le range de l'iptype ne correspondent pas!")
return
def save(self, *args, **kwargs):
self.clean()
super(IpList, self).save(*args, **kwargs)
def __str__(self): def __str__(self):
return self.ipv4 return self.ipv4
@ -173,3 +236,8 @@ def interface_post_delete(sender, **kwargs):
user = interface.machine.user user = interface.machine.user
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True) user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
@receiver(post_save, sender=IpType)
def iptype_post_save(sender, **kwargs):
iptype = kwargs['instance']
iptype.gen_ip_range()

View file

@ -44,26 +44,12 @@ from reversion.models import Version
import re import re
from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm
from .forms import IpTypeForm, DelIpTypeForm, AliasForm, DelAliasForm, NsForm, DelNsForm, MxForm, DelMxForm from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, AliasForm, DelAliasForm, NsForm, DelNsForm, MxForm, DelMxForm
from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain
from users.models import User from users.models import User
from users.models import all_has_access from users.models import all_has_access
from preferences.models import GeneralOption, OptionalMachine from preferences.models import GeneralOption, OptionalMachine
def full_domain_validator(request, domain):
""" Validation du nom de domaine, extensions dans type de machine, prefixe pas plus long que 63 caractères """
HOSTNAME_LABEL_PATTERN = re.compile("(?!-)[A-Z\d-]+(?<!-)$", re.IGNORECASE)
dns = domain.name.lower()
if len(dns) > 63:
messages.error(request,
"Le nom de domaine %s est trop long (maximum de 63 caractères)." % dns)
return False
if not HOSTNAME_LABEL_PATTERN.match(dns):
messages.error(request,
"Ce nom de domaine %s contient des carractères interdits." % dns)
return False
return True
def all_active_interfaces(): def all_active_interfaces():
"""Renvoie l'ensemble des machines autorisées à sortir sur internet """ """Renvoie l'ensemble des machines autorisées à sortir sur internet """
return Interface.objects.filter(machine__in=Machine.objects.filter(user__in=all_has_access()).filter(active=True)).select_related('domain').select_related('machine').select_related('type').select_related('ipv4').select_related('domain__extension').select_related('ipv4__ip_type').distinct() return Interface.objects.filter(machine__in=Machine.objects.filter(user__in=all_has_access()).filter(active=True)).select_related('domain').select_related('machine').select_related('type').select_related('ipv4').select_related('domain__extension').select_related('ipv4__ip_type').distinct()
@ -99,10 +85,7 @@ def assign_ips(user):
def free_ip(type): def free_ip(type):
""" Renvoie la liste des ip disponibles """ """ Renvoie la liste des ip disponibles """
if not type.need_infra: return IpList.objects.filter(interface__isnull=True).filter(ip_type=type)
return IpList.objects.filter(interface__isnull=True).filter(ip_type=type).filter(need_infra=False)
else:
return IpList.objects.filter(interface__isnull=True).filter(ip_type=type)
def assign_ipv4(interface): def assign_ipv4(interface):
""" Assigne une ip à l'interface """ """ Assigne une ip à l'interface """
@ -148,27 +131,26 @@ def new_machine(request, userid):
new_machine.user = user new_machine.user = user
new_interface = interface.save(commit=False) new_interface = interface.save(commit=False)
new_domain = domain.save(commit=False) new_domain = domain.save(commit=False)
if full_domain_validator(request, new_domain): with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_machine.save()
new_machine.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") new_interface.machine = new_machine
new_interface.machine = new_machine if free_ip(new_interface.type.ip_type) and not new_interface.ipv4:
if free_ip(new_interface.type.ip_type) and not new_interface.ipv4: new_interface = assign_ipv4(new_interface)
new_interface = assign_ipv4(new_interface) elif not new_interface.ipv4:
elif not new_interface.ipv4: messages.error(request, u"Il n'y a plus d'ip disponibles")
messages.error(request, u"Il n'y a plus d'ip disponibles") with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_interface.save()
new_interface.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") new_domain.interface_parent = new_interface
new_domain.interface_parent = new_interface with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_domain.save()
new_domain.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") messages.success(request, "La machine a été crée")
messages.success(request, "La machine a été crée") return redirect("/users/profil/" + str(user.id))
return redirect("/users/profil/" + str(user.id))
except TypeError: except TypeError:
messages.error(request, u"Adresse mac invalide") messages.error(request, u"Adresse mac invalide")
return form({'machineform': machine, 'interfaceform': interface, 'domainform': domain}, 'machines/machine.html', request) return form({'machineform': machine, 'interfaceform': interface, 'domainform': domain}, 'machines/machine.html', request)
@ -195,23 +177,22 @@ def edit_interface(request, interfaceid):
new_interface = interface_form.save(commit=False) new_interface = interface_form.save(commit=False)
new_machine = machine_form.save(commit=False) new_machine = machine_form.save(commit=False)
new_domain = domain_form.save(commit=False) new_domain = domain_form.save(commit=False)
if full_domain_validator(request, new_domain): with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_machine.save()
new_machine.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in machine_form.changed_data))
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in machine_form.changed_data)) if free_ip(new_interface.type.ip_type) and not new_interface.ipv4:
if free_ip(new_interface.type.ip_type) and not new_interface.ipv4: new_interface = assign_ipv4(new_interface)
new_interface = assign_ipv4(new_interface) with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_interface.save()
new_interface.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in interface_form.changed_data))
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in interface_form.changed_data)) with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_domain.save()
new_domain.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in domain_form.changed_data))
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in domain_form.changed_data)) messages.success(request, "La machine a été modifiée")
messages.success(request, "La machine a été modifiée") return redirect("/users/profil/" + str(interface.machine.user.id))
return redirect("/users/profil/" + str(interface.machine.user.id))
except TypeError: except TypeError:
messages.error(request, u"Adresse mac invalide") messages.error(request, u"Adresse mac invalide")
return form({'machineform': machine_form, 'interfaceform': interface_form, 'domainform': domain_form}, 'machines/machine.html', request) return form({'machineform': machine_form, 'interfaceform': interface_form, 'domainform': domain_form}, 'machines/machine.html', request)
@ -258,22 +239,21 @@ def new_interface(request, machineid):
new_interface = interface_form.save(commit=False) new_interface = interface_form.save(commit=False)
new_interface.machine = machine new_interface.machine = machine
new_domain = domain_form.save(commit=False) new_domain = domain_form.save(commit=False)
if full_domain_validator(request, new_domain): if free_ip(new_interface.type.ip_type) and not new_interface.ipv4:
if free_ip(new_interface.type.ip_type) and not new_interface.ipv4: new_interface = assign_ipv4(new_interface)
new_interface = assign_ipv4(new_interface) elif not new_interface.ipv4:
elif not new_interface.ipv4: messages.error(request, u"Il n'y a plus d'ip disponibles")
messages.error(request, u"Il n'y a plus d'ip disponibles") with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_interface.save()
new_interface.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") new_domain.interface_parent = new_interface
new_domain.interface_parent = new_interface with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_domain.save()
new_domain.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") messages.success(request, "L'interface a été ajoutée")
messages.success(request, "L'interface a été ajoutée") return redirect("/users/profil/" + str(machine.user.id))
return redirect("/users/profil/" + str(machine.user.id))
except TypeError: except TypeError:
messages.error(request, u"Adresse mac invalide") messages.error(request, u"Adresse mac invalide")
return form({'interfaceform': interface_form, 'domainform': domain_form}, 'machines/machine.html', request) return form({'interfaceform': interface_form, 'domainform': domain_form}, 'machines/machine.html', request)
@ -321,7 +301,7 @@ def edit_iptype(request, iptypeid):
except IpType.DoesNotExist: except IpType.DoesNotExist:
messages.error(request, u"Entrée inexistante" ) messages.error(request, u"Entrée inexistante" )
return redirect("/machines/index_iptype/") return redirect("/machines/index_iptype/")
iptype = IpTypeForm(request.POST or None, instance=iptype_instance) iptype = EditIpTypeForm(request.POST or None, instance=iptype_instance)
if iptype.is_valid(): if iptype.is_valid():
with transaction.atomic(), reversion.create_revision(): with transaction.atomic(), reversion.create_revision():
iptype.save() iptype.save()

View file

@ -35,7 +35,7 @@ from users.views import form
from users.models import User from users.models import User
from machines.forms import AliasForm, NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm from machines.forms import AliasForm, NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm
from machines.views import free_ip, full_domain_validator, assign_ipv4 from machines.views import free_ip, assign_ipv4
from preferences.models import GeneralOption from preferences.models import GeneralOption
from re2o.settings import ASSO_PSEUDO from re2o.settings import ASSO_PSEUDO
@ -161,32 +161,31 @@ def new_switch(request):
new_interface = interface.save(commit=False) new_interface = interface.save(commit=False)
new_switch = switch.save(commit=False) new_switch = switch.save(commit=False)
new_domain = domain.save(commit=False) new_domain = domain.save(commit=False)
if full_domain_validator(request, new_domain): with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_machine.save()
new_machine.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") new_interface.machine = new_machine
new_interface.machine = new_machine if free_ip(new_interface.type.ip_type) and not new_interface.ipv4:
if free_ip(new_interface.type.ip_type) and not new_interface.ipv4: new_interface = assign_ipv4(new_interface)
new_interface = assign_ipv4(new_interface) elif not new_interface.ipv4:
elif not new_interface.ipv4: messages.error(request, "Il n'y a plus d'ip disponibles")
messages.error(request, "Il n'y a plus d'ip disponibles") with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_interface.save()
new_interface.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") new_domain.interface_parent = new_interface
new_domain.interface_parent = new_interface with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_domain.save()
new_domain.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") new_switch.switch_interface = new_interface
new_switch.switch_interface = new_interface with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_switch.save()
new_switch.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Création")
reversion.set_comment("Création") messages.success(request, "Le switch a été crée")
messages.success(request, "Le switch a été crée") return redirect("/topologie/")
return redirect("/topologie/")
return form({'topoform':switch, 'machineform': machine, 'interfaceform': interface, 'domainform': domain}, 'topologie/switch.html', request) return form({'topoform':switch, 'machineform': machine, 'interfaceform': interface, 'domainform': domain}, 'topologie/switch.html', request)
@login_required @login_required
@ -206,25 +205,24 @@ def edit_switch(request, switch_id):
new_machine = machine_form.save(commit=False) new_machine = machine_form.save(commit=False)
new_switch = switch_form.save(commit=False) new_switch = switch_form.save(commit=False)
new_domain = domain_form.save(commit=False) new_domain = domain_form.save(commit=False)
if full_domain_validator(request, new_domain): with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_machine.save()
new_machine.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in machine_form.changed_data))
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in machine_form.changed_data)) with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_interface.save()
new_interface.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in interface_form.changed_data))
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in interface_form.changed_data)) with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_domain.save()
new_domain.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in domain_form.changed_data))
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in domain_form.changed_data)) with transaction.atomic(), reversion.create_revision():
with transaction.atomic(), reversion.create_revision(): new_switch.save()
new_switch.save() reversion.set_user(request.user)
reversion.set_user(request.user) reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in switch_form.changed_data))
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in switch_form.changed_data)) messages.success(request, "Le switch a bien été modifié")
messages.success(request, "Le switch a bien été modifié") return redirect("/topologie/")
return redirect("/topologie/")
return form({'topoform':switch_form, 'machineform': machine_form, 'interfaceform': interface_form, 'domainform': domain_form}, 'topologie/switch.html', request) return form({'topoform':switch_form, 'machineform': machine_form, 'interfaceform': interface_form, 'domainform': domain_form}, 'topologie/switch.html', request)
@login_required @login_required