8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-05 01:16:27 +00:00

Serialisation des roles et réglages par vlan des switches

This commit is contained in:
Gabriel Detraz 2018-07-08 04:08:01 +02:00 committed by grizzly
parent 20126a3cd6
commit 30bb38d75f
10 changed files with 208 additions and 12 deletions

View file

@ -153,7 +153,7 @@ class VlanSerializer(NamespacedHMSerializer):
""" """
class Meta: class Meta:
model = machines.Vlan model = machines.Vlan
fields = ('vlan_id', 'name', 'comment', 'api_url') fields = ('vlan_id', 'name', 'comment', 'arp_protect', 'dhcp_snooping', 'dhcpv6_snooping', 'api_url')
class NasSerializer(NamespacedHMSerializer): class NasSerializer(NamespacedHMSerializer):
@ -310,6 +310,16 @@ class OuverturePortSerializer(NamespacedHMSerializer):
fields = ('begin', 'end', 'port_list', 'protocole', 'io', 'api_url') fields = ('begin', 'end', 'port_list', 'protocole', 'io', 'api_url')
class RoleSerializer(NamespacedHMSerializer):
"""Serialize `machines.models.OuverturePort` objects.
"""
servers = InterfaceSerializer(read_only=True, many=True)
class Meta:
model = machines.Role
fields = ('role_type', 'servers', 'api_url')
# PREFERENCES # PREFERENCES
@ -660,10 +670,38 @@ class ServiceRegenSerializer(NamespacedHMSerializer):
# Switches et ports # Switches et ports
class InterfaceVlanSerializer(NamespacedHMSerializer):
domain = serializers.CharField(read_only=True)
ipv4 = serializers.CharField(read_only=True)
ipv6 = Ipv6ListSerializer(read_only=True, many=True)
vlan_id = serializers.IntegerField(source='type.ip_type.vlan.vlan_id', read_only=True)
class Meta:
model = machines.Interface
fields = ('ipv4', 'ipv6', 'domain', 'vlan_id')
class InterfaceRoleSerializer(NamespacedHMSerializer):
interface = InterfaceVlanSerializer(source='machine.interface_set', read_only=True, many=True)
class Meta:
model = machines.Interface
fields = ('interface',)
class RoleSerializer(NamespacedHMSerializer):
"""Serialize `machines.models.OuverturePort` objects.
"""
servers = InterfaceRoleSerializer(read_only=True, many=True)
class Meta:
model = machines.Role
fields = ('role_type', 'servers')
class VlanPortSerializer(NamespacedHMSerializer): class VlanPortSerializer(NamespacedHMSerializer):
class Meta: class Meta:
model = machines.Vlan model = machines.Vlan
fields = ('vlan_id', 'name') fields = ('vlan_id', 'name')
class ProfilSerializer(NamespacedHMSerializer): class ProfilSerializer(NamespacedHMSerializer):
@ -695,7 +733,7 @@ class PortsSerializer(NamespacedHMSerializer):
class Meta: class Meta:
model = topologie.Port model = topologie.Port
fields = ('state', 'port', 'get_port_profil') fields = ('state', 'port', 'pretty_name', 'get_port_profil')
@ -708,7 +746,7 @@ class SwitchPortSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = topologie.Switch model = topologie.Switch
fields = ('short_name', 'model', 'switchbay', 'ports', 'subnet', 'subnet6') fields = ('short_name', 'model', 'switchbay', 'ports', 'ipv4', 'ipv6', 'subnet', 'subnet6')
# LOCAL EMAILS # LOCAL EMAILS

View file

@ -63,6 +63,7 @@ router.register_viewset(r'machines/service', views.ServiceViewSet)
router.register_viewset(r'machines/servicelink', views.ServiceLinkViewSet, base_name='servicelink') router.register_viewset(r'machines/servicelink', views.ServiceLinkViewSet, base_name='servicelink')
router.register_viewset(r'machines/ouvertureportlist', views.OuverturePortListViewSet) router.register_viewset(r'machines/ouvertureportlist', views.OuverturePortListViewSet)
router.register_viewset(r'machines/ouvertureport', views.OuverturePortViewSet) router.register_viewset(r'machines/ouvertureport', views.OuverturePortViewSet)
router.register_viewset(r'machines/role', views.RoleViewSet)
# PREFERENCES # PREFERENCES
router.register_view(r'preferences/optionaluser', views.OptionalUserView), router.register_view(r'preferences/optionaluser', views.OptionalUserView),
router.register_view(r'preferences/optionalmachine', views.OptionalMachineView), router.register_view(r'preferences/optionalmachine', views.OptionalMachineView),
@ -108,6 +109,7 @@ router.register_view(r'firewall/subnet-ports', views.SubnetPortsOpenView),
router.register_view(r'firewall/interface-ports', views.InterfacePortsOpenView), router.register_view(r'firewall/interface-ports', views.InterfacePortsOpenView),
# Switches config # Switches config
router.register_view(r'switchs/ports-config', views.SwitchPortView), router.register_view(r'switchs/ports-config', views.SwitchPortView),
router.register_view(r'switchs/role', views.RoleView),
# DNS # DNS
router.register_view(r'dns/zones', views.DNSZonesView), router.register_view(r'dns/zones', views.DNSZonesView),
router.register_view(r'dns/reverse-zones', views.DNSReverseZonesView), router.register_view(r'dns/reverse-zones', views.DNSReverseZonesView),

View file

@ -242,6 +242,13 @@ class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = serializers.OuverturePortSerializer serializer_class = serializers.OuverturePortSerializer
class RoleViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Machine` objects.
"""
queryset = machines.Role.objects.all()
serializer_class = serializers.RoleSerializer
# PREFERENCES # PREFERENCES
# Those views differ a bit because there is only one object # Those views differ a bit because there is only one object
# to display, so we don't bother with the listing part # to display, so we don't bother with the listing part
@ -532,6 +539,14 @@ class SwitchPortView(generics.ListAPIView):
serializer_class = serializers.SwitchPortSerializer serializer_class = serializers.SwitchPortSerializer
class RoleView(generics.ListAPIView):
"""Exposes the associations between hostname, mac address and IPv4 in
order to build the DHCP lease files.
"""
queryset = machines.Role.objects.all().prefetch_related('servers')
serializer_class = serializers.RoleSerializer
# LOCAL EMAILS # LOCAL EMAILS

View file

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-07-07 18:40
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('machines', '0090_auto_20180625_1706'),
]
operations = [
migrations.AddField(
model_name='vlan',
name='arp_protect',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='vlan',
name='dhcp_snooping',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='vlan',
name='dhcpv6_snooping',
field=models.BooleanField(default=False),
),
]

View file

@ -371,7 +371,7 @@ class IpType(RevMixin, AclMixin, models.Model):
'netmask' : 'ffff:ffff:ffff:ffff::', 'netmask' : 'ffff:ffff:ffff:ffff::',
'netmask_cidr' : str(self.prefix_v6_length), 'netmask_cidr' : str(self.prefix_v6_length),
'vlan': str(self.vlan), 'vlan': str(self.vlan),
'vlan_id': self.vlan.vlan_id 'vlan_id': str(self.vlan.vlan_id)
} }
else: else:
return None return None
@ -515,7 +515,11 @@ class Vlan(RevMixin, AclMixin, models.Model):
vlan_id = models.PositiveIntegerField(validators=[MaxValueValidator(4095)]) vlan_id = models.PositiveIntegerField(validators=[MaxValueValidator(4095)])
name = models.CharField(max_length=256) name = models.CharField(max_length=256)
comment = models.CharField(max_length=256, blank=True) comment = models.CharField(max_length=256, blank=True)
#Réglages supplémentaires
arp_protect = models.BooleanField(default=False)
dhcp_snooping = models.BooleanField(default=False)
dhcpv6_snooping = models.BooleanField(default=False)
class Meta: class Meta:
permissions = ( permissions = (
("view_vlan", _("Can view a VLAN object")), ("view_vlan", _("Can view a VLAN object")),

View file

@ -291,6 +291,14 @@ class Switch(AclMixin, Machine):
@cached_property @cached_property
def get_name(self): def get_name(self):
return self.name or self.main_interface().domain.name return self.name or self.main_interface().domain.name
@cached_property
def ipv4(self):
return str(self.main_interface().ipv4)
@cached_property
def ipv6(self):
return str(self.main_interface().ipv6().first())
@cached_property @cached_property
def subnet(self): def subnet(self):
@ -445,8 +453,20 @@ class Port(AclMixin, RevMixin, models.Model):
verbose_name_plural = _("ports") verbose_name_plural = _("ports")
@cached_property @cached_property
def get_port_profile(self): def pretty_name(self):
"""Return the config profile for this port """More elaborated name for label on switch conf"""
if self.related:
return "Uplink : " + self.related.switch.short_name
elif self.machine_interface:
return "Machine : " + str(self.machine_interface.domain)
elif self.room:
return "Chambre : " + str(self.room)
else:
return "Inconnue"
@cached_property
def get_port_profil(self):
"""Return the config profil for this port
:returns: the profile of self (port)""" :returns: the profile of self (port)"""
def profile_or_nothing(profile): def profile_or_nothing(profile):
port_profile = PortProfile.objects.filter( port_profile = PortProfile.objects.filter(

View file

@ -0,0 +1,55 @@
{% 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 acl %}
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Nom</th>
<th>Arp Protect</th>
<th>Dhcp Snooping</th>
<th>Dhcpv6 Snooping</th>
<th></th>
</tr>
</thead>
{% for vlan in vlan_list %}
<tr>
<td>{{ vlan.vlan_id }}</td>
<td>{{ vlan.name }}</td>
<td>{{ vlan.arp_protect }}</td>
<td>{{ vlan.dhcp_snooping }}</td>
<td>{{ vlan.dhcpv6_snooping }}</td>
<td class="text-right">
{% can_edit vlan %}
{% include 'buttons/edit.html' with href='topologie:edit-vlanoptions' id=vlan.id %}
{% acl_end %}
{% include 'buttons/history.html' with href='machines:history' name='vlan' id=vlan.id %}
</td>
</tr>
{% endfor %}
</table>
</div>

View file

@ -30,12 +30,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% block content %} {% block content %}
<h2>{% trans "Port profiles" %}</h2> <h2>{% trans "Port profiles" %}</h2>
{% can_create PortProfile %} {% can_create PortProfile %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'topologie:new-port-profile' %}"><i class="fa fa-plus"></i>{% trans " Add a port profile" %}</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'topologie:new-port-profile' %}"><i class="fa fa-plus"></i>{% trans " Add a port profile" %}</a>
<hr> <hr>
{% acl_end %} {% acl_end %}
{% include "topologie/aff_port_profile.html" with port_profile_list=port_profile_list %} {% include "topologie/aff_port_profile.html" with port_profile_list=port_profile_list %}
<h2>{% trans "Sécurité par vlan" %}</h2>
{% include "topologie/aff_vlanoptions.html" with vlan_list=vlan_list %}
<br /> <br />
<br /> <br />
<br /> <br />

View file

@ -120,4 +120,7 @@ urlpatterns = [
url(r'^del_port_profile/(?P<portprofileid>[0-9]+)$', url(r'^del_port_profile/(?P<portprofileid>[0-9]+)$',
views.del_port_profile, views.del_port_profile,
name='del-port-profile'), name='del-port-profile'),
] url(r'^edit_vlanoptions/(?P<vlanid>[0-9]+)$',
views.edit_vlanoptions,
name='edit-vlanoptions'),
]

View file

@ -60,10 +60,15 @@ from re2o.settings import MEDIA_ROOT
from machines.forms import ( from machines.forms import (
DomainForm, DomainForm,
EditInterfaceForm, EditInterfaceForm,
AddInterfaceForm AddInterfaceForm,
EditOptionVlanForm
) )
from machines.views import generate_ipv4_mbf_param from machines.views import generate_ipv4_mbf_param
from machines.models import Interface, Service_link from machines.models import (
Interface,
Service_link,
Vlan
)
from preferences.models import AssoOption, GeneralOption from preferences.models import AssoOption, GeneralOption
from .models import ( from .models import (
@ -153,10 +158,11 @@ def index_port_profile(request):
'vlan_untagged') 'vlan_untagged')
port_profile_list = re2o_paginator( port_profile_list = re2o_paginator(
request, port_profile_list, pagination_number) request, port_profile_list, pagination_number)
vlan_list = Vlan.objects.all().order_by('vlan_id')
return render( return render(
request, request,
'topologie/index_portprofile.html', 'topologie/index_portprofile.html',
{'port_profile_list': port_profile_list} {'port_profile_list': port_profile_list, 'vlan_list': vlan_list}
) )
@ -307,6 +313,23 @@ def index_model_switch(request):
) )
@login_required
@can_edit(Vlan)
def edit_vlanoptions(request, vlan_instance, **_kwargs):
""" View used to edit options for switch of VLAN object """
vlan = EditOptionVlanForm(request.POST or None, instance=vlan_instance)
if vlan.is_valid():
if vlan.changed_data:
vlan.save()
messages.success(request, "Vlan modifié")
return redirect(reverse('topologie:index-port-profile'))
return form(
{'vlanform': vlan, 'action_name': 'Editer'},
'machines/machine.html',
request
)
@login_required @login_required
@can_create(Port) @can_create(Port)
def new_port(request, switchid): def new_port(request, switchid):