8
0
Fork 0
mirror of https://gitlab.federez.net/re2o/re2o synced 2024-06-02 16:02:16 +00:00

Add or translate some docstrings in topologie/

This commit is contained in:
Laouen Fernet 2020-04-29 15:00:47 +02:00 committed by Gabriel Detraz
parent d186449767
commit 7939a986d0
4 changed files with 363 additions and 264 deletions

View file

@ -20,8 +20,8 @@
# You should have received a copy of the GNU General Public License along # 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., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
""" """topologie.admin
Fichier définissant les administration des models dans l'interface admin The objects, fields and datastructures visible in the Django admin view.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
@ -45,67 +45,67 @@ from .models import (
class StackAdmin(VersionAdmin): class StackAdmin(VersionAdmin):
"""Administration d'une stack de switches (inclus des switches)""" """Admin class of stacks (includes switches)."""
pass pass
class SwitchAdmin(VersionAdmin): class SwitchAdmin(VersionAdmin):
"""Administration d'un switch""" """Admin class of switches."""
pass pass
class PortAdmin(VersionAdmin): class PortAdmin(VersionAdmin):
"""Administration d'un port de switches""" """Admin class of switch ports."""
pass pass
class AccessPointAdmin(VersionAdmin): class AccessPointAdmin(VersionAdmin):
"""Administration d'une borne""" """Admin class of APs."""
pass pass
class RoomAdmin(VersionAdmin): class RoomAdmin(VersionAdmin):
"""Administration d'un chambre""" """Admin class of rooms."""
pass pass
class ModelSwitchAdmin(VersionAdmin): class ModelSwitchAdmin(VersionAdmin):
"""Administration d'un modèle de switch""" """Admin class of switch models."""
pass pass
class ConstructorSwitchAdmin(VersionAdmin): class ConstructorSwitchAdmin(VersionAdmin):
"""Administration d'un constructeur d'un switch""" """Admin class of switch constructors."""
pass pass
class SwitchBayAdmin(VersionAdmin): class SwitchBayAdmin(VersionAdmin):
"""Administration d'une baie de brassage""" """Admin class of switch bays."""
pass pass
class BuildingAdmin(VersionAdmin): class BuildingAdmin(VersionAdmin):
"""Administration d'un batiment""" """Admin class of buildings."""
pass pass
class DormitoryAdmin(VersionAdmin): class DormitoryAdmin(VersionAdmin):
"""Administration d'une residence""" """Admin class of dormitories."""
pass pass
class PortProfileAdmin(VersionAdmin): class PortProfileAdmin(VersionAdmin):
"""Administration of a port profile""" """Admin class of port profiles."""
pass pass

View file

@ -20,14 +20,12 @@
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
""" """
Un forms le plus simple possible pour les objets topologie de re2o. Forms for the topologie app of re2o.
Permet de créer et supprimer : un Port de switch, relié à un switch. The forms are used to:
* create and delete switch ports, related to a switch.
Permet de créer des stacks et d'y ajouter des switchs (StackForm) * create stacks and add switches to them (StackForm).
* create, edit and delete a switch (NewSwitchForm, EditSwitchForm).
Permet de créer, supprimer et editer un switch (EditSwitchForm,
NewSwitchForm)
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
@ -59,8 +57,7 @@ from .models import (
class PortForm(FormRevMixin, ModelForm): class PortForm(FormRevMixin, ModelForm):
"""Formulaire pour la création d'un port d'un switch """Form used to manage a switch's port."""
Relié directement au modèle port"""
class Meta: class Meta:
model = Port model = Port
@ -72,14 +69,11 @@ class PortForm(FormRevMixin, ModelForm):
class EditPortForm(FormRevMixin, ModelForm): class EditPortForm(FormRevMixin, ModelForm):
"""Form pour l'édition d'un port de switche : changement des reglages """Form used to edit a switch's port: change in RADIUS or VLANs settings,
radius ou vlan, ou attribution d'une chambre, autre port ou machine assignement to a room, port or machine.
Un port est relié à une chambre, un autre port (uplink) ou une machine A port is related to either a room, another port (uplink) or a machine (server or AP).
(serveur ou borne), mutuellement exclusif """
Optimisation sur les queryset pour machines et port_related pour
optimiser le temps de chargement avec select_related (vraiment
lent sans)"""
class Meta(PortForm.Meta): class Meta(PortForm.Meta):
fields = [ fields = [
@ -106,8 +100,7 @@ class EditPortForm(FormRevMixin, ModelForm):
class AddPortForm(FormRevMixin, ModelForm): class AddPortForm(FormRevMixin, ModelForm):
"""Permet d'ajouter un port de switch. Voir EditPortForm pour plus """Form used to add a switch's port. See EditPortForm."""
d'informations"""
class Meta(PortForm.Meta): class Meta(PortForm.Meta):
fields = [ fields = [
@ -139,8 +132,7 @@ class AddPortForm(FormRevMixin, ModelForm):
class StackForm(FormRevMixin, ModelForm): class StackForm(FormRevMixin, ModelForm):
"""Permet d'edition d'une stack : stack_id, et switches membres """Form used to create and edit stacks."""
de la stack"""
class Meta: class Meta:
model = Stack model = Stack
@ -152,8 +144,7 @@ class StackForm(FormRevMixin, ModelForm):
class AddAccessPointForm(NewMachineForm): class AddAccessPointForm(NewMachineForm):
"""Formulaire pour la création d'une borne """Form used to create access points."""
Relié directement au modèle borne"""
class Meta: class Meta:
model = AccessPoint model = AccessPoint
@ -161,7 +152,7 @@ class AddAccessPointForm(NewMachineForm):
class EditAccessPointForm(EditMachineForm): class EditAccessPointForm(EditMachineForm):
"""Edition d'une borne. Edition complète""" """Form used to edit access points."""
class Meta: class Meta:
model = AccessPoint model = AccessPoint
@ -169,7 +160,7 @@ class EditAccessPointForm(EditMachineForm):
class EditSwitchForm(EditMachineForm): class EditSwitchForm(EditMachineForm):
"""Permet d'éditer un switch : nom et nombre de ports""" """Form used to edit switches."""
class Meta: class Meta:
model = Switch model = Switch
@ -177,15 +168,14 @@ class EditSwitchForm(EditMachineForm):
class NewSwitchForm(NewMachineForm): class NewSwitchForm(NewMachineForm):
"""Permet de créer un switch : emplacement, paramètres machine, """Form used to create a switch."""
membre d'un stack (option), nombre de ports (number)"""
class Meta(EditSwitchForm.Meta): class Meta(EditSwitchForm.Meta):
fields = ["name", "switchbay", "number", "stack", "stack_member_id"] fields = ["name", "switchbay", "number", "stack", "stack_member_id"]
class EditRoomForm(FormRevMixin, ModelForm): class EditRoomForm(FormRevMixin, ModelForm):
"""Permet d'éediter le nom et commentaire d'une prise murale""" """Form used to edit a room."""
class Meta: class Meta:
model = Room model = Room
@ -197,14 +187,14 @@ class EditRoomForm(FormRevMixin, ModelForm):
class CreatePortsForm(forms.Form): class CreatePortsForm(forms.Form):
"""Permet de créer une liste de ports pour un switch.""" """Form used to create switch ports lists."""
begin = forms.IntegerField(label=_("Start:"), min_value=0) begin = forms.IntegerField(label=_("Start:"), min_value=0)
end = forms.IntegerField(label=_("End:"), min_value=0) end = forms.IntegerField(label=_("End:"), min_value=0)
class EditModelSwitchForm(FormRevMixin, ModelForm): class EditModelSwitchForm(FormRevMixin, ModelForm):
"""Permet d'éediter un modèle de switch : nom et constructeur""" """Form used to edit switch models."""
members = forms.ModelMultipleChoiceField(Switch.objects.all(), required=False) members = forms.ModelMultipleChoiceField(Switch.objects.all(), required=False)
@ -226,7 +216,7 @@ class EditModelSwitchForm(FormRevMixin, ModelForm):
class EditConstructorSwitchForm(FormRevMixin, ModelForm): class EditConstructorSwitchForm(FormRevMixin, ModelForm):
"""Permet d'éediter le nom d'un constructeur""" """Form used to edit switch constructors."""
class Meta: class Meta:
model = ConstructorSwitch model = ConstructorSwitch
@ -238,7 +228,7 @@ class EditConstructorSwitchForm(FormRevMixin, ModelForm):
class EditSwitchBayForm(FormRevMixin, ModelForm): class EditSwitchBayForm(FormRevMixin, ModelForm):
"""Permet d'éditer une baie de brassage""" """Form used to edit switch bays."""
members = forms.ModelMultipleChoiceField(Switch.objects.all(), required=False) members = forms.ModelMultipleChoiceField(Switch.objects.all(), required=False)
@ -260,7 +250,7 @@ class EditSwitchBayForm(FormRevMixin, ModelForm):
class EditBuildingForm(FormRevMixin, ModelForm): class EditBuildingForm(FormRevMixin, ModelForm):
"""Permet d'éditer le batiment""" """Form used to edit buildings."""
class Meta: class Meta:
model = Building model = Building
@ -272,7 +262,7 @@ class EditBuildingForm(FormRevMixin, ModelForm):
class EditDormitoryForm(FormRevMixin, ModelForm): class EditDormitoryForm(FormRevMixin, ModelForm):
"""Enable dormitory edition""" """Form used to edit dormitories."""
class Meta: class Meta:
model = Dormitory model = Dormitory
@ -284,7 +274,7 @@ class EditDormitoryForm(FormRevMixin, ModelForm):
class EditPortProfileForm(FormRevMixin, ModelForm): class EditPortProfileForm(FormRevMixin, ModelForm):
"""Form to edit a port profile""" """Form used to edit port profiles."""
class Meta: class Meta:
model = PortProfile model = PortProfile
@ -296,7 +286,7 @@ class EditPortProfileForm(FormRevMixin, ModelForm):
class EditModuleForm(FormRevMixin, ModelForm): class EditModuleForm(FormRevMixin, ModelForm):
"""Add and edit module instance""" """Form used to add and edit switch modules."""
class Meta: class Meta:
model = ModuleSwitch model = ModuleSwitch
@ -308,7 +298,7 @@ class EditModuleForm(FormRevMixin, ModelForm):
class EditSwitchModuleForm(FormRevMixin, ModelForm): class EditSwitchModuleForm(FormRevMixin, ModelForm):
"""Add/edit a switch to a module""" """Form used to add and edit modules related to a switch."""
class Meta: class Meta:
model = ModuleOnSwitch model = ModuleOnSwitch

View file

@ -21,18 +21,15 @@
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
""" """
Definition des modèles de l'application topologie. Definition of models for the 'topologie' app.
On défini les models suivants : The following models are defined:
* stack (grouping switches): id, id_min, id_max and name
- stack (id, id_min, id_max et nom) regrouppant les switches * switch: name, number of ports, related interface and machine (MAC
- switch : nom, nombre de port, et interface address, IP address etc.) (see machines.models.interface)
machine correspondante (mac, ip, etc) (voir machines.models.interface) * port: related to a switch by foreign_key, number of the port, related
- Port: relié à un switch parent par foreign_key, numero du port, exclusively to another port, machine (server or AP) or room outlets
relié de façon exclusive à un autre port, une machine * room: list of outlets, name and comments about the plug's state
(serveur ou borne) ou une prise murale
- room : liste des prises murales, nom et commentaire de l'état de
la prise
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
@ -56,9 +53,15 @@ from re2o.mixins import AclMixin, RevMixin
class Stack(AclMixin, RevMixin, models.Model): class Stack(AclMixin, RevMixin, models.Model):
"""Un objet stack. Regrouppe des switchs en foreign key """Switch stack.
,contient une id de stack, un switch id min et max dans
le stack""" Attributes:
name: the name of the stack.
stack_id: the ID of the stack, as a text chosen by the user.
details: the description to provide details about the stack.
member_id_min: the minimum switch ID in the stack.
member_id_max: the maximum switch ID in the stack.
"""
name = models.CharField(max_length=32, blank=True, null=True) name = models.CharField(max_length=32, blank=True, null=True)
stack_id = models.CharField(max_length=32, unique=True) stack_id = models.CharField(max_length=32, unique=True)
@ -89,9 +92,10 @@ class Stack(AclMixin, RevMixin, models.Model):
class AccessPoint(Machine): class AccessPoint(Machine):
"""Define a wireless AP. Inherit from machines.interfaces """Wireless Access Point. Inherits from machines.interfaces.
Definition pour une borne wifi , hérite de machines.interfaces Attributes:
location: the text to provide details about the AP's location.
""" """
location = models.CharField( location = models.CharField(
@ -107,17 +111,16 @@ class AccessPoint(Machine):
verbose_name_plural = _("access points") verbose_name_plural = _("access points")
def port(self): def port(self):
"""Return the queryset of ports for this device""" """Return the queryset of ports for this device."""
return Port.objects.filter(machine_interface__machine=self) return Port.objects.filter(machine_interface__machine=self)
def switch(self): def switch(self):
"""Return the switch where this is plugged""" """Return the switch where this is plugged."""
return Switch.objects.filter(ports__machine_interface__machine=self) return Switch.objects.filter(ports__machine_interface__machine=self)
def building(self): def building(self):
""" """Return the building of the AP/Server (building of the switches
Return the building of the AP/Server (building of the switchs connected to...).
connected to...)
""" """
return Building.objects.filter(switchbay__switch=self.switch()) return Building.objects.filter(switchbay__switch=self.switch())
@ -127,7 +130,14 @@ class AccessPoint(Machine):
@classmethod @classmethod
def all_ap_in(cls, building_instance): def all_ap_in(cls, building_instance):
"""Get a building as argument, returns all ap of a building""" """Get all the APs of the given building.
Args:
building_instance: the building used to find APs.
Returns:
The queryset of all APs in the given building.
"""
return cls.objects.filter( return cls.objects.filter(
interface__port__switch__switchbay__building=building_instance interface__port__switch__switchbay__building=building_instance
) )
@ -158,25 +168,24 @@ class AccessPoint(Machine):
class Server(Machine): class Server(Machine):
""" """Dummy class, to retrieve servers of a building, or get switch of a
Dummy class, to retrieve servers of a building, or get switch of a server server.
""" """
class Meta: class Meta:
proxy = True proxy = True
def port(self): def port(self):
"""Return the queryset of ports for this device""" """Return the queryset of ports for this device."""
return Port.objects.filter(machine_interface__machine=self) return Port.objects.filter(machine_interface__machine=self)
def switch(self): def switch(self):
"""Return the switch where this is plugged""" """Return the switch where this is plugged."""
return Switch.objects.filter(ports__machine_interface__machine=self) return Switch.objects.filter(ports__machine_interface__machine=self)
def building(self): def building(self):
""" """Return the building of the AP/Server (building of the switches
Return the building of the AP/Server connected to...).
(building of the switchs connected to...)
""" """
return Building.objects.filter(switchbay__switch=self.switch()) return Building.objects.filter(switchbay__switch=self.switch())
@ -186,7 +195,14 @@ class Server(Machine):
@classmethod @classmethod
def all_server_in(cls, building_instance): def all_server_in(cls, building_instance):
"""Get a building as argument, returns all server of a building""" """Get all the servers of the given building.
Args:
building_instance: the building used to find servers.
Returns:
The queryset of all servers in the given building.
"""
return cls.objects.filter( return cls.objects.filter(
interface__port__switch__switchbay__building=building_instance interface__port__switch__switchbay__building=building_instance
).exclude(accesspoint__isnull=False) ).exclude(accesspoint__isnull=False)
@ -217,17 +233,19 @@ class Server(Machine):
class Switch(Machine): class Switch(Machine):
""" Definition d'un switch. Contient un nombre de ports (number), """Switch.
un emplacement (location), un stack parent (optionnel, stack)
et un id de membre dans le stack (stack_member_id)
relié en onetoone à une interface
Pourquoi ne pas avoir fait hériter switch de interface ?
Principalement par méconnaissance de la puissance de cette façon de faire.
Ceci étant entendu, django crée en interne un onetoone, ce qui a un
effet identique avec ce que l'on fait ici
Validation au save que l'id du stack est bien dans le range id_min Attributes:
id_max de la stack parente""" number: the number of ports of the switch.
stack: the stack the switch is a part of.
stack_member_id: the ID of the switch in the related stack.
model: the model of the switch.
switchbay: the bay in which the switch is located.
radius_key: the RADIUS key of the switch.
management_creds: the management credentials of the switch.
automatic_provision: whether automatic provision is enabled for the
switch.
"""
number = models.PositiveIntegerField(help_text=_("Number of ports.")) number = models.PositiveIntegerField(help_text=_("Number of ports."))
stack = models.ForeignKey( stack = models.ForeignKey(
@ -269,8 +287,9 @@ class Switch(Machine):
verbose_name_plural = _("switches") verbose_name_plural = _("switches")
def clean(self): def clean(self):
""" Verifie que l'id stack est dans le bon range """Check if the stack member ID is in the range of the stack's IDs and
Appelle également le clean de la classe parente""" calls the clean of the parent class.
"""
super(Switch, self).clean() super(Switch, self).clean()
if self.stack is not None: if self.stack is not None:
if self.stack_member_id is not None: if self.stack_member_id is not None:
@ -293,6 +312,12 @@ class Switch(Machine):
def create_ports(self, begin, end): def create_ports(self, begin, end):
""" Crée les ports de begin à end si les valeurs données """ Crée les ports de begin à end si les valeurs données
sont cohérentes. """ sont cohérentes. """
"""Create ports for the switch if the values are consistent.
Args:
begin: the number of the start port.
end: the number of the end port.
"""
if end < begin: if end < begin:
raise ValidationError(_("The end port is less than the start port.")) raise ValidationError(_("The end port is less than the start port."))
ports_to_create = range(begin, end + 1) ports_to_create = range(begin, end + 1)
@ -313,8 +338,7 @@ class Switch(Machine):
) )
def main_interface(self): def main_interface(self):
""" Returns the 'main' interface of the switch """Get the main interface of the switch (the management interface)."""
It must the the management interface for that device"""
switch_iptype = OptionalTopologie.get_cached_value("switchs_ip_type") switch_iptype = OptionalTopologie.get_cached_value("switchs_ip_type")
if switch_iptype: if switch_iptype:
return ( return (
@ -329,12 +353,14 @@ class Switch(Machine):
@cached_property @cached_property
def get_radius_key(self): def get_radius_key(self):
"""Retourne l'objet de la clef radius de ce switch""" """Get the RADIUS key object related to the switch."""
return self.radius_key or RadiusKey.objects.filter(default_switch=True).first() return self.radius_key or RadiusKey.objects.filter(default_switch=True).first()
@cached_property @cached_property
def get_radius_key_value(self): def get_radius_key_value(self):
"""Retourne la valeur en str de la clef radius, none si il n'y en a pas""" """Get the RADIUS key as a string, or None if there are no RADIUS key
related to the switch.
"""
if self.get_radius_key: if self.get_radius_key:
return self.get_radius_key.radius_key return self.get_radius_key.radius_key
else: else:
@ -362,7 +388,7 @@ class Switch(Machine):
@cached_property @cached_property
def get_management_cred(self): def get_management_cred(self):
"""Retourne l'objet des creds de managament de ce switch""" """Get the management credentials objects of the switch."""
return ( return (
self.management_creds self.management_creds
or SwitchManagementCred.objects.filter(default_switch=True).first() or SwitchManagementCred.objects.filter(default_switch=True).first()
@ -370,7 +396,9 @@ class Switch(Machine):
@cached_property @cached_property
def get_management_cred_value(self): def get_management_cred_value(self):
"""Retourne un dict des creds de management du switch""" """Get the management credentials as a dictionary, or None if there are
no management credentials related to the switch.
"""
if self.get_management_cred: if self.get_management_cred:
return { return {
"id": self.get_management_cred.management_id, "id": self.get_management_cred.management_id,
@ -401,17 +429,19 @@ class Switch(Machine):
@cached_property @cached_property
def ipv4(self): def ipv4(self):
"""Return the switch's management ipv4""" """Get the IPv4 address of the switch's management interface."""
return str(self.main_interface().ipv4) return str(self.main_interface().ipv4)
@cached_property @cached_property
def ipv6(self): def ipv6(self):
"""Returne the switch's management ipv6""" """Get the IPv6 address of the switch's management interface."""
return str(self.main_interface().ipv6().first()) return str(self.main_interface().ipv6().first())
@cached_property @cached_property
def interfaces_subnet(self): def interfaces_subnet(self):
"""Return dict ip:subnet for all ip of the switch""" """Get a dictionary of IPv4 addresses:subnets of all the switch's
interfaces.
"""
return dict( return dict(
( (
str(interface.ipv4), str(interface.ipv4),
@ -423,7 +453,9 @@ class Switch(Machine):
@cached_property @cached_property
def interfaces6_subnet(self): def interfaces6_subnet(self):
"""Return dict ip6:subnet for all ipv6 of the switch""" """Get a dictionary of IPv6 addresses:subnets of all the switch's
interfaces.
"""
return dict( return dict(
( (
str(interface.ipv6().first()), str(interface.ipv6().first()),
@ -434,7 +466,9 @@ class Switch(Machine):
@cached_property @cached_property
def list_modules(self): def list_modules(self):
"""Return modules of that switch, list of dict (rank, reference)""" """Get the list of dictionaries (rank, reference) of modules related to
the switch.
"""
modules = [] modules = []
if getattr(self.model, "is_modular", None): if getattr(self.model, "is_modular", None):
if self.model.is_itself_module: if self.model.is_itself_module:
@ -445,7 +479,7 @@ class Switch(Machine):
@cached_property @cached_property
def get_dormitory(self): def get_dormitory(self):
"""Returns the dormitory of that switch""" """Get the dormitory in which the switch is located."""
if self.switchbay: if self.switchbay:
return self.switchbay.building.dormitory return self.switchbay.building.dormitory
else: else:
@ -453,19 +487,19 @@ class Switch(Machine):
@classmethod @classmethod
def nothing_profile(cls): def nothing_profile(cls):
"""Return default nothing port profile""" """Return default nothing port profile."""
nothing_profile, _created = PortProfile.objects.get_or_create( nothing_profile, _created = PortProfile.objects.get_or_create(
profil_default="nothing", name="nothing", radius_type="NO" profil_default="nothing", name="nothing", radius_type="NO"
) )
return nothing_profile return nothing_profile
def profile_type_or_nothing(self, profile_type): def profile_type_or_nothing(self, profile_type):
"""Return the profile for a profile_type of this switch """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 If it exists, return the defined default profile for a profile type on
the switch belongs the dormitory which the switch belongs.
Otherwise, return the nothing profile.
Otherwise, returns the nothing profile""" """
profile_queryset = PortProfile.objects.filter(profil_default=profile_type) profile_queryset = PortProfile.objects.filter(profil_default=profile_type)
if self.get_dormitory: if self.get_dormitory:
port_profile = ( port_profile = (
@ -478,22 +512,22 @@ class Switch(Machine):
@cached_property @cached_property
def default_uplink_profile(self): def default_uplink_profile(self):
"""Default uplink profile for that switch -- in cache""" """Default uplink profile for that switch -- in cache."""
return self.profile_type_or_nothing("uplink") return self.profile_type_or_nothing("uplink")
@cached_property @cached_property
def default_access_point_profile(self): def default_access_point_profile(self):
"""Default ap profile for that switch -- in cache""" """Default AP profile for that switch -- in cache."""
return self.profile_type_or_nothing("access_point") return self.profile_type_or_nothing("access_point")
@cached_property @cached_property
def default_room_profile(self): def default_room_profile(self):
"""Default room profile for that switch -- in cache""" """Default room profile for that switch -- in cache."""
return self.profile_type_or_nothing("room") return self.profile_type_or_nothing("room")
@cached_property @cached_property
def default_asso_machine_profile(self): def default_asso_machine_profile(self):
"""Default asso machine profile for that switch -- in cache""" """Default asso machine profile for that switch -- in cache."""
return self.profile_type_or_nothing("asso_machine") return self.profile_type_or_nothing("asso_machine")
def __str__(self): def __str__(self):
@ -522,7 +556,16 @@ class Switch(Machine):
class ModelSwitch(AclMixin, RevMixin, models.Model): class ModelSwitch(AclMixin, RevMixin, models.Model):
"""Un modèle (au sens constructeur) de switch""" """Switch model.
Attributes:
reference: the reference of the switch model.
commercial_name: the commercial name of the switch model.
constructor: the constructor of the switch model.
firmware: the firmware of the switch model.
is_modular: whether the switch model is modular.
is_itself_module: whether the switch is considered as a module.
"""
reference = models.CharField(max_length=255) reference = models.CharField(max_length=255)
commercial_name = models.CharField(max_length=255, null=True, blank=True) commercial_name = models.CharField(max_length=255, null=True, blank=True)
@ -550,7 +593,12 @@ class ModelSwitch(AclMixin, RevMixin, models.Model):
class ModuleSwitch(AclMixin, RevMixin, models.Model): class ModuleSwitch(AclMixin, RevMixin, models.Model):
"""A module of a switch""" """Switch module.
Attributes:
reference: the reference of the switch module.
comment: the comment to describe the switch module.
"""
reference = models.CharField( reference = models.CharField(
max_length=255, max_length=255,
@ -575,7 +623,13 @@ class ModuleSwitch(AclMixin, RevMixin, models.Model):
class ModuleOnSwitch(AclMixin, RevMixin, models.Model): class ModuleOnSwitch(AclMixin, RevMixin, models.Model):
"""Link beetween module and switch""" """Link beetween module and switch.
Attributes:
module: the switch module related to the link.
switch: the switch related to the link.
slot: the slot on the switch related to the link.
"""
module = models.ForeignKey("ModuleSwitch", on_delete=models.CASCADE) module = models.ForeignKey("ModuleSwitch", on_delete=models.CASCADE)
switch = models.ForeignKey("Switch", on_delete=models.CASCADE) switch = models.ForeignKey("Switch", on_delete=models.CASCADE)
@ -601,7 +655,11 @@ class ModuleOnSwitch(AclMixin, RevMixin, models.Model):
class ConstructorSwitch(AclMixin, RevMixin, models.Model): class ConstructorSwitch(AclMixin, RevMixin, models.Model):
"""Un constructeur de switch""" """Switch constructor.
Attributes:
name: the name of the switch constructor.
"""
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
@ -617,7 +675,13 @@ class ConstructorSwitch(AclMixin, RevMixin, models.Model):
class SwitchBay(AclMixin, RevMixin, models.Model): class SwitchBay(AclMixin, RevMixin, models.Model):
"""Une baie de brassage""" """Switch bay.
Attributes:
name: the name of the switch bay.
building: the building in which the switch bay is located.
info: the information to describe to switch bay.
"""
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
building = models.ForeignKey("Building", on_delete=models.PROTECT) building = models.ForeignKey("Building", on_delete=models.PROTECT)
@ -633,8 +697,11 @@ class SwitchBay(AclMixin, RevMixin, models.Model):
class Dormitory(AclMixin, RevMixin, models.Model): class Dormitory(AclMixin, RevMixin, models.Model):
"""A student accomodation/dormitory """Dormitory.
Une résidence universitaire"""
Attributes:
name: the name of the dormitory.
"""
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
@ -644,7 +711,7 @@ class Dormitory(AclMixin, RevMixin, models.Model):
verbose_name_plural = _("dormitories") verbose_name_plural = _("dormitories")
def all_ap_in(self): def all_ap_in(self):
"""Returns all ap of the dorms""" """Get all the APs in the dormitory."""
return AccessPoint.all_ap_in(self.building_set.all()) return AccessPoint.all_ap_in(self.building_set.all())
@classmethod @classmethod
@ -660,8 +727,13 @@ class Dormitory(AclMixin, RevMixin, models.Model):
class Building(AclMixin, RevMixin, models.Model): class Building(AclMixin, RevMixin, models.Model):
"""A building of a dormitory """Building.
Un batiment"""
Attributes:
name: the name of the building.
dormitory: the dormitory of the building (a Dormitory can contain
multiple dormitories).
"""
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
dormitory = models.ForeignKey("Dormitory", on_delete=models.PROTECT) dormitory = models.ForeignKey("Dormitory", on_delete=models.PROTECT)
@ -672,7 +744,7 @@ class Building(AclMixin, RevMixin, models.Model):
verbose_name_plural = _("buildings") verbose_name_plural = _("buildings")
def all_ap_in(self): def all_ap_in(self):
"""Returns all ap of the building""" """Get all the APs in the building."""
return AccessPoint.all_ap_in(self) return AccessPoint.all_ap_in(self)
def get_name(self): def get_name(self):
@ -690,21 +762,32 @@ class Building(AclMixin, RevMixin, models.Model):
class Port(AclMixin, RevMixin, models.Model): class Port(AclMixin, RevMixin, models.Model):
""" Definition d'un port. Relié à un switch(foreign_key), """Port of a switch.
un port peut etre relié de manière exclusive à :
- une chambre (room) A port is related exclusively to either:
- une machine (serveur etc) (machine_interface) * a room
- un autre port (uplink) (related) * a machine, e.g. server
Champs supplémentaires : * another port
- RADIUS (mode STRICT : connexion sur port uniquement si machine Behaviour according to the RADIUS mode:
d'un adhérent à jour de cotisation et que la chambre est également à * STRICT: connection only if the machine and room have access
jour de cotisation * COMMON: check only the machine's state
mode COMMON : vérification uniquement du statut de la machine * NO: accept only request coming from the port and set on the standard
mode NO : accepte toute demande venant du port et place sur le vlan normal VLAN.
mode BLOQ : rejet de toute authentification * BLOQ: reject all requests.
- vlan_force : override la politique générale de placement vlan, permet The VLAN can be forced to override the general policy for VLAN setting.
de forcer un port sur un vlan particulier. S'additionne à la politique This enables to force a port to a particular VLAN. It adds to the RADIUS
RADIUS""" policy.
Attributes:
switch: the switch to which the port belongs.
port: the port number on the switch for the Port object.
room: the room to which the port is related.
machine_interface: the machine to which the port is related
related: the other port to which is port is related.
custom_profile: the port profile of the port.
state: whether the port is active.
details: the details to describre the port.
"""
switch = models.ForeignKey("Switch", related_name="ports", on_delete=models.CASCADE) switch = models.ForeignKey("Switch", related_name="ports", on_delete=models.CASCADE)
port = models.PositiveIntegerField() port = models.PositiveIntegerField()
@ -733,7 +816,7 @@ class Port(AclMixin, RevMixin, models.Model):
@cached_property @cached_property
def pretty_name(self): def pretty_name(self):
"""More elaborated name for label on switch conf""" """More elaborated name for label on switch configuration."""
if self.related: if self.related:
return _("Uplink: ") + self.related.switch.short_name return _("Uplink: ") + self.related.switch.short_name
elif self.machine_interface: elif self.machine_interface:
@ -745,14 +828,13 @@ class Port(AclMixin, RevMixin, models.Model):
@cached_property @cached_property
def get_port_profile(self): def get_port_profile(self):
"""Return the config profil for this port """Get the configuration profile for this port.
: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"""
Returns:
The custom profile if it exists, else the default profile of the
dormitory if it exists, else the global default profile, else the
nothing profile.
"""
if self.custom_profile: if self.custom_profile:
return self.custom_profile return self.custom_profile
elif self.related: elif self.related:
@ -779,26 +861,25 @@ class Port(AclMixin, RevMixin, models.Model):
) )
def make_port_related(self): def make_port_related(self):
""" Synchronise le port distant sur self""" """Synchronise the related port with self."""
related_port = self.related related_port = self.related
related_port.related = self related_port.related = self
related_port.save() related_port.save()
def clean_port_related(self): def clean_port_related(self):
""" Supprime la relation related sur self""" """Delete the related relation on self."""
related_port = self.related_port related_port = self.related_port
related_port.related = None related_port.related = None
related_port.save() related_port.save()
def clean(self): def clean(self):
""" Verifie que un seul de chambre, interface_parent et related_port """
est rempli. Verifie que le related n'est pas le port lui-même.... Check if the port is only related exclusively to either a room, a
Verifie que le related n'est pas déjà occupé par une machine ou une machine or another port.
chambre. Si ce n'est pas le cas, applique la relation related Check if the related port is not self and applies the relation to the
Si un port related point vers self, on nettoie la relation related port if the relation is correct.
A priori pas d'autre solution que de faire ça à la main. A priori Delete the relation if it points to self.
tout cela est dans un bloc transaction, donc pas de problème de """
cohérence"""
if hasattr(self, "switch"): if hasattr(self, "switch"):
if self.port > self.switch.number: if self.port > self.switch.number:
raise ValidationError( raise ValidationError(
@ -835,7 +916,13 @@ class Port(AclMixin, RevMixin, models.Model):
class Room(AclMixin, RevMixin, models.Model): class Room(AclMixin, RevMixin, models.Model):
"""Une chambre/local contenant une prise murale""" """Room.
Attributes:
name: the name of the room.
details: the details describing the room.
building: the building in which the room is located.
"""
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
details = models.CharField(max_length=255, blank=True) details = models.CharField(max_length=255, blank=True)
@ -853,7 +940,28 @@ class Room(AclMixin, RevMixin, models.Model):
class PortProfile(AclMixin, RevMixin, models.Model): class PortProfile(AclMixin, RevMixin, models.Model):
"""Contains the information of the ports' configuration for a switch""" """Port profile.
Contains the information of the ports' configuration for a switch.
Attributes:
name: the name of the port profile.
profil_default: the type of default profile (room, AP, uplink etc.).
on_dormitory: the dormitory with this default port profile.
vlan_untagged: the VLAN untagged of the port profile.
vlan_tagged: the VLAN(s) tagged of the port profile.
radius_type: the type of RADIUS authentication (inactive, MAC-address
or 802.1X) of the port profile.
radius_mode: the RADIUS mode of the port profile.
speed: the port speed limit of the port profile.
mac_limit: the MAC limit of the port profile.
flow_control: whether flow control is enabled.
dhcp_snooping: whether DHCP snooping is enabled.
dhcpv6_snooping: whether DHCPv6 snooping is enabled.
arp_protect: whether ARP protection is enabled.
ra_guard: whether RA guard is enabled.
loop_protect: whether loop protection is enabled.
"""
TYPES = (("NO", "NO"), ("802.1X", "802.1X"), ("MAC-radius", _("MAC-RADIUS"))) TYPES = (("NO", "NO"), ("802.1X", "802.1X"), ("MAC-radius", _("MAC-RADIUS")))
MODES = (("STRICT", "STRICT"), ("COMMON", "COMMON")) MODES = (("STRICT", "STRICT"), ("COMMON", "COMMON"))
@ -983,7 +1091,7 @@ class PortProfile(AclMixin, RevMixin, models.Model):
return ",".join(self.security_parameters_enabled) return ",".join(self.security_parameters_enabled)
def clean(self): def clean(self):
""" Check that there is only one generic profil default""" """Check that there is only one generic profile default."""
super(PortProfile, self).clean() super(PortProfile, self).clean()
if ( if (
self.profil_default self.profil_default
@ -1007,21 +1115,21 @@ class PortProfile(AclMixin, RevMixin, models.Model):
@receiver(post_save, sender=AccessPoint) @receiver(post_save, sender=AccessPoint)
def ap_post_save(**_kwargs): def ap_post_save(**_kwargs):
"""Regeneration des noms des bornes vers le controleur""" """Regenerate the AP names towards the controller."""
regen("unifi-ap-names") regen("unifi-ap-names")
regen("graph_topo") regen("graph_topo")
@receiver(post_delete, sender=AccessPoint) @receiver(post_delete, sender=AccessPoint)
def ap_post_delete(**_kwargs): def ap_post_delete(**_kwargs):
"""Regeneration des noms des bornes vers le controleur""" """Regenerate the AP names towards the controller."""
regen("unifi-ap-names") regen("unifi-ap-names")
regen("graph_topo") regen("graph_topo")
@receiver(post_delete, sender=Stack) @receiver(post_delete, sender=Stack)
def stack_post_delete(**_kwargs): def stack_post_delete(**_kwargs):
"""Vide les id des switches membres d'une stack supprimée""" """Empty the stack member ID of switches when a stack is deleted."""
Switch.objects.filter(stack=None).update(stack_member_id=None) Switch.objects.filter(stack=None).update(stack_member_id=None)

View file

@ -20,18 +20,17 @@
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
""" """
Page des vues de l'application topologie Views for the 'topologie' app of re2o.
Permet de créer, modifier et supprimer : They are used to create, edit and delete:
- un port (add_port, edit_port, del_port) * a port (add_port, edit_port, del_port)
- un switch : les vues d'ajout et d'édition font appel aux forms de creation * a switch: the views call forms for switches but also machines (domain,
de switch, mais aussi aux forms de machines.forms (domain, interface et interface and machine), send and save them at the same time.
machine). Le views les envoie et les save en même temps. TODO : rationaliser TODO rationalise, enforce the creation of machines (interfaces, domains
et faire que la creation de machines (interfaces, domain etc) soit gérée etc.) in models and forms from 'topologie'
coté models et forms de topologie * a room (new_room, edit_room, del_room)
- une chambre (new_room, edit_room, del_room) * a stack
- une stack * histories of all objects mentioned.
- l'historique de tous les objets cités
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
@ -105,7 +104,7 @@ from os.path import isfile
@login_required @login_required
@can_view_all(Switch) @can_view_all(Switch)
def index(request): def index(request):
""" Vue d'affichage de tous les swicthes""" """View used to display all switches."""
switch_list = ( switch_list = (
Switch.objects.prefetch_related( Switch.objects.prefetch_related(
Prefetch( Prefetch(
@ -171,7 +170,7 @@ def index_port_profile(request):
@can_view_all(Port) @can_view_all(Port)
@can_view(Switch) @can_view(Switch)
def index_port(request, switch, switchid): def index_port(request, switch, switchid):
""" Affichage de l'ensemble des ports reliés à un switch particulier""" """View used to display all ports related to the given switch."""
port_list = ( port_list = (
Port.objects.filter(switch=switch) Port.objects.filter(switch=switch)
.select_related("room__building__dormitory") .select_related("room__building__dormitory")
@ -204,7 +203,7 @@ def index_port(request, switch, switchid):
@login_required @login_required
@can_view_all(Room) @can_view_all(Room)
def index_room(request): def index_room(request):
""" Affichage de l'ensemble des chambres""" """View used to display all rooms."""
room_list = Room.objects.select_related("building__dormitory") room_list = Room.objects.select_related("building__dormitory")
room_list = SortTable.sort( room_list = SortTable.sort(
room_list, room_list,
@ -220,7 +219,7 @@ def index_room(request):
@login_required @login_required
@can_view_all(AccessPoint) @can_view_all(AccessPoint)
def index_ap(request): def index_ap(request):
""" Affichage de l'ensemble des bornes""" """View used to display all APs."""
ap_list = AccessPoint.objects.prefetch_related( ap_list = AccessPoint.objects.prefetch_related(
Prefetch( Prefetch(
"interface_set", "interface_set",
@ -245,7 +244,7 @@ def index_ap(request):
@login_required @login_required
@can_view_all(Stack, Building, Dormitory, SwitchBay) @can_view_all(Stack, Building, Dormitory, SwitchBay)
def index_physical_grouping(request): def index_physical_grouping(request):
"""Affichage de la liste des stacks (affiche l'ensemble des switches)""" """View used to display the list of stacks (display all switches)."""
stack_list = Stack.objects.prefetch_related( stack_list = Stack.objects.prefetch_related(
"switch_set__interface_set__domain__extension" "switch_set__interface_set__domain__extension"
) )
@ -293,7 +292,7 @@ def index_physical_grouping(request):
@login_required @login_required
@can_view_all(ModelSwitch, ConstructorSwitch) @can_view_all(ModelSwitch, ConstructorSwitch)
def index_model_switch(request): def index_model_switch(request):
""" Affichage de l'ensemble des modèles de switches""" """View used to display all switch models."""
model_switch_list = ModelSwitch.objects.select_related( model_switch_list = ModelSwitch.objects.select_related(
"constructor" "constructor"
).prefetch_related("switch_set__interface_set__domain") ).prefetch_related("switch_set__interface_set__domain")
@ -323,7 +322,7 @@ def index_model_switch(request):
@login_required @login_required
@can_view_all(ModuleSwitch) @can_view_all(ModuleSwitch)
def index_module(request): def index_module(request):
"""Display all modules of switchs""" """View used to display all switch modules."""
module_list = ModuleSwitch.objects.all() module_list = ModuleSwitch.objects.all()
modular_switchs = ( modular_switchs = (
Switch.objects.filter(model__is_modular=True) Switch.objects.filter(model__is_modular=True)
@ -342,7 +341,7 @@ def index_module(request):
@login_required @login_required
@can_edit(Vlan) @can_edit(Vlan)
def edit_vlanoptions(request, vlan_instance, **_kwargs): def edit_vlanoptions(request, vlan_instance, **_kwargs):
""" View used to edit options for switch of VLAN object """ """View used to edit options for switch of VLAN object."""
vlan = EditOptionVlanForm(request.POST or None, instance=vlan_instance) vlan = EditOptionVlanForm(request.POST or None, instance=vlan_instance)
if vlan.is_valid(): if vlan.is_valid():
if vlan.changed_data: if vlan.changed_data:
@ -357,7 +356,7 @@ def edit_vlanoptions(request, vlan_instance, **_kwargs):
@login_required @login_required
@can_create(Port) @can_create(Port)
def new_port(request, switchid): def new_port(request, switchid):
""" Nouveau port""" """View used to create ports."""
try: try:
switch = Switch.objects.get(pk=switchid) switch = Switch.objects.get(pk=switchid)
except Switch.DoesNotExist: except Switch.DoesNotExist:
@ -383,9 +382,10 @@ def new_port(request, switchid):
@login_required @login_required
@can_edit(Port) @can_edit(Port)
def edit_port(request, port_object, **_kwargs): def edit_port(request, port_object, **_kwargs):
""" Edition d'un port. Permet de changer le switch parent et """View used to edit ports.
l'affectation du port"""
It enables to change the related switch and the port assignment.
"""
port = EditPortForm(request.POST or None, instance=port_object) port = EditPortForm(request.POST or None, instance=port_object)
if port.is_valid(): if port.is_valid():
if port.changed_data: if port.changed_data:
@ -410,7 +410,7 @@ def edit_port(request, port_object, **_kwargs):
@login_required @login_required
@can_delete(Port) @can_delete(Port)
def del_port(request, port, **_kwargs): def del_port(request, port, **_kwargs):
""" Supprime le port""" """View used to delete ports."""
if request.method == "POST": if request.method == "POST":
try: try:
port.delete() port.delete()
@ -435,7 +435,7 @@ def del_port(request, port, **_kwargs):
@login_required @login_required
@can_create(Stack) @can_create(Stack)
def new_stack(request): def new_stack(request):
"""Ajoute un nouveau stack : stackid_min, max, et nombre de switches""" """View used to create stacks."""
stack = StackForm(request.POST or None) stack = StackForm(request.POST or None)
if stack.is_valid(): if stack.is_valid():
stack.save() stack.save()
@ -449,7 +449,7 @@ def new_stack(request):
@login_required @login_required
@can_edit(Stack) @can_edit(Stack)
def edit_stack(request, stack, **_kwargs): def edit_stack(request, stack, **_kwargs):
"""Edition d'un stack (nombre de switches, nom...)""" """View used to edit stacks."""
stack = StackForm(request.POST or None, instance=stack) stack = StackForm(request.POST or None, instance=stack)
if stack.is_valid(): if stack.is_valid():
if stack.changed_data: if stack.changed_data:
@ -464,7 +464,7 @@ def edit_stack(request, stack, **_kwargs):
@login_required @login_required
@can_delete(Stack) @can_delete(Stack)
def del_stack(request, stack, **_kwargs): def del_stack(request, stack, **_kwargs):
"""Supprime un stack""" """View used to delete stacks."""
if request.method == "POST": if request.method == "POST":
try: try:
stack.delete() stack.delete()
@ -487,8 +487,7 @@ def del_stack(request, stack, **_kwargs):
@login_required @login_required
@can_edit(Stack) @can_edit(Stack)
def edit_switchs_stack(request, stack, **_kwargs): def edit_switchs_stack(request, stack, **_kwargs):
"""Permet d'éditer la liste des switches dans une stack et l'ajouter""" """View used to edit the list of switches of the given stack."""
if request.method == "POST": if request.method == "POST":
pass pass
else: else:
@ -500,9 +499,12 @@ def edit_switchs_stack(request, stack, **_kwargs):
@login_required @login_required
@can_create(Switch) @can_create(Switch)
def new_switch(request): def new_switch(request):
""" Creation d'un switch. Cree en meme temps l'interface et la machine """View used to create switches.
associée. Vue complexe. Appelle successivement les 4 models forms
adaptés : machine, interface, domain et switch""" At the same time, it creates the related interface and machine. The view
successively calls the 4 appropriate forms: machine, interface, domain and
switch.
"""
switch = NewSwitchForm(request.POST or None, user=request.user) switch = NewSwitchForm(request.POST or None, user=request.user)
interface = AddInterfaceForm(request.POST or None, user=request.user) interface = AddInterfaceForm(request.POST or None, user=request.user)
domain = DomainForm(request.POST or None, user=request.user) domain = DomainForm(request.POST or None, user=request.user)
@ -549,7 +551,7 @@ def new_switch(request):
@login_required @login_required
@can_create(Port) @can_create(Port)
def create_ports(request, switchid): def create_ports(request, switchid):
""" Création d'une liste de ports pour un switch.""" """View used to create port lists for the given switch."""
try: try:
switch = Switch.objects.get(pk=switchid) switch = Switch.objects.get(pk=switchid)
except Switch.DoesNotExist: except Switch.DoesNotExist:
@ -578,9 +580,11 @@ def create_ports(request, switchid):
@login_required @login_required
@can_edit(Switch) @can_edit(Switch)
def edit_switch(request, switch, switchid): def edit_switch(request, switch, switchid):
""" Edition d'un switch. Permet de chambre nombre de ports, """View used to edit switches.
place dans le stack, interface et machine associée"""
It enables to change the number of ports, location in the stack, or the
related interface and machine.
"""
switch_form = EditSwitchForm( switch_form = EditSwitchForm(
request.POST or None, instance=switch, user=request.user request.POST or None, instance=switch, user=request.user
) )
@ -622,9 +626,11 @@ def edit_switch(request, switch, switchid):
@login_required @login_required
@can_create(AccessPoint) @can_create(AccessPoint)
def new_ap(request): def new_ap(request):
""" Creation d'une ap. Cree en meme temps l'interface et la machine """View used to create APs.
associée. Vue complexe. Appelle successivement les 3 models forms
adaptés : machine, interface, domain et switch""" At the same time, it creates the related interface and machine. The view
successively calls the 3 appropriate forms: machine, interface, domain.
"""
ap = AddAccessPointForm(request.POST or None, user=request.user) ap = AddAccessPointForm(request.POST or None, user=request.user)
interface = AddInterfaceForm(request.POST or None, user=request.user) interface = AddInterfaceForm(request.POST or None, user=request.user)
domain = DomainForm(request.POST or None, user=request.user) domain = DomainForm(request.POST or None, user=request.user)
@ -671,8 +677,7 @@ def new_ap(request):
@login_required @login_required
@can_edit(AccessPoint) @can_edit(AccessPoint)
def edit_ap(request, ap, **_kwargs): def edit_ap(request, ap, **_kwargs):
""" Edition d'un switch. Permet de chambre nombre de ports, """View used to edit APs."""
place dans le stack, interface et machine associée"""
interface_form = EditInterfaceForm( interface_form = EditInterfaceForm(
request.POST or None, user=request.user, instance=ap.interface_set.first() request.POST or None, user=request.user, instance=ap.interface_set.first()
) )
@ -723,7 +728,7 @@ def edit_ap(request, ap, **_kwargs):
@login_required @login_required
@can_create(Room) @can_create(Room)
def new_room(request): def new_room(request):
"""Nouvelle chambre """ """View used to create rooms."""
room = EditRoomForm(request.POST or None) room = EditRoomForm(request.POST or None)
if room.is_valid(): if room.is_valid():
room.save() room.save()
@ -737,7 +742,7 @@ def new_room(request):
@login_required @login_required
@can_edit(Room) @can_edit(Room)
def edit_room(request, room, **_kwargs): def edit_room(request, room, **_kwargs):
""" Edition numero et details de la chambre""" """View used to edit rooms."""
room = EditRoomForm(request.POST or None, instance=room) room = EditRoomForm(request.POST or None, instance=room)
if room.is_valid(): if room.is_valid():
if room.changed_data: if room.changed_data:
@ -752,7 +757,7 @@ def edit_room(request, room, **_kwargs):
@login_required @login_required
@can_delete(Room) @can_delete(Room)
def del_room(request, room, **_kwargs): def del_room(request, room, **_kwargs):
""" Suppression d'un chambre""" """View used to delete rooms."""
if request.method == "POST": if request.method == "POST":
try: try:
room.delete() room.delete()
@ -777,7 +782,7 @@ def del_room(request, room, **_kwargs):
@login_required @login_required
@can_create(ModelSwitch) @can_create(ModelSwitch)
def new_model_switch(request): def new_model_switch(request):
"""Nouveau modèle de switch""" """View used to create switch models."""
model_switch = EditModelSwitchForm(request.POST or None) model_switch = EditModelSwitchForm(request.POST or None)
if model_switch.is_valid(): if model_switch.is_valid():
model_switch.save() model_switch.save()
@ -793,8 +798,7 @@ def new_model_switch(request):
@login_required @login_required
@can_edit(ModelSwitch) @can_edit(ModelSwitch)
def edit_model_switch(request, model_switch, **_kwargs): def edit_model_switch(request, model_switch, **_kwargs):
""" Edition d'un modèle de switch""" """View used to edit switch models."""
model_switch = EditModelSwitchForm(request.POST or None, instance=model_switch) model_switch = EditModelSwitchForm(request.POST or None, instance=model_switch)
if model_switch.is_valid(): if model_switch.is_valid():
if model_switch.changed_data: if model_switch.changed_data:
@ -811,7 +815,7 @@ def edit_model_switch(request, model_switch, **_kwargs):
@login_required @login_required
@can_delete(ModelSwitch) @can_delete(ModelSwitch)
def del_model_switch(request, model_switch, **_kwargs): def del_model_switch(request, model_switch, **_kwargs):
""" Suppression d'un modèle de switch""" """View used to delete switch models."""
if request.method == "POST": if request.method == "POST":
try: try:
model_switch.delete() model_switch.delete()
@ -838,7 +842,7 @@ def del_model_switch(request, model_switch, **_kwargs):
@login_required @login_required
@can_create(SwitchBay) @can_create(SwitchBay)
def new_switch_bay(request): def new_switch_bay(request):
"""Nouvelle baie de switch""" """View used to create switch bays."""
switch_bay = EditSwitchBayForm(request.POST or None) switch_bay = EditSwitchBayForm(request.POST or None)
if switch_bay.is_valid(): if switch_bay.is_valid():
switch_bay.save() switch_bay.save()
@ -854,7 +858,7 @@ def new_switch_bay(request):
@login_required @login_required
@can_edit(SwitchBay) @can_edit(SwitchBay)
def edit_switch_bay(request, switch_bay, **_kwargs): def edit_switch_bay(request, switch_bay, **_kwargs):
""" Edition d'une baie de switch""" """View used to edit switch bays."""
switch_bay = EditSwitchBayForm(request.POST or None, instance=switch_bay) switch_bay = EditSwitchBayForm(request.POST or None, instance=switch_bay)
if switch_bay.is_valid(): if switch_bay.is_valid():
if switch_bay.changed_data: if switch_bay.changed_data:
@ -871,7 +875,7 @@ def edit_switch_bay(request, switch_bay, **_kwargs):
@login_required @login_required
@can_delete(SwitchBay) @can_delete(SwitchBay)
def del_switch_bay(request, switch_bay, **_kwargs): def del_switch_bay(request, switch_bay, **_kwargs):
""" Suppression d'une baie de switch""" """View used to delete switch bays."""
if request.method == "POST": if request.method == "POST":
try: try:
switch_bay.delete() switch_bay.delete()
@ -898,8 +902,7 @@ def del_switch_bay(request, switch_bay, **_kwargs):
@login_required @login_required
@can_create(Building) @can_create(Building)
def new_building(request): def new_building(request):
"""New Building of a dorm """View used to create buildings."""
Nouveau batiment"""
building = EditBuildingForm(request.POST or None) building = EditBuildingForm(request.POST or None)
if building.is_valid(): if building.is_valid():
building.save() building.save()
@ -915,8 +918,7 @@ def new_building(request):
@login_required @login_required
@can_edit(Building) @can_edit(Building)
def edit_building(request, building, **_kwargs): def edit_building(request, building, **_kwargs):
"""Edit a building """View used to edit buildings."""
Edition d'un batiment"""
building = EditBuildingForm(request.POST or None, instance=building) building = EditBuildingForm(request.POST or None, instance=building)
if building.is_valid(): if building.is_valid():
if building.changed_data: if building.changed_data:
@ -931,8 +933,7 @@ def edit_building(request, building, **_kwargs):
@login_required @login_required
@can_delete(Building) @can_delete(Building)
def del_building(request, building, **_kwargs): def del_building(request, building, **_kwargs):
"""Delete a building """View used to delete buildings."""
Suppression d'un batiment"""
if request.method == "POST": if request.method == "POST":
try: try:
building.delete() building.delete()
@ -959,8 +960,7 @@ def del_building(request, building, **_kwargs):
@login_required @login_required
@can_create(Dormitory) @can_create(Dormitory)
def new_dormitory(request): def new_dormitory(request):
"""A new dormitory """View used to create dormitories."""
Nouvelle residence"""
dormitory = EditDormitoryForm(request.POST or None) dormitory = EditDormitoryForm(request.POST or None)
if dormitory.is_valid(): if dormitory.is_valid():
dormitory.save() dormitory.save()
@ -976,8 +976,7 @@ def new_dormitory(request):
@login_required @login_required
@can_edit(Dormitory) @can_edit(Dormitory)
def edit_dormitory(request, dormitory, **_kwargs): def edit_dormitory(request, dormitory, **_kwargs):
"""Edit a dormitory """View used to edit dormitories."""
Edition d'une residence"""
dormitory = EditDormitoryForm(request.POST or None, instance=dormitory) dormitory = EditDormitoryForm(request.POST or None, instance=dormitory)
if dormitory.is_valid(): if dormitory.is_valid():
if dormitory.changed_data: if dormitory.changed_data:
@ -994,8 +993,7 @@ def edit_dormitory(request, dormitory, **_kwargs):
@login_required @login_required
@can_delete(Dormitory) @can_delete(Dormitory)
def del_dormitory(request, dormitory, **_kwargs): def del_dormitory(request, dormitory, **_kwargs):
"""Delete a dormitory """View used to delete dormitories."""
Suppression d'une residence"""
if request.method == "POST": if request.method == "POST":
try: try:
dormitory.delete() dormitory.delete()
@ -1022,7 +1020,7 @@ def del_dormitory(request, dormitory, **_kwargs):
@login_required @login_required
@can_create(ConstructorSwitch) @can_create(ConstructorSwitch)
def new_constructor_switch(request): def new_constructor_switch(request):
"""Nouveau constructeur de switch""" """View used to create switch constructors."""
constructor_switch = EditConstructorSwitchForm(request.POST or None) constructor_switch = EditConstructorSwitchForm(request.POST or None)
if constructor_switch.is_valid(): if constructor_switch.is_valid():
constructor_switch.save() constructor_switch.save()
@ -1038,8 +1036,7 @@ def new_constructor_switch(request):
@login_required @login_required
@can_edit(ConstructorSwitch) @can_edit(ConstructorSwitch)
def edit_constructor_switch(request, constructor_switch, **_kwargs): def edit_constructor_switch(request, constructor_switch, **_kwargs):
""" Edition d'un constructeur de switch""" """View used to edit switch constructors."""
constructor_switch = EditConstructorSwitchForm( constructor_switch = EditConstructorSwitchForm(
request.POST or None, instance=constructor_switch request.POST or None, instance=constructor_switch
) )
@ -1058,7 +1055,7 @@ def edit_constructor_switch(request, constructor_switch, **_kwargs):
@login_required @login_required
@can_delete(ConstructorSwitch) @can_delete(ConstructorSwitch)
def del_constructor_switch(request, constructor_switch, **_kwargs): def del_constructor_switch(request, constructor_switch, **_kwargs):
""" Suppression d'un constructeur de switch""" """View used to delete switch constructors."""
if request.method == "POST": if request.method == "POST":
try: try:
constructor_switch.delete() constructor_switch.delete()
@ -1085,7 +1082,7 @@ def del_constructor_switch(request, constructor_switch, **_kwargs):
@login_required @login_required
@can_create(PortProfile) @can_create(PortProfile)
def new_port_profile(request): def new_port_profile(request):
"""Create a new port profile""" """View used to create port profiles."""
port_profile = EditPortProfileForm(request.POST or None) port_profile = EditPortProfileForm(request.POST or None)
if port_profile.is_valid(): if port_profile.is_valid():
port_profile.save() port_profile.save()
@ -1101,7 +1098,7 @@ def new_port_profile(request):
@login_required @login_required
@can_edit(PortProfile) @can_edit(PortProfile)
def edit_port_profile(request, port_profile, **_kwargs): def edit_port_profile(request, port_profile, **_kwargs):
"""Edit a port profile""" """View used to edit port profiles."""
port_profile = EditPortProfileForm(request.POST or None, instance=port_profile) port_profile = EditPortProfileForm(request.POST or None, instance=port_profile)
if port_profile.is_valid(): if port_profile.is_valid():
if port_profile.changed_data: if port_profile.changed_data:
@ -1118,7 +1115,7 @@ def edit_port_profile(request, port_profile, **_kwargs):
@login_required @login_required
@can_delete(PortProfile) @can_delete(PortProfile)
def del_port_profile(request, port_profile, **_kwargs): def del_port_profile(request, port_profile, **_kwargs):
"""Delete a port profile""" """View used to delete port profiles."""
if request.method == "POST": if request.method == "POST":
try: try:
port_profile.delete() port_profile.delete()
@ -1136,7 +1133,7 @@ def del_port_profile(request, port_profile, **_kwargs):
@login_required @login_required
@can_create(ModuleSwitch) @can_create(ModuleSwitch)
def add_module(request): def add_module(request):
""" View used to add a Module object """ """View used to create switch modules."""
module = EditModuleForm(request.POST or None) module = EditModuleForm(request.POST or None)
if module.is_valid(): if module.is_valid():
module.save() module.save()
@ -1150,7 +1147,7 @@ def add_module(request):
@login_required @login_required
@can_edit(ModuleSwitch) @can_edit(ModuleSwitch)
def edit_module(request, module_instance, **_kwargs): def edit_module(request, module_instance, **_kwargs):
""" View used to edit a Module object """ """View used to edit switch modules."""
module = EditModuleForm(request.POST or None, instance=module_instance) module = EditModuleForm(request.POST or None, instance=module_instance)
if module.is_valid(): if module.is_valid():
if module.changed_data: if module.changed_data:
@ -1165,7 +1162,7 @@ def edit_module(request, module_instance, **_kwargs):
@login_required @login_required
@can_delete(ModuleSwitch) @can_delete(ModuleSwitch)
def del_module(request, module, **_kwargs): def del_module(request, module, **_kwargs):
"""Compleete delete a module""" """View used to delete switch modules."""
if request.method == "POST": if request.method == "POST":
try: try:
module.delete() module.delete()
@ -1190,7 +1187,7 @@ def del_module(request, module, **_kwargs):
@login_required @login_required
@can_create(ModuleOnSwitch) @can_create(ModuleOnSwitch)
def add_module_on(request): def add_module_on(request):
"""Add a module to a switch""" """View used to add a module to a switch."""
module_switch = EditSwitchModuleForm(request.POST or None) module_switch = EditSwitchModuleForm(request.POST or None)
if module_switch.is_valid(): if module_switch.is_valid():
module_switch.save() module_switch.save()
@ -1206,7 +1203,7 @@ def add_module_on(request):
@login_required @login_required
@can_edit(ModuleOnSwitch) @can_edit(ModuleOnSwitch)
def edit_module_on(request, module_instance, **_kwargs): def edit_module_on(request, module_instance, **_kwargs):
""" View used to edit a Module object """ """View used to edit a module on a switch."""
module = EditSwitchModuleForm(request.POST or None, instance=module_instance) module = EditSwitchModuleForm(request.POST or None, instance=module_instance)
if module.is_valid(): if module.is_valid():
if module.changed_data: if module.changed_data:
@ -1221,7 +1218,7 @@ def edit_module_on(request, module_instance, **_kwargs):
@login_required @login_required
@can_delete(ModuleOnSwitch) @can_delete(ModuleOnSwitch)
def del_module_on(request, module, **_kwargs): def del_module_on(request, module, **_kwargs):
"""Compleete delete a module""" """View used to delete a module on a switch."""
if request.method == "POST": if request.method == "POST":
try: try:
module.delete() module.delete()
@ -1244,9 +1241,7 @@ def del_module_on(request, module, **_kwargs):
def make_machine_graph(): def make_machine_graph():
""" """Create the graph of switches, machines and access points."""
Create the graph of switchs, machines and access points.
"""
dico = { dico = {
"subs": [], "subs": [],
"links": [], "links": [],
@ -1284,7 +1279,7 @@ def make_machine_graph():
"machines": [], "machines": [],
} }
) )
# Visit all switchs in this building # Visit all switches in this building
for switch in ( for switch in (
Switch.objects.filter(switchbay__building=building) Switch.objects.filter(switchbay__building=building)
.prefetch_related( .prefetch_related(
@ -1311,7 +1306,7 @@ def make_machine_graph():
"ports": [], "ports": [],
} }
) )
# visit all ports of this switch and add the switchs linked to it # visit all ports of this switch and add the switches linked to it
for port in switch.ports.filter(related__isnull=False).select_related( for port in switch.ports.filter(related__isnull=False).select_related(
"related__switch" "related__switch"
): ):
@ -1365,29 +1360,29 @@ def make_machine_graph():
links, new_detected = recursive_switchs(missing[0], None, [missing[0]]) links, new_detected = recursive_switchs(missing[0], None, [missing[0]])
for link in links: for link in links:
dico["links"].append(link) dico["links"].append(link)
# Update the lists of missings and already detected switchs # Update the lists of missings and already detected switches
missing = [i for i in missing if i not in new_detected] missing = [i for i in missing if i not in new_detected]
detected += new_detected detected += new_detected
# If the switch have no ports, don't explore it and hop to the next one # If the switch has no ports, don't explore it and hop to the next one
else: else:
del missing[0] del missing[0]
# Switchs that are not connected or not in a building # Switches that are not connected or not in a building
for switch in Switch.objects.filter(switchbay__isnull=True).exclude( for switch in Switch.objects.filter(switchbay__isnull=True).exclude(
ports__related__isnull=False ports__related__isnull=False
): ):
dico["alone"].append({"id": switch.id, "name": switch.get_name}) dico["alone"].append({"id": switch.id, "name": switch.get_name})
# generate the dot file # Generate the dot file
dot_data = generate_dot(dico, "topologie/graph_switch.dot") dot_data = generate_dot(dico, "topologie/graph_switch.dot")
# Create a temporary file to store the dot data # Create a temporary file to store the dot data
f = tempfile.NamedTemporaryFile(mode="w+", encoding="utf-8", delete=False) f = tempfile.NamedTemporaryFile(mode="w+", encoding="utf-8", delete=False)
with f: with f:
f.write(dot_data) f.write(dot_data)
unflatten = Popen( # unflatten the graph to make it look better unflatten = Popen( # Unflatten the graph to make it look better
["unflatten", "-l", "3", f.name], stdout=PIPE ["unflatten", "-l", "3", f.name], stdout=PIPE
) )
Popen( # pipe the result of the first command into the second Popen( # Pipe the result of the first command into the second
["dot", "-Tpng", "-o", MEDIA_ROOT + "/images/switchs.png"], ["dot", "-Tpng", "-o", MEDIA_ROOT + "/images/switchs.png"],
stdin=unflatten.stdout, stdin=unflatten.stdout,
stdout=PIPE, stdout=PIPE,
@ -1395,10 +1390,15 @@ def make_machine_graph():
def generate_dot(data, template): def generate_dot(data, template):
"""create the dot file """Generate a dot file from the data and template given.
:param data: dictionary passed to the template
:param template: path to the dot template Args:
:return: all the lines of the dot file""" data: dictionary passed to the template.
template: path to the dot template.
Returns:
All the lines of the dot file.
"""
t = loader.get_template(template) t = loader.get_template(template)
if not isinstance(t, Template) and not ( if not isinstance(t, Template) and not (
hasattr(t, "template") and isinstance(t.template, Template) hasattr(t, "template") and isinstance(t.template, Template)
@ -1415,18 +1415,19 @@ def generate_dot(data, template):
def recursive_switchs(switch_start, switch_before, detected): def recursive_switchs(switch_start, switch_before, detected):
"""Visit the switch and travel to the switchs linked to it. """Visit the switch and travel to the switches linked to it.
:param switch_start: the switch to begin the visit on
:param switch_before: the switch that you come from. Args:
None if switch_start is the first one switch_start: the switch to begin the visit on.
:param detected: list of all switchs already visited. switch_before: the switch that you come from. None if switch_start is the first one.
None if switch_start is the first one detected: list of all switches already visited. None if switch_start is the first one.
:return: A list of all the links found and a list of
all the switchs visited Returns:
A list of all the links found and a list of all the switches visited.
""" """
detected.append(switch_start) detected.append(switch_start)
links_return = [] # list of dictionaries of the links to be detected links_return = [] # List of dictionaries of the links to be detected
# create links to every switchs below # Create links to every switches below
for port in switch_start.ports.filter(related__isnull=False): for port in switch_start.ports.filter(related__isnull=False):
# Not the switch that we come from, not the current switch # Not the switch that we come from, not the current switch
if ( if (
@ -1440,11 +1441,11 @@ def recursive_switchs(switch_start, switch_before, detected):
} }
links_return.append(links) # Add current and below levels links links_return.append(links) # Add current and below levels links
# go down on every related switchs # Go down on every related switches
for port in switch_start.ports.filter(related__isnull=False): for port in switch_start.ports.filter(related__isnull=False):
# The switch at the end of this link has not been visited # The switch at the end of this link has not been visited
if port.related.switch not in detected: if port.related.switch not in detected:
# explore it and get the results # Explore it and get the results
links_down, detected = recursive_switchs( links_down, detected = recursive_switchs(
port.related.switch, switch_start, detected port.related.switch, switch_start, detected
) )