models.py 5.72 KB
Newer Older
lhark's avatar
lhark committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 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
23
from django.db import models
guimoz's avatar
guimoz committed
24
25
from django.db.models.signals import post_delete
from django.dispatch import receiver
Dalahro's avatar
Dalahro committed
26
from django.forms import ModelForm, Form
chirac's avatar
chirac committed
27
28
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
29
from django.core.exceptions import ValidationError
30
import reversion
31

32
from machines.models import Vlan
Gabriel Detraz's avatar
Gabriel Detraz committed
33

34
35
36
37
38
39
40
41
42
def make_port_related(port):
    related_port = port.related
    related_port.related = port
    related_port.save()
    
def clean_port_related(port):
    related_port = port.related_port
    related_port.related = None
    related_port.save()
chirac's avatar
chirac committed
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class Stack(models.Model):
    PRETTY_NAME = "Stack de switchs"

    name = models.CharField(max_length=32, blank=True, null=True)
    stack_id = models.CharField(max_length=32, unique=True)
    details = models.CharField(max_length=255, blank=True, null=True)
    member_id_min = models.IntegerField()
    member_id_max = models.IntegerField()

    def __str__(self):
        return " ".join([self.name, self.stack_id])

    def save(self, *args, **kwargs):
        if not self.name:
            self.name = self.stack_id
        super(Stack, self).save(*args, **kwargs)

    def clean(self):
        if self.member_id_max < self.member_id_min:
            raise ValidationError({'member_id_max':"L'id maximale est inférieure à l'id minimale"})

chirac's avatar
chirac committed
65
class Switch(models.Model):
66
67
    PRETTY_NAME = "Switch / Commutateur"

chirac's avatar
chirac committed
68
69
    switch_interface = models.OneToOneField('machines.Interface', on_delete=models.CASCADE)
    location = models.CharField(max_length=255)
chirac's avatar
chirac committed
70
    number = models.IntegerField()
chirac's avatar
chirac committed
71
    details = models.CharField(max_length=255, blank=True)
guimoz's avatar
guimoz committed
72
    stack = models.ForeignKey(Stack, blank=True, null=True, on_delete=models.SET_NULL)
73
74
75
76
    stack_member_id = models.IntegerField(blank=True, null=True)

    class Meta:
        unique_together = ('stack','stack_member_id')
chirac's avatar
chirac committed
77
78

    def __str__(self):
79
        return str(self.location) + ' ' + str(self.switch_interface)
chirac's avatar
chirac committed
80

81
82
83
84
85
86
87
88
    def clean(self):
        if self.stack is not None:
            if self.stack_member_id is not None:
                if (self.stack_member_id > self.stack.member_id_max) or (self.stack_member_id < self.stack.member_id_min):
                    raise ValidationError({'stack_member_id': "L'id de ce switch est en dehors des bornes permises pas la stack"})
            else:
                raise ValidationError({'stack_member_id': "L'id dans la stack ne peut être nul"})

chirac's avatar
chirac committed
89
class Port(models.Model):
90
    PRETTY_NAME = "Port de switch"
Gabriel Detraz's avatar
Gabriel Detraz committed
91
92
93
94
95
96
    STATES_BASE = (
            ('NO', 'NO'),
            ('STRICT', 'STRICT'),
            ('BLOQ', 'BLOQ'),
            ('COMMON', 'COMMON'),
            )
97
98
99
100
    try:
        STATES = STATES_BASE + tuple([(str(id), str(id)) for id in list(Vlan.objects.values_list('vlan_id', flat=True).order_by('vlan_id'))])
    except:
        STATES = STATES_BASE 
101

Dalahro's avatar
Dalahro committed
102
    switch = models.ForeignKey('Switch', related_name="ports")
chirac's avatar
chirac committed
103
104
    port = models.IntegerField()
    room = models.ForeignKey('Room', on_delete=models.PROTECT, blank=True, null=True)
105
    machine_interface = models.ForeignKey('machines.Interface', on_delete=models.SET_NULL, blank=True, null=True)
106
    related = models.OneToOneField('self', null=True, blank=True, related_name='related_port')
Gabriel Detraz's avatar
Gabriel Detraz committed
107
    radius = models.CharField(max_length=32, choices=STATES, default='NO')
Dalahro's avatar
Dalahro committed
108
    details = models.CharField(max_length=255, blank=True)
chirac's avatar
chirac committed
109
110

    class Meta:
111
112
113
        unique_together = ('switch', 'port')

    def clean(self):
lhark's avatar
lhark committed
114
115
116
        if hasattr(self, 'switch'):
            if self.port > self.switch.number:
                raise ValidationError("Ce port ne peut exister, numero trop élevé")
117
118
119
120
121
122
123
124
125
126
127
        if self.room and self.machine_interface or self.room and self.related or self.machine_interface and self.related:
            raise ValidationError("Chambre, interface et related_port sont mutuellement exclusifs")
        if self.related==self:
            raise ValidationError("On ne peut relier un port à lui même")
        if self.related and not self.related.related:
            if self.related.machine_interface or self.related.room:
                raise ValidationError("Le port relié est déjà occupé, veuillez le libérer avant de créer une relation")
            else:
                make_port_related(self)
        elif hasattr(self, 'related_port'):
            clean_port_related(self)
chirac's avatar
chirac committed
128
129

    def __str__(self):
chirac's avatar
chirac committed
130
        return str(self.switch) + " - " + str(self.port)
chirac's avatar
chirac committed
131

chirac's avatar
chirac committed
132
class Room(models.Model):
133
134
    PRETTY_NAME = "Chambre/ Prise murale"

lhark's avatar
lhark committed
135
    name = models.CharField(max_length=255, unique=True)
chirac's avatar
chirac committed
136
    details = models.CharField(max_length=255, blank=True)
chirac's avatar
chirac committed
137
138

    def __str__(self):
lhark's avatar
lhark committed
139
        return str(self.name)
chirac's avatar
chirac committed
140

guimoz's avatar
guimoz committed
141
142
143
@receiver(post_delete, sender=Stack)
def stack_post_delete(sender, **kwargs):
    Switch.objects.filter(stack=None).update(stack_member_id = None)