diff --git a/topologie/migrations/0072_auto_20190720_2318.py b/topologie/migrations/0072_auto_20190720_2318.py new file mode 100644 index 00000000..3c403bfa --- /dev/null +++ b/topologie/migrations/0072_auto_20190720_2318.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2019-07-20 21:18 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('topologie', '0071_auto_20190218_1936'), + ] + + operations = [ + migrations.AlterModelOptions( + name='room', + options={'ordering': ['building__name'], 'permissions': (('view_room', 'Can view a room object'),), 'verbose_name': 'room', 'verbose_name_plural': 'rooms'}, + ), + migrations.AddField( + model_name='portprofile', + name='on_dormitory', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='dormitory_ofprofil', to='topologie.Dormitory', verbose_name='Profil on dormitory'), + ), + migrations.AlterField( + model_name='portprofile', + name='profil_default', + field=models.CharField(blank=True, choices=[('room', 'Room'), ('access_point', 'Access point'), ('uplink', 'Uplink'), ('asso_machine', 'Organisation machine'), ('nothing', 'Nothing')], max_length=32, null=True, verbose_name='Default profile'), + ), + migrations.AlterUniqueTogether( + name='portprofile', + unique_together=set([('on_dormitory', 'profil_default')]), + ), + ] diff --git a/topologie/models.py b/topologie/models.py index dee8abb3..2eaa3364 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -379,6 +379,58 @@ class Switch(AclMixin, Machine): modules.append((module_of_self.slot, module_of_self.module.reference)) return modules + @cached_property + def get_dormitory(self): + """Returns the dormitory of that switch""" + if self.switchbay: + return self.switchbay.building.dormitory + else: + return None + + @classmethod + def nothing_profile(cls): + """Return default nothing port profile""" + nothing_profile, _created = PortProfile.objects.get_or_create( + profil_default='nothing', + name='nothing', + radius_type='NO' + ) + return nothing_profile + + def profile_type_or_nothing(self, profile_type): + """Return the profile for a profile_type of this switch + + If exists, returns the defined default profile for a profile type on the dormitory which + the switch belongs + + Otherwise, returns the nothing profile""" + profile_queryset = PortProfile.objects.filter(profil_default=profile_type) + if self.get_dormitory: + port_profile = profile_queryset.filter(on_dormitory=self.get_dormitory).first() or profile_queryset.first() + else: + port_profile = profile_queryset.first() + return port_profile or Switch.nothing_profile + + @cached_property + def default_uplink_profile(self): + """Default uplink profile for that switch -- in cache""" + return self.profile_type_or_nothing('uplink') + + @cached_property + def default_access_point_profile(self): + """Default ap profile for that switch -- in cache""" + return self.profile_type_or_nothing('access_point') + + @cached_property + def default_room_profile(self): + """Default room profile for that switch -- in cache""" + return self.profile_type_or_nothing('room') + + @cached_property + def default_asso_machine_profile(self): + """Default asso machine profile for that switch -- in cache""" + return self.profile_type_or_nothing('asso_machine') + def __str__(self): return str(self.get_name) @@ -647,33 +699,26 @@ class Port(AclMixin, RevMixin, models.Model): @cached_property def get_port_profile(self): """Return the config profil for this port - :returns: the profile of self (port)""" - def profile_or_nothing(profile): - port_profile = PortProfile.objects.filter( - profil_default=profile).first() - if port_profile: - return port_profile - else: - nothing_profile, _created = PortProfile.objects.get_or_create( - profil_default='nothing', - name='nothing', - radius_type='NO' - ) - return nothing_profile + :returns: the profile of self (port) + + If is defined a custom profile, returns it + elIf a default profile is defined for its dormitory, returns it + Else, returns the global default profil + If not exists, create a nothing profile""" if self.custom_profile: return self.custom_profile elif self.related: - return profile_or_nothing('uplink') + return self.switch.default_uplink_profile elif self.machine_interface: if hasattr(self.machine_interface.machine, 'accesspoint'): - return profile_or_nothing('access_point') + return self.switch.default_access_point_profile else: - return profile_or_nothing('asso_machine') + return self.switch.default_asso_machine_profile elif self.room: - return profile_or_nothing('room') + return self.switch.default_room_profile else: - return profile_or_nothing('nothing') + return Switch.nothing_profile @classmethod def get_instance(cls, portid, *_args, **kwargs): @@ -791,9 +836,16 @@ class PortProfile(AclMixin, RevMixin, models.Model): choices=PROFIL_DEFAULT, blank=True, null=True, - unique=True, verbose_name=_("Default profile") ) + on_dormitory = models.ForeignKey( + 'topologie.Dormitory', + related_name='dormitory_ofprofil', + on_delete=models.SET_NULL, + blank=True, + null=True, + verbose_name=_("Profil on dormitory") + ) vlan_untagged = models.ForeignKey( 'machines.Vlan', related_name='vlan_untagged', @@ -871,6 +923,7 @@ class PortProfile(AclMixin, RevMixin, models.Model): ) verbose_name = _("port profile") verbose_name_plural = _("port profiles") + unique_together = ['on_dormitory', 'profil_default'] security_parameters_fields = [ 'loop_protect', @@ -893,6 +946,14 @@ class PortProfile(AclMixin, RevMixin, models.Model): def security_parameters_as_str(self): return ','.join(self.security_parameters_enabled) + def clean(self): + """ Check that there is only one generic profil default""" + super(PortProfile, self).clean() + if self.profil_default and not self.on_dormitory and PortProfile.objects.exclude(id=self.id).filter(profil_default=self.profil_default).exclude(on_dormitory__isnull=False).exists(): + raise ValidationError( + {'profil_default': _("A default profile for all dormitory of that type already exists.")} + ) + def __str__(self): return self.name diff --git a/topologie/templates/topologie/aff_port.html b/topologie/templates/topologie/aff_port.html index 6a02b484..c789694e 100644 --- a/topologie/templates/topologie/aff_port.html +++ b/topologie/templates/topologie/aff_port.html @@ -88,7 +88,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endif %} - {% if not port.custom_profil %} + {% if not port.custom_profile %} {% trans "Default: " %} {% endif %} {{ port.get_port_profile }} diff --git a/topologie/templates/topologie/aff_port_profile.html b/topologie/templates/topologie/aff_port_profile.html index b335904e..4ed8a7b4 100644 --- a/topologie/templates/topologie/aff_port_profile.html +++ b/topologie/templates/topologie/aff_port_profile.html @@ -35,7 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% trans "Name" %} - {% trans "Default for" %} + {% trans "Default for and place" %} {% trans "VLANs" %} {% trans "RADIUS settings" %} {% trans "Speed limit" %} @@ -47,7 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% for port_profile in port_profile_list %} {{ port_profile.name }} - {{ port_profile.profil_default }} + {{ port_profile.profil_default }} {% if port_profile.profil_default%} - {% if port_profile.on_dormitory %} on {{ port_profile.on_dormitory }} {% else %} Everywhere {% endif %}{% endif %} {% if port_profile.vlan_untagged %} {% trans "Untagged: " %}{{ port_profile.vlan_untagged }}