8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-23 20:03:11 +00:00
re2o/topologie/views.py

1209 lines
39 KiB
Python
Raw Normal View History

2017-01-15 23:01:18 +00:00
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
# Copyright © 2017 Gabriel Détraz
# Copyright © 2017 Goulven Kermarec
# Copyright © 2017 Augustin Lemesle
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2017-10-13 23:43:01 +00:00
"""
Page des vues de l'application topologie
2017-01-15 23:01:18 +00:00
2017-10-13 23:43:01 +00:00
Permet de créer, modifier et supprimer :
- un port (add_port, edit_port, del_port)
- un switch : les vues d'ajout et d'édition font appel aux forms de creation
de switch, mais aussi aux forms de machines.forms (domain, interface et
machine). Le views les envoie et les save en même temps. TODO : rationaliser
et faire que la creation de machines (interfaces, domain etc) soit gérée
coté models et forms de topologie
- une chambre (new_room, edit_room, del_room)
- une stack
- l'historique de tous les objets cités
"""
from __future__ import unicode_literals
2017-10-26 15:58:41 +00:00
from django.urls import reverse
from django.shortcuts import render, redirect
from django.contrib import messages
2018-04-14 22:06:29 +00:00
from django.contrib.auth.decorators import login_required
2016-07-06 21:29:31 +00:00
from django.db import IntegrityError
from django.db.models import ProtectedError, Prefetch
2017-10-26 21:29:26 +00:00
from django.core.exceptions import ValidationError
2018-05-15 18:42:00 +00:00
from django.template import Context, Template, loader
2018-05-26 22:36:25 +00:00
from django.utils.translation import ugettext as _
2018-05-15 18:42:00 +00:00
2018-05-21 20:05:31 +00:00
import tempfile
2018-04-14 22:06:29 +00:00
from users.views import form
from re2o.utils import re2o_paginator, SortTable
from re2o.acl import (
can_create,
can_edit,
can_delete,
can_view,
can_view_all,
)
2018-05-15 18:42:00 +00:00
from re2o.settings import MEDIA_ROOT
2018-04-14 22:06:29 +00:00
from machines.forms import (
DomainForm,
EditInterfaceForm,
AddInterfaceForm,
EditOptionVlanForm
2018-04-14 22:06:29 +00:00
)
from machines.views import generate_ipv4_mbf_param
from machines.models import (
Interface,
Service_link,
Vlan
)
2018-04-14 22:06:29 +00:00
from preferences.models import AssoOption, GeneralOption
from .models import (
2017-10-26 03:07:11 +00:00
Switch,
Port,
Room,
Stack,
ModelSwitch,
2018-03-23 23:50:11 +00:00
ConstructorSwitch,
2018-04-07 18:45:29 +00:00
AccessPoint,
SwitchBay,
2018-05-15 18:42:00 +00:00
Building,
2018-05-19 19:20:55 +00:00
Server,
2018-05-26 22:36:25 +00:00
PortProfile,
2017-10-26 03:07:11 +00:00
)
2018-04-14 22:06:29 +00:00
from .forms import (
EditPortForm,
NewSwitchForm,
EditSwitchForm,
2017-10-26 03:07:11 +00:00
AddPortForm,
EditRoomForm,
StackForm,
2017-12-28 11:39:25 +00:00
EditModelSwitchForm,
2017-10-26 19:38:55 +00:00
EditConstructorSwitchForm,
2018-03-23 23:50:11 +00:00
CreatePortsForm,
2018-03-25 22:08:24 +00:00
AddAccessPointForm,
2018-04-07 18:45:29 +00:00
EditAccessPointForm,
EditSwitchBayForm,
2018-05-26 22:36:25 +00:00
EditBuildingForm,
EditPortProfileForm,
2017-10-26 03:07:11 +00:00
)
2018-05-21 19:13:44 +00:00
from subprocess import (
Popen,
PIPE
)
2018-07-11 17:37:22 +00:00
from os.path import isfile
2016-07-27 01:36:28 +00:00
2016-07-08 10:35:53 +00:00
@login_required
2017-12-27 22:07:05 +00:00
@can_view_all(Switch)
def index(request):
2017-10-06 02:17:45 +00:00
""" Vue d'affichage de tous les swicthes"""
2018-04-14 00:20:44 +00:00
switch_list = (Switch.objects
.prefetch_related(Prefetch(
'interface_set',
queryset=(Interface.objects
.select_related('ipv4__ip_type__extension')
.select_related('domain__extension'))
))
.select_related('stack'))
switch_list = SortTable.sort(
switch_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX
)
2018-05-26 22:36:25 +00:00
pagination_number = GeneralOption.get_cached_value('pagination_number')
switch_list = re2o_paginator(request, switch_list, pagination_number)
2018-05-15 18:42:00 +00:00
2018-07-11 17:37:22 +00:00
if any(
service_link.need_regen
for service_link in Service_link.objects.filter(
service__service_type='graph_topo')
):
2018-05-15 18:42:00 +00:00
make_machine_graph()
2018-07-11 17:37:22 +00:00
for service_link in Service_link.objects.filter(
service__service_type='graph_topo'):
2018-05-15 18:42:00 +00:00
service_link.done_regen()
2018-05-21 19:13:44 +00:00
if not isfile("/var/www/re2o/media/images/switchs.png"):
make_machine_graph()
2018-04-14 00:20:44 +00:00
return render(
request,
'topologie/index.html',
{'switch_list': switch_list}
)
@login_required
@can_view_all(PortProfile)
def index_port_profile(request):
pagination_number = GeneralOption.get_cached_value('pagination_number')
2018-07-11 17:37:22 +00:00
port_profile_list = PortProfile.objects.all().select_related(
'vlan_untagged')
port_profile_list = re2o_paginator(
request, port_profile_list, pagination_number)
vlan_list = Vlan.objects.all().order_by('vlan_id')
return render(
request,
'topologie/index_portprofile.html',
{'port_profile_list': port_profile_list, 'vlan_list': vlan_list}
2018-04-14 00:20:44 +00:00
)
2017-10-13 23:43:01 +00:00
2016-07-08 10:35:53 +00:00
@login_required
2017-12-27 22:07:05 +00:00
@can_view_all(Port)
@can_view(Switch)
2018-03-28 18:32:03 +00:00
def index_port(request, switch, switchid):
2017-10-06 02:17:45 +00:00
""" Affichage de l'ensemble des ports reliés à un switch particulier"""
2018-04-14 00:20:44 +00:00
port_list = (Port.objects
.filter(switch=switch)
.select_related('room')
.select_related('machine_interface__domain__extension')
.select_related('machine_interface__machine__user')
.select_related('related__switch')
.prefetch_related(Prefetch(
'related__switch__interface_set',
queryset=(Interface.objects
.select_related('domain__extension'))
))
.select_related('switch'))
port_list = SortTable.sort(
port_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_PORT
)
2018-04-14 00:20:44 +00:00
return render(
request,
'topologie/index_p.html',
{
'port_list': port_list,
'id_switch': switchid,
2018-09-26 13:42:31 +00:00
'switch': switch
2018-04-14 00:20:44 +00:00
}
)
2017-10-13 23:43:01 +00:00
2016-07-06 21:29:31 +00:00
2016-07-19 00:30:52 +00:00
@login_required
2017-12-27 22:07:05 +00:00
@can_view_all(Room)
2016-07-19 00:30:52 +00:00
def index_room(request):
2017-10-06 02:17:45 +00:00
""" Affichage de l'ensemble des chambres"""
room_list = Room.objects
room_list = SortTable.sort(
room_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_ROOM
)
pagination_number = GeneralOption.get_cached_value('pagination_number')
room_list = re2o_paginator(request, room_list, pagination_number)
2018-04-14 00:20:44 +00:00
return render(
request,
'topologie/index_room.html',
{'room_list': room_list}
)
2017-10-13 23:43:01 +00:00
2016-07-19 00:30:52 +00:00
2018-03-23 23:50:11 +00:00
@login_required
2018-03-25 22:08:24 +00:00
@can_view_all(AccessPoint)
def index_ap(request):
2018-03-23 23:50:11 +00:00
""" Affichage de l'ensemble des bornes"""
2018-04-14 00:20:44 +00:00
ap_list = (AccessPoint.objects
.prefetch_related(Prefetch(
'interface_set',
queryset=(Interface.objects
.select_related('ipv4__ip_type__extension')
.select_related('domain__extension'))
)))
2018-03-25 22:08:24 +00:00
ap_list = SortTable.sort(
ap_list,
2018-03-23 23:50:11 +00:00
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_BORNE
)
pagination_number = GeneralOption.get_cached_value('pagination_number')
ap_list = re2o_paginator(request, ap_list, pagination_number)
2018-04-14 00:20:44 +00:00
return render(
request,
'topologie/index_ap.html',
{'ap_list': ap_list}
)
2018-03-23 23:50:11 +00:00
@login_required
@can_view_all(Stack, Building, SwitchBay)
def index_physical_grouping(request):
2017-10-13 23:43:01 +00:00
"""Affichage de la liste des stacks (affiche l'ensemble des switches)"""
2018-04-14 00:20:44 +00:00
stack_list = (Stack.objects
.prefetch_related(
'switch_set__interface_set__domain__extension'
))
building_list = Building.objects.all()
switch_bay_list = SwitchBay.objects.select_related('building')
stack_list = SortTable.sort(
stack_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_STACK
)
building_list = SortTable.sort(
building_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_BUILDING
)
switch_bay_list = SortTable.sort(
switch_bay_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_SWITCH_BAY
)
2018-04-14 00:20:44 +00:00
return render(
request,
'topologie/index_physical_grouping.html',
{
'stack_list': stack_list,
'switch_bay_list': switch_bay_list,
'building_list': building_list,
}
)
2017-10-26 03:07:11 +00:00
@login_required
@can_view_all(ModelSwitch, ConstructorSwitch)
2017-10-26 03:07:11 +00:00
def index_model_switch(request):
""" Affichage de l'ensemble des modèles de switches"""
2018-01-31 02:27:59 +00:00
model_switch_list = ModelSwitch.objects.select_related('constructor')
2017-10-26 03:07:11 +00:00
constructor_switch_list = ConstructorSwitch.objects
model_switch_list = SortTable.sort(
model_switch_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_MODEL_SWITCH
)
constructor_switch_list = SortTable.sort(
constructor_switch_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_CONSTRUCTOR_SWITCH
)
2018-04-14 00:20:44 +00:00
return render(
request,
'topologie/index_model_switch.html',
{
'model_switch_list': model_switch_list,
'constructor_switch_list': constructor_switch_list,
}
)
2017-10-26 03:07:11 +00:00
@login_required
@can_edit(Vlan)
def edit_vlanoptions(request, vlan_instance, **_kwargs):
""" View used to edit options for switch of VLAN object """
vlan = EditOptionVlanForm(request.POST or None, instance=vlan_instance)
if vlan.is_valid():
if vlan.changed_data:
vlan.save()
messages.success(request, "Vlan modifié")
return redirect(reverse('topologie:index-port-profile'))
return form(
{'vlanform': vlan, 'action_name': 'Editer'},
'machines/machine.html',
request
)
2016-07-08 10:35:53 +00:00
@login_required
@can_create(Port)
2018-03-28 18:32:03 +00:00
def new_port(request, switchid):
2017-10-06 02:17:45 +00:00
""" Nouveau port"""
2016-07-06 21:29:31 +00:00
try:
2018-03-28 18:32:03 +00:00
switch = Switch.objects.get(pk=switchid)
2016-07-06 21:29:31 +00:00
except Switch.DoesNotExist:
2018-08-05 16:48:56 +00:00
messages.error(request, _("Nonexistent switch."))
2017-10-26 15:58:41 +00:00
return redirect(reverse('topologie:index'))
2016-07-06 21:29:31 +00:00
port = AddPortForm(request.POST or None)
if port.is_valid():
port = port.save(commit=False)
port.switch = switch
try:
port.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The port was added."))
2016-07-06 21:29:31 +00:00
except IntegrityError:
2018-08-05 16:48:56 +00:00
messages.error(request, _("The port already exists."))
2017-10-26 15:58:41 +00:00
return redirect(reverse(
2017-12-28 11:39:25 +00:00
'topologie:index-port',
2018-04-14 00:20:44 +00:00
kwargs={'switchid': switchid}
))
return form(
2018-08-05 16:48:56 +00:00
{'id_switch': switchid, 'topoform': port, 'action_name': _("Add")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request)
2017-10-13 23:43:01 +00:00
2016-07-08 10:35:53 +00:00
@login_required
@can_edit(Port)
2018-04-15 01:00:05 +00:00
def edit_port(request, port_object, **_kwargs):
2017-10-13 23:43:01 +00:00
""" Edition d'un port. Permet de changer le switch parent et
l'affectation du port"""
2017-12-28 11:39:25 +00:00
port = EditPortForm(request.POST or None, instance=port_object)
if port.is_valid():
if port.changed_data:
port.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The port was edited."))
2017-10-26 15:58:41 +00:00
return redirect(reverse(
'topologie:index-port',
2018-03-28 18:32:03 +00:00
kwargs={'switchid': str(port_object.switch.id)}
2018-04-14 00:20:44 +00:00
))
return form(
{
'id_switch': str(port_object.switch.id),
'topoform': port,
2018-08-05 16:48:56 +00:00
'action_name': _("Edit")
2018-04-14 00:20:44 +00:00
},
'topologie/topo.html',
request
)
2017-10-13 23:43:01 +00:00
2016-07-08 10:35:53 +00:00
@login_required
@can_delete(Port)
2018-04-15 01:00:05 +00:00
def del_port(request, port, **_kwargs):
2017-10-06 02:17:45 +00:00
""" Supprime le port"""
2017-09-04 02:45:36 +00:00
if request.method == "POST":
try:
port.delete()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The port was deleted."))
2017-09-04 02:45:36 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The port %s is used by another object, impossible to"
" delete it.") % port)
2018-04-14 00:20:44 +00:00
)
2017-10-26 15:58:41 +00:00
return redirect(reverse(
'topologie:index-port',
2018-04-14 00:20:44 +00:00
kwargs={'switchid': str(port.switch.id)}
))
2017-10-13 23:43:01 +00:00
return form({'objet': port}, 'topologie/delete.html', request)
2017-09-04 02:45:36 +00:00
@login_required
@can_create(Stack)
def new_stack(request):
2018-03-28 18:32:03 +00:00
"""Ajoute un nouveau stack : stackid_min, max, et nombre de switches"""
stack = StackForm(request.POST or None)
2017-10-13 23:43:01 +00:00
if stack.is_valid():
stack.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The stack was created."))
2018-04-16 04:54:34 +00:00
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': stack, 'action_name': _("Create")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
@login_required
@can_edit(Stack)
2018-04-15 01:00:05 +00:00
def edit_stack(request, stack, **_kwargs):
2017-10-13 23:43:01 +00:00
"""Edition d'un stack (nombre de switches, nom...)"""
stack = StackForm(request.POST or None, instance=stack)
if stack.is_valid():
if stack.changed_data:
stack.save()
2018-04-16 04:54:34 +00:00
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': stack, 'action_name': _("Edit")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2017-10-13 23:43:01 +00:00
2017-08-18 12:20:51 +00:00
@login_required
@can_delete(Stack)
2018-04-15 01:00:05 +00:00
def del_stack(request, stack, **_kwargs):
2017-10-13 23:43:01 +00:00
"""Supprime un stack"""
2017-08-18 12:20:51 +00:00
if request.method == "POST":
try:
stack.delete()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The stack was deleted."))
2017-08-18 12:20:51 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The stack %s is used by another object, impossible to"
" deleted it.") % stack)
2018-04-14 00:20:44 +00:00
)
return redirect(reverse('topologie:index-physical-grouping'))
2017-10-13 23:43:01 +00:00
return form({'objet': stack}, 'topologie/delete.html', request)
2017-08-18 12:20:51 +00:00
@login_required
@can_edit(Stack)
2018-04-15 01:00:05 +00:00
def edit_switchs_stack(request, stack, **_kwargs):
2017-10-13 23:43:01 +00:00
"""Permet d'éditer la liste des switches dans une stack et l'ajouter"""
2017-12-28 11:39:25 +00:00
if request.method == "POST":
pass
else:
context = {'stack': stack}
context['switchs_stack'] = stack.switchs_set.all()
context['switchs_autres'] = Switch.object.filter(stack=None)
2016-07-08 10:35:53 +00:00
@login_required
@can_create(Switch)
2016-07-06 21:29:31 +00:00
def new_switch(request):
2017-10-13 23:43:01 +00:00
""" Creation d'un switch. Cree en meme temps l'interface et la machine
associée. Vue complexe. Appelle successivement les 4 models forms
adaptés : machine, interface, domain et switch"""
2018-03-25 02:05:26 +00:00
switch = NewSwitchForm(
2017-12-30 01:00:32 +00:00
request.POST or None,
user=request.user
)
2018-03-26 03:12:01 +00:00
interface = AddInterfaceForm(
2017-10-13 23:43:01 +00:00
request.POST or None,
2017-12-30 01:00:32 +00:00
user=request.user
2018-03-25 02:05:26 +00:00
)
2017-10-18 00:27:42 +00:00
domain = DomainForm(
2017-10-13 23:43:01 +00:00
request.POST or None,
2018-07-11 17:37:22 +00:00
)
2018-03-26 03:12:01 +00:00
if switch.is_valid() and interface.is_valid():
user = AssoOption.get_cached_value('utilisateur_asso')
if not user:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The organisation's user doesn't exist yet, please create"
" or link it in the preferences."))
2018-04-14 00:20:44 +00:00
)
2017-10-26 15:58:41 +00:00
return redirect(reverse('topologie:index'))
2018-04-14 22:06:29 +00:00
new_switch_obj = switch.save(commit=False)
new_switch_obj.user = user
new_interface_obj = interface.save(commit=False)
domain.instance.interface_parent = new_interface_obj
2018-03-25 02:05:26 +00:00
if domain.is_valid():
2018-04-14 22:06:29 +00:00
new_domain_obj = domain.save(commit=False)
new_switch_obj.save()
new_interface_obj.machine = new_switch_obj
new_interface_obj.save()
new_domain_obj.interface_parent = new_interface_obj
new_domain_obj.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch was created."))
2018-03-25 02:05:26 +00:00
return redirect(reverse('topologie:index'))
2018-03-26 03:12:01 +00:00
i_mbf_param = generate_ipv4_mbf_param(interface, False)
2018-04-14 00:20:44 +00:00
return form(
{
'topoform': interface,
'machineform': switch,
'domainform': domain,
'i_mbf_param': i_mbf_param,
'device': 'switch',
},
'topologie/topo_more.html',
request
)
2017-10-13 23:56:14 +00:00
2016-07-06 21:29:31 +00:00
@login_required
@can_create(Port)
2018-03-28 18:32:03 +00:00
def create_ports(request, switchid):
""" Création d'une liste de ports pour un switch."""
try:
2018-03-28 18:32:03 +00:00
switch = Switch.objects.get(pk=switchid)
except Switch.DoesNotExist:
2018-08-05 16:48:56 +00:00
messages.error(request, _("Nonexistent switch"))
return redirect(reverse('topologie:index'))
2017-12-28 11:39:25 +00:00
s_begin = s_end = 0
2017-10-26 09:05:27 +00:00
nb_ports = switch.ports.count()
if nb_ports > 0:
2017-10-26 09:51:41 +00:00
ports = switch.ports.order_by('port').values('port')
s_begin = ports.first().get('port')
s_end = ports.last().get('port')
2017-12-28 11:39:25 +00:00
port_form = CreatePortsForm(
request.POST or None,
2017-10-26 19:29:34 +00:00
initial={'begin': s_begin, 'end': s_end}
)
2017-10-26 21:29:26 +00:00
if port_form.is_valid():
begin = port_form.cleaned_data['begin']
end = port_form.cleaned_data['end']
2017-10-26 21:29:26 +00:00
try:
switch.create_ports(begin, end)
2018-08-05 16:48:56 +00:00
messages.success(request, _("The ports were created."))
2017-10-26 21:29:26 +00:00
except ValidationError as e:
messages.error(request, ''.join(e))
return redirect(reverse(
'topologie:index-port',
2018-04-14 00:20:44 +00:00
kwargs={'switchid': switchid}
2018-07-11 17:37:22 +00:00
))
2018-04-14 00:20:44 +00:00
return form(
{'id_switch': switchid, 'topoform': port_form},
'topologie/switch.html',
request
)
2017-10-26 19:29:34 +00:00
2016-07-06 21:29:31 +00:00
2016-07-08 10:35:53 +00:00
@login_required
@can_edit(Switch)
2018-03-28 18:32:03 +00:00
def edit_switch(request, switch, switchid):
2017-10-13 23:43:01 +00:00
""" Edition d'un switch. Permet de chambre nombre de ports,
place dans le stack, interface et machine associée"""
2018-03-25 02:05:26 +00:00
switch_form = EditSwitchForm(
2017-10-13 23:43:01 +00:00
request.POST or None,
2018-03-25 02:05:26 +00:00
instance=switch,
user=request.user
2018-07-11 17:37:22 +00:00
)
2018-03-26 03:12:01 +00:00
interface_form = EditInterfaceForm(
2017-10-13 23:43:01 +00:00
request.POST or None,
2018-03-26 03:12:01 +00:00
instance=switch.interface_set.first(),
user=request.user
2018-07-11 17:37:22 +00:00
)
2017-10-18 00:27:42 +00:00
domain_form = DomainForm(
2017-10-13 23:43:01 +00:00
request.POST or None,
2018-03-26 03:12:01 +00:00
instance=switch.interface_set.first().domain
2018-07-11 17:37:22 +00:00
)
2018-03-26 03:12:01 +00:00
if switch_form.is_valid() and interface_form.is_valid():
2018-04-14 22:06:29 +00:00
new_switch_obj = switch_form.save(commit=False)
new_interface_obj = interface_form.save(commit=False)
new_domain_obj = domain_form.save(commit=False)
if switch_form.changed_data:
2018-04-14 22:06:29 +00:00
new_switch_obj.save()
if interface_form.changed_data:
2018-04-14 22:06:29 +00:00
new_interface_obj.save()
if domain_form.changed_data:
2018-04-14 22:06:29 +00:00
new_domain_obj.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch was edited."))
2017-11-15 10:37:10 +00:00
return redirect(reverse('topologie:index'))
2018-04-14 00:20:44 +00:00
i_mbf_param = generate_ipv4_mbf_param(interface_form, False)
return form(
{
'id_switch': switchid,
'topoform': interface_form,
'machineform': switch_form,
'domainform': domain_form,
'i_mbf_param': i_mbf_param,
'device': 'switch',
},
'topologie/topo_more.html',
request
)
2017-10-13 23:56:14 +00:00
2016-07-19 00:30:52 +00:00
2018-03-23 23:50:11 +00:00
@login_required
2018-03-25 22:08:24 +00:00
@can_create(AccessPoint)
def new_ap(request):
""" Creation d'une ap. Cree en meme temps l'interface et la machine
2018-03-23 23:50:11 +00:00
associée. Vue complexe. Appelle successivement les 3 models forms
adaptés : machine, interface, domain et switch"""
2018-03-25 22:08:24 +00:00
ap = AddAccessPointForm(
2018-03-23 23:50:11 +00:00
request.POST or None,
user=request.user
)
2018-03-26 01:09:42 +00:00
interface = AddInterfaceForm(
2018-03-23 23:50:11 +00:00
request.POST or None,
user=request.user
)
domain = DomainForm(
request.POST or None,
2018-07-11 17:37:22 +00:00
)
2018-03-26 01:09:42 +00:00
if ap.is_valid() and interface.is_valid():
2018-03-23 23:50:11 +00:00
user = AssoOption.get_cached_value('utilisateur_asso')
if not user:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The organisation's user doesn't exist yet, please create"
" or link it in the preferences."))
2018-04-14 00:20:44 +00:00
)
2018-03-23 23:50:11 +00:00
return redirect(reverse('topologie:index'))
2018-04-14 22:06:29 +00:00
new_ap_obj = ap.save(commit=False)
new_ap_obj.user = user
new_interface_obj = interface.save(commit=False)
domain.instance.interface_parent = new_interface_obj
2018-03-23 23:50:11 +00:00
if domain.is_valid():
2018-04-14 22:06:29 +00:00
new_domain_obj = domain.save(commit=False)
new_ap_obj.save()
new_interface_obj.machine = new_ap_obj
new_interface_obj.save()
new_domain_obj.interface_parent = new_interface_obj
new_domain_obj.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The access point was created."))
2018-03-25 22:08:24 +00:00
return redirect(reverse('topologie:index-ap'))
2018-03-26 01:09:42 +00:00
i_mbf_param = generate_ipv4_mbf_param(interface, False)
2018-04-14 00:20:44 +00:00
return form(
{
'topoform': interface,
'machineform': ap,
'domainform': domain,
'i_mbf_param': i_mbf_param,
'device': 'wifi ap',
},
'topologie/topo_more.html',
request
)
2018-03-23 23:50:11 +00:00
@login_required
2018-03-25 22:08:24 +00:00
@can_edit(AccessPoint)
2018-04-15 01:00:05 +00:00
def edit_ap(request, ap, **_kwargs):
2018-03-23 23:50:11 +00:00
""" Edition d'un switch. Permet de chambre nombre de ports,
place dans le stack, interface et machine associée"""
2018-03-26 01:09:42 +00:00
interface_form = EditInterfaceForm(
2018-03-23 23:50:11 +00:00
request.POST or None,
user=request.user,
2018-03-26 01:09:42 +00:00
instance=ap.interface_set.first()
2018-03-23 23:50:11 +00:00
)
2018-03-26 01:09:42 +00:00
ap_form = EditAccessPointForm(
2018-03-23 23:50:11 +00:00
request.POST or None,
user=request.user,
2018-03-26 01:09:42 +00:00
instance=ap
2018-03-23 23:50:11 +00:00
)
domain_form = DomainForm(
request.POST or None,
2018-03-26 01:09:42 +00:00
instance=ap.interface_set.first().domain
2018-07-11 17:37:22 +00:00
)
2018-03-26 01:09:42 +00:00
if ap_form.is_valid() and interface_form.is_valid():
2018-03-23 23:50:11 +00:00
user = AssoOption.get_cached_value('utilisateur_asso')
if not user:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The organisation's user doesn't exist yet, please create"
" or link it in the preferences."))
2018-04-14 00:20:44 +00:00
)
2018-03-25 22:08:24 +00:00
return redirect(reverse('topologie:index-ap'))
2018-04-14 22:06:29 +00:00
new_ap_obj = ap_form.save(commit=False)
new_interface_obj = interface_form.save(commit=False)
new_domain_obj = domain_form.save(commit=False)
if ap_form.changed_data:
2018-04-14 22:06:29 +00:00
new_ap_obj.save()
if interface_form.changed_data:
2018-04-14 22:06:29 +00:00
new_interface_obj.save()
if domain_form.changed_data:
2018-04-14 22:06:29 +00:00
new_domain_obj.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The access point was edited."))
2018-03-25 22:08:24 +00:00
return redirect(reverse('topologie:index-ap'))
2018-04-14 00:20:44 +00:00
i_mbf_param = generate_ipv4_mbf_param(interface_form, False)
return form(
{
'topoform': interface_form,
'machineform': ap_form,
'domainform': domain_form,
'i_mbf_param': i_mbf_param,
'device': 'wifi ap',
},
'topologie/topo_more.html',
request
)
2018-03-23 23:50:11 +00:00
2016-07-19 00:30:52 +00:00
@login_required
@can_create(Room)
2016-07-19 00:30:52 +00:00
def new_room(request):
2017-10-06 02:17:45 +00:00
"""Nouvelle chambre """
2016-07-19 00:30:52 +00:00
room = EditRoomForm(request.POST or None)
if room.is_valid():
room.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The room was created."))
2017-10-26 15:58:41 +00:00
return redirect(reverse('topologie:index-room'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': room, 'action_name': _("Add")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2017-10-13 23:43:01 +00:00
2016-07-19 00:30:52 +00:00
@login_required
@can_edit(Room)
2018-04-15 01:00:05 +00:00
def edit_room(request, room, **_kwargs):
2017-10-06 02:17:45 +00:00
""" Edition numero et details de la chambre"""
2016-07-19 00:30:52 +00:00
room = EditRoomForm(request.POST or None, instance=room)
if room.is_valid():
if room.changed_data:
room.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The room was edited."))
2017-10-26 15:58:41 +00:00
return redirect(reverse('topologie:index-room'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': room, 'action_name': _("Edit")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2017-10-13 23:43:01 +00:00
2016-07-19 00:30:52 +00:00
@login_required
@can_delete(Room)
2018-04-15 01:00:05 +00:00
def del_room(request, room, **_kwargs):
2017-10-06 02:17:45 +00:00
""" Suppression d'un chambre"""
2016-07-19 00:30:52 +00:00
if request.method == "POST":
try:
room.delete()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The room was deleted."))
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The room %s is used by another object, impossible to"
" deleted it.") % room)
2018-04-14 00:20:44 +00:00
)
return redirect(reverse('topologie:index-room'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'objet': room, 'objet_name': _("Room")},
2018-04-14 00:20:44 +00:00
'topologie/delete.html',
request
)
2017-10-26 03:07:11 +00:00
@login_required
@can_create(ModelSwitch)
2017-10-26 03:07:11 +00:00
def new_model_switch(request):
"""Nouveau modèle de switch"""
model_switch = EditModelSwitchForm(request.POST or None)
if model_switch.is_valid():
model_switch.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The swich model was created."))
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': model_switch, 'action_name': _("Add")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2017-10-26 03:07:11 +00:00
@login_required
@can_edit(ModelSwitch)
2018-04-15 01:00:05 +00:00
def edit_model_switch(request, model_switch, **_kwargs):
2017-10-26 03:07:11 +00:00
""" Edition d'un modèle de switch"""
2018-04-14 00:20:44 +00:00
model_switch = EditModelSwitchForm(
request.POST or None,
instance=model_switch
)
2017-10-26 03:07:11 +00:00
if model_switch.is_valid():
if model_switch.changed_data:
model_switch.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch model was edited."))
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': model_switch, 'action_name': _("Edit")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2017-10-26 03:07:11 +00:00
@login_required
@can_delete(ModelSwitch)
2018-04-15 01:00:05 +00:00
def del_model_switch(request, model_switch, **_kwargs):
2017-10-26 03:07:11 +00:00
""" Suppression d'un modèle de switch"""
if request.method == "POST":
try:
model_switch.delete()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch model was deleted."))
2017-10-26 03:07:11 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The switch model %s is used by another object,"
" impossible to delete it.") % model_switch)
2018-04-14 00:20:44 +00:00
)
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'objet': model_switch, 'objet_name': _("Switch model")},
2018-04-14 00:20:44 +00:00
'topologie/delete.html',
request
)
2017-10-26 03:07:11 +00:00
2018-04-07 18:45:29 +00:00
@login_required
@can_create(SwitchBay)
def new_switch_bay(request):
"""Nouvelle baie de switch"""
switch_bay = EditSwitchBayForm(request.POST or None)
if switch_bay.is_valid():
switch_bay.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch bay was created."))
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': switch_bay, 'action_name': _("Add")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2018-04-07 18:45:29 +00:00
@login_required
@can_edit(SwitchBay)
2018-04-15 01:00:05 +00:00
def edit_switch_bay(request, switch_bay, **_kwargs):
2018-04-07 18:45:29 +00:00
""" Edition d'une baie de switch"""
switch_bay = EditSwitchBayForm(request.POST or None, instance=switch_bay)
if switch_bay.is_valid():
if switch_bay.changed_data:
switch_bay.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch bay was edited."))
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': switch_bay, 'action_name': _("Edit")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2018-04-07 18:45:29 +00:00
@login_required
@can_delete(SwitchBay)
2018-04-15 01:00:05 +00:00
def del_switch_bay(request, switch_bay, **_kwargs):
2018-04-07 18:45:29 +00:00
""" Suppression d'une baie de switch"""
if request.method == "POST":
try:
switch_bay.delete()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch bay was deleted."))
2018-04-07 18:45:29 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The switch bay %s is used by another object,"
" impossible to delete it.") % switch_bay)
2018-04-14 00:20:44 +00:00
)
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'objet': switch_bay, 'objet_name': _("Switch bay")},
2018-04-14 00:20:44 +00:00
'topologie/delete.html',
request
)
2018-04-07 18:45:29 +00:00
@login_required
@can_create(Building)
def new_building(request):
"""Nouveau batiment"""
building = EditBuildingForm(request.POST or None)
if building.is_valid():
building.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The building was created."))
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': building, 'action_name': _("Add")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
@login_required
@can_edit(Building)
2018-04-15 01:00:05 +00:00
def edit_building(request, building, **_kwargs):
""" Edition d'un batiment"""
building = EditBuildingForm(request.POST or None, instance=building)
if building.is_valid():
if building.changed_data:
building.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The building was edited."))
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': building, 'action_name': _("Edit")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
@login_required
@can_delete(Building)
2018-04-15 01:00:05 +00:00
def del_building(request, building, **_kwargs):
""" Suppression d'un batiment"""
if request.method == "POST":
try:
building.delete()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The building was deleted."))
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The building %s is used by another object, impossible"
" to delete it.") % building)
2018-04-14 00:20:44 +00:00
)
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'objet': building, 'objet_name': _("Building")},
2018-04-14 00:20:44 +00:00
'topologie/delete.html',
request
)
2017-10-26 03:07:11 +00:00
@login_required
@can_create(ConstructorSwitch)
2017-10-26 03:07:11 +00:00
def new_constructor_switch(request):
"""Nouveau constructeur de switch"""
constructor_switch = EditConstructorSwitchForm(request.POST or None)
if constructor_switch.is_valid():
constructor_switch.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch constructor was created."))
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': constructor_switch, 'action_name': _("Add")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2017-10-26 03:07:11 +00:00
@login_required
@can_edit(ConstructorSwitch)
2018-04-15 01:00:05 +00:00
def edit_constructor_switch(request, constructor_switch, **_kwargs):
2017-10-26 03:07:11 +00:00
""" Edition d'un constructeur de switch"""
2018-04-14 00:20:44 +00:00
constructor_switch = EditConstructorSwitchForm(
request.POST or None,
instance=constructor_switch
)
2017-10-26 03:07:11 +00:00
if constructor_switch.is_valid():
if constructor_switch.changed_data:
constructor_switch.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch constructor was edited."))
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
2018-08-05 16:48:56 +00:00
{'topoform': constructor_switch, 'action_name': _("Edit")},
2018-04-14 00:20:44 +00:00
'topologie/topo.html',
request
)
2017-10-26 03:07:11 +00:00
@login_required
@can_delete(ConstructorSwitch)
2018-04-15 01:00:05 +00:00
def del_constructor_switch(request, constructor_switch, **_kwargs):
2017-10-26 03:07:11 +00:00
""" Suppression d'un constructeur de switch"""
if request.method == "POST":
try:
constructor_switch.delete()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The switch constructor was deleted."))
2017-10-26 03:07:11 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
2018-08-05 16:48:56 +00:00
(_("The switch constructor %s is used by another object,"
" impossible to delete it.") % constructor_switch)
2018-04-14 00:20:44 +00:00
)
return redirect(reverse('topologie:index-model-switch'))
2017-10-26 03:07:11 +00:00
return form({
'objet': constructor_switch,
2018-08-05 16:48:56 +00:00
'objet_name': _("Switch constructor")
2018-07-11 17:37:22 +00:00
}, 'topologie/delete.html', request)
2018-05-26 22:36:25 +00:00
@login_required
@can_create(PortProfile)
def new_port_profile(request):
"""Create a new port profile"""
2018-06-26 23:29:40 +00:00
port_profile = EditPortProfileForm(request.POST or None)
2018-05-26 22:36:25 +00:00
if port_profile.is_valid():
port_profile.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The port profile was created."))
return redirect(reverse('topologie:index-port-profile'))
2018-05-26 22:36:25 +00:00
return form(
{'topoform': port_profile, 'action_name': _("Create")},
'topologie/topo.html',
request
)
@login_required
@can_edit(PortProfile)
def edit_port_profile(request, port_profile, **_kwargs):
"""Edit a port profile"""
2018-07-11 17:37:22 +00:00
port_profile = EditPortProfileForm(
request.POST or None, instance=port_profile)
2018-05-26 22:36:25 +00:00
if port_profile.is_valid():
if port_profile.changed_data:
port_profile.save()
2018-08-05 16:48:56 +00:00
messages.success(request, _("The port profile was edited."))
return redirect(reverse('topologie:index-port-profile'))
2018-05-26 22:36:25 +00:00
return form(
{'topoform': port_profile, 'action_name': _("Edit")},
'topologie/topo.html',
request
)
@login_required
@can_delete(PortProfile)
def del_port_profile(request, port_profile, **_kwargs):
"""Delete a port profile"""
if request.method == 'POST':
try:
port_profile.delete()
2018-07-11 17:37:22 +00:00
messages.success(request,
2018-08-05 16:48:56 +00:00
_("The port profile was deleted."))
2018-05-26 22:36:25 +00:00
except ProtectedError:
2018-07-11 17:37:22 +00:00
messages.success(request,
2018-08-05 16:48:56 +00:00
_("Impossible to delete the port profile."))
return redirect(reverse('topologie:index-port-profile'))
2018-05-26 22:36:25 +00:00
return form(
2018-07-11 17:37:22 +00:00
{'objet': port_profile, 'objet_name': _("Port profile")},
'topologie/delete.html',
request
2018-05-26 22:36:25 +00:00
)
2018-07-11 17:37:22 +00:00
def make_machine_graph():
"""
2018-05-19 19:20:55 +00:00
Create the graph of switchs, machines and access points.
"""
2018-05-15 18:42:00 +00:00
dico = {
'subs': [],
2018-07-11 17:37:22 +00:00
'links': [],
2018-05-15 18:42:00 +00:00
'alone': [],
'colors': {
2018-05-21 19:13:44 +00:00
'head': "#7f0505", # Color parameters for the graph
2018-05-15 18:42:00 +00:00
'back': "#b5adad",
'texte': "#563d01",
'border_bornes': "#02078e",
'head_bornes': "#25771c",
'head_server': "#1c3777"
}
2018-07-11 17:37:22 +00:00
}
2018-05-15 18:42:00 +00:00
missing = list(Switch.objects.all())
detected = []
2018-05-21 19:13:44 +00:00
for building in Building.objects.all(): # Visit all buildings
2018-05-15 18:42:00 +00:00
dico['subs'].append(
{
2018-07-11 17:37:22 +00:00
'bat_id': building.id,
'bat_name': building,
'switchs': [],
'bornes': [],
'machines': []
2018-05-15 18:42:00 +00:00
}
)
2018-05-21 19:13:44 +00:00
# Visit all switchs in this building
2018-07-11 17:37:22 +00:00
for switch in Switch.objects.filter(switchbay__building=building):
2018-05-15 18:42:00 +00:00
dico['subs'][-1]['switchs'].append({
'name': switch.main_interface().domain.name,
'nombre': switch.number,
'model': switch.model,
'id': switch.id,
'batiment': building,
'ports': []
})
2018-05-21 19:13:44 +00:00
# visit all ports of this switch and add the switchs linked to it
2018-07-11 17:37:22 +00:00
for port in switch.ports.filter(related__isnull=False):
2018-05-15 18:42:00 +00:00
dico['subs'][-1]['switchs'][-1]['ports'].append({
'numero': port.port,
'related': port.related.switch.main_interface().domain.name
})
for ap in AccessPoint.all_ap_in(building):
dico['subs'][-1]['bornes'].append({
'name': ap.short_name,
'switch': ap.switch()[0].main_interface().domain.name,
'port': ap.switch()[0].ports.filter(
machine_interface__machine=ap
)[0].port
})
for server in Server.all_server_in(building):
dico['subs'][-1]['machines'].append({
'name': server.short_name,
'switch': server.switch()[0].main_interface().domain.name,
2018-07-11 17:37:22 +00:00
'port': Port.objects.filter(
machine_interface__machine=server
)[0].port
2018-05-15 18:42:00 +00:00
})
2018-05-21 19:13:44 +00:00
# While the list of forgotten ones is not empty
2018-05-15 18:42:00 +00:00
while missing:
2018-05-21 19:13:44 +00:00
if missing[0].ports.count(): # The switch is not empty
2018-07-11 17:37:22 +00:00
links, new_detected = recursive_switchs(
missing[0], None, [missing[0]])
2018-05-15 18:42:00 +00:00
for link in links:
dico['links'].append(link)
2018-05-21 19:13:44 +00:00
# Update the lists of missings and already detected switchs
2018-07-11 17:37:22 +00:00
missing = [i for i in missing if i not in new_detected]
2018-05-15 18:42:00 +00:00
detected += new_detected
2018-07-11 17:37:22 +00:00
# If the switch have no ports, don't explore it and hop to the next one
else:
2018-05-15 18:42:00 +00:00
del missing[0]
2018-05-21 19:13:44 +00:00
# Switchs that are not connected or not in a building
2018-07-11 17:37:22 +00:00
for switch in Switch.objects.filter(
switchbay__isnull=True).exclude(ports__related__isnull=False):
2018-05-15 18:42:00 +00:00
dico['alone'].append({
'id': switch.id,
'name': switch.main_interface().domain.name
2018-07-11 17:37:22 +00:00
})
2018-05-19 19:20:55 +00:00
2018-07-11 17:37:22 +00:00
# generate the dot file
dot_data = generate_dot(dico, 'topologie/graph_switch.dot')
2018-05-21 20:05:31 +00:00
2018-07-11 17:37:22 +00:00
# Create a temporary file to store the dot data
f = tempfile.NamedTemporaryFile(mode='w+', encoding='utf-8', delete=False)
2018-05-21 20:05:31 +00:00
with f:
2018-07-11 17:37:22 +00:00
f.write(dot_data)
2018-05-21 19:13:44 +00:00
unflatten = Popen( # unflatten the graph to make it look better
2018-07-11 17:37:22 +00:00
["unflatten", "-l", "3", f.name],
2018-05-15 18:42:00 +00:00
stdout=PIPE
)
2018-07-11 17:37:22 +00:00
Popen( # pipe the result of the first command into the second
2018-05-15 18:42:00 +00:00
["dot", "-Tpng", "-o", MEDIA_ROOT + "/images/switchs.png"],
stdin=unflatten.stdout,
stdout=PIPE
)
2018-07-11 17:37:22 +00:00
def generate_dot(data, template):
2018-05-19 19:20:55 +00:00
"""create the dot file
2018-05-20 09:42:35 +00:00
:param data: dictionary passed to the template
:param template: path to the dot template
:return: all the lines of the dot file"""
2018-05-15 18:42:00 +00:00
t = loader.get_template(template)
2018-07-11 17:37:22 +00:00
if not isinstance(t, Template) and \
not (hasattr(t, 'template') and isinstance(t.template, Template)):
2018-08-05 16:48:56 +00:00
raise Exception(_("The default Django template isn't used. This can"
" lead to rendering errors. Check the parameters."))
2018-05-15 18:42:00 +00:00
c = Context(data).flatten()
dot = t.render(c)
return(dot)
2018-07-11 17:37:22 +00:00
2018-05-19 19:20:55 +00:00
def recursive_switchs(switch_start, switch_before, detected):
"""Visit the switch and travel to the switchs linked to it.
2018-05-20 09:42:35 +00:00
:param switch_start: the switch to begin the visit on
2018-07-11 17:37:22 +00:00
:param switch_before: the switch that you come from.
None if switch_start is the first one
: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
"""
2018-05-30 20:07:43 +00:00
detected.append(switch_start)
2018-07-11 17:37:22 +00:00
links_return = [] # list of dictionaries of the links to be detected
# create links to every switchs below
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:
2018-05-21 19:13:44 +00:00
links = { # Dictionary of a link
2018-07-11 17:37:22 +00:00
'depart': switch_start.id,
'arrive': port.related.switch.id
2018-05-15 18:42:00 +00:00
}
2018-05-21 19:13:44 +00:00
links_return.append(links) # Add current and below levels links
2018-05-30 20:07:43 +00:00
2018-07-11 17:37:22 +00:00
# go down on every related switchs
for port in switch_start.ports.filter(related__isnull=False):
# The switch at the end of this link has not been visited
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:
2018-05-30 20:07:43 +00:00
if link:
2018-07-11 17:37:22 +00:00
links_return.append(link)
2018-05-15 18:42:00 +00:00
return (links_return, detected)
2018-08-05 16:48:56 +00:00