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 29.8 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
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 56 57
from topologie.models import (
    Switch,
    Port,
    Room,
    Stack,
    ModelSwitch,
    ConstructorSwitch
)
chirac's avatar
chirac committed
58
from topologie.forms import EditPortForm, NewSwitchForm, EditSwitchForm
59 60 61 62 63
from topologie.forms import (
    AddPortForm,
    EditRoomForm,
    StackForm,
    EditModelSwitchForm, 
64 65
    EditConstructorSwitchForm,
    CreatePortsForm
66
)
Dalahro's avatar
Dalahro committed
67
from users.views import form
68
from re2o.utils import SortTable
69 70 71 72 73 74 75
from machines.forms import (
    DomainForm,
    NewMachineForm,
    EditMachineForm,
    EditInterfaceForm,
    AddInterfaceForm
)
76
from machines.views import generate_ipv4_mbf_param
77
from preferences.models import AssoOption, GeneralOption
78

chirac's avatar
chirac committed
79

chirac's avatar
chirac committed
80
@login_required
chirac's avatar
chirac committed
81
@permission_required('cableur')
Dalahro's avatar
Dalahro committed
82
def index(request):
83
    """ Vue d'affichage de tous les swicthes"""
84
    switch_list = Switch.objects\
chirac's avatar
chirac committed
85 86 87 88
        .select_related('switch_interface__domain__extension')\
        .select_related('switch_interface__ipv4')\
        .select_related('switch_interface__domain')\
        .select_related('stack')
89 90 91 92 93 94
    switch_list = SortTable.sort(
        switch_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX
    )
Gabriel Detraz's avatar
Gabriel Detraz committed
95 96 97 98 99 100 101 102 103 104 105 106
    options, _created = GeneralOption.objects.get_or_create()
    pagination_number = options.pagination_number
    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
107 108 109 110
    return render(request, 'topologie/index.html', {
        'switch_list': switch_list
        })

Dalahro's avatar
Dalahro committed
111

112 113
@login_required
@permission_required('cableur')
chirac's avatar
chirac committed
114
def history(request, object_name, object_id):
115
    """ Vue générique pour afficher l'historique complet d'un objet"""
chirac's avatar
chirac committed
116
    if object_name == 'switch':
117
        try:
chirac's avatar
chirac committed
118
            object_instance = Switch.objects.get(pk=object_id)
119
        except Switch.DoesNotExist:
chirac's avatar
chirac committed
120
            messages.error(request, "Switch inexistant")
121
            return redirect(reverse('topologie:index'))
chirac's avatar
chirac committed
122
    elif object_name == 'port':
123
        try:
chirac's avatar
chirac committed
124
            object_instance = Port.objects.get(pk=object_id)
125
        except Port.DoesNotExist:
chirac's avatar
chirac committed
126
            messages.error(request, "Port inexistant")
127
            return redirect(reverse('topologie:index'))
chirac's avatar
chirac committed
128
    elif object_name == 'room':
129
        try:
chirac's avatar
chirac committed
130
            object_instance = Room.objects.get(pk=object_id)
131
        except Room.DoesNotExist:
chirac's avatar
chirac committed
132
            messages.error(request, "Chambre inexistante")
133
            return redirect(reverse('topologie:index'))
chirac's avatar
chirac committed
134
    elif object_name == 'stack':
135
        try:
chirac's avatar
chirac committed
136
            object_instance = Stack.objects.get(pk=object_id)
137
        except Room.DoesNotExist:
chirac's avatar
chirac committed
138
            messages.error(request, "Stack inexistante")
139
            return redirect(reverse('topologie:index'))
140 141 142 143 144
    elif object_name == 'model_switch':
        try:
            object_instance = ModelSwitch.objects.get(pk=object_id)
        except ModelSwitch.DoesNotExist:
            messages.error(request, "SwitchModel inexistant")
145
            return redirect(reverse('topologie:index'))
146 147 148 149 150
    elif object_name == 'constructor_switch':
        try:
            object_instance = ConstructorSwitch.objects.get(pk=object_id)
        except ConstructorSwitch.DoesNotExist:
            messages.error(request, "SwitchConstructor inexistant")
151
            return redirect(reverse('topologie:index'))
152 153
    else:
        messages.error(request, "Objet  inconnu")
154
        return redirect(reverse('topologie:index'))
chirac's avatar
chirac committed
155
    options, _created = GeneralOption.objects.get_or_create()
156
    pagination_number = options.pagination_number
root's avatar
root committed
157
    reversions = Version.objects.get_for_object(object_instance)
158
    paginator = Paginator(reversions, pagination_number)
chirac's avatar
chirac committed
159 160 161 162 163 164 165 166 167
    page = request.GET.get('page')
    try:
        reversions = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        reversions = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        reversions = paginator.page(paginator.num_pages)
chirac's avatar
chirac committed
168 169 170 171 172
    return render(request, 're2o/history.html', {
        'reversions': reversions,
        'object': object_instance
        })

173

chirac's avatar
chirac committed
174
@login_required
chirac's avatar
chirac committed
175
@permission_required('cableur')
Dalahro's avatar
Dalahro committed
176
def index_port(request, switch_id):
177
    """ Affichage de l'ensemble des ports reliés à un switch particulier"""
Dalahro's avatar
Dalahro committed
178 179 180 181
    try:
        switch = Switch.objects.get(pk=switch_id)
    except Switch.DoesNotExist:
        messages.error(request, u"Switch inexistant")
182
        return redirect(reverse('topologie:index'))
chirac's avatar
chirac committed
183 184 185
    port_list = Port.objects.filter(switch=switch)\
        .select_related('room')\
        .select_related('machine_interface__domain__extension')\
186
        .select_related('machine_interface__machine__user')\
187 188 189
        .select_related(
            'related__switch__switch_interface__domain__extension'
        )\
190 191 192 193 194 195 196
        .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
197 198 199 200 201 202
    return render(request, 'topologie/index_p.html', {
        'port_list': port_list,
        'id_switch': switch_id,
        'nom_switch': switch
        })

Dalahro's avatar
Dalahro committed
203

chirac's avatar
chirac committed
204 205 206
@login_required
@permission_required('cableur')
def index_room(request):
207
    """ Affichage de l'ensemble des chambres"""
208
    room_list = Room.objects
209 210 211 212 213 214
    room_list = SortTable.sort(
        room_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_ROOM
    )
chirac's avatar
chirac committed
215
    options, _created = GeneralOption.objects.get_or_create()
Gabriel Detraz's avatar
Gabriel Detraz committed
216 217 218 219 220 221 222 223 224 225 226
    pagination_number = options.pagination_number
    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
227 228 229 230
    return render(request, 'topologie/index_room.html', {
        'room_list': room_list
        })

chirac's avatar
chirac committed
231

232 233 234
@login_required
@permission_required('infra')
def index_stack(request):
chirac's avatar
chirac committed
235
    """Affichage de la liste des stacks (affiche l'ensemble des switches)"""
236
    stack_list = Stack.objects\
chirac's avatar
chirac committed
237
        .prefetch_related('switch_set__switch_interface__domain__extension')
238 239 240 241 242 243
    stack_list = SortTable.sort(
        stack_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.TOPOLOGIE_INDEX_STACK
    )
chirac's avatar
chirac committed
244 245 246
    return render(request, 'topologie/index_stack.html', {
        'stack_list': stack_list
        })
247 248


249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
@login_required
@permission_required('cableur')
def index_model_switch(request):
    """ Affichage de l'ensemble des modèles de switches"""
    model_switch_list = ModelSwitch.objects
    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
273
@login_required
274
@permission_required('infra')
Dalahro's avatar
Dalahro committed
275
def new_port(request, switch_id):
276
    """ Nouveau port"""
Dalahro's avatar
Dalahro committed
277 278 279 280
    try:
        switch = Switch.objects.get(pk=switch_id)
    except Switch.DoesNotExist:
        messages.error(request, u"Switch inexistant")
281
        return redirect(reverse('topologie:index'))
Dalahro's avatar
Dalahro committed
282 283 284 285 286
    port = AddPortForm(request.POST or None)
    if port.is_valid():
        port = port.save(commit=False)
        port.switch = switch
        try:
287 288 289 290
            with transaction.atomic(), reversion.create_revision():
                port.save()
                reversion.set_user(request.user)
                reversion.set_comment("Création")
Dalahro's avatar
Dalahro committed
291 292
            messages.success(request, "Port ajouté")
        except IntegrityError:
chirac's avatar
chirac committed
293
            messages.error(request, "Ce port existe déjà")
294 295 296 297
        return redirect(reverse(
            'topologie:index-port', 
            kwargs={'switch_id':switch_id}
            ))
chirac's avatar
chirac committed
298 299
    return form({'topoform': port}, 'topologie/topo.html', request)

Dalahro's avatar
Dalahro committed
300

chirac's avatar
chirac committed
301
@login_required
302
@permission_required('infra')
Dalahro's avatar
Dalahro committed
303
def edit_port(request, port_id):
chirac's avatar
chirac committed
304 305
    """ Edition d'un port. Permet de changer le switch parent et
    l'affectation du port"""
Dalahro's avatar
Dalahro committed
306
    try:
chirac's avatar
chirac committed
307 308 309 310 311 312 313
        port_object = Port.objects\
            .select_related('switch__switch_interface__domain__extension')\
            .select_related('machine_interface__domain__extension')\
            .select_related('machine_interface__switch')\
            .select_related('room')\
            .select_related('related')\
            .get(pk=port_id)
Dalahro's avatar
Dalahro committed
314 315
    except Port.DoesNotExist:
        messages.error(request, u"Port inexistant")
316
        return redirect(reverse('topologie:index'))
317
    port = EditPortForm(request.POST or None, instance=port_object)
Dalahro's avatar
Dalahro committed
318
    if port.is_valid():
319 320 321
        with transaction.atomic(), reversion.create_revision():
            port.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
322 323 324
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in port.changed_data
                ))
Dalahro's avatar
Dalahro committed
325
        messages.success(request, "Le port a bien été modifié")
326 327 328 329
        return redirect(reverse(
            'topologie:index-port',
            kwargs={'switch_id': str(port_object.switch.id)}
            ))
chirac's avatar
chirac committed
330 331
    return form({'topoform': port}, 'topologie/topo.html', request)

chirac's avatar
chirac committed
332

333
@login_required
Gabriel Detraz's avatar
Gabriel Detraz committed
334
@permission_required('infra')
chirac's avatar
chirac committed
335
def del_port(request, port_id):
336
    """ Supprime le port"""
Gabriel Detraz's avatar
Gabriel Detraz committed
337 338 339 340
    try:
        port = Port.objects.get(pk=port_id)
    except Port.DoesNotExist:
        messages.error(request, u"Port inexistant")
341
        return redirect(reverse('topologie:index'))
Gabriel Detraz's avatar
Gabriel Detraz committed
342 343 344 345 346 347
    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
348
                messages.success(request, "Le port a été détruit")
Gabriel Detraz's avatar
Gabriel Detraz committed
349
        except ProtectedError:
chirac's avatar
chirac committed
350 351
            messages.error(request, "Le port %s est affecté à un autre objet,\
                impossible de le supprimer" % port)
352 353
        return redirect(reverse(
            'topologie:index-port',
354
            kwargs={'switch_id':str(port.switch.id)}
355
            ))
chirac's avatar
chirac committed
356 357
    return form({'objet': port}, 'topologie/delete.html', request)

Gabriel Detraz's avatar
Gabriel Detraz committed
358 359

@login_required
360 361
@permission_required('infra')
def new_stack(request):
chirac's avatar
chirac committed
362
    """Ajoute un nouveau stack : stack_id_min, max, et nombre de switches"""
363
    stack = StackForm(request.POST or None)
chirac's avatar
chirac committed
364 365 366 367 368 369 370
    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")
    return form({'topoform': stack}, 'topologie/topo.html', request)
371 372 373 374


@login_required
@permission_required('infra')
chirac's avatar
chirac committed
375 376
def edit_stack(request, stack_id):
    """Edition d'un stack (nombre de switches, nom...)"""
377 378 379 380
    try:
        stack = Stack.objects.get(pk=stack_id)
    except Stack.DoesNotExist:
        messages.error(request, u"Stack inexistante")
381
        return redirect(reverse('topologie:index-stack'))
382 383 384 385 386
    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
387 388 389 390 391
            reversion.set_comment(
                "Champs modifié(s) : %s" % ', '.join(
                    field for field in stack.changed_data
                    )
                )
392
            return redirect(reverse('topologie:index-stack'))
chirac's avatar
chirac committed
393 394
    return form({'topoform': stack}, 'topologie/topo.html', request)

395

396 397
@login_required
@permission_required('infra')
chirac's avatar
chirac committed
398 399
def del_stack(request, stack_id):
    """Supprime un stack"""
400 401 402 403
    try:
        stack = Stack.objects.get(pk=stack_id)
    except Stack.DoesNotExist:
        messages.error(request, u"Stack inexistante")
404
        return redirect(reverse('topologie:index-stack'))
405 406 407 408 409 410 411 412
    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
413 414
            messages.error(request, "La stack %s est affectée à un autre\
                objet, impossible de la supprimer" % stack)
415
            return redirect(reverse('topologie:index-stack'))
chirac's avatar
chirac committed
416 417
    return form({'objet': stack}, 'topologie/delete.html', request)

418

419 420
@login_required
@permission_required('infra')
chirac's avatar
chirac committed
421 422
def edit_switchs_stack(request, stack_id):
    """Permet d'éditer la liste des switches dans une stack et l'ajouter"""
423 424 425 426
    try:
        stack = Stack.objects.get(pk=stack_id)
    except Stack.DoesNotExist:
        messages.error(request, u"Stack inexistante")
427
        return redirect(reverse('topologie:index-stack'))
428 429 430 431 432 433 434 435
    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
436
@login_required
437
@permission_required('infra')
Dalahro's avatar
Dalahro committed
438
def new_switch(request):
chirac's avatar
chirac committed
439 440 441
    """ 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"""
442 443
    switch = NewSwitchForm(request.POST or None)
    machine = NewMachineForm(request.POST or None)
chirac's avatar
chirac committed
444 445 446 447
    interface = AddInterfaceForm(
        request.POST or None,
        infra=request.user.has_perms(('infra',))
        )
448
    domain = DomainForm(
chirac's avatar
chirac committed
449 450
        request.POST or None,
        )
451
    if switch.is_valid() and machine.is_valid() and interface.is_valid():
chirac's avatar
chirac committed
452
        options, _created = AssoOption.objects.get_or_create()
453 454
        user = options.utilisateur_asso
        if not user:
chirac's avatar
chirac committed
455 456
            messages.error(request, "L'user association n'existe pas encore,\
            veuillez le créer ou le linker dans preferences")
457
            return redirect(reverse('topologie:index'))
458 459 460
        new_machine = machine.save(commit=False)
        new_machine.user = user
        new_interface = interface.save(commit=False)
chirac's avatar
chirac committed
461 462
        new_switch_instance = switch.save(commit=False)
        new_domain_instance = domain.save(commit=False)
463 464 465 466 467 468 469 470 471
        with transaction.atomic(), reversion.create_revision():
            new_machine.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
        new_interface.machine = new_machine
        with transaction.atomic(), reversion.create_revision():
            new_interface.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
chirac's avatar
chirac committed
472
        new_domain_instance.interface_parent = new_interface
473
        with transaction.atomic(), reversion.create_revision():
chirac's avatar
chirac committed
474
            new_domain_instance.save()
475 476
            reversion.set_user(request.user)
            reversion.set_comment("Création")
chirac's avatar
chirac committed
477
        new_switch_instance.switch_interface = new_interface
478
        with transaction.atomic(), reversion.create_revision():
chirac's avatar
chirac committed
479
            new_switch_instance.save()
480 481
            reversion.set_user(request.user)
            reversion.set_comment("Création")
482
        messages.success(request, "Le switch a été créé")
483
        return redirect(reverse('topologie:index'))
484
    i_mbf_param = generate_ipv4_mbf_param( interface, False)
chirac's avatar
chirac committed
485 486 487 488 489
    return form({
        'topoform': switch,
        'machineform': machine,
        'interfaceform': interface,
        'domainform': domain,
490
        'i_mbf_param': i_mbf_param
chirac's avatar
chirac committed
491 492
        }, 'topologie/switch.html', request)

Dalahro's avatar
Dalahro committed
493

494 495 496 497 498 499 500 501 502
@login_required
@permission_required('infra')
def create_ports(request, switch_id):
    """ Création d'une liste de ports pour un switch."""
    try:
        switch = Switch.objects.get(pk=switch_id)
    except Switch.DoesNotExist:
        messages.error(request, u"Switch inexistant")
        return redirect("/topologie/")
503
    
504
    s_begin = s_end = 0
505 506
    nb_ports = switch.ports.count()
    if nb_ports > 0:
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
507 508 509
        ports = switch.ports.order_by('port').values('port')
        s_begin = ports.first().get('port')
        s_end = ports.last().get('port')
510
    
511 512
    port_form = CreatePortsForm(
        request.POST or None,
513
        initial={'begin': s_begin, 'end': s_end}
514
    )
515

516 517 518
    if port_form.is_valid():
        begin = port_form.cleaned_data['begin']
        end = port_form.cleaned_data['end']
519 520 521 522 523 524
        try:
            switch.create_ports(begin, end)
            messages.success(request, "Ports créés.")
        except ValidationError as e:
            messages.error(request, ''.join(e))

525
        return redirect("/topologie/switch/" + str(switch.id))
526

527 528
    return form({'topoform': port_form}, 'topologie/switch.html', request)

Dalahro's avatar
Dalahro committed
529

chirac's avatar
chirac committed
530
@login_required
531
@permission_required('infra')
Dalahro's avatar
Dalahro committed
532
def edit_switch(request, switch_id):
chirac's avatar
chirac committed
533 534
    """ Edition d'un switch. Permet de chambre nombre de ports,
    place dans le stack, interface et machine associée"""
Dalahro's avatar
Dalahro committed
535 536 537 538
    try:
        switch = Switch.objects.get(pk=switch_id)
    except Switch.DoesNotExist:
        messages.error(request, u"Switch inexistant")
539
        return redirect(reverse('topologie:index'))
540
    switch_form = EditSwitchForm(request.POST or None, instance=switch)
chirac's avatar
chirac committed
541 542 543 544 545 546 547 548
    machine_form = EditMachineForm(
        request.POST or None,
        instance=switch.switch_interface.machine
        )
    interface_form = EditInterfaceForm(
        request.POST or None,
        instance=switch.switch_interface
        )
549
    domain_form = DomainForm(
chirac's avatar
chirac committed
550 551 552 553 554
        request.POST or None,
        instance=switch.switch_interface.domain
        )
    if switch_form.is_valid() and machine_form.is_valid()\
            and interface_form.is_valid():
555 556
        new_interface = interface_form.save(commit=False)
        new_machine = machine_form.save(commit=False)
chirac's avatar
chirac committed
557
        new_switch_instance = switch_form.save(commit=False)
chirac's avatar
chirac committed
558
        new_domain = domain_form.save(commit=False)
559 560 561
        with transaction.atomic(), reversion.create_revision():
            new_machine.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
562 563 564 565 566
            reversion.set_comment(
                "Champs modifié(s) : %s" % ', '.join(
                    field for field in machine_form.changed_data
                    )
                )
567 568 569
        with transaction.atomic(), reversion.create_revision():
            new_interface.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
570 571 572
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in interface_form.changed_data)
                                 )
573 574 575
        with transaction.atomic(), reversion.create_revision():
            new_domain.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
576 577 578
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in domain_form.changed_data)
                                 )
579
        with transaction.atomic(), reversion.create_revision():
chirac's avatar
chirac committed
580
            new_switch_instance.save()
581
            reversion.set_user(request.user)
chirac's avatar
chirac committed
582 583 584
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in switch_form.changed_data)
                                 )
585
        messages.success(request, "Le switch a bien été modifié")
586
        return redirect(reverse('topologie'))
587
    i_mbf_param = generate_ipv4_mbf_param( interface_form, False )
chirac's avatar
chirac committed
588 589 590 591 592
    return form({
        'topoform': switch_form,
        'machineform': machine_form,
        'interfaceform': interface_form,
        'domainform': domain_form,
593
        'i_mbf_param': i_mbf_param
chirac's avatar
chirac committed
594 595
        }, 'topologie/switch.html', request)

chirac's avatar
chirac committed
596 597 598 599

@login_required
@permission_required('infra')
def new_room(request):
600
    """Nouvelle chambre """
chirac's avatar
chirac committed
601 602
    room = EditRoomForm(request.POST or None)
    if room.is_valid():
603 604 605 606
        with transaction.atomic(), reversion.create_revision():
            room.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
chirac's avatar
chirac committed
607
        messages.success(request, "La chambre a été créé")
608
        return redirect(reverse('topologie:index-room'))
chirac's avatar
chirac committed
609 610
    return form({'topoform': room}, 'topologie/topo.html', request)

chirac's avatar
chirac committed
611 612 613 614

@login_required
@permission_required('infra')
def edit_room(request, room_id):
615
    """ Edition numero et details de la chambre"""
chirac's avatar
chirac committed
616 617 618 619
    try:
        room = Room.objects.get(pk=room_id)
    except Room.DoesNotExist:
        messages.error(request, u"Chambre inexistante")
620
        return redirect(reverse('topologie:index-room'))
chirac's avatar
chirac committed
621 622
    room = EditRoomForm(request.POST or None, instance=room)
    if room.is_valid():
623 624 625
        with transaction.atomic(), reversion.create_revision():
            room.save()
            reversion.set_user(request.user)
chirac's avatar
chirac committed
626 627 628
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in room.changed_data)
                                 )
chirac's avatar
chirac committed
629
        messages.success(request, "La chambre a bien été modifiée")
630
        return redirect(reverse('topologie:index-room'))
chirac's avatar
chirac committed
631 632
    return form({'topoform': room}, 'topologie/topo.html', request)

chirac's avatar
chirac committed
633 634 635 636

@login_required
@permission_required('infra')
def del_room(request, room_id):
637
    """ Suppression d'un chambre"""
chirac's avatar
chirac committed
638 639 640
    try:
        room = Room.objects.get(pk=room_id)
    except Room.DoesNotExist:
chirac's avatar
chirac committed
641
        messages.error(request, u"Chambre inexistante")
642
        return redirect(reverse('topologie:index-room'))
chirac's avatar
chirac committed
643
    if request.method == "POST":
644 645 646 647 648 649 650
        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
651 652
            messages.error(request, "La chambre %s est affectée à un autre objet,\
                impossible de la supprimer (switch ou user)" % room)
653
            return redirect(reverse('topologie:index-room'))
chirac's avatar
chirac committed
654 655 656 657
    return form({
        'objet': room,
        'objet_name': 'Chambre'
        }, 'topologie/delete.html', request)
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783


@login_required
@permission_required('infra')
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éé")
        return redirect("/topologie/index_model_switch/")
    return form({'topoform': model_switch}, 'topologie/topo.html', request)


@login_required
@permission_required('infra')
def edit_model_switch(request, model_switch_id):
    """ Edition d'un modèle de switch"""
    try:
        model_switch = ModelSwitch.objects.get(pk=model_switch_id)
    except ModelSwitch.DoesNotExist:
        messages.error(request, u"Modèle inconnu")
        return redirect("/topologie/index_model_switch/")
    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é")
        return redirect("/topologie/index_model_switch/")
    return form({'topoform': model_switch}, 'topologie/topo.html', request)


@login_required
@permission_required('infra')
def del_model_switch(request, model_switch_id):
    """ Suppression d'un modèle de switch"""
    try:
        model_switch = ModelSwitch.objects.get(pk=model_switch_id)
    except ModelSwitch.DoesNotExist:
        messages.error(request, u"Modèle inexistant")
        return redirect("/topologie/index_model_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)
        return redirect("/topologie/index_model_switch/")
    return form({
        'objet': model_switch,
        'objet_name': 'Modèle de switch'
        }, 'topologie/delete.html', request)


@login_required
@permission_required('infra')
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éé")
        return redirect("/topologie/index_model_switch/")
    return form({'topoform': constructor_switch}, 'topologie/topo.html', request)


@login_required
@permission_required('infra')
def edit_constructor_switch(request, constructor_switch_id):
    """ Edition d'un constructeur de switch"""
    try:
        constructor_switch = ConstructorSwitch.objects.get(pk=constructor_switch_id)
    except ConstructorSwitch.DoesNotExist:
        messages.error(request, u"Constructeur inconnu")
        return redirect("/topologie/index_model_switch/")
    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é")
        return redirect("/topologie/index_model_switch/")
    return form({'topoform': constructor_switch}, 'topologie/topo.html', request)


@login_required
@permission_required('infra')
def del_constructor_switch(request, constructor_switch_id):
    """ Suppression d'un constructeur de switch"""
    try:
        constructor_switch = ConstructorSwitch.objects.get(pk=constructor_switch_id)
    except ConstructorSwitch.DoesNotExist:
        messages.error(request, u"Constructeur inexistant")
        return redirect("/topologie/index_model_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)
        return redirect("/topologie/index_model_switch/")
    return form({
        'objet': constructor_switch,
        'objet_name': 'Constructeur de switch'
        }, 'topologie/delete.html', request)