Ce serveur Gitlab sera éteint le 30 juin 2020, pensez à migrer vos projets vers les serveurs gitlab-research.centralesupelec.fr et gitlab-student.centralesupelec.fr !

views.py 30 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
chirac's avatar
chirac committed
46
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
47
from reversion import revisions as reversion
root's avatar
root committed
48
from reversion.models import Version
Dalahro's avatar
Dalahro committed
49

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

chirac's avatar
chirac committed
90

chirac's avatar
chirac committed
91
@login_required
92
@can_view_all(Switch)
Dalahro's avatar
Dalahro committed
93
def index(request):
94
    """ Vue d'affichage de tous les swicthes"""
95
    switch_list = Switch.objects\
96 97 98 99
        .prefetch_related(Prefetch(
            'interface_set',
        queryset=Interface.objects.select_related('ipv4__ip_type__extension').select_related('domain__extension')
        ))\
chirac's avatar
chirac committed
100
        .select_related('stack')
101 102 103 104 105 106
    switch_list = SortTable.sort(
        switch_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX
    )
107
    pagination_number = GeneralOption.get_cached_value('pagination_number')
Gabriel Detraz's avatar
Gabriel Detraz committed
108 109 110 111 112 113 114 115 116 117
    paginator = Paginator(switch_list, pagination_number)
    page = request.GET.get('page')
    try:
        switch_list = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        switch_list = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        switch_list = paginator.page(paginator.num_pages)
chirac's avatar
chirac committed
118 119 120 121
    return render(request, 'topologie/index.html', {
        'switch_list': switch_list
        })

Dalahro's avatar
Dalahro committed
122

chirac's avatar
chirac committed
123
@login_required
124 125
@can_view_all(Port)
@can_view(Switch)
126
def index_port(request, switch, switchid):
127
    """ Affichage de l'ensemble des ports reliés à un switch particulier"""
chirac's avatar
chirac committed
128 129 130
    port_list = Port.objects.filter(switch=switch)\
        .select_related('room')\
        .select_related('machine_interface__domain__extension')\
131
        .select_related('machine_interface__machine__user')\
132
        .select_related('related__switch')\
133 134 135 136
        .prefetch_related(Prefetch(
            'related__switch__interface_set',
            queryset=Interface.objects.select_related('domain__extension')
        ))\
137 138 139 140 141 142 143
        .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
144 145
    return render(request, 'topologie/index_p.html', {
        'port_list': port_list,
146
        'id_switch': switchid,
chirac's avatar
chirac committed
147 148 149
        'nom_switch': switch
        })

Dalahro's avatar
Dalahro committed
150

chirac's avatar
chirac committed
151
@login_required
152
@can_view_all(Room)
chirac's avatar
chirac committed
153
def index_room(request):
154
    """ Affichage de l'ensemble des chambres"""
155
    room_list = Room.objects
156 157 158 159 160 161
    room_list = SortTable.sort(
        room_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_ROOM
    )
162
    pagination_number = GeneralOption.get_cached_value('pagination_number')
Gabriel Detraz's avatar
Gabriel Detraz committed
163 164 165 166 167 168 169 170 171 172
    paginator = Paginator(room_list, pagination_number)
    page = request.GET.get('page')
    try:
        room_list = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        room_list = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        room_list = paginator.page(paginator.num_pages)
chirac's avatar
chirac committed
173 174 175 176
    return render(request, 'topologie/index_room.html', {
        'room_list': room_list
        })

chirac's avatar
chirac committed
177

178
@login_required
179 180
@can_view_all(AccessPoint)
def index_ap(request):
181
    """ Affichage de l'ensemble des bornes"""
182 183 184 185 186
    ap_list = AccessPoint.objects\
        .prefetch_related(Prefetch(
            'interface_set',
            queryset=Interface.objects.select_related('ipv4__ip_type__extension').select_related('domain__extension')
        ))
187 188
    ap_list = SortTable.sort(
        ap_list,
189 190 191 192 193
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_BORNE
    )
    pagination_number = GeneralOption.get_cached_value('pagination_number')
194
    paginator = Paginator(ap_list, pagination_number)
195 196
    page = request.GET.get('page')
    try:
197
        ap_list = paginator.page(page)
198 199
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
200
        ap_list = paginator.page(1)
201 202
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
203 204 205
        ap_list = paginator.page(paginator.num_pages)
    return render(request, 'topologie/index_ap.html', {
        'ap_list': ap_list
206 207 208
        })


209
@login_required
210
@can_view_all(Stack)
211
def index_stack(request):
chirac's avatar
chirac committed
212
    """Affichage de la liste des stacks (affiche l'ensemble des switches)"""
213
    stack_list = Stack.objects\
214
        .prefetch_related('switch_set__interface_set__domain__extension')
215 216 217 218 219 220
    stack_list = SortTable.sort(
        stack_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_STACK
    )
chirac's avatar
chirac committed
221 222 223
    return render(request, 'topologie/index_stack.html', {
        'stack_list': stack_list
        })
224 225


226
@login_required
227 228
@can_view_all(ModelSwitch)
@can_view_all(ConstructorSwitch)
229 230
def index_model_switch(request):
    """ Affichage de l'ensemble des modèles de switches"""
231
    model_switch_list = ModelSwitch.objects.select_related('constructor')
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    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
251
@login_required
252
@can_create(Port)
253
def new_port(request, switchid):
254
    """ Nouveau port"""
Dalahro's avatar
Dalahro committed
255
    try:
256
        switch = Switch.objects.get(pk=switchid)
Dalahro's avatar
Dalahro committed
257 258
    except Switch.DoesNotExist:
        messages.error(request, u"Switch inexistant")
259
        return redirect(reverse('topologie:index'))
Dalahro's avatar
Dalahro committed
260 261 262 263 264
    port = AddPortForm(request.POST or None)
    if port.is_valid():
        port = port.save(commit=False)
        port.switch = switch
        try:
265 266 267 268
            with transaction.atomic(), reversion.create_revision():
                port.save()
                reversion.set_user(request.user)
                reversion.set_comment("Création")
Dalahro's avatar
Dalahro committed
269 270
            messages.success(request, "Port ajouté")
        except IntegrityError:
chirac's avatar
chirac committed
271
            messages.error(request, "Ce port existe déjà")
272
        return redirect(reverse(
273
            'topologie:index-port',
274
            kwargs={'switchid':switchid}
275
            ))
276
    return form({'id_switch': switchid,'topoform': port, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
277

Dalahro's avatar
Dalahro committed
278

chirac's avatar
chirac committed
279
@login_required
280
@can_edit(Port)
281
def edit_port(request, port_object, portid):
chirac's avatar
chirac committed
282 283
    """ Edition d'un port. Permet de changer le switch parent et
    l'affectation du port"""
284

285
    port = EditPortForm(request.POST or None, instance=port_object)
Dalahro's avatar
Dalahro committed
286
    if port.is_valid():
287 288 289
        with transaction.atomic(), reversion.create_revision():
            port.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
290 291 292
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in port.changed_data
                ))
Dalahro's avatar
Dalahro committed
293
        messages.success(request, "Le port a bien été modifié")
294 295
        return redirect(reverse(
            'topologie:index-port',
296
            kwargs={'switchid': str(port_object.switch.id)}
297
            ))
298
    return form({'id_switch': str(port_object.switch.id), 'topoform': port, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
299

chirac's avatar
chirac committed
300

301
@login_required
302
@can_delete(Port)
303
def del_port(request, port, portid):
304
    """ Supprime le port"""
Gabriel Detraz's avatar
Gabriel Detraz committed
305 306 307 308 309 310
    if request.method == "POST":
        try:
            with transaction.atomic(), reversion.create_revision():
                port.delete()
                reversion.set_user(request.user)
                reversion.set_comment("Destruction")
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
311
                messages.success(request, "Le port a été détruit")
Gabriel Detraz's avatar
Gabriel Detraz committed
312
        except ProtectedError:
chirac's avatar
chirac committed
313 314
            messages.error(request, "Le port %s est affecté à un autre objet,\
                impossible de le supprimer" % port)
315 316
        return redirect(reverse(
            'topologie:index-port',
317
            kwargs={'switchid':str(port.switch.id)}
318
            ))
chirac's avatar
chirac committed
319 320
    return form({'objet': port}, 'topologie/delete.html', request)

Gabriel Detraz's avatar
Gabriel Detraz committed
321 322

@login_required
323
@can_create(Stack)
324
def new_stack(request):
325
    """Ajoute un nouveau stack : stackid_min, max, et nombre de switches"""
326
    stack = StackForm(request.POST or None)
chirac's avatar
chirac committed
327 328 329 330 331 332
    if stack.is_valid():
        with transaction.atomic(), reversion.create_revision():
            stack.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
        messages.success(request, "Stack crée")
333
    return form({'topoform': stack, 'action_name' : 'Créer'}, 'topologie/topo.html', request)
334 335 336


@login_required
337
@can_edit(Stack)
338
def edit_stack(request, stack, stackid):
chirac's avatar
chirac committed
339
    """Edition d'un stack (nombre de switches, nom...)"""
340

341 342 343 344 345
    stack = StackForm(request.POST or None, instance=stack)
    if stack.is_valid():
        with transaction.atomic(), reversion.create_revision():
            stack.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
346 347 348 349 350
            reversion.set_comment(
                "Champs modifié(s) : %s" % ', '.join(
                    field for field in stack.changed_data
                    )
                )
351
            return redirect(reverse('topologie:index-stack'))
352
    return form({'topoform': stack, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
353

354

355
@login_required
356
@can_delete(Stack)
357
def del_stack(request, stack, stackid):
chirac's avatar
chirac committed
358
    """Supprime un stack"""
359 360 361 362 363 364 365 366
    if request.method == "POST":
        try:
            with transaction.atomic(), reversion.create_revision():
                stack.delete()
                reversion.set_user(request.user)
                reversion.set_comment("Destruction")
                messages.success(request, "La stack a eté détruite")
        except ProtectedError:
chirac's avatar
chirac committed
367 368
            messages.error(request, "La stack %s est affectée à un autre\
                objet, impossible de la supprimer" % stack)
369
        return redirect(reverse('topologie:index-stack'))
chirac's avatar
chirac committed
370 371
    return form({'objet': stack}, 'topologie/delete.html', request)

372

373
@login_required
374
@can_edit(Stack)
375
def edit_switchs_stack(request, stack, stackid):
chirac's avatar
chirac committed
376
    """Permet d'éditer la liste des switches dans une stack et l'ajouter"""
377

378 379 380 381 382 383 384 385
    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
386
@login_required
387
@can_create(Switch)
Dalahro's avatar
Dalahro committed
388
def new_switch(request):
chirac's avatar
chirac committed
389 390 391
    """ 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"""
392
    switch = NewSwitchForm(
393 394 395
        request.POST or None,
        user=request.user
    )
396
    interface = AddInterfaceForm(
chirac's avatar
chirac committed
397
        request.POST or None,
398
        user=request.user
399
    )
400
    domain = DomainForm(
chirac's avatar
chirac committed
401 402
        request.POST or None,
        )
403
    if switch.is_valid() and interface.is_valid():
404
        user = AssoOption.get_cached_value('utilisateur_asso')
405
        if not user:
chirac's avatar
chirac committed
406 407
            messages.error(request, "L'user association n'existe pas encore,\
            veuillez le créer ou le linker dans preferences")
408
            return redirect(reverse('topologie:index'))
409 410 411 412
        new_switch = switch.save(commit=False)
        new_switch.user = user
        new_interface_instance = interface.save(commit=False)
        domain.instance.interface_parent = new_interface_instance
413 414 415
        if domain.is_valid():
            new_domain_instance = domain.save(commit=False)
            with transaction.atomic(), reversion.create_revision():
416
                new_switch.save()
417 418
                reversion.set_user(request.user)
                reversion.set_comment("Création")
419
            new_interface_instance.machine = new_switch
420
            with transaction.atomic(), reversion.create_revision():
421
                new_interface_instance.save()
422 423
                reversion.set_user(request.user)
                reversion.set_comment("Création")
424
            new_domain_instance.interface_parent = new_interface_instance
425 426 427 428 429 430
            with transaction.atomic(), reversion.create_revision():
                new_domain_instance.save()
                reversion.set_user(request.user)
                reversion.set_comment("Création")
            messages.success(request, "Le switch a été créé")
            return redirect(reverse('topologie:index'))
431
    i_mbf_param = generate_ipv4_mbf_param(interface, False)
chirac's avatar
chirac committed
432
    return form({
433 434
        'topoform': interface,
        'machineform': switch,
chirac's avatar
chirac committed
435
        'domainform': domain,
436 437 438
        'i_mbf_param': i_mbf_param,
        'device' : 'switch',
        }, 'topologie/topo_more.html', request)
chirac's avatar
chirac committed
439

Dalahro's avatar
Dalahro committed
440

441
@login_required
442
@can_create(Port)
443
def create_ports(request, switchid):
444 445
    """ Création d'une liste de ports pour un switch."""
    try:
446
        switch = Switch.objects.get(pk=switchid)
447 448
    except Switch.DoesNotExist:
        messages.error(request, u"Switch inexistant")
449
        return redirect(reverse('topologie:index'))
450

451
    s_begin = s_end = 0
452 453
    nb_ports = switch.ports.count()
    if nb_ports > 0:
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
454 455 456
        ports = switch.ports.order_by('port').values('port')
        s_begin = ports.first().get('port')
        s_end = ports.last().get('port')
457

458 459
    port_form = CreatePortsForm(
        request.POST or None,
460
        initial={'begin': s_begin, 'end': s_end}
461
    )
462

463 464 465
    if port_form.is_valid():
        begin = port_form.cleaned_data['begin']
        end = port_form.cleaned_data['end']
466 467 468 469 470 471
        try:
            switch.create_ports(begin, end)
            messages.success(request, "Ports créés.")
        except ValidationError as e:
            messages.error(request, ''.join(e))

472 473
        return redirect(reverse(
            'topologie:index-port',
474
            kwargs={'switchid':switchid}
475
            ))
476
    return form({'id_switch': switchid, 'topoform': port_form}, 'topologie/switch.html', request)
477

Dalahro's avatar
Dalahro committed
478

chirac's avatar
chirac committed
479
@login_required
480
@can_edit(Switch)
481
def edit_switch(request, switch, switchid):
chirac's avatar
chirac committed
482 483
    """ Edition d'un switch. Permet de chambre nombre de ports,
    place dans le stack, interface et machine associée"""
484

485
    switch_form = EditSwitchForm(
chirac's avatar
chirac committed
486
        request.POST or None,
487
        instance=switch,
488
        user=request.user
chirac's avatar
chirac committed
489
        )
490
    interface_form = EditInterfaceForm(
chirac's avatar
chirac committed
491
        request.POST or None,
492
        instance=switch.interface_set.first(),
493
        user=request.user
chirac's avatar
chirac committed
494
        )
495
    domain_form = DomainForm(
chirac's avatar
chirac committed
496
        request.POST or None,
497
        instance=switch.interface_set.first().domain
chirac's avatar
chirac committed
498
        )
499 500 501
    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
502
        new_domain = domain_form.save(commit=False)
503
        with transaction.atomic(), reversion.create_revision():
504
            new_switch.save()
505
            reversion.set_user(request.user)
chirac's avatar
chirac committed
506 507
            reversion.set_comment(
                "Champs modifié(s) : %s" % ', '.join(
508
                    field for field in switch_form.changed_data
chirac's avatar
chirac committed
509 510
                    )
                )
511
        with transaction.atomic(), reversion.create_revision():
512
            new_interface_instance.save()
513
            reversion.set_user(request.user)
chirac's avatar
chirac committed
514
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
515
                field for field in interface_form.changed_data)
chirac's avatar
chirac committed
516
                                 )
517 518 519
        with transaction.atomic(), reversion.create_revision():
            new_domain.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
520 521 522
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in domain_form.changed_data)
                                 )
523
        messages.success(request, "Le switch a bien été modifié")
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
524
        return redirect(reverse('topologie:index'))
525
    i_mbf_param = generate_ipv4_mbf_param(interface_form, False )
chirac's avatar
chirac committed
526
    return form({
527
        'id_switch': switchid,
528 529
        'topoform': interface_form,
        'machineform': switch_form,
chirac's avatar
chirac committed
530
        'domainform': domain_form,
531 532 533
        'i_mbf_param': i_mbf_param,
        'device' : 'switch',
        }, 'topologie/topo_more.html', request)
chirac's avatar
chirac committed
534

chirac's avatar
chirac committed
535

536
@login_required
537 538 539
@can_create(AccessPoint)
def new_ap(request):
    """ Creation d'une ap. Cree en meme temps l'interface et la machine
540 541
    associée. Vue complexe. Appelle successivement les 3 models forms
    adaptés : machine, interface, domain et switch"""
542
    ap = AddAccessPointForm(
543 544 545
        request.POST or None,
        user=request.user
    )
546
    interface = AddInterfaceForm(
547 548 549 550 551 552
        request.POST or None,
        user=request.user
    )
    domain = DomainForm(
        request.POST or None,
        )
553
    if ap.is_valid() and interface.is_valid():
554 555 556 557 558
        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'))
559
        new_ap = ap.save(commit=False)
560 561 562
        new_ap.user = user
        new_interface = interface.save(commit=False)
        domain.instance.interface_parent = new_interface
563 564 565
        if domain.is_valid():
            new_domain_instance = domain.save(commit=False)
            with transaction.atomic(), reversion.create_revision():
566
                new_ap.save()
567 568
                reversion.set_user(request.user)
                reversion.set_comment("Création")
569
            new_interface.machine = new_ap
570
            with transaction.atomic(), reversion.create_revision():
571
                new_interface.save()
572 573
                reversion.set_user(request.user)
                reversion.set_comment("Création")
574
            new_domain_instance.interface_parent = new_interface
575 576 577 578 579
            with transaction.atomic(), reversion.create_revision():
                new_domain_instance.save()
                reversion.set_user(request.user)
                reversion.set_comment("Création")
            messages.success(request, "La borne a été créé")
580
            return redirect(reverse('topologie:index-ap'))
581
    i_mbf_param = generate_ipv4_mbf_param(interface, False)
582
    return form({
583 584
        'topoform': interface,
        'machineform': ap,
585
        'domainform': domain,
586 587 588
        'i_mbf_param': i_mbf_param,
        'device' : 'wifi ap',
        }, 'topologie/topo_more.html', request)
589 590 591


@login_required
592
@can_edit(AccessPoint)
593
def edit_ap(request, ap, accesspointid):
594 595
    """ Edition d'un switch. Permet de chambre nombre de ports,
    place dans le stack, interface et machine associée"""
596
    interface_form = EditInterfaceForm(
597 598
        request.POST or None,
        user=request.user,
599
        instance=ap.interface_set.first()
600
    )
601
    ap_form = EditAccessPointForm(
602 603
        request.POST or None,
        user=request.user,
604
        instance=ap
605 606 607
    )
    domain_form = DomainForm(
        request.POST or None,
608
        instance=ap.interface_set.first().domain
609
        )
610
    if ap_form.is_valid() and interface_form.is_valid():
611 612 613 614
        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")
615 616
            return redirect(reverse('topologie:index-ap'))
        new_ap = ap_form.save(commit=False)
617
        new_interface = interface_form.save(commit=False)
618 619
        new_domain = domain_form.save(commit=False)
        with transaction.atomic(), reversion.create_revision():
620
            new_ap.save()
621 622 623
            reversion.set_user(request.user)
            reversion.set_comment(
                "Champs modifié(s) : %s" % ', '.join(
624
                    field for field in ap_form.changed_data)
625 626
            )
        with transaction.atomic(), reversion.create_revision():
627
            new_interface.save()
628 629
            reversion.set_user(request.user)
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
630
                field for field in interface_form.changed_data)
631 632 633 634 635 636 637 638 639
            )
            reversion.set_comment("Création")
        with transaction.atomic(), reversion.create_revision():
            new_domain.save()
            reversion.set_user(request.user)
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in domain_form.changed_data)
            )
        messages.success(request, "La borne a été modifiée")
640
        return redirect(reverse('topologie:index-ap'))
641
    i_mbf_param = generate_ipv4_mbf_param(interface_form, False )
642
    return form({
643 644
        'topoform': interface_form,
        'machineform': ap_form,
645
        'domainform': domain_form,
646 647 648
        'i_mbf_param': i_mbf_param,
        'device' : 'wifi ap',
        }, 'topologie/topo_more.html', request)
649 650
    

chirac's avatar
chirac committed
651
@login_required
652
@can_create(Room)
chirac's avatar
chirac committed
653
def new_room(request):
654
    """Nouvelle chambre """
chirac's avatar
chirac committed
655 656
    room = EditRoomForm(request.POST or None)
    if room.is_valid():
657 658 659 660
        with transaction.atomic(), reversion.create_revision():
            room.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
chirac's avatar
chirac committed
661
        messages.success(request, "La chambre a été créé")
662
        return redirect(reverse('topologie:index-room'))
663
    return form({'topoform': room, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
664

chirac's avatar
chirac committed
665 666

@login_required
667
@can_edit(Room)
668
def edit_room(request, room, roomid):
669
    """ Edition numero et details de la chambre"""
670

chirac's avatar
chirac committed
671 672
    room = EditRoomForm(request.POST or None, instance=room)
    if room.is_valid():
673 674 675
        with transaction.atomic(), reversion.create_revision():
            room.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
676 677 678
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in room.changed_data)
                                 )
chirac's avatar
chirac committed
679
        messages.success(request, "La chambre a bien été modifiée")
680
        return redirect(reverse('topologie:index-room'))
681
    return form({'topoform': room, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
chirac's avatar
chirac committed
682

chirac's avatar
chirac committed
683 684

@login_required
685
@can_delete(Room)
686
def del_room(request, room, roomid):
687
    """ Suppression d'un chambre"""
chirac's avatar
chirac committed
688
    if request.method == "POST":
689 690 691 692 693 694 695
        try:
            with transaction.atomic(), reversion.create_revision():
                room.delete()
                reversion.set_user(request.user)
                reversion.set_comment("Destruction")
                messages.success(request, "La chambre/prise a été détruite")
        except ProtectedError:
chirac's avatar
chirac committed
696 697
            messages.error(request, "La chambre %s est affectée à un autre objet,\
                impossible de la supprimer (switch ou user)" % room)
698
        return redirect(reverse('topologie:index-room'))
chirac's avatar
chirac committed
699 700 701 702
    return form({
        'objet': room,
        'objet_name': 'Chambre'
        }, 'topologie/delete.html', request)
703 704 705


@login_required
706
@can_create(ModelSwitch)
707 708 709 710 711 712 713 714 715
def new_model_switch(request):
    """Nouveau modèle de switch"""
    model_switch = EditModelSwitchForm(request.POST or None)
    if model_switch.is_valid():
        with transaction.atomic(), reversion.create_revision():
            model_switch.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
        messages.success(request, "Le modèle a été créé")
716
        return redirect(reverse('topologie:index-model-switch'))
717
    return form({'topoform': model_switch, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request)
718 719 720


@login_required
721
@can_edit(ModelSwitch)
722
def edit_model_switch(request, model_switch, modelswitchid):
723
    """ Edition d'un modèle de switch"""
724

725 726 727 728 729 730 731 732 733
    model_switch = EditModelSwitchForm(request.POST or None, instance=model_switch)
    if model_switch.is_valid():
        with transaction.atomic(), reversion.create_revision():
            model_switch.save()
            reversion.set_user(request.user)
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in model_switch.changed_data)
            )
        messages.success(request, "Le modèle a bien été modifié")
734
        return redirect(reverse('topologie:index-model-switch'))
735
    return form({'topoform': model_switch, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
736 737 738


@login_required
739
@can_delete(ModelSwitch)
740
def del_model_switch(request, model_switch, modelswitchid):
741 742 743 744 745 746 747 748 749 750 751
    """ Suppression d'un modèle de switch"""
    if request.method == "POST":
        try:
            with transaction.atomic(), reversion.create_revision():
                model_switch.delete()
                reversion.set_user(request.user)
                reversion.set_comment("Destruction")
                messages.success(request, "Le modèle a été détruit")
        except ProtectedError:
            messages.error(request, "Le modèle %s est affectée à un autre objet,\
                impossible de la supprimer (switch ou user)" % model_switch)
752
        return redirect(reverse('topologie:index-model-switch'))
753 754 755 756 757 758 759
    return form({
        'objet': model_switch,
        'objet_name': 'Modèle de switch'
        }, 'topologie/delete.html', request)


@login_required
760
@can_create(ConstructorSwitch)
761 762 763 764 765 766 767 768 769
def new_constructor_switch(request):
    """Nouveau constructeur de switch"""
    constructor_switch = EditConstructorSwitchForm(request.POST or None)
    if constructor_switch.is_valid():
        with transaction.atomic(), reversion.create_revision():
            constructor_switch.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
        messages.success(request, "Le constructeur a été créé")
770
        return redirect(reverse('topologie:index-model-switch'))
771
    return form({'topoform': constructor_switch, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request)
772 773 774


@login_required
775
@can_edit(ConstructorSwitch)
776
def edit_constructor_switch(request, constructor_switch, constructorswitchid):
777
    """ Edition d'un constructeur de switch"""
778

779 780 781 782 783 784 785 786 787
    constructor_switch = EditConstructorSwitchForm(request.POST or None, instance=constructor_switch)
    if constructor_switch.is_valid():
        with transaction.atomic(), reversion.create_revision():
            constructor_switch.save()
            reversion.set_user(request.user)
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in constructor_switch.changed_data)
            )
        messages.success(request, "Le modèle a bien été modifié")
788
        return redirect(reverse('topologie:index-model-switch'))
789
    return form({'topoform': constructor_switch, 'action_name' : 'Editer'}, 'topologie/topo.html', request)
790 791 792


@login_required
793
@can_delete(ConstructorSwitch)
794
def del_constructor_switch(request, constructor_switch, constructorswitchid):
795 796 797 798 799 800 801 802 803 804 805
    """ Suppression d'un constructeur de switch"""
    if request.method == "POST":
        try:
            with transaction.atomic(), reversion.create_revision():
                constructor_switch.delete()
                reversion.set_user(request.user)
                reversion.set_comment("Destruction")
                messages.success(request, "Le constructeur a été détruit")
        except ProtectedError:
            messages.error(request, "Le constructeur %s est affecté à un autre objet,\
                impossible de la supprimer (switch ou user)" % constructor_switch)
806
        return redirect(reverse('topologie:index-model-switch'))
807 808 809 810
    return form({
        'objet': constructor_switch,
        'objet_name': 'Constructeur de switch'
        }, 'topologie/delete.html', request)