8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-23 23:43:47 +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"
if not infra:
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:
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"
if not infra:
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:
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True)
@ -152,14 +152,13 @@ class IpTypeForm(ModelForm):
super(IpTypeForm, self).__init__(*args, **kwargs)
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)
class Meta:
exclude = ['type','extension','need_infra','domaine_ip','domaine_range']
model = IpType
class ExtensionForm(ModelForm):
class Meta:
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.
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.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 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
@ -59,6 +60,48 @@ class IpType(models.Model):
domaine_ip = models.GenericIPAddressField(protocol='IPv4')
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):
return self.type
@ -133,10 +176,18 @@ class Domain(models.Model):
unique_together = ("name", "extension")
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:
raise ValidationError("On ne peut créer à la fois A et CNAME")
if self.cname==self:
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):
return str(self.name) + str(self.extension)
@ -145,8 +196,20 @@ class IpList(models.Model):
PRETTY_NAME = "Addresses ipv4"
ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True)
ip_type = models.ForeignKey('IpType', on_delete=models.PROTECT)
need_infra = models.BooleanField(default=False)
ip_type = models.ForeignKey('IpType', on_delete=models.CASCADE)
@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):
return self.ipv4
@ -173,3 +236,8 @@ def interface_post_delete(sender, **kwargs):
user = interface.machine.user
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
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 users.models import User
from users.models import all_has_access
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():
"""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()
@ -99,10 +85,7 @@ def assign_ips(user):
def free_ip(type):
""" Renvoie la liste des ip disponibles """
if not type.need_infra:
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)
return IpList.objects.filter(interface__isnull=True).filter(ip_type=type)
def assign_ipv4(interface):
""" Assigne une ip à l'interface """
@ -148,27 +131,26 @@ def new_machine(request, userid):
new_machine.user = user
new_interface = interface.save(commit=False)
new_domain = domain.save(commit=False)
if full_domain_validator(request, new_domain):
with transaction.atomic(), reversion.create_revision():
new_machine.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
new_interface.machine = new_machine
if free_ip(new_interface.type.ip_type) and not new_interface.ipv4:
new_interface = assign_ipv4(new_interface)
elif not new_interface.ipv4:
messages.error(request, u"Il n'y a plus d'ip disponibles")
with transaction.atomic(), reversion.create_revision():
new_interface.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
new_domain.interface_parent = new_interface
with transaction.atomic(), reversion.create_revision():
new_domain.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
messages.success(request, "La machine a été crée")
return redirect("/users/profil/" + str(user.id))
with transaction.atomic(), reversion.create_revision():
new_machine.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
new_interface.machine = new_machine
if free_ip(new_interface.type.ip_type) and not new_interface.ipv4:
new_interface = assign_ipv4(new_interface)
elif not new_interface.ipv4:
messages.error(request, u"Il n'y a plus d'ip disponibles")
with transaction.atomic(), reversion.create_revision():
new_interface.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
new_domain.interface_parent = new_interface
with transaction.atomic(), reversion.create_revision():
new_domain.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
messages.success(request, "La machine a été crée")
return redirect("/users/profil/" + str(user.id))
except TypeError:
messages.error(request, u"Adresse mac invalide")
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_machine = machine_form.save(commit=False)
new_domain = domain_form.save(commit=False)
if full_domain_validator(request, new_domain):
with transaction.atomic(), reversion.create_revision():
new_machine.save()
reversion.set_user(request.user)
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:
new_interface = assign_ipv4(new_interface)
with transaction.atomic(), reversion.create_revision():
new_interface.save()
reversion.set_user(request.user)
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in interface_form.changed_data))
with transaction.atomic(), reversion.create_revision():
new_domain.save()
reversion.set_user(request.user)
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")
return redirect("/users/profil/" + str(interface.machine.user.id))
with transaction.atomic(), reversion.create_revision():
new_machine.save()
reversion.set_user(request.user)
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:
new_interface = assign_ipv4(new_interface)
with transaction.atomic(), reversion.create_revision():
new_interface.save()
reversion.set_user(request.user)
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in interface_form.changed_data))
with transaction.atomic(), reversion.create_revision():
new_domain.save()
reversion.set_user(request.user)
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")
return redirect("/users/profil/" + str(interface.machine.user.id))
except TypeError:
messages.error(request, u"Adresse mac invalide")
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.machine = machine
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:
new_interface = assign_ipv4(new_interface)
elif not new_interface.ipv4:
messages.error(request, u"Il n'y a plus d'ip disponibles")
with transaction.atomic(), reversion.create_revision():
new_interface.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
new_domain.interface_parent = new_interface
with transaction.atomic(), reversion.create_revision():
new_domain.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
messages.success(request, "L'interface a été ajoutée")
return redirect("/users/profil/" + str(machine.user.id))
if free_ip(new_interface.type.ip_type) and not new_interface.ipv4:
new_interface = assign_ipv4(new_interface)
elif not new_interface.ipv4:
messages.error(request, u"Il n'y a plus d'ip disponibles")
with transaction.atomic(), reversion.create_revision():
new_interface.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
new_domain.interface_parent = new_interface
with transaction.atomic(), reversion.create_revision():
new_domain.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
messages.success(request, "L'interface a été ajoutée")
return redirect("/users/profil/" + str(machine.user.id))
except TypeError:
messages.error(request, u"Adresse mac invalide")
return form({'interfaceform': interface_form, 'domainform': domain_form}, 'machines/machine.html', request)
@ -321,7 +301,7 @@ def edit_iptype(request, iptypeid):
except IpType.DoesNotExist:
messages.error(request, u"Entrée inexistante" )
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():
with transaction.atomic(), reversion.create_revision():
iptype.save()

View file

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