8
0
Fork 0
mirror of https://gitlab.federez.net/re2o/re2o synced 2024-06-02 07:52:23 +00:00
re2o/topologie/views.py

1075 lines
35 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
from django.contrib.staticfiles.storage import staticfiles_storage
2018-05-15 18:42:00 +00:00
from django.template.loader import get_template
from django.template import Context, Template, loader
import pprint
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
)
from machines.views import generate_ipv4_mbf_param
2018-05-15 18:42:00 +00:00
from machines.models import Interface, Service_link
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,
Server
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,
EditBuildingForm
2017-10-26 03:07:11 +00:00
)
from subprocess import Popen,PIPE
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
)
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
if any(service_link.need_regen() for service_link in Service_link.objects.filter(service__service_type='graph_topo')):
make_machine_graph()
for service_link in Service_link.objects.filter(service__service_type='graph_topo'):
service_link.done_regen()
2018-04-14 00:20:44 +00:00
return render(
request,
'topologie/index.html',
{'switch_list': switch_list}
)
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,
'nom_switch': switch
}
)
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
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:
messages.error(request, u"Switch inexistant")
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()
2016-07-06 21:29:31 +00:00
messages.success(request, "Port ajouté")
except IntegrityError:
2017-10-13 23:43:01 +00:00
messages.error(request, "Ce port existe déjà")
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(
{'id_switch': switchid, 'topoform': port, 'action_name': 'Ajouter'},
'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()
messages.success(request, "Le port a bien été modifié")
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,
'action_name': 'Editer'
},
'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()
messages.success(request, "Le port a été détruit")
2017-09-04 02:45:36 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
("Le port %s est affecté à un autre objet, impossible "
"de le supprimer" % port)
)
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()
2017-10-13 23:43:01 +00:00
messages.success(request, "Stack crée")
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(
{'topoform': stack, 'action_name': 'Créer'},
'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(
{'topoform': stack, 'action_name': 'Editer'},
'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()
messages.success(request, "La stack a eté détruite")
2017-08-18 12:20:51 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
("La stack %s est affectée à un autre objet, impossible "
"de la supprimer" % stack)
)
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-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,
("L'user association n'existe pas encore, veuillez le "
"créer ou le linker dans preferences")
)
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-03-25 02:05:26 +00:00
messages.success(request, "Le switch a été créé")
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:
messages.error(request, u"Switch inexistant")
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)
messages.success(request, "Ports créés.")
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-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
2017-10-13 23:43:01 +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
2017-10-13 23:43:01 +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
2017-10-13 23:43:01 +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()
messages.success(request, "Le switch a bien été modifié")
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-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,
("L'user association n'existe pas encore, veuillez le "
"créer ou le linker dans preferences")
)
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-03-23 23:50:11 +00:00
messages.success(request, "La borne a été créé")
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-03-23 23:50:11 +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,
("L'user association n'existe pas encore, veuillez le "
"créer ou le linker dans preferences")
)
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-03-23 23:50:11 +00:00
messages.success(request, "La borne a été modifiée")
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()
2016-07-19 00:30:52 +00:00
messages.success(request, "La chambre a été créé")
2017-10-26 15:58:41 +00:00
return redirect(reverse('topologie:index-room'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': room, 'action_name': 'Ajouter'},
'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()
messages.success(request, "La chambre a bien été modifiée")
2017-10-26 15:58:41 +00:00
return redirect(reverse('topologie:index-room'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': room, 'action_name': 'Editer'},
'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()
messages.success(request, "La chambre/prise a été détruite")
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
("La chambre %s est affectée à un autre objet, impossible "
"de la supprimer (switch ou user)" % room)
)
return redirect(reverse('topologie:index-room'))
2018-04-14 00:20:44 +00:00
return form(
{'objet': room, 'objet_name': 'Chambre'},
'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()
2017-10-26 03:07:11 +00:00
messages.success(request, "Le modèle a été créé")
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': model_switch, 'action_name': 'Ajouter'},
'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()
messages.success(request, "Le modèle a bien été modifié")
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': model_switch, 'action_name': 'Editer'},
'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()
messages.success(request, "Le modèle a été détruit")
2017-10-26 03:07:11 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
("Le modèle %s est affectée à un autre objet, impossible "
"de la supprimer (switch ou user)" % model_switch)
)
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
{'objet': model_switch, 'objet_name': 'Modèle de switch'},
'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()
messages.success(request, "La baie a été créé")
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': switch_bay, 'action_name': 'Ajouter'},
'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()
messages.success(request, "Le switch a bien été modifié")
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': switch_bay, 'action_name': 'Editer'},
'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()
messages.success(request, "La baie a été détruite")
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
("La baie %s est affecté à un autre objet, impossible "
"de la supprimer (switch ou user)" % switch_bay)
)
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
{'objet': switch_bay, 'objet_name': 'Baie de switch'},
'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()
messages.success(request, "Le batiment a été créé")
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': building, 'action_name': 'Ajouter'},
'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()
messages.success(request, "Le batiment a bien été modifié")
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': building, 'action_name': 'Editer'},
'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()
messages.success(request, "La batiment a été détruit")
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
("Le batiment %s est affecté à un autre objet, impossible "
"de la supprimer (switch ou user)" % building)
)
return redirect(reverse('topologie:index-physical-grouping'))
2018-04-14 00:20:44 +00:00
return form(
{'objet': building, 'objet_name': 'Bâtiment'},
'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()
2017-10-26 03:07:11 +00:00
messages.success(request, "Le constructeur a été créé")
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': constructor_switch, 'action_name': 'Ajouter'},
'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()
messages.success(request, "Le modèle a bien été modifié")
return redirect(reverse('topologie:index-model-switch'))
2018-04-14 00:20:44 +00:00
return form(
{'topoform': constructor_switch, 'action_name': 'Editer'},
'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()
messages.success(request, "Le constructeur a été détruit")
2017-10-26 03:07:11 +00:00
except ProtectedError:
2018-04-14 00:20:44 +00:00
messages.error(
request,
("Le constructeur %s est affecté à un autre objet, impossible "
"de la supprimer (switch ou user)" % constructor_switch)
)
return redirect(reverse('topologie:index-model-switch'))
2017-10-26 03:07:11 +00:00
return form({
'objet': constructor_switch,
'objet_name': 'Constructeur de switch'
}, 'topologie/delete.html', request)
def make_machine_graph():
"""
Crée le fichier dot et l'image du graph des Switchs
"""
2018-05-15 18:42:00 +00:00
dico = {
'subs': [],
'links' : [],
'alone': [],
'colors': {
'head': "#7f0505",
'back': "#b5adad",
'texte': "#563d01",
'border_bornes': "#02078e",
'head_bornes': "#25771c",
'head_server': "#1c3777"
}
}
missing = list(Switch.objects.all())
detected = []
#Parcours tous les batiments
2018-05-11 16:52:45 +00:00
for building in Building.objects.all():
2018-05-15 18:42:00 +00:00
dico['subs'].append(
{
'bat_id': building.id,
'bat_name': building,
'switchs': [],
'bornes': [],
'machines': []
}
)
#Parcours tous les switchs de ce batiment
2018-05-11 16:52:45 +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': []
})
#Parcours tous les ports liés de ce switch, on ajoute les switchs relié à celui-ci
for port in switch.ports.filter(related__isnull=False):
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,
'port': Port.objects.filter(machine_interface__machine=server)[0].port
})
#Tant que la liste des oubliés n'est pas vide i.e on les a pas tous passer
while missing:
print("depart initial sur:{}".format(missing[0]))
if missing[0].ports.count():#le switch à des ports
links, new_detected = recursive_switchs(missing[0].ports.first(), None, [missing[0]])
for link in links:
dico['links'].append(link)
#On recrée la liste des oubliés et des detectés
missing=[i for i in missing if i not in new_detected]
detected += new_detected
else:#Si le switch n'a pas de port, on explore pas et on passe au suivant
del missing[0]
#Tous ceux qui ne sont ni connectés ni dans un batiment
for switch in Switch.objects.filter(switchbay__isnull=True).exclude(ports__related__isnull=False):
dico['alone'].append({
'id': switch.id,
'name': switch.main_interface().domain.name
})
#Exportation du dot et génération de l'image
dot_data=generate_image(dico)
fichier = open(MEDIA_ROOT + "/images/switchs.dot","w", encoding='utf-8')
fichier.write(dot_data)
fichier.close()
2018-05-15 18:42:00 +00:00
unflatten = Popen(
["unflatten","-l", "3", MEDIA_ROOT + "/images/switchs.dot"],
stdout=PIPE
)
image = Popen(
["dot", "-Tpng", "-o", MEDIA_ROOT + "/images/switchs.png"],
stdin=unflatten.stdout,
stdout=PIPE
)
2018-05-15 18:42:00 +00:00
def generate_image(data,template='topologie/graph_switch.dot'):
t = loader.get_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é."
"Cela peut mener à des erreurs de rendu."
"Vérifiez les paramètres")
c = Context(data).flatten()
dot = t.render(c)
return(dot)
def recursive_switchs(port_start, switch_before, detected):
"""
Parcour récursivement le switchs auquel appartient port_start pour trouver les ports suivants liés
"""
2018-05-15 18:42:00 +00:00
links_return=[]#Liste de dictionaires qui stockes les nouveaux liens trouvés
for port in port_start.switch.ports.filter(related__isnull=False):#Liste des ports dont le related est non null
if port.related.switch!=switch_before and port.related.switch != port.switch:#Pas le switch dont on descend, pas le switch actuel
links = {#dictionaire contenant le lien
'depart':port_start.switch.id,
'arrive':port.related.switch.id
}
if port.related.switch not in detected:#si le switch au bout de ce lien n'a pas été déjà exploré
links_down, detected = recursive_switchs(port.related, port_start.switch, detected)#On l'explore et on récupère le résultat
for link in links_down:#On ajoute les résultats du niveau inférieur à ceux du niveau actuel
if link:
links_return.append(link)
links_return.append(links)#Ajout des liens trouvés (niveau inférieur et actuel) à la liste à renvoyer
detected.append(port_start.switch)#Le switch est considéré comme parcouru
return (links_return, detected)