8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-03 18:12:24 +00:00

PEP8 mon amour + typos

This commit is contained in:
Hugo LEVY-FALK 2018-07-11 19:37:22 +02:00
parent a07e0d922a
commit eefa0b4add
4 changed files with 172 additions and 118 deletions

View file

@ -363,12 +363,12 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
return (sw_name, "Chambre inconnue", u'Port inconnu', VLAN_OK) return (sw_name, "Chambre inconnue", u'Port inconnu', VLAN_OK)
# On récupère le profil du port # On récupère le profil du port
port_profil = port.get_port_profil port_profile = port.get_port_profile
# Si un vlan a été précisé dans la config du port, # Si un vlan a été précisé dans la config du port,
# on l'utilise pour VLAN_OK # on l'utilise pour VLAN_OK
if port_profil.vlan_untagged: if port_profile.vlan_untagged:
DECISION_VLAN = int(port_profil.vlan_untagged.vlan_id) DECISION_VLAN = int(port_profile.vlan_untagged.vlan_id)
extra_log = u"Force sur vlan " + str(DECISION_VLAN) extra_log = u"Force sur vlan " + str(DECISION_VLAN)
else: else:
DECISION_VLAN = VLAN_OK DECISION_VLAN = VLAN_OK
@ -378,7 +378,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
return (sw_name, port.room, u'Port desactivé', VLAN_NOK) return (sw_name, port.room, u'Port desactivé', VLAN_NOK)
# Si radius est désactivé, on laisse passer # Si radius est désactivé, on laisse passer
if port_profil.radius_type == 'NO': if port_profile.radius_type == 'NO':
return (sw_name, return (sw_name,
"", "",
u"Pas d'authentification sur ce port" + extra_log, u"Pas d'authentification sur ce port" + extra_log,
@ -386,7 +386,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
# Si le 802.1X est activé sur ce port, cela veut dire que la personne a été accept précédemment # Si le 802.1X est activé sur ce port, cela veut dire que la personne a été accept précédemment
# Par conséquent, on laisse passer sur le bon vlan # Par conséquent, on laisse passer sur le bon vlan
if nas_type.port_access_mode == '802.1X' and port_profil.radius_type == '802.1X': if nas_type.port_access_mode == '802.1X' and port_profile.radius_type == '802.1X':
room = port.room or "Chambre/local inconnu" room = port.room or "Chambre/local inconnu"
return (sw_name, room, u'Acceptation authentification 802.1X', DECISION_VLAN) return (sw_name, room, u'Acceptation authentification 802.1X', DECISION_VLAN)
@ -395,7 +395,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
# rattachés à ce port sont bien à jour de cotisation. Sinon on rejette (anti squattage) # rattachés à ce port sont bien à jour de cotisation. Sinon on rejette (anti squattage)
# Il n'est pas possible de se connecter sur une prise strict sans adhérent à jour de cotis # Il n'est pas possible de se connecter sur une prise strict sans adhérent à jour de cotis
# dedans # dedans
if port_profil.radius_mode == 'STRICT': if port_profile.radius_mode == 'STRICT':
room = port.room room = port.room
if not room: if not room:
return (sw_name, "Inconnue", u'Chambre inconnue', VLAN_NOK) return (sw_name, "Inconnue", u'Chambre inconnue', VLAN_NOK)
@ -411,7 +411,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
# else: user OK, on passe à la verif MAC # else: user OK, on passe à la verif MAC
# Si on fait de l'auth par mac, on cherche l'interface via sa mac dans la bdd # Si on fait de l'auth par mac, on cherche l'interface via sa mac dans la bdd
if port_profil.radius_mode == 'COMMON' or port_profil.radius_mode == 'STRICT': if port_profile.radius_mode == 'COMMON' or port_profile.radius_mode == 'STRICT':
# Authentification par mac # Authentification par mac
interface = (Interface.objects interface = (Interface.objects
.filter(mac_address=mac_address) .filter(mac_address=mac_address)

View file

@ -40,7 +40,7 @@ from __future__ import unicode_literals
import itertools import itertools
from django.db import models from django.db import models
from django.db.models.signals import pre_save, post_save, post_delete from django.db.models.signals import post_save, post_delete
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.dispatch import receiver from django.dispatch import receiver
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@ -52,11 +52,6 @@ from reversion import revisions as reversion
from machines.models import Machine, regen from machines.models import Machine, regen
from re2o.mixins import AclMixin, RevMixin from re2o.mixins import AclMixin, RevMixin
from os.path import isfile
from os import remove
class Stack(AclMixin, RevMixin, models.Model): class Stack(AclMixin, RevMixin, models.Model):
"""Un objet stack. Regrouppe des switchs en foreign key """Un objet stack. Regrouppe des switchs en foreign key
@ -123,7 +118,10 @@ class AccessPoint(AclMixin, Machine):
) )
def building(self): def building(self):
"""Return the building of the AP/Server (building of the switchs connected to...)""" """
Return the building of the AP/Server (building of the switchs
connected to...)
"""
return Building.objects.filter( return Building.objects.filter(
switchbay__switch=self.switch() switchbay__switch=self.switch()
) )
@ -135,14 +133,18 @@ class AccessPoint(AclMixin, 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 a building as argument, returns all ap of a building"""
return cls.objects.filter(interface__port__switch__switchbay__building=building_instance) return cls.objects.filter(
interface__port__switch__switchbay__building=building_instance
)
def __str__(self): def __str__(self):
return str(self.interface_set.first()) return str(self.interface_set.first())
class Server(Machine): class Server(Machine):
"""Dummy class, to retrieve servers of a building, or get switch of a server""" """
Dummy class, to retrieve servers of a building, or get switch of a server
"""
class Meta: class Meta:
proxy = True proxy = True
@ -160,7 +162,10 @@ class Server(Machine):
) )
def building(self): def building(self):
"""Return the building of the AP/Server (building of the switchs connected to...)""" """
Return the building of the AP/Server
(building of the switchs connected to...)
"""
return Building.objects.filter( return Building.objects.filter(
switchbay__switch=self.switch() switchbay__switch=self.switch()
) )
@ -172,7 +177,9 @@ 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 a building as argument, returns all server of a building"""
return cls.objects.filter(interface__port__switch__switchbay__building=building_instance).exclude(accesspoint__isnull=False) return cls.objects.filter(
interface__port__switch__switchbay__building=building_instance
).exclude(accesspoint__isnull=False)
def __str__(self): def __str__(self):
return str(self.interface_set.first()) return str(self.interface_set.first())
@ -200,7 +207,7 @@ class Switch(AclMixin, Machine):
blank=True, blank=True,
null=True, null=True,
on_delete=models.SET_NULL on_delete=models.SET_NULL
) )
stack_member_id = models.PositiveIntegerField( stack_member_id = models.PositiveIntegerField(
blank=True, blank=True,
null=True, null=True,
@ -238,7 +245,7 @@ class Switch(AclMixin, Machine):
raise ValidationError( raise ValidationError(
{'stack_member_id': "L'id de ce switch est en\ {'stack_member_id': "L'id de ce switch est en\
dehors des bornes permises pas la stack"} dehors des bornes permises pas la stack"}
) )
else: else:
raise ValidationError({'stack_member_id': "L'id dans la stack\ raise ValidationError({'stack_member_id': "L'id dans la stack\
ne peut être nul"}) ne peut être nul"})
@ -378,25 +385,25 @@ class Port(AclMixin, RevMixin, models.Model):
on_delete=models.PROTECT, on_delete=models.PROTECT,
blank=True, blank=True,
null=True null=True
) )
machine_interface = models.ForeignKey( machine_interface = models.ForeignKey(
'machines.Interface', 'machines.Interface',
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
blank=True, blank=True,
null=True null=True
) )
related = models.OneToOneField( related = models.OneToOneField(
'self', 'self',
null=True, null=True,
blank=True, blank=True,
related_name='related_port' related_name='related_port'
) )
custom_profile = models.ForeignKey( custom_profile = models.ForeignKey(
'PortProfile', 'PortProfile',
on_delete=models.PROTECT, on_delete=models.PROTECT,
blank=True, blank=True,
null=True null=True
) )
state = models.BooleanField( state = models.BooleanField(
default=True, default=True,
help_text='Port state Active', help_text='Port state Active',
@ -411,32 +418,35 @@ class Port(AclMixin, RevMixin, models.Model):
) )
@cached_property @cached_property
def get_port_profil(self): def get_port_profile(self):
"""Return the config profil for this port """Return the config profile for this port
:returns: the profile of self (port)""" :returns: the profile of self (port)"""
def profil_or_nothing(profil): def profile_or_nothing(profile):
port_profil = PortProfile.objects.filter(profil_default=profil).first() port_profile = PortProfile.objects.filter(
if port_profil: profile_default=profile).first()
return port_profil if port_profile:
return port_profile
else: else:
nothing = PortProfile.objects.filter(profil_default='nothing').first() nothing_profile, _created = PortProfile.objects.get_or_create(
if not nothing: profile_default='nothing',
nothing = PortProfile.objects.create(profil_default='nothing', name='nothing', radius_type='NO') name='nothing',
return nothing radius_type='NO'
)
return nothing_profile
if self.custom_profile: if self.custom_profile:
return self.custom_profile return self.custom_profile
elif self.related: elif self.related:
return profil_or_nothing('uplink') return profile_or_nothing('uplink')
elif self.machine_interface: elif self.machine_interface:
if hasattr(self.machine_interface.machine, 'accesspoint'): if hasattr(self.machine_interface.machine, 'accesspoint'):
return profil_or_nothing('access_point') return profile_or_nothing('access_point')
else: else:
return profil_or_nothing('asso_machine') return profile_or_nothing('asso_machine')
elif self.room: elif self.room:
return profil_or_nothing('room') return profile_or_nothing('room')
else: else:
return profil_or_nothing('nothing') return profile_or_nothing('nothing')
@classmethod @classmethod
def get_instance(cls, portid, *_args, **kwargs): def get_instance(cls, portid, *_args, **kwargs):
@ -521,11 +531,11 @@ class PortProfile(AclMixin, RevMixin, models.Model):
('NO', 'NO'), ('NO', 'NO'),
('802.1X', '802.1X'), ('802.1X', '802.1X'),
('MAC-radius', 'MAC-radius'), ('MAC-radius', 'MAC-radius'),
) )
MODES = ( MODES = (
('STRICT', 'STRICT'), ('STRICT', 'STRICT'),
('COMMON', 'COMMON'), ('COMMON', 'COMMON'),
) )
SPEED = ( SPEED = (
('10-half', '10-half'), ('10-half', '10-half'),
('100-half', '100-half'), ('100-half', '100-half'),
@ -535,14 +545,14 @@ class PortProfile(AclMixin, RevMixin, models.Model):
('auto', 'auto'), ('auto', 'auto'),
('auto-10', 'auto-10'), ('auto-10', 'auto-10'),
('auto-100', 'auto-100'), ('auto-100', 'auto-100'),
) )
PROFIL_DEFAULT= ( PROFIL_DEFAULT = (
('room', 'room'), ('room', 'room'),
('accespoint', 'accesspoint'), ('accespoint', 'accesspoint'),
('uplink', 'uplink'), ('uplink', 'uplink'),
('asso_machine', 'asso_machine'), ('asso_machine', 'asso_machine'),
('nothing', 'nothing'), ('nothing', 'nothing'),
) )
name = models.CharField(max_length=255, verbose_name=_("Name")) name = models.CharField(max_length=255, verbose_name=_("Name"))
profil_default = models.CharField( profil_default = models.CharField(
max_length=32, max_length=32,
@ -625,16 +635,27 @@ class PortProfile(AclMixin, RevMixin, models.Model):
class Meta: class Meta:
permissions = ( permissions = (
("view_port_profile", _("Can view a port profile object")), ("view_port_profile", _("Can view a port profile object")),
) )
verbose_name = _("Port profile") verbose_name = _("Port profile")
verbose_name_plural = _("Port profiles") verbose_name_plural = _("Port profiles")
security_parameters_fields = ['loop_protect', 'ra_guard', 'arp_protect', 'dhcpv6_snooping', 'dhcp_snooping', 'flow_control'] security_parameters_fields = [
'loop_protect',
'ra_guard',
'arp_protect',
'dhcpv6_snooping',
'dhcp_snooping',
'flow_control'
]
@cached_property @cached_property
def security_parameters_enabled(self): def security_parameters_enabled(self):
return [parameter for parameter in self.security_parameters_fields if getattr(self, parameter)] return [
parameter
for parameter in self.security_parameters_fields
if getattr(self, parameter)
]
@cached_property @cached_property
def security_parameters_as_str(self): def security_parameters_as_str(self):
@ -650,45 +671,55 @@ def ap_post_save(**_kwargs):
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""" """Regeneration des noms des bornes vers le controleur"""
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""" """Vide les id des switches membres d'une stack supprimée"""
Switch.objects.filter(stack=None).update(stack_member_id=None) Switch.objects.filter(stack=None).update(stack_member_id=None)
@receiver(post_save, sender=Port) @receiver(post_save, sender=Port)
def port_post_save(**_kwargs): def port_post_save(**_kwargs):
regen("graph_topo") regen("graph_topo")
@receiver(post_delete, sender=Port) @receiver(post_delete, sender=Port)
def port_post_delete(**_kwargs): def port_post_delete(**_kwargs):
regen("graph_topo") regen("graph_topo")
@receiver(post_save, sender=ModelSwitch) @receiver(post_save, sender=ModelSwitch)
def modelswitch_post_save(**_kwargs): def modelswitch_post_save(**_kwargs):
regen("graph_topo") regen("graph_topo")
@receiver(post_delete, sender=ModelSwitch) @receiver(post_delete, sender=ModelSwitch)
def modelswitch_post_delete(**_kwargs): def modelswitch_post_delete(**_kwargs):
regen("graph_topo") regen("graph_topo")
@receiver(post_save, sender=Building) @receiver(post_save, sender=Building)
def building_post_save(**_kwargs): def building_post_save(**_kwargs):
regen("graph_topo") regen("graph_topo")
@receiver(post_delete, sender=Building) @receiver(post_delete, sender=Building)
def building_post_delete(**_kwargs): def building_post_delete(**_kwargs):
regen("graph_topo") regen("graph_topo")
@receiver(post_save, sender=Switch) @receiver(post_save, sender=Switch)
def switch_post_save(**_kwargs): def switch_post_save(**_kwargs):
regen("graph_topo") regen("graph_topo")
@receiver(post_delete, sender=Switch) @receiver(post_delete, sender=Switch)
def switch_post_delete(**_kwargs): def switch_post_delete(**_kwargs):
regen("graph_topo") regen("graph_topo")

View file

@ -29,9 +29,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% include "pagination.html" with list=port_profile_list %} {% include "pagination.html" with list=port_profile_list %}
{% endif %} {% endif %}
<thead>
<table class="table table-striped"> <table class="table table-striped">
<thead>
<tr> <tr>
<th>{% trans "Name" %}</th> <th>{% trans "Name" %}</th>
<th>{% trans "Default for" %}</th> <th>{% trans "Default for" %}</th>

View file

@ -42,11 +42,7 @@ from django.contrib.auth.decorators import login_required
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import ProtectedError, Prefetch from django.db.models import ProtectedError, Prefetch
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.contrib.staticfiles.storage import staticfiles_storage
from django.template.loader import get_template
from django.template import Context, Template, loader from django.template import Context, Template, loader
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
import tempfile import tempfile
@ -106,7 +102,6 @@ from subprocess import (
) )
from os.path import isfile from os.path import isfile
from os import remove
@login_required @login_required
@ -128,13 +123,17 @@ def index(request):
SortTable.TOPOLOGIE_INDEX SortTable.TOPOLOGIE_INDEX
) )
pagination_number = GeneralOption.get_cached_value('pagination_number') pagination_number = GeneralOption.get_cached_value('pagination_number')
switch_list = re2o_paginator(request, switch_list, pagination_number) switch_list = re2o_paginator(request, switch_list, pagination_number)
if any(service_link.need_regen for service_link in Service_link.objects.filter(service__service_type='graph_topo')): if any(
service_link.need_regen
for service_link in Service_link.objects.filter(
service__service_type='graph_topo')
):
make_machine_graph() make_machine_graph()
for service_link in Service_link.objects.filter(service__service_type='graph_topo'): for service_link in Service_link.objects.filter(
service__service_type='graph_topo'):
service_link.done_regen() service_link.done_regen()
if not isfile("/var/www/re2o/media/images/switchs.png"): if not isfile("/var/www/re2o/media/images/switchs.png"):
@ -150,8 +149,10 @@ def index(request):
@can_view_all(PortProfile) @can_view_all(PortProfile)
def index_port_profile(request): def index_port_profile(request):
pagination_number = GeneralOption.get_cached_value('pagination_number') pagination_number = GeneralOption.get_cached_value('pagination_number')
port_profile_list = PortProfile.objects.all().select_related('vlan_untagged') port_profile_list = PortProfile.objects.all().select_related(
port_profile_list = re2o_paginator(request, port_profile_list, pagination_number) 'vlan_untagged')
port_profile_list = re2o_paginator(
request, port_profile_list, pagination_number)
return render( return render(
request, request,
'topologie/index_portprofile.html', 'topologie/index_portprofile.html',
@ -460,7 +461,7 @@ def new_switch(request):
) )
domain = DomainForm( domain = DomainForm(
request.POST or None, request.POST or None,
) )
if switch.is_valid() and interface.is_valid(): if switch.is_valid() and interface.is_valid():
user = AssoOption.get_cached_value('utilisateur_asso') user = AssoOption.get_cached_value('utilisateur_asso')
if not user: if not user:
@ -530,7 +531,7 @@ def create_ports(request, switchid):
return redirect(reverse( return redirect(reverse(
'topologie:index-port', 'topologie:index-port',
kwargs={'switchid': switchid} kwargs={'switchid': switchid}
)) ))
return form( return form(
{'id_switch': switchid, 'topoform': port_form}, {'id_switch': switchid, 'topoform': port_form},
'topologie/switch.html', 'topologie/switch.html',
@ -548,16 +549,16 @@ def edit_switch(request, switch, switchid):
request.POST or None, request.POST or None,
instance=switch, instance=switch,
user=request.user user=request.user
) )
interface_form = EditInterfaceForm( interface_form = EditInterfaceForm(
request.POST or None, request.POST or None,
instance=switch.interface_set.first(), instance=switch.interface_set.first(),
user=request.user user=request.user
) )
domain_form = DomainForm( domain_form = DomainForm(
request.POST or None, request.POST or None,
instance=switch.interface_set.first().domain instance=switch.interface_set.first().domain
) )
if switch_form.is_valid() and interface_form.is_valid(): if switch_form.is_valid() and interface_form.is_valid():
new_switch_obj = switch_form.save(commit=False) new_switch_obj = switch_form.save(commit=False)
new_interface_obj = interface_form.save(commit=False) new_interface_obj = interface_form.save(commit=False)
@ -601,7 +602,7 @@ def new_ap(request):
) )
domain = DomainForm( domain = DomainForm(
request.POST or None, request.POST or None,
) )
if ap.is_valid() and interface.is_valid(): if ap.is_valid() and interface.is_valid():
user = AssoOption.get_cached_value('utilisateur_asso') user = AssoOption.get_cached_value('utilisateur_asso')
if not user: if not user:
@ -656,7 +657,7 @@ def edit_ap(request, ap, **_kwargs):
domain_form = DomainForm( domain_form = DomainForm(
request.POST or None, request.POST or None,
instance=ap.interface_set.first().domain instance=ap.interface_set.first().domain
) )
if ap_form.is_valid() and interface_form.is_valid(): if ap_form.is_valid() and interface_form.is_valid():
user = AssoOption.get_cached_value('utilisateur_asso') user = AssoOption.get_cached_value('utilisateur_asso')
if not user: if not user:
@ -970,7 +971,7 @@ def del_constructor_switch(request, constructor_switch, **_kwargs):
return form({ return form({
'objet': constructor_switch, 'objet': constructor_switch,
'objet_name': 'Constructeur de switch' 'objet_name': 'Constructeur de switch'
}, 'topologie/delete.html', request) }, 'topologie/delete.html', request)
@login_required @login_required
@ -993,7 +994,8 @@ def new_port_profile(request):
@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""" """Edit a port profile"""
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:
port_profile.save() port_profile.save()
@ -1006,7 +1008,6 @@ 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):
@ -1015,24 +1016,25 @@ def del_port_profile(request, port_profile, **_kwargs):
try: try:
port_profile.delete() port_profile.delete()
messages.success(request, messages.success(request,
_("The port profile was successfully deleted")) _("The port profile was successfully deleted"))
except ProtectedError: except ProtectedError:
messages.success(request, messages.success(request,
_("Impossible to delete the port profile")) _("Impossible to delete the port profile"))
return redirect(reverse('topologie:index')) return redirect(reverse('topologie:index'))
return form( return form(
{'objet': port_profile, 'objet_name': _("Port profile")}, {'objet': port_profile, 'objet_name': _("Port profile")},
'topologie/delete.html', 'topologie/delete.html',
request request
) )
def make_machine_graph(): def make_machine_graph():
""" """
Create the graph of switchs, machines and access points. Create the graph of switchs, machines and access points.
""" """
dico = { dico = {
'subs': [], 'subs': [],
'links' : [], 'links': [],
'alone': [], 'alone': [],
'colors': { 'colors': {
'head': "#7f0505", # Color parameters for the graph 'head': "#7f0505", # Color parameters for the graph
@ -1041,19 +1043,19 @@ def make_machine_graph():
'border_bornes': "#02078e", 'border_bornes': "#02078e",
'head_bornes': "#25771c", 'head_bornes': "#25771c",
'head_server': "#1c3777" 'head_server': "#1c3777"
}
} }
}
missing = list(Switch.objects.all()) missing = list(Switch.objects.all())
detected = [] detected = []
for building in Building.objects.all(): # Visit all buildings for building in Building.objects.all(): # Visit all buildings
dico['subs'].append( dico['subs'].append(
{ {
'bat_id': building.id, 'bat_id': building.id,
'bat_name': building, 'bat_name': building,
'switchs': [], 'switchs': [],
'bornes': [], 'bornes': [],
'machines': [] 'machines': []
} }
) )
# Visit all switchs in this building # Visit all switchs in this building
@ -1085,50 +1087,58 @@ def make_machine_graph():
dico['subs'][-1]['machines'].append({ dico['subs'][-1]['machines'].append({
'name': server.short_name, 'name': server.short_name,
'switch': server.switch()[0].main_interface().domain.name, 'switch': server.switch()[0].main_interface().domain.name,
'port': Port.objects.filter(machine_interface__machine=server)[0].port 'port': Port.objects.filter(
machine_interface__machine=server
)[0].port
}) })
# While the list of forgotten ones is not empty # While the list of forgotten ones is not empty
while missing: while missing:
if missing[0].ports.count(): # The switch is not empty if missing[0].ports.count(): # The switch is not empty
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 switchs
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
else: # If the switch have no ports, don't explore it and hop to the next one # If the switch have no ports, don't explore it and hop to the next one
else:
del missing[0] del missing[0]
# Switchs that are not connected or not in a building # Switchs that are not connected or not in a building
for switch in Switch.objects.filter(switchbay__isnull=True).exclude(ports__related__isnull=False): for switch in Switch.objects.filter(
switchbay__isnull=True).exclude(ports__related__isnull=False):
dico['alone'].append({ dico['alone'].append({
'id': switch.id, 'id': switch.id,
'name': switch.main_interface().domain.name 'name': switch.main_interface().domain.name
}) })
# generate the dot file
dot_data = generate_dot(dico, 'topologie/graph_switch.dot')
dot_data=generate_dot(dico,'topologie/graph_switch.dot') # generate the dot file # 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) # Create a temporary file to store the dot data
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], ["unflatten", "-l", "3", f.name],
stdout=PIPE stdout=PIPE
) )
image = 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
) )
def generate_dot(data,template):
def generate_dot(data, template):
"""create the dot file """create the dot file
:param data: dictionary passed to the template :param data: dictionary passed to the template
:param template: path to the dot template :param template: path to the dot template
:return: all the lines of the dot file""" :return: all the lines of the dot file"""
t = loader.get_template(template) t = loader.get_template(template)
if not isinstance(t, Template) and not (hasattr(t, 'template') and isinstance(t.template, Template)): if not isinstance(t, Template) and \
not (hasattr(t, 'template') and isinstance(t.template, Template)):
raise Exception("Le template par défaut de Django n'est pas utilisé." raise Exception("Le template par défaut de Django n'est pas utilisé."
"Cela peut mener à des erreurs de rendu." "Cela peut mener à des erreurs de rendu."
"Vérifiez les paramètres") "Vérifiez les paramètres")
@ -1136,27 +1146,40 @@ def generate_dot(data,template):
dot = t.render(c) dot = t.render(c)
return(dot) return(dot)
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 switchs linked to it.
:param switch_start: the switch to begin the visit on :param switch_start: the switch to begin the visit on
:param switch_before: the switch that you come from. None if switch_start is the first one :param switch_before: the switch that you come from.
:param detected: list of all switchs already visited. None if switch_start is the first one None if switch_start is the first one
:return: A list of all the links found and a list of all the switchs visited""" :param detected: list of all switchs 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
"""
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
for port in switch_start.ports.filter(related__isnull=False): # create links to every switchs below # create links to every switchs below
if port.related.switch != switch_before and port.related.switch != port.switch and port.related.switch not in detected: # Not the switch that we come from, not the current switch for port in switch_start.ports.filter(related__isnull=False):
# Not the switch that we come from, not the current switch
if port.related.switch != switch_before \
and port.related.switch != port.switch \
and port.related.switch not in detected:
links = { # Dictionary of a link links = { # Dictionary of a link
'depart':switch_start.id, 'depart': switch_start.id,
'arrive':port.related.switch.id 'arrive': port.related.switch.id
} }
links_return.append(links) # Add current and below levels links links_return.append(links) # Add current and below levels links
for port in switch_start.ports.filter(related__isnull=False): # go down on every related switchs # go down on every related switchs
if port.related.switch not in detected: # The switch at the end of this link has not been visited for port in switch_start.ports.filter(related__isnull=False):
links_down, detected = recursive_switchs(port.related.switch, switch_start, detected) # explore it and get the results # The switch at the end of this link has not been visited
for link in links_down: # Add the non empty links to the current list if port.related.switch not in detected:
# explore it and get the results
links_down, detected = recursive_switchs(
port.related.switch, switch_start, detected)
# Add the non empty links to the current list
for link in links_down:
if link: if link:
links_return.append(link) links_return.append(link)
return (links_return, detected) return (links_return, detected)