diff --git a/api/serializers.py b/api/serializers.py index 6967dba8..58de859b 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -153,7 +153,7 @@ class VlanSerializer(NamespacedHMSerializer): """ class Meta: 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): @@ -303,6 +303,16 @@ class OuverturePortSerializer(NamespacedHMSerializer): 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 @@ -634,10 +644,38 @@ class ServiceRegenSerializer(NamespacedHMSerializer): # 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 Meta: model = machines.Vlan - fields = ('vlan_id', 'name') + fields = ('vlan_id', 'name') class ProfilSerializer(NamespacedHMSerializer): @@ -669,7 +707,7 @@ class PortsSerializer(NamespacedHMSerializer): class Meta: model = topologie.Port - fields = ('state', 'port', 'get_port_profil') + fields = ('state', 'port', 'pretty_name', 'get_port_profil') @@ -682,7 +720,7 @@ class SwitchPortSerializer(serializers.ModelSerializer): class Meta: model = topologie.Switch - fields = ('short_name', 'model', 'switchbay', 'ports', 'subnet', 'subnet6') + fields = ('short_name', 'model', 'switchbay', 'ports', 'ipv4', 'ipv6', 'subnet', 'subnet6') # DHCP diff --git a/api/urls.py b/api/urls.py index a707ab57..83b1108c 100644 --- a/api/urls.py +++ b/api/urls.py @@ -62,6 +62,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/ouvertureportlist', views.OuverturePortListViewSet) router.register_viewset(r'machines/ouvertureport', views.OuverturePortViewSet) +router.register_viewset(r'machines/role', views.RoleViewSet) # PREFERENCES router.register_view(r'preferences/optionaluser', views.OptionalUserView), router.register_view(r'preferences/optionalmachine', views.OptionalMachineView), @@ -100,6 +101,7 @@ router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name= router.register_view(r'dhcp/hostmacip', views.HostMacIpView), # Switches config router.register_view(r'switchs/ports-config', views.SwitchPortView), +router.register_view(r'switchs/role', views.RoleView), # Reminder router.register_view(r'reminder/get-users', views.ReminderView), # DNS diff --git a/api/views.py b/api/views.py index ea384ad9..03ebe349 100644 --- a/api/views.py +++ b/api/views.py @@ -234,6 +234,13 @@ class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet): 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 # Those views differ a bit because there is only one object # to display, so we don't bother with the listing part @@ -504,6 +511,15 @@ class SwitchPortView(generics.ListAPIView): queryset = topologie.Switch.objects.all().prefetch_related('ports__custom_profile') 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 + + # Rappel fin adhésion class ReminderView(generics.ListAPIView): diff --git a/machines/migrations/0091_auto_20180707_2040.py b/machines/migrations/0091_auto_20180707_2040.py new file mode 100644 index 00000000..a2aea3a6 --- /dev/null +++ b/machines/migrations/0091_auto_20180707_2040.py @@ -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), + ), + ] diff --git a/machines/models.py b/machines/models.py index 5113c34c..7e5062c0 100644 --- a/machines/models.py +++ b/machines/models.py @@ -387,6 +387,8 @@ class IpType(RevMixin, AclMixin, models.Model): 'network': str(ip_set.network), 'netmask': str(ip_set.netmask), 'broadcast': str(ip_set.broadcast), + 'vlan': str(self.vlan), + 'vlan_id': self.vlan.vlan_id } for ip_set in self.ip_set.iter_cidrs() ] @@ -395,7 +397,9 @@ class IpType(RevMixin, AclMixin, models.Model): if self.prefix_v6: return { 'network' : str(self.prefix_v6), - 'netmask' : 'ffff:ffff:ffff:ffff::' + 'netmask' : 'ffff:ffff:ffff:ffff::', + 'vlan': str(self.vlan), + 'vlan_id': str(self.vlan.vlan_id) } else: return None @@ -494,7 +498,11 @@ class Vlan(RevMixin, AclMixin, models.Model): vlan_id = models.PositiveIntegerField(validators=[MaxValueValidator(4095)]) name = models.CharField(max_length=256) 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: permissions = ( ("view_vlan", "Peut voir un objet vlan"), diff --git a/topologie/models.py b/topologie/models.py index 700b6c16..27952a4e 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -271,6 +271,14 @@ class Switch(AclMixin, Machine): """ Returns the 'main' interface of the switch """ return self.interface_set.first() + @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 def subnet(self): return self.main_interface().type.ip_type.ip_set_full_info @@ -414,6 +422,18 @@ class Port(AclMixin, RevMixin, models.Model): ("view_port", "Peut voir un objet port"), ) + @cached_property + def pretty_name(self): + """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 diff --git a/topologie/templates/topologie/aff_vlanoptions.html b/topologie/templates/topologie/aff_vlanoptions.html new file mode 100644 index 00000000..d9e6f117 --- /dev/null +++ b/topologie/templates/topologie/aff_vlanoptions.html @@ -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 %} + +
Id | +Nom | +Arp Protect | +Dhcp Snooping | +Dhcpv6 Snooping | ++ |
---|---|---|---|---|---|
{{ vlan.vlan_id }} | +{{ vlan.name }} | +{{ vlan.arp_protect }} | +{{ vlan.dhcp_snooping }} | +{{ vlan.dhcpv6_snooping }} | ++ {% 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 %} + | +