8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-26 08:53:46 +00:00

Omnibus : ajout du suport de la liste vlan + corrections mineures

This commit is contained in:
Gabriel Detraz 2017-08-26 15:10:18 +02:00 committed by root
parent b4567677ce
commit 6a50888e40
25 changed files with 386 additions and 38 deletions

View file

@ -49,7 +49,7 @@ class Facture(models.Model):
return Vente.objects.filter(facture=self).aggregate(total=models.Sum(models.F('prix')*models.F('number'), output_field=models.FloatField()))['total'] return Vente.objects.filter(facture=self).aggregate(total=models.Sum(models.F('prix')*models.F('number'), output_field=models.FloatField()))['total']
def name(self): def name(self):
name = ' - '.join(vente.name for vente in Vente.objects.filter(facture=self)) name = ' - '.join(Vente.objects.filter(facture=self).values_list('name', flat=True))
return name return name
def __str__(self): def __str__(self):

View file

@ -40,11 +40,12 @@ from django.db.models import Q
from machines.models import Interface, IpList, Domain from machines.models import Interface, IpList, Domain
from topologie.models import Room, Port, Switch from topologie.models import Room, Port, Switch
from users.models import User from users.models import User
from preferences.models import OptionalTopologie
from re2o.settings import RADIUS_VLAN_DECISION options, created = OptionalTopologie.objects.get_or_create()
VLAN_NOK = options.vlan_decision_nok.vlan_id
VLAN_OK = options.vlan_decision_ok.vlan_id
VLAN_NOK = RADIUS_VLAN_DECISION['VLAN_NOK']
VLAN_OK = RADIUS_VLAN_DECISION['VLAN_OK']
def decide_vlan(switch_id, port_number, mac_address): def decide_vlan(switch_id, port_number, mac_address):
# Get port from switch and port number # Get port from switch and port number

View file

@ -23,29 +23,31 @@
from django.contrib import admin from django.contrib import admin
from reversion.admin import VersionAdmin from reversion.admin import VersionAdmin
from .models import IpType, Machine, MachineType, Domain, IpList, Interface, Extension, Mx, Ns, Service from .models import IpType, Machine, MachineType, Domain, IpList, Interface, Extension, Mx, Ns, Vlan, Service
class MachineAdmin(VersionAdmin): class MachineAdmin(VersionAdmin):
list_display = ('user','name','active') pass
class IpTypeAdmin(VersionAdmin): class IpTypeAdmin(VersionAdmin):
list_display = ('type','extension','need_infra','domaine_ip','domaine_range') pass
class MachineTypeAdmin(VersionAdmin): class MachineTypeAdmin(VersionAdmin):
list_display = ('type','ip_type') pass
class VlanAdmin(VersionAdmin):
pass
class ExtensionAdmin(VersionAdmin): class ExtensionAdmin(VersionAdmin):
list_display = ('name','origin') pass
class MxAdmin(VersionAdmin): class MxAdmin(VersionAdmin):
list_display = ('zone', 'priority', 'name') pass
class NsAdmin(VersionAdmin): class NsAdmin(VersionAdmin):
list_display = ('zone', 'ns') pass
class IpListAdmin(VersionAdmin): class IpListAdmin(VersionAdmin):
list_display = ('ipv4','ip_type') pass
class InterfaceAdmin(VersionAdmin): class InterfaceAdmin(VersionAdmin):
list_display = ('machine','type','mac_address','ipv4','details') list_display = ('machine','type','mac_address','ipv4','details')
@ -66,3 +68,4 @@ admin.site.register(IpList, IpListAdmin)
admin.site.register(Interface, InterfaceAdmin) admin.site.register(Interface, InterfaceAdmin)
admin.site.register(Domain, DomainAdmin) admin.site.register(Domain, DomainAdmin)
admin.site.register(Service, ServiceAdmin) admin.site.register(Service, ServiceAdmin)
admin.site.register(Vlan, VlanAdmin)

View file

@ -22,7 +22,7 @@
from django.forms import ModelForm, Form, ValidationError from django.forms import ModelForm, Form, ValidationError
from django import forms from django import forms
from .models import Domain, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Service, IpType from .models import Domain, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Service, Vlan, IpType
from django.db.models import Q from django.db.models import Q
from django.core.validators import validate_email from django.core.validators import validate_email
@ -143,7 +143,7 @@ class DelMachineTypeForm(Form):
class IpTypeForm(ModelForm): class IpTypeForm(ModelForm):
class Meta: class Meta:
model = IpType model = IpType
fields = ['type','extension','need_infra','domaine_ip','domaine_range'] fields = ['type','extension','need_infra','domaine_ip','domaine_range', 'vlan']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(IpTypeForm, self).__init__(*args, **kwargs) super(IpTypeForm, self).__init__(*args, **kwargs)
@ -151,7 +151,7 @@ class IpTypeForm(ModelForm):
class EditIpTypeForm(IpTypeForm): class EditIpTypeForm(IpTypeForm):
class Meta(IpTypeForm.Meta): class Meta(IpTypeForm.Meta):
fields = ['extension','type','need_infra'] fields = ['extension','type','need_infra', 'vlan']
class DelIpTypeForm(Form): class DelIpTypeForm(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)
@ -208,3 +208,13 @@ class ServiceForm(ModelForm):
class DelServiceForm(Form): class DelServiceForm(Form):
service = forms.ModelMultipleChoiceField(queryset=Service.objects.all(), label="Services actuels", widget=forms.CheckboxSelectMultiple) service = forms.ModelMultipleChoiceField(queryset=Service.objects.all(), label="Services actuels", widget=forms.CheckboxSelectMultiple)
class VlanForm(ModelForm):
class Meta:
model = Vlan
fields = '__all__'
class DelVlanForm(Form):
vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple)

View file

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-08-25 21:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('machines', '0048_auto_20170823_2315'),
]
operations = [
migrations.CreateModel(
name='Vlan',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('vlan_id', models.IntegerField()),
('name', models.CharField(max_length=256)),
('comment', models.CharField(max_length=256)),
],
),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-08-25 22:22
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('machines', '0049_vlan'),
]
operations = [
migrations.AlterField(
model_name='vlan',
name='comment',
field=models.CharField(blank=True, max_length=256),
),
]

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-08-25 23:04
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('machines', '0050_auto_20170826_0022'),
]
operations = [
migrations.AddField(
model_name='iptype',
name='vlan',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='machines.Vlan'),
),
]

View file

@ -69,6 +69,7 @@ class IpType(models.Model):
need_infra = models.BooleanField(default=False) need_infra = models.BooleanField(default=False)
domaine_ip = models.GenericIPAddressField(protocol='IPv4') domaine_ip = models.GenericIPAddressField(protocol='IPv4')
domaine_range = models.IntegerField(validators=[MinValueValidator(16), MaxValueValidator(32)]) domaine_range = models.IntegerField(validators=[MinValueValidator(16), MaxValueValidator(32)])
vlan = models.ForeignKey('Vlan', on_delete=models.PROTECT, blank=True, null=True)
@cached_property @cached_property
def network(self): def network(self):
@ -107,7 +108,7 @@ class IpType(models.Model):
def clean(self): def clean(self):
# On check que les / ne se recoupent pas # On check que les / ne se recoupent pas
for element in IpType.objects.all(): for element in IpType.objects.all().exclude(pk=self.pk):
if not self.ip_set.isdisjoint(element.ip_set): if not self.ip_set.isdisjoint(element.ip_set):
raise ValidationError("Le range indiqué n'est pas disjoint des ranges existants") raise ValidationError("Le range indiqué n'est pas disjoint des ranges existants")
return return
@ -119,6 +120,16 @@ class IpType(models.Model):
def __str__(self): def __str__(self):
return self.type return self.type
class Vlan(models.Model):
PRETTY_NAME = "Vlans"
vlan_id = models.IntegerField()
name = models.CharField(max_length=256)
comment = models.CharField(max_length=256, blank=True)
def __str__(self):
return self.name
class Extension(models.Model): class Extension(models.Model):
PRETTY_NAME = "Extensions dns" PRETTY_NAME = "Extensions dns"
@ -360,6 +371,7 @@ def interface_post_delete(sender, **kwargs):
@receiver(post_save, sender=IpType) @receiver(post_save, sender=IpType)
def iptype_post_save(sender, **kwargs): def iptype_post_save(sender, **kwargs):
iptype = kwargs['instance'] iptype = kwargs['instance']
if not iptype.ip_objects():
iptype.gen_ip_range() iptype.gen_ip_range()
@receiver(post_save, sender=MachineType) @receiver(post_save, sender=MachineType)

View file

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<th>Nécessite l'autorisation infra</th> <th>Nécessite l'autorisation infra</th>
<th>Domaine d'ip</th> <th>Domaine d'ip</th>
<th>Range</th> <th>Range</th>
<th>Sur vlan</th>
<th></th> <th></th>
<th></th> <th></th>
</tr> </tr>
@ -41,6 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td>{{ type.need_infra }}</td> <td>{{ type.need_infra }}</td>
<td>{{ type.domaine_ip }}</td> <td>{{ type.domaine_ip }}</td>
<td>{{ type.domaine_range }}</td> <td>{{ type.domaine_range }}</td>
<td>{{ type.vlan }}</td>
<td class="text-right"> <td class="text-right">
{% if is_infra %} {% if is_infra %}
{% include 'buttons/edit.html' with href='machines:edit-iptype' id=type.id %} {% include 'buttons/edit.html' with href='machines:edit-iptype' id=type.id %}

View file

@ -0,0 +1,50 @@
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Nom</th>
<th>Commentaire</th>
<th>Ranges ip</th>
<th></th>
</tr>
</thead>
{% for vlan in vlan_list %}
<tr>
<td>{{ vlan.vlan_id }}</td>
<td>{{ vlan.name }}</td>
<td>{{ vlan.comment }}</td>
<td>{% for range in vlan.iptype_set.all %}{{ range }}, {% endfor%}</td>
<td class="text-right">
{% if is_infra %}
{% include 'buttons/edit.html' with href='machines:edit-vlan' id=vlan.id %}
{% endif %}
{% include 'buttons/history.html' with href='machines:history' name='vlan' id=vlan.id %}
</td>
</tr>
{% endfor %}
</table>

View file

@ -0,0 +1,39 @@
{% extends "machines/sidebar.html" %}
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load bootstrap3 %}
{% block title %}Machines{% endblock %}
{% block content %}
<h2>Liste des vlans</h2>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-vlan' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter un vlan</a>
<a class="btn btn-danger btn-sm" role="button" href="{% url 'machines:del-vlan' %}"><i class="glyphicon glyphicon-trash"></i> Supprimer un ou plusieurs vlan</a>
{% include "machines/aff_vlan.html" with vlan_list=vlan_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -42,6 +42,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<i class="glyphicon glyphicon-list"></i> <i class="glyphicon glyphicon-list"></i>
Plages d'IP Plages d'IP
</a> </a>
<a class="list-group-item list-group-item-info" href="{% url "machines:index-vlan" %}">
<i class="glyphicon glyphicon-list"></i>
Vlans
</a>
<a class="list-group-item list-group-item-info" href="{% url "machines:index-service" %}"> <a class="list-group-item list-group-item-info" href="{% url "machines:index-service" %}">
<i class="glyphicon glyphicon-list"></i> <i class="glyphicon glyphicon-list"></i>
Services (dhcp, dns...) Services (dhcp, dns...)

View file

@ -56,6 +56,10 @@ urlpatterns = [
url(r'^edit_service/(?P<serviceid>[0-9]+)$', views.edit_service, name='edit-service'), url(r'^edit_service/(?P<serviceid>[0-9]+)$', views.edit_service, name='edit-service'),
url(r'^del_service/$', views.del_service, name='del-service'), url(r'^del_service/$', views.del_service, name='del-service'),
url(r'^index_service/$', views.index_service, name='index-service'), url(r'^index_service/$', views.index_service, name='index-service'),
url(r'^add_vlan/$', views.add_vlan, name='add-vlan'),
url(r'^edit_vlan/(?P<vlanid>[0-9]+)$', views.edit_vlan, name='edit-vlan'),
url(r'^del_vlan/$', views.del_vlan, name='del-vlan'),
url(r'^index_vlan/$', views.index_vlan, name='index-vlan'),
url(r'^history/(?P<object>machine)/(?P<id>[0-9]+)$', views.history, name='history'), url(r'^history/(?P<object>machine)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>interface)/(?P<id>[0-9]+)$', views.history, name='history'), url(r'^history/(?P<object>interface)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>machinetype)/(?P<id>[0-9]+)$', views.history, name='history'), url(r'^history/(?P<object>machinetype)/(?P<id>[0-9]+)$', views.history, name='history'),
@ -64,6 +68,7 @@ urlpatterns = [
url(r'^history/(?P<object>ns)/(?P<id>[0-9]+)$', views.history, name='history'), url(r'^history/(?P<object>ns)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>iptype)/(?P<id>[0-9]+)$', views.history, name='history'), url(r'^history/(?P<object>iptype)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>alias)/(?P<id>[0-9]+)$', views.history, name='history'), url(r'^history/(?P<object>alias)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>vlan)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>service)/(?P<id>[0-9]+)$', views.history, name='history'), url(r'^history/(?P<object>service)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^$', views.index, name='index'), url(r'^$', views.index, name='index'),
url(r'^rest/mac-ip/$', views.mac_ip, name='mac-ip'), url(r'^rest/mac-ip/$', views.mac_ip, name='mac-ip'),

View file

@ -44,8 +44,8 @@ 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 EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, MxForm, DelMxForm, ServiceForm, DelServiceForm from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm
from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan
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
@ -592,6 +592,54 @@ def del_service(request):
return redirect("/machines/index_service") return redirect("/machines/index_service")
return form({'machineform': service}, 'machines/machine.html', request) return form({'machineform': service}, 'machines/machine.html', request)
@login_required
@permission_required('infra')
def add_vlan(request):
vlan = VlanForm(request.POST or None)
if vlan.is_valid():
with transaction.atomic(), reversion.create_revision():
vlan.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
messages.success(request, "Cet enregistrement vlan a été ajouté")
return redirect("/machines/index_vlan")
return form({'machineform': vlan, 'interfaceform': None}, 'machines/machine.html', request)
@login_required
@permission_required('infra')
def edit_vlan(request, vlanid):
try:
vlan_instance = Vlan.objects.get(pk=vlanid)
except Vlan.DoesNotExist:
messages.error(request, u"Entrée inexistante" )
return redirect("/machines/index_vlan/")
vlan = VlanForm(request.POST or None, instance=vlan_instance)
if vlan.is_valid():
with transaction.atomic(), reversion.create_revision():
vlan.save()
reversion.set_user(request.user)
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in vlan.changed_data))
messages.success(request, "Vlan modifié")
return redirect("/machines/index_vlan/")
return form({'machineform': vlan}, 'machines/machine.html', request)
@login_required
@permission_required('infra')
def del_vlan(request):
vlan = DelVlanForm(request.POST or None)
if vlan.is_valid():
vlan_dels = vlan.cleaned_data['vlan']
for vlan_del in ns_dels:
try:
with transaction.atomic(), reversion.create_revision():
vlan_del.delete()
reversion.set_user(request.user)
messages.success(request, "Le vlan a été supprimée")
except ProtectedError:
messages.error(request, "Erreur le Vlan suivant %s ne peut être supprimé" % vlan_del)
return redirect("/machines/index_vlan")
return form({'machineform': vlan, 'interfaceform': None}, 'machines/machine.html', request)
@login_required @login_required
@permission_required('cableur') @permission_required('cableur')
def index(request): def index(request):
@ -616,6 +664,12 @@ def index_iptype(request):
iptype_list = IpType.objects.select_related('extension').order_by('type') iptype_list = IpType.objects.select_related('extension').order_by('type')
return render(request, 'machines/index_iptype.html', {'iptype_list':iptype_list}) return render(request, 'machines/index_iptype.html', {'iptype_list':iptype_list})
@login_required
@permission_required('cableur')
def index_vlan(request):
vlan_list = Vlan.objects.order_by('vlan_id')
return render(request, 'machines/index_vlan.html', {'vlan_list':vlan_list})
@login_required @login_required
@permission_required('cableur') @permission_required('cableur')
def index_machinetype(request): def index_machinetype(request):
@ -715,6 +769,12 @@ def history(request, object, id):
except Service.DoesNotExist: except Service.DoesNotExist:
messages.error(request, "Service inexistant") messages.error(request, "Service inexistant")
return redirect("/machines/") return redirect("/machines/")
elif object == 'vlan' and request.user.has_perms(('cableur',)):
try:
object_instance = Vlan.objects.get(pk=id)
except Vlan.DoesNotExist:
messages.error(request, "Vlan inexistant")
return redirect("/machines/")
else: else:
messages.error(request, "Objet inconnu") messages.error(request, "Objet inconnu")
return redirect("/machines/") return redirect("/machines/")

View file

@ -23,11 +23,15 @@
from django.contrib import admin from django.contrib import admin
from reversion.admin import VersionAdmin from reversion.admin import VersionAdmin
from .models import OptionalUser, OptionalMachine, GeneralOption, Service, AssoOption from .models import OptionalUser, OptionalMachine, OptionalTopologie, GeneralOption, Service, AssoOption
class OptionalUserAdmin(VersionAdmin): class OptionalUserAdmin(VersionAdmin):
pass pass
class OptionalTopologieAdmin(VersionAdmin):
pass
class OptionalMachineAdmin(VersionAdmin): class OptionalMachineAdmin(VersionAdmin):
pass pass
@ -42,6 +46,7 @@ class AssoOptionAdmin(VersionAdmin):
admin.site.register(OptionalUser, OptionalUserAdmin) admin.site.register(OptionalUser, OptionalUserAdmin)
admin.site.register(OptionalMachine, OptionalMachineAdmin) admin.site.register(OptionalMachine, OptionalMachineAdmin)
admin.site.register(OptionalTopologie, OptionalTopologieAdmin)
admin.site.register(GeneralOption, GeneralOptionAdmin) admin.site.register(GeneralOption, GeneralOptionAdmin)
admin.site.register(Service, ServiceAdmin) admin.site.register(Service, ServiceAdmin)
admin.site.register(AssoOption, AssoOptionAdmin) admin.site.register(AssoOption, AssoOptionAdmin)

View file

@ -22,7 +22,7 @@
from django.forms import ModelForm, Form, ValidationError from django.forms import ModelForm, Form, ValidationError
from django import forms from django import forms
from .models import OptionalUser, OptionalMachine, GeneralOption, AssoOption, Service from .models import OptionalUser, OptionalMachine, OptionalTopologie, GeneralOption, AssoOption, Service
from django.db.models import Q from django.db.models import Q
class EditOptionalUserForm(ModelForm): class EditOptionalUserForm(ModelForm):
@ -46,6 +46,15 @@ class EditOptionalMachineForm(ModelForm):
self.fields['max_lambdauser_interfaces'].label = "Maximum d'interfaces autorisées pour un user normal" self.fields['max_lambdauser_interfaces'].label = "Maximum d'interfaces autorisées pour un user normal"
self.fields['max_lambdauser_aliases'].label = "Maximum d'alias dns autorisés pour un user normal" self.fields['max_lambdauser_aliases'].label = "Maximum d'alias dns autorisés pour un user normal"
class EditOptionalTopologieForm(ModelForm):
class Meta:
model = OptionalTopologie
fields = '__all__'
def __init__(self, *args, **kwargs):
super(EditOptionalTopologieForm, self).__init__(*args, **kwargs)
self.fields['vlan_decision_ok'].label = "Vlan où placer les machines après acceptation RADIUS"
self.fields['vlan_decision_nok'].label = "Vlan où placer les machines après rejet RADIUS"
class EditGeneralOptionForm(ModelForm): class EditGeneralOptionForm(ModelForm):
class Meta: class Meta:

View file

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-08-25 02:59
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('preferences', '0009_assooption_utilisateur_asso'),
]
operations = [
migrations.CreateModel(
name='OptionalTopologie',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
migrations.CreateModel(
name='Vlan',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('vlan_id', models.IntegerField()),
('comment', models.CharField(max_length=256)),
],
),
migrations.AddField(
model_name='optionaltopologie',
name='vlan_decision_nok',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='decision_nok', to='preferences.Vlan'),
),
migrations.AddField(
model_name='optionaltopologie',
name='vlan_decision_ok',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='decision_ok', to='preferences.Vlan'),
),
]

View file

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-08-25 21:07
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('preferences', '0010_auto_20170825_0459'),
]
operations = [
migrations.AlterField(
model_name='optionaltopologie',
name='vlan_decision_nok',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='decision_nok', to='machines.Vlan'),
),
migrations.AlterField(
model_name='optionaltopologie',
name='vlan_decision_ok',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='decision_ok', to='machines.Vlan'),
),
migrations.DeleteModel(
name='Vlan',
),
]

View file

@ -23,6 +23,7 @@
from django.db import models from django.db import models
from cotisations.models import Paiement from cotisations.models import Paiement
from machines.models import Vlan
class OptionalUser(models.Model): class OptionalUser(models.Model):
PRETTY_NAME = "Options utilisateur" PRETTY_NAME = "Options utilisateur"
@ -43,8 +44,11 @@ class OptionalMachine(models.Model):
max_lambdauser_interfaces = models.IntegerField(default=10) max_lambdauser_interfaces = models.IntegerField(default=10)
max_lambdauser_aliases = models.IntegerField(default=10) max_lambdauser_aliases = models.IntegerField(default=10)
#class OptionalTopologie(models.Model): class OptionalTopologie(models.Model):
PRETTY_NAME = "Options topologie"
vlan_decision_ok = models.OneToOneField('machines.Vlan', on_delete=models.PROTECT, related_name='decision_ok', blank=True, null=True)
vlan_decision_nok = models.OneToOneField('machines.Vlan', on_delete=models.PROTECT, related_name='decision_nok', blank=True, null=True)
class GeneralOption(models.Model): class GeneralOption(models.Model):
PRETTY_NAME = "Options générales" PRETTY_NAME = "Options générales"

View file

@ -70,6 +70,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td>{{ machineoptions.max_lambdauser_aliases }}</td> <td>{{ machineoptions.max_lambdauser_aliases }}</td>
</tr> </tr>
</table> </table>
<h4>Préférences topologie</h4>
{% if is_bureau %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalTopologie' %}">
<i class="glyphicon glyphicon-edit"></i>
Editer
</a>
{% endif %}
<p>
</p>
<table class="table table-striped">
<tr>
<th>Vlan où placer les machines après acceptation RADIUS</th>
<td>{{ topologieoptions.vlan_decision_ok }}</td>
<th>Vlan où placer les machines après rejet RADIUS</th>
<td>{{ topologieoptions.vlan_decision_nok }}</td>
</tr>
</table>
<h4>Préférences generales</h4> <h4>Préférences generales</h4>
{% if is_bureau %} {% if is_bureau %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'GeneralOption' %}"> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'GeneralOption' %}">

View file

@ -28,6 +28,7 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^edit_options/(?P<section>OptionalUser)$', views.edit_options, name='edit-options'), url(r'^edit_options/(?P<section>OptionalUser)$', views.edit_options, name='edit-options'),
url(r'^edit_options/(?P<section>OptionalMachine)$', views.edit_options, name='edit-options'), url(r'^edit_options/(?P<section>OptionalMachine)$', views.edit_options, name='edit-options'),
url(r'^edit_options/(?P<section>OptionalTopologie)$', views.edit_options, name='edit-options'),
url(r'^edit_options/(?P<section>GeneralOption)$', views.edit_options, name='edit-options'), url(r'^edit_options/(?P<section>GeneralOption)$', views.edit_options, name='edit-options'),
url(r'^edit_options/(?P<section>AssoOption)$', views.edit_options, name='edit-options'), url(r'^edit_options/(?P<section>AssoOption)$', views.edit_options, name='edit-options'),
url(r'^add_services/$', views.add_services, name='add-services'), url(r'^add_services/$', views.add_services, name='add-services'),

View file

@ -43,7 +43,7 @@ from reversion.models import Version
from reversion import revisions as reversion from reversion import revisions as reversion
from .forms import ServiceForm, DelServiceForm from .forms import ServiceForm, DelServiceForm
from .models import Service, OptionalUser, OptionalMachine, AssoOption, GeneralOption from .models import Service, OptionalUser, OptionalMachine, AssoOption, GeneralOption, OptionalTopologie
from . import models from . import models
from . import forms from . import forms
@ -58,10 +58,11 @@ def form(ctx, template, request):
def display_options(request): def display_options(request):
useroptions, created = OptionalUser.objects.get_or_create() useroptions, created = OptionalUser.objects.get_or_create()
machineoptions, created = OptionalMachine.objects.get_or_create() machineoptions, created = OptionalMachine.objects.get_or_create()
topologieoptions, created = OptionalTopologie.objects.get_or_create()
generaloptions, created = GeneralOption.objects.get_or_create() generaloptions, created = GeneralOption.objects.get_or_create()
assooptions, crated = AssoOption.objects.get_or_create() assooptions, crated = AssoOption.objects.get_or_create()
service_list = Service.objects.all() service_list = Service.objects.all()
return form({'useroptions': useroptions, 'machineoptions': machineoptions, 'generaloptions': generaloptions, 'assooptions' : assooptions, 'service_list':service_list}, 'preferences/display_preferences.html', request) return form({'useroptions': useroptions, 'machineoptions': machineoptions, 'topologieoptions': topologieoptions, 'generaloptions': generaloptions, 'assooptions' : assooptions, 'service_list':service_list}, 'preferences/display_preferences.html', request)
@login_required @login_required
@permission_required('admin') @permission_required('admin')

View file

@ -98,14 +98,5 @@ GID_RANGES = {
'posix' : [501, 600], 'posix' : [501, 600],
} }
# Liste des vlans id disponible sur un switch
VLAN_ID_LIST = [7,8,42,69]
# Décision radius à prendre
RADIUS_VLAN_DECISION = {
'VLAN_NOK' : 42,
'VLAN_OK' : 69,
}
OPTIONNAL_APPS = () OPTIONNAL_APPS = ()

View file

@ -27,7 +27,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
import reversion import reversion
from re2o.settings import VLAN_ID_LIST from machines.models import Vlan
def make_port_related(port): def make_port_related(port):
related_port = port.related related_port = port.related
@ -58,7 +58,7 @@ class Port(models.Model):
('BLOQ', 'BLOQ'), ('BLOQ', 'BLOQ'),
('COMMON', 'COMMON'), ('COMMON', 'COMMON'),
) )
STATES = STATES_BASE + tuple([(str(id), str(id)) for id in VLAN_ID_LIST]) STATES = STATES_BASE + tuple([(str(id), str(id)) for id in list(Vlan.objects.values_list('vlan_id', flat=True).order_by('vlan_id'))])
switch = models.ForeignKey('Switch', related_name="ports") switch = models.ForeignKey('Switch', related_name="ports")
port = models.IntegerField() port = models.IntegerField()

View file

@ -74,7 +74,7 @@ def linux_user_validator(login):
def get_fresh_user_uid(): def get_fresh_user_uid():
uids = list(range(int(min(UID_RANGES['users'])),int(max(UID_RANGES['users'])))) uids = list(range(int(min(UID_RANGES['users'])),int(max(UID_RANGES['users']))))
try: try:
used_uids = [ user.uid_number for user in User.objects.all()] used_uids = list(User.objects.values_list('uid_number', flat=True))
except: except:
used_uids = [] used_uids = []
free_uids = [ id for id in uids if id not in used_uids] free_uids = [ id for id in uids if id not in used_uids]
@ -82,7 +82,7 @@ def get_fresh_user_uid():
def get_fresh_gid(): def get_fresh_gid():
gids = list(range(int(min(GID_RANGES['posix'])),int(max(GID_RANGES['posix'])))) gids = list(range(int(min(GID_RANGES['posix'])),int(max(GID_RANGES['posix']))))
used_gids = [ right.gid for right in ListRight.objects.all()] used_gids = list(ListRight.objects.values_list('gid', flat=True))
free_gids = [ id for id in gids if id not in used_gids] free_gids = [ id for id in gids if id not in used_gids]
return min(free_gids) return min(free_gids)
@ -462,7 +462,7 @@ class ServiceUser(AbstractBaseUser):
group = LdapServiceUserGroup.objects.get(name=self.access_group) group = LdapServiceUserGroup.objects.get(name=self.access_group)
except: except:
group = LdapServiceUserGroup(name=self.access_group) group = LdapServiceUserGroup(name=self.access_group)
group.members = [serviceuser.dn for serviceuser in LdapServiceUser.objects.filter(name__in=[user.pseudo for user in ServiceUser.objects.filter(access_group=self.access_group)])] group.members = list(LdapServiceUser.objects.filter(name__in=[user.pseudo for user in ServiceUser.objects.filter(access_group=self.access_group)]).values_list('dn', flat=True))
group.save() group.save()
def __str__(self): def __str__(self):