views.py 23.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
# 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.
chirac's avatar
chirac committed
22 23
"""
Page des vues de l'application topologie
24

chirac's avatar
chirac committed
25 26 27 28 29 30 31 32 33 34 35
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
"""
36 37
from __future__ import unicode_literals

38
from django.urls import reverse
Dalahro's avatar
Dalahro committed
39 40
from django.shortcuts import render, redirect
from django.contrib import messages
41
from django.contrib.auth.decorators import login_required, permission_required
Dalahro's avatar
Dalahro committed
42
from django.db import IntegrityError
43
from django.db import transaction
44
from django.db.models import ProtectedError, Prefetch
45
from django.core.exceptions import ValidationError
Dalahro's avatar
Dalahro committed
46

47 48 49 50 51 52
from topologie.models import (
    Switch,
    Port,
    Room,
    Stack,
    ModelSwitch,
53
    ConstructorSwitch,
54
    AccessPoint
55
)
chirac's avatar
chirac committed
56
from topologie.forms import EditPortForm, NewSwitchForm, EditSwitchForm
57 58 59 60
from topologie.forms import (
    AddPortForm,
    EditRoomForm,
    StackForm,
61
    EditModelSwitchForm,
62
    EditConstructorSwitchForm,
63
    CreatePortsForm,
64 65
    AddAccessPointForm,
    EditAccessPointForm
66
)
Dalahro's avatar
Dalahro committed
67
from users.views import form
68
from re2o.utils import re2o_paginator, SortTable
69
from re2o.acl import (
70 71 72
    can_create,
    can_edit,
    can_delete,
73 74
    can_view,
    can_view_all,
75
)
76 77 78 79 80 81 82
from machines.forms import (
    DomainForm,
    NewMachineForm,
    EditMachineForm,
    EditInterfaceForm,
    AddInterfaceForm
)
83
from machines.views import generate_ipv4_mbf_param
84
from machines.models import Interface
85
from preferences.models import AssoOption, GeneralOption
86

chirac's avatar
chirac committed
87

chirac's avatar
chirac committed
88
@login_required
89
@can_view_all(Switch)
Dalahro's avatar
Dalahro committed
90
def index(request):
91
    """ Vue d'affichage de tous les swicthes"""
92
    switch_list = Switch.objects\
93 94 95 96
        .prefetch_related(Prefetch(
            'interface_set',
        queryset=Interface.objects.select_related('ipv4__ip_type__extension').select_related('domain__extension')
        ))\
chirac's avatar
chirac committed
97
        .select_related('stack')
98 99 100 101 102 103
    switch_list = SortTable.sort(
        switch_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX
    )
104
    pagination_number = GeneralOption.get_cached_value('pagination_number')
105
    switch_list = re2o_paginator(request, switch_list, pagination_number)
chirac's avatar
chirac committed
106 107 108 109
    return render(request, 'topologie/index.html', {
        'switch_list': switch_list
        })

Dalahro's avatar
Dalahro committed
110

chirac's avatar
chirac committed
111
@login_required
112 113
@can_view_all(Port)
@can_view(Switch)
114
def index_port(request, switch, switchid):
115
    """ Affichage de l'ensemble des ports reliés à un switch particulier"""
chirac's avatar
chirac committed
116 117 118
    port_list = Port.objects.filter(switch=switch)\
        .select_related('room')\
        .select_related('machine_interface__domain__extension')\
119
        .select_related('machine_interface__machine__user')\
120
        .select_related('related__switch')\
121 122 123 124
        .prefetch_related(Prefetch(
            'related__switch__interface_set',
            queryset=Interface.objects.select_related('domain__extension')
        ))\
125 126 127 128 129 130 131
        .select_related('switch')
    port_list = SortTable.sort(
        port_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_PORT
    )
chirac's avatar
chirac committed
132 133
    return render(request, 'topologie/index_p.html', {
        'port_list': port_list,
134
        'id_switch': switchid,
chirac's avatar
chirac committed
135 136 137
        'nom_switch': switch
        })

Dalahro's avatar
Dalahro committed
138

chirac's avatar
chirac committed
139
@login_required
140
@can_view_all(Room)
chirac's avatar
chirac committed
141
def index_room(request):
142
    """ Affichage de l'ensemble des chambres"""
143
    room_list = Room.objects
144 145 146 147 148 149
    room_list = SortTable.sort(
        room_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_ROOM
    )
150
    pagination_number = GeneralOption.get_cached_value('pagination_number')
151
    room_list = re2o_paginator(request, room_list, pagination_number)
chirac's avatar
chirac committed
152 153 154 155
    return render(request, 'topologie/index_room.html', {
        'room_list': room_list
        })

chirac's avatar
chirac committed
156

157
@login_required
158 159
@can_view_all(AccessPoint)
def index_ap(request):
160
    """ Affichage de l'ensemble des bornes"""
161 162 163 164 165
    ap_list = AccessPoint.objects\
        .prefetch_related(Prefetch(
            'interface_set',
            queryset=Interface.objects.select_related('ipv4__ip_type__extension').select_related('domain__extension')
        ))
166 167
    ap_list = SortTable.sort(
        ap_list,
168 169 170 171 172
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_BORNE
    )
    pagination_number = GeneralOption.get_cached_value('pagination_number')
173
    ap_list = re2o_paginator(request, ap_list, pagination_number)
174 175
    return render(request, 'topologie/index_ap.html', {
        'ap_list': ap_list
176 177 178
        })


179
@login_required
180
@can_view_all(Stack)
181
def index_stack(request):
chirac's avatar
chirac committed
182
    """Affichage de la liste des stacks (affiche l'ensemble des switches)"""
183
    stack_list = Stack.objects\
184
        .prefetch_related('switch_set__domain__extension')
185 186 187 188 189 190
    stack_list = SortTable.sort(
        stack_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_STACK
    )
chirac's avatar
chirac committed
191 192 193
    return render(request, 'topologie/index_stack.html', {
        'stack_list': stack_list
        })
194 195


196
@login_required
197 198
@can_view_all(ModelSwitch)
@can_view_all(ConstructorSwitch)
199 200
def index_model_switch(request):
    """ Affichage de l'ensemble des modèles de switches"""
201
    model_switch_list = ModelSwitch.objects.select_related('constructor')
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
    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
    )
    return render(request, 'topologie/index_model_switch.html', {
        'model_switch_list': model_switch_list,
        'constructor_switch_list': constructor_switch_list,
        })


chirac's avatar
chirac committed
221
@login_required
222
@can_create(Port)
223
def new_port(request, switchid):
224
    """ Nouveau port"""
Dalahro's avatar
Dalahro committed
225
    try:
226
        switch = Switch.objects.get(pk=switchid)
Dalahro's avatar
Dalahro committed
227 228
    except Switch.DoesNotExist:
        messages.error(request, u"Switch inexistant")
229
        return redirect(reverse('topologie:index'))
Dalahro's avatar
Dalahro committed
230 231 232 233 234
    port = AddPortForm(request.POST or None)
    if port.is_valid():
        port = port.save(commit=False)
        port.switch = switch
        try:
235
            port.save()
Dalahro's avatar
Dalahro committed
236 237
            messages.success(request, "Port ajouté")
        except IntegrityError:
chirac's avatar
chirac committed
238
            messages.error(request, "Ce port existe déjà")
239
        return redirect(reverse(
240
            'topologie:index-port',
241
            kwargs={'switchid':switchid}
242
            ))
243
    return form({'id_switch': switchid,'topoform': port, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
244

Dalahro's avatar
Dalahro committed
245

chirac's avatar
chirac committed
246
@login_required
247
@can_edit(Port)
248
def edit_port(request, port_object, portid):
chirac's avatar
chirac committed
249 250
    """ Edition d'un port. Permet de changer le switch parent et
    l'affectation du port"""
251

252
    port = EditPortForm(request.POST or None, instance=port_object)
Dalahro's avatar
Dalahro committed
253
    if port.is_valid():
254 255 256
        if port.changed_data:
            port.save()
            messages.success(request, "Le port a bien été modifié")
257 258
        return redirect(reverse(
            'topologie:index-port',
259
            kwargs={'switchid': str(port_object.switch.id)}
260
            ))
261
    return form({'id_switch': str(port_object.switch.id), 'topoform': port, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
262

chirac's avatar
chirac committed
263

264
@login_required
265
@can_delete(Port)
266
def del_port(request, port, portid):
267
    """ Supprime le port"""
Gabriel Detraz's avatar
Gabriel Detraz committed
268 269
    if request.method == "POST":
        try:
270 271
            port.delete()
            messages.success(request, "Le port a été détruit")
Gabriel Detraz's avatar
Gabriel Detraz committed
272
        except ProtectedError:
chirac's avatar
chirac committed
273 274
            messages.error(request, "Le port %s est affecté à un autre objet,\
                impossible de le supprimer" % port)
275 276
        return redirect(reverse(
            'topologie:index-port',
277
            kwargs={'switchid':str(port.switch.id)}
278
            ))
chirac's avatar
chirac committed
279 280
    return form({'objet': port}, 'topologie/delete.html', request)

Gabriel Detraz's avatar
Gabriel Detraz committed
281 282

@login_required
283
@can_create(Stack)
284
def new_stack(request):
285
    """Ajoute un nouveau stack : stackid_min, max, et nombre de switches"""
286
    stack = StackForm(request.POST or None)
chirac's avatar
chirac committed
287
    if stack.is_valid():
288
        stack.save()
chirac's avatar
chirac committed
289
        messages.success(request, "Stack crée")
290
    return form({'topoform': stack, 'action_name' : 'Créer'}, 'topologie/topo.html', request)
291 292 293


@login_required
294
@can_edit(Stack)
295
def edit_stack(request, stack, stackid):
chirac's avatar
chirac committed
296
    """Edition d'un stack (nombre de switches, nom...)"""
297 298
    stack = StackForm(request.POST or None, instance=stack)
    if stack.is_valid():
299 300 301
        if stack.changed_data:
            stack.save()
            return redirect(reverse('topologie:index-stack'))
302
    return form({'topoform': stack, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
303

304

305
@login_required
306
@can_delete(Stack)
307
def del_stack(request, stack, stackid):
chirac's avatar
chirac committed
308
    """Supprime un stack"""
309 310
    if request.method == "POST":
        try:
311 312
            stack.delete()
            messages.success(request, "La stack a eté détruite")
313
        except ProtectedError:
chirac's avatar
chirac committed
314 315
            messages.error(request, "La stack %s est affectée à un autre\
                objet, impossible de la supprimer" % stack)
316
        return redirect(reverse('topologie:index-stack'))
chirac's avatar
chirac committed
317 318
    return form({'objet': stack}, 'topologie/delete.html', request)

319

320
@login_required
321
@can_edit(Stack)
322
def edit_switchs_stack(request, stack, stackid):
chirac's avatar
chirac committed
323
    """Permet d'éditer la liste des switches dans une stack et l'ajouter"""
324

325 326 327 328 329 330 331 332
    if request.method == "POST":
        pass
    else:
        context = {'stack': stack}
        context['switchs_stack'] = stack.switchs_set.all()
        context['switchs_autres'] = Switch.object.filter(stack=None)


chirac's avatar
chirac committed
333
@login_required
334
@can_create(Switch)
Dalahro's avatar
Dalahro committed
335
def new_switch(request):
chirac's avatar
chirac committed
336 337 338
    """ 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"""
339
    switch = NewSwitchForm(
340 341 342
        request.POST or None,
        user=request.user
    )
343
    interface = AddInterfaceForm(
chirac's avatar
chirac committed
344
        request.POST or None,
345
        user=request.user
346
    )
347
    domain = DomainForm(
chirac's avatar
chirac committed
348 349
        request.POST or None,
        )
350
    if switch.is_valid() and interface.is_valid():
351
        user = AssoOption.get_cached_value('utilisateur_asso')
352
        if not user:
chirac's avatar
chirac committed
353 354
            messages.error(request, "L'user association n'existe pas encore,\
            veuillez le créer ou le linker dans preferences")
355
            return redirect(reverse('topologie:index'))
356 357 358 359
        new_switch = switch.save(commit=False)
        new_switch.user = user
        new_interface_instance = interface.save(commit=False)
        domain.instance.interface_parent = new_interface_instance
360 361
        if domain.is_valid():
            new_domain_instance = domain.save(commit=False)
362
            new_switch.save()
363
            new_interface_instance.machine = new_switch
364
            new_interface_instance.save()
365
            new_domain_instance.interface_parent = new_interface_instance
366
            new_domain_instance.save()
367 368
            messages.success(request, "Le switch a été créé")
            return redirect(reverse('topologie:index'))
369
    i_mbf_param = generate_ipv4_mbf_param(interface, False)
chirac's avatar
chirac committed
370
    return form({
371 372
        'topoform': interface,
        'machineform': switch,
chirac's avatar
chirac committed
373
        'domainform': domain,
374 375 376
        'i_mbf_param': i_mbf_param,
        'device' : 'switch',
        }, 'topologie/topo_more.html', request)
chirac's avatar
chirac committed
377

Dalahro's avatar
Dalahro committed
378

379
@login_required
380
@can_create(Port)
381
def create_ports(request, switchid):
382 383
    """ Création d'une liste de ports pour un switch."""
    try:
384
        switch = Switch.objects.get(pk=switchid)
385 386
    except Switch.DoesNotExist:
        messages.error(request, u"Switch inexistant")
387
        return redirect(reverse('topologie:index'))
388

389
    s_begin = s_end = 0
390 391
    nb_ports = switch.ports.count()
    if nb_ports > 0:
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
392 393 394
        ports = switch.ports.order_by('port').values('port')
        s_begin = ports.first().get('port')
        s_end = ports.last().get('port')
395

396 397
    port_form = CreatePortsForm(
        request.POST or None,
398
        initial={'begin': s_begin, 'end': s_end}
399
    )
400

401 402 403
    if port_form.is_valid():
        begin = port_form.cleaned_data['begin']
        end = port_form.cleaned_data['end']
404 405 406 407 408
        try:
            switch.create_ports(begin, end)
            messages.success(request, "Ports créés.")
        except ValidationError as e:
            messages.error(request, ''.join(e))
409 410
        return redirect(reverse(
            'topologie:index-port',
411
            kwargs={'switchid':switchid}
412
            ))
413
    return form({'id_switch': switchid, 'topoform': port_form}, 'topologie/switch.html', request)
414

Dalahro's avatar
Dalahro committed
415

chirac's avatar
chirac committed
416
@login_required
417
@can_edit(Switch)
418
def edit_switch(request, switch, switchid):
chirac's avatar
chirac committed
419 420
    """ Edition d'un switch. Permet de chambre nombre de ports,
    place dans le stack, interface et machine associée"""
421

422
    switch_form = EditSwitchForm(
chirac's avatar
chirac committed
423
        request.POST or None,
424
        instance=switch,
425
        user=request.user
chirac's avatar
chirac committed
426
        )
427
    interface_form = EditInterfaceForm(
chirac's avatar
chirac committed
428
        request.POST or None,
429
        instance=switch.interface_set.first(),
430
        user=request.user
chirac's avatar
chirac committed
431
        )
432
    domain_form = DomainForm(
chirac's avatar
chirac committed
433
        request.POST or None,
434
        instance=switch.interface_set.first().domain
chirac's avatar
chirac committed
435
        )
436 437 438
    if switch_form.is_valid() and interface_form.is_valid():
        new_switch = switch_form.save(commit=False)
        new_interface_instance = interface_form.save(commit=False)
chirac's avatar
chirac committed
439
        new_domain = domain_form.save(commit=False)
440 441 442 443 444 445
        if switch_form.changed_data:
            new_switch.save()
        if interface_form.changed_data:
            new_interface_instance.save()
        if domain_form.changed_data:
            new_domain.save()
446
        messages.success(request, "Le switch a bien été modifié")
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
447
        return redirect(reverse('topologie:index'))
448
    i_mbf_param = generate_ipv4_mbf_param(interface_form, False )
chirac's avatar
chirac committed
449
    return form({
450
        'id_switch': switchid,
451 452
        'topoform': interface_form,
        'machineform': switch_form,
chirac's avatar
chirac committed
453
        'domainform': domain_form,
454 455 456
        'i_mbf_param': i_mbf_param,
        'device' : 'switch',
        }, 'topologie/topo_more.html', request)
chirac's avatar
chirac committed
457

chirac's avatar
chirac committed
458

459
@login_required
460 461 462
@can_create(AccessPoint)
def new_ap(request):
    """ Creation d'une ap. Cree en meme temps l'interface et la machine
463 464
    associée. Vue complexe. Appelle successivement les 3 models forms
    adaptés : machine, interface, domain et switch"""
465
    ap = AddAccessPointForm(
466 467 468
        request.POST or None,
        user=request.user
    )
469
    interface = AddInterfaceForm(
470 471 472 473 474 475
        request.POST or None,
        user=request.user
    )
    domain = DomainForm(
        request.POST or None,
        )
476
    if ap.is_valid() and interface.is_valid():
477 478 479 480 481
        user = AssoOption.get_cached_value('utilisateur_asso')
        if not user:
            messages.error(request, "L'user association n'existe pas encore,\
            veuillez le créer ou le linker dans preferences")
            return redirect(reverse('topologie:index'))
482
        new_ap = ap.save(commit=False)
483 484 485
        new_ap.user = user
        new_interface = interface.save(commit=False)
        domain.instance.interface_parent = new_interface
486 487
        if domain.is_valid():
            new_domain_instance = domain.save(commit=False)
488
            new_ap.save()
489
            new_interface.machine = new_ap
490
            new_interface.save()
491
            new_domain_instance.interface_parent = new_interface
492
            new_domain_instance.save()
493
            messages.success(request, "La borne a été créé")
494
            return redirect(reverse('topologie:index-ap'))
495
    i_mbf_param = generate_ipv4_mbf_param(interface, False)
496
    return form({
497 498
        'topoform': interface,
        'machineform': ap,
499
        'domainform': domain,
500 501 502
        'i_mbf_param': i_mbf_param,
        'device' : 'wifi ap',
        }, 'topologie/topo_more.html', request)
503 504 505


@login_required
506
@can_edit(AccessPoint)
507
def edit_ap(request, ap, accesspointid):
508 509
    """ Edition d'un switch. Permet de chambre nombre de ports,
    place dans le stack, interface et machine associée"""
510
    interface_form = EditInterfaceForm(
511 512
        request.POST or None,
        user=request.user,
513
        instance=ap.interface_set.first()
514
    )
515
    ap_form = EditAccessPointForm(
516 517
        request.POST or None,
        user=request.user,
518
        instance=ap
519 520 521
    )
    domain_form = DomainForm(
        request.POST or None,
522
        instance=ap.interface_set.first().domain
523
        )
524
    if ap_form.is_valid() and interface_form.is_valid():
525 526 527 528
        user = AssoOption.get_cached_value('utilisateur_asso')
        if not user:
            messages.error(request, "L'user association n'existe pas encore,\
            veuillez le créer ou le linker dans preferences")
529 530
            return redirect(reverse('topologie:index-ap'))
        new_ap = ap_form.save(commit=False)
531
        new_interface = interface_form.save(commit=False)
532
        new_domain = domain_form.save(commit=False)
533 534 535 536 537 538
        if ap_form.changed_data:
            new_ap.save()
        if interface_form.changed_data:
            new_interface.save()
        if domain_form.changed_data:
            new_domain.save()
539
        messages.success(request, "La borne a été modifiée")
540
        return redirect(reverse('topologie:index-ap'))
541
    i_mbf_param = generate_ipv4_mbf_param(interface_form, False )
542
    return form({
543 544
        'topoform': interface_form,
        'machineform': ap_form,
545
        'domainform': domain_form,
546 547 548
        'i_mbf_param': i_mbf_param,
        'device' : 'wifi ap',
        }, 'topologie/topo_more.html', request)
549 550
    

chirac's avatar
chirac committed
551
@login_required
552
@can_create(Room)
chirac's avatar
chirac committed
553
def new_room(request):
554
    """Nouvelle chambre """
chirac's avatar
chirac committed
555 556
    room = EditRoomForm(request.POST or None)
    if room.is_valid():
557
        room.save()
chirac's avatar
chirac committed
558
        messages.success(request, "La chambre a été créé")
559
        return redirect(reverse('topologie:index-room'))
560
    return form({'topoform': room, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
561

chirac's avatar
chirac committed
562 563

@login_required
564
@can_edit(Room)
565
def edit_room(request, room, roomid):
566
    """ Edition numero et details de la chambre"""
chirac's avatar
chirac committed
567 568
    room = EditRoomForm(request.POST or None, instance=room)
    if room.is_valid():
569 570 571
        if room.changed_data:
            room.save()
            messages.success(request, "La chambre a bien été modifiée")
572
        return redirect(reverse('topologie:index-room'))
573
    return form({'topoform': room, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
574

chirac's avatar
chirac committed
575 576

@login_required
577
@can_delete(Room)
578
def del_room(request, room, roomid):
579
    """ Suppression d'un chambre"""
chirac's avatar
chirac committed
580
    if request.method == "POST":
581
        try:
582 583
            room.delete()
            messages.success(request, "La chambre/prise a été détruite")
584
        except ProtectedError:
chirac's avatar
chirac committed
585 586
            messages.error(request, "La chambre %s est affectée à un autre objet,\
                impossible de la supprimer (switch ou user)" % room)
587
        return redirect(reverse('topologie:index-room'))
chirac's avatar
chirac committed
588 589 590 591
    return form({
        'objet': room,
        'objet_name': 'Chambre'
        }, 'topologie/delete.html', request)
592 593 594


@login_required
595
@can_create(ModelSwitch)
596 597 598 599
def new_model_switch(request):
    """Nouveau modèle de switch"""
    model_switch = EditModelSwitchForm(request.POST or None)
    if model_switch.is_valid():
600
        model_switch.save()
601
        messages.success(request, "Le modèle a été créé")
602
        return redirect(reverse('topologie:index-model-switch'))
603
    return form({'topoform': model_switch, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request)
604 605 606


@login_required
607
@can_edit(ModelSwitch)
608
def edit_model_switch(request, model_switch, modelswitchid):
609
    """ Edition d'un modèle de switch"""
610

611 612
    model_switch = EditModelSwitchForm(request.POST or None, instance=model_switch)
    if model_switch.is_valid():
613 614 615
        if model_switch.changed_data:
            model_switch.save()
            messages.success(request, "Le modèle a bien été modifié")
616
        return redirect(reverse('topologie:index-model-switch'))
617
    return form({'topoform': model_switch, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
618 619 620


@login_required
621
@can_delete(ModelSwitch)
622
def del_model_switch(request, model_switch, modelswitchid):
623 624 625
    """ Suppression d'un modèle de switch"""
    if request.method == "POST":
        try:
626 627
            model_switch.delete()
            messages.success(request, "Le modèle a été détruit")
628 629 630
        except ProtectedError:
            messages.error(request, "Le modèle %s est affectée à un autre objet,\
                impossible de la supprimer (switch ou user)" % model_switch)
631
        return redirect(reverse('topologie:index-model-switch'))
632 633 634 635 636 637 638
    return form({
        'objet': model_switch,
        'objet_name': 'Modèle de switch'
        }, 'topologie/delete.html', request)


@login_required
639
@can_create(ConstructorSwitch)
640 641 642 643
def new_constructor_switch(request):
    """Nouveau constructeur de switch"""
    constructor_switch = EditConstructorSwitchForm(request.POST or None)
    if constructor_switch.is_valid():
644
        constructor_switch.save()
645
        messages.success(request, "Le constructeur a été créé")
646
        return redirect(reverse('topologie:index-model-switch'))
647
    return form({'topoform': constructor_switch, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request)
648 649 650


@login_required
651
@can_edit(ConstructorSwitch)
652
def edit_constructor_switch(request, constructor_switch, constructorswitchid):
653
    """ Edition d'un constructeur de switch"""
654

655 656
    constructor_switch = EditConstructorSwitchForm(request.POST or None, instance=constructor_switch)
    if constructor_switch.is_valid():
657 658 659
        if constructor_switch.changed_data:
            constructor_switch.save()
            messages.success(request, "Le modèle a bien été modifié")
660
        return redirect(reverse('topologie:index-model-switch'))
661
    return form({'topoform': constructor_switch, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
662 663 664


@login_required
665
@can_delete(ConstructorSwitch)
666
def del_constructor_switch(request, constructor_switch, constructorswitchid):
667 668 669
    """ Suppression d'un constructeur de switch"""
    if request.method == "POST":
        try:
670 671
            constructor_switch.delete()
            messages.success(request, "Le constructeur a été détruit")
672 673 674
        except ProtectedError:
            messages.error(request, "Le constructeur %s est affecté à un autre objet,\
                impossible de la supprimer (switch ou user)" % constructor_switch)
675
        return redirect(reverse('topologie:index-model-switch'))
676 677 678 679
    return form({
        'objet': constructor_switch,
        'objet_name': 'Constructeur de switch'
        }, 'topologie/delete.html', request)