diff --git a/api/serializers.py b/api/serializers.py index a9c05978..8d556771 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): @@ -310,6 +310,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 @@ -660,10 +670,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): @@ -695,7 +733,7 @@ class PortsSerializer(NamespacedHMSerializer): class Meta: 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: model = topologie.Switch - fields = ('short_name', 'model', 'switchbay', 'ports', 'subnet', 'subnet6') + fields = ('short_name', 'model', 'switchbay', 'ports', 'ipv4', 'ipv6', 'subnet', 'subnet6') # LOCAL EMAILS diff --git a/api/urls.py b/api/urls.py index 9de02578..e8c63657 100644 --- a/api/urls.py +++ b/api/urls.py @@ -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/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), @@ -108,6 +109,7 @@ router.register_view(r'firewall/subnet-ports', views.SubnetPortsOpenView), router.register_view(r'firewall/interface-ports', views.InterfacePortsOpenView), # Switches config router.register_view(r'switchs/ports-config', views.SwitchPortView), +router.register_view(r'switchs/role', views.RoleView), # DNS router.register_view(r'dns/zones', views.DNSZonesView), router.register_view(r'dns/reverse-zones', views.DNSReverseZonesView), diff --git a/api/views.py b/api/views.py index 3c2fe7d3..40cf8eae 100644 --- a/api/views.py +++ b/api/views.py @@ -242,6 +242,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 @@ -532,6 +539,14 @@ class SwitchPortView(generics.ListAPIView): 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 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 4de0b012..b59d48ae 100644 --- a/machines/models.py +++ b/machines/models.py @@ -371,7 +371,7 @@ class IpType(RevMixin, AclMixin, models.Model): 'netmask' : 'ffff:ffff:ffff:ffff::', 'netmask_cidr' : str(self.prefix_v6_length), 'vlan': str(self.vlan), - 'vlan_id': self.vlan.vlan_id + 'vlan_id': str(self.vlan.vlan_id) } else: return None @@ -515,7 +515,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", _("Can view a VLAN object")), diff --git a/topologie/models.py b/topologie/models.py index aa1c4ef8..7ca285be 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -291,6 +291,14 @@ class Switch(AclMixin, Machine): @cached_property def get_name(self): 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 def subnet(self): @@ -445,8 +453,20 @@ class Port(AclMixin, RevMixin, models.Model): verbose_name_plural = _("ports") @cached_property - def get_port_profile(self): - """Return the config profile for this port + 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 :returns: the profile of self (port)""" def profile_or_nothing(profile): port_profile = PortProfile.objects.filter( 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 %} + | +