mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-26 22:52:26 +00:00
Doc on models machines
This commit is contained in:
parent
367da2d9c1
commit
33f1a21a0a
1 changed files with 54 additions and 1 deletions
|
@ -56,6 +56,7 @@ class MachineType(models.Model):
|
||||||
ip_type = models.ForeignKey('IpType', on_delete=models.PROTECT, blank=True, null=True)
|
ip_type = models.ForeignKey('IpType', on_delete=models.PROTECT, blank=True, null=True)
|
||||||
|
|
||||||
def all_interfaces(self):
|
def all_interfaces(self):
|
||||||
|
""" Renvoie toutes les interfaces (cartes réseaux) de type machinetype"""
|
||||||
return Interface.objects.filter(type=self)
|
return Interface.objects.filter(type=self)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -75,23 +76,31 @@ class IpType(models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ip_range(self):
|
def ip_range(self):
|
||||||
|
""" Renvoie un objet IPRange à partir de l'objet IpType"""
|
||||||
return IPRange(self.domaine_ip_start, end=self.domaine_ip_stop)
|
return IPRange(self.domaine_ip_start, end=self.domaine_ip_stop)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ip_set(self):
|
def ip_set(self):
|
||||||
|
""" Renvoie une IPSet à partir de l'iptype"""
|
||||||
return IPSet(self.ip_range)
|
return IPSet(self.ip_range)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ip_set_as_str(self):
|
def ip_set_as_str(self):
|
||||||
|
""" Renvoie une liste des ip en string"""
|
||||||
return [str(x) for x in self.ip_set]
|
return [str(x) for x in self.ip_set]
|
||||||
|
|
||||||
def ip_objects(self):
|
def ip_objects(self):
|
||||||
|
""" Renvoie tous les objets ipv4 relié à ce type"""
|
||||||
return IpList.objects.filter(ip_type=self)
|
return IpList.objects.filter(ip_type=self)
|
||||||
|
|
||||||
def free_ip(self):
|
def free_ip(self):
|
||||||
|
""" Renvoie toutes les ip libres associées au type donné (self)"""
|
||||||
return IpList.objects.filter(interface__isnull=True).filter(ip_type=self)
|
return IpList.objects.filter(interface__isnull=True).filter(ip_type=self)
|
||||||
|
|
||||||
def gen_ip_range(self):
|
def gen_ip_range(self):
|
||||||
|
""" Cree les IpList associées au type self. Parcours pédestrement et crée
|
||||||
|
les ip une par une. Si elles existent déjà, met à jour le type associé
|
||||||
|
à l'ip"""
|
||||||
# Creation du range d'ip dans les objets iplist
|
# Creation du range d'ip dans les objets iplist
|
||||||
networks = []
|
networks = []
|
||||||
for net in self.ip_range.cidrs():
|
for net in self.ip_range.cidrs():
|
||||||
|
@ -114,6 +123,11 @@ class IpType(models.Model):
|
||||||
ip.delete()
|
ip.delete()
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
""" Nettoyage. Vérifie :
|
||||||
|
- Que ip_stop est après ip_start
|
||||||
|
- Qu'on ne crée pas plus gros qu'un /16
|
||||||
|
- Que le range crée ne recoupe pas un range existant
|
||||||
|
- Formate l'ipv6 donnée en /64"""
|
||||||
if IPAddress(self.domaine_ip_start) > IPAddress(self.domaine_ip_stop):
|
if IPAddress(self.domaine_ip_start) > IPAddress(self.domaine_ip_stop):
|
||||||
raise ValidationError("Domaine end doit être après start...")
|
raise ValidationError("Domaine end doit être après start...")
|
||||||
# On ne crée pas plus grand qu'un /16
|
# On ne crée pas plus grand qu'un /16
|
||||||
|
@ -136,6 +150,7 @@ class IpType(models.Model):
|
||||||
return self.type
|
return self.type
|
||||||
|
|
||||||
class Vlan(models.Model):
|
class Vlan(models.Model):
|
||||||
|
""" Un vlan : vlan_id et nom"""
|
||||||
PRETTY_NAME = "Vlans"
|
PRETTY_NAME = "Vlans"
|
||||||
|
|
||||||
vlan_id = models.IntegerField()
|
vlan_id = models.IntegerField()
|
||||||
|
@ -146,6 +161,9 @@ class Vlan(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Nas(models.Model):
|
class Nas(models.Model):
|
||||||
|
""" Les nas. Associé à un machine_type.
|
||||||
|
Permet aussi de régler le port_access_mode (802.1X ou mac-address) pour
|
||||||
|
le radius. Champ autocapture de la mac à true ou false"""
|
||||||
PRETTY_NAME = "Correspondance entre les nas et les machines connectées"
|
PRETTY_NAME = "Correspondance entre les nas et les machines connectées"
|
||||||
|
|
||||||
default_mode = '802.1X'
|
default_mode = '802.1X'
|
||||||
|
@ -164,6 +182,8 @@ class Nas(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Extension(models.Model):
|
class Extension(models.Model):
|
||||||
|
""" Extension dns type example.org. Précise si tout le monde peut l'utiliser,
|
||||||
|
associé à un origin (ip d'origine)"""
|
||||||
PRETTY_NAME = "Extensions dns"
|
PRETTY_NAME = "Extensions dns"
|
||||||
|
|
||||||
name = models.CharField(max_length=255, unique=True)
|
name = models.CharField(max_length=255, unique=True)
|
||||||
|
@ -172,12 +192,15 @@ class Extension(models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
|
""" Une entrée DNS A"""
|
||||||
return "@ IN A " + str(self.origin)
|
return "@ IN A " + str(self.origin)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Mx(models.Model):
|
class Mx(models.Model):
|
||||||
|
""" Entrées des MX. Enregistre la zone (extension) associée et la priorité
|
||||||
|
Todo : pouvoir associer un MX à une interface """
|
||||||
PRETTY_NAME = "Enregistrements MX"
|
PRETTY_NAME = "Enregistrements MX"
|
||||||
|
|
||||||
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
||||||
|
@ -205,6 +228,7 @@ class Ns(models.Model):
|
||||||
return str(self.zone) + ' ' + str(self.ns)
|
return str(self.zone) + ' ' + str(self.ns)
|
||||||
|
|
||||||
class Text(models.Model):
|
class Text(models.Model):
|
||||||
|
""" Un enregistrement TXT associé à une extension"""
|
||||||
PRETTY_NAME = "Enregistrement text"
|
PRETTY_NAME = "Enregistrement text"
|
||||||
|
|
||||||
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
||||||
|
@ -219,6 +243,12 @@ class Text(models.Model):
|
||||||
return str(self.field1) + " IN TXT " + str(self.field2)
|
return str(self.field1) + " IN TXT " + str(self.field2)
|
||||||
|
|
||||||
class Interface(models.Model):
|
class Interface(models.Model):
|
||||||
|
""" Une interface. Objet clef de l'application machine :
|
||||||
|
- une address mac unique. Possibilité de la rendre unique avec le typemachine
|
||||||
|
- une onetoone vers IpList pour attribution ipv4
|
||||||
|
- le type parent associé au range ip et à l'extension
|
||||||
|
- un objet domain associé contenant son nom
|
||||||
|
- la liste des ports oiuvert"""
|
||||||
PRETTY_NAME = "Interface"
|
PRETTY_NAME = "Interface"
|
||||||
|
|
||||||
ipv4 = models.OneToOneField('IpList', on_delete=models.PROTECT, blank=True, null=True)
|
ipv4 = models.OneToOneField('IpList', on_delete=models.PROTECT, blank=True, null=True)
|
||||||
|
@ -238,6 +268,7 @@ class Interface(models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ipv6_object(self):
|
def ipv6_object(self):
|
||||||
|
""" Renvoie un objet type ipv6 à partir du prefix associé à l'iptype parent"""
|
||||||
if self.type.ip_type.prefix_v6:
|
if self.type.ip_type.prefix_v6:
|
||||||
return EUI(self.mac_address).ipv6(IPNetwork(self.type.ip_type.prefix_v6).network)
|
return EUI(self.mac_address).ipv6(IPNetwork(self.type.ip_type.prefix_v6).network)
|
||||||
else:
|
else:
|
||||||
|
@ -245,18 +276,23 @@ class Interface(models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ipv6(self):
|
def ipv6(self):
|
||||||
|
""" Renvoie l'ipv6 en str. Mise en cache et propriété de l'objet"""
|
||||||
return str(self.ipv6_object)
|
return str(self.ipv6_object)
|
||||||
|
|
||||||
def mac_bare(self):
|
def mac_bare(self):
|
||||||
|
""" Formatage de la mac type mac_bare"""
|
||||||
return str(EUI(self.mac_address, dialect=mac_bare)).lower()
|
return str(EUI(self.mac_address, dialect=mac_bare)).lower()
|
||||||
|
|
||||||
def filter_macaddress(self):
|
def filter_macaddress(self):
|
||||||
|
""" Tente un formatage mac_bare, si échoue, lève une erreur de validation"""
|
||||||
try:
|
try:
|
||||||
self.mac_address = str(EUI(self.mac_address))
|
self.mac_address = str(EUI(self.mac_address))
|
||||||
except :
|
except :
|
||||||
raise ValidationError("La mac donnée est invalide")
|
raise ValidationError("La mac donnée est invalide")
|
||||||
|
|
||||||
def clean(self, *args, **kwargs):
|
def clean(self, *args, **kwargs):
|
||||||
|
""" Formate l'addresse mac en mac_bare (fonction filter_mac)
|
||||||
|
et assigne une ipv4 dans le bon range si inexistante ou incohérente"""
|
||||||
self.filter_macaddress()
|
self.filter_macaddress()
|
||||||
self.mac_address = str(EUI(self.mac_address)) or None
|
self.mac_address = str(EUI(self.mac_address)) or None
|
||||||
if not self.ipv4 or self.type.ip_type != self.ipv4.ip_type:
|
if not self.ipv4 or self.type.ip_type != self.ipv4.ip_type:
|
||||||
|
@ -273,6 +309,7 @@ class Interface(models.Model):
|
||||||
return
|
return
|
||||||
|
|
||||||
def unassign_ipv4(self):
|
def unassign_ipv4(self):
|
||||||
|
""" Sans commentaire, désassigne une ipv4"""
|
||||||
self.ipv4 = None
|
self.ipv4 = None
|
||||||
|
|
||||||
def update_type(self):
|
def update_type(self):
|
||||||
|
@ -295,15 +332,20 @@ class Interface(models.Model):
|
||||||
return str(domain)
|
return str(domain)
|
||||||
|
|
||||||
def has_private_ip(self):
|
def has_private_ip(self):
|
||||||
|
""" True si l'ip associée est privée"""
|
||||||
if self.ipv4:
|
if self.ipv4:
|
||||||
return IPAddress(str(self.ipv4)).is_private()
|
return IPAddress(str(self.ipv4)).is_private()
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def may_have_port_open(self):
|
def may_have_port_open(self):
|
||||||
|
""" True si l'interface a une ip et une ip publique.
|
||||||
|
Permet de ne pas exporter des ouvertures sur des ip privées (useless)"""
|
||||||
return self.ipv4 and not self.has_private_ip()
|
return self.ipv4 and not self.has_private_ip()
|
||||||
|
|
||||||
class Domain(models.Model):
|
class Domain(models.Model):
|
||||||
|
""" Objet domain. Enregistrement A et CNAME en même temps : permet de stocker les
|
||||||
|
alias et les nom de machines, suivant si interface_parent ou cname sont remplis"""
|
||||||
PRETTY_NAME = "Domaine dns"
|
PRETTY_NAME = "Domaine dns"
|
||||||
|
|
||||||
interface_parent = models.OneToOneField('Interface', on_delete=models.CASCADE, blank=True, null=True)
|
interface_parent = models.OneToOneField('Interface', on_delete=models.CASCADE, blank=True, null=True)
|
||||||
|
@ -315,6 +357,8 @@ class Domain(models.Model):
|
||||||
unique_together = (("name", "extension"),)
|
unique_together = (("name", "extension"),)
|
||||||
|
|
||||||
def get_extension(self):
|
def get_extension(self):
|
||||||
|
""" Retourne l'extension de l'interface parente si c'est un A
|
||||||
|
Retourne l'extension propre si c'est un cname, renvoie None sinon"""
|
||||||
if self.interface_parent:
|
if self.interface_parent:
|
||||||
return self.interface_parent.type.ip_type.extension
|
return self.interface_parent.type.ip_type.extension
|
||||||
elif hasattr(self,'extension'):
|
elif hasattr(self,'extension'):
|
||||||
|
@ -323,6 +367,11 @@ class Domain(models.Model):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
""" Validation :
|
||||||
|
- l'objet est bien soit A soit CNAME
|
||||||
|
- le cname est pas pointé sur lui-même
|
||||||
|
- le nom contient bien les caractères autorisés par la norme dns et moins de 63 caractères au total
|
||||||
|
- le couple nom/extension est bien unique"""
|
||||||
if self.get_extension():
|
if self.get_extension():
|
||||||
self.extension=self.get_extension()
|
self.extension=self.get_extension()
|
||||||
""" Validation du nom de domaine, extensions dans type de machine, prefixe pas plus long que 63 caractères """
|
""" Validation du nom de domaine, extensions dans type de machine, prefixe pas plus long que 63 caractères """
|
||||||
|
@ -341,10 +390,12 @@ class Domain(models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
|
""" Une entrée DNS"""
|
||||||
if self.cname:
|
if self.cname:
|
||||||
return str(self.name) + " IN CNAME " + str(self.cname) + "."
|
return str(self.name) + " IN CNAME " + str(self.cname) + "."
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
""" Empèche le save sans extension valide. Force à avoir appellé clean avant"""
|
||||||
if not self.get_extension():
|
if not self.get_extension():
|
||||||
raise ValidationError("Extension invalide")
|
raise ValidationError("Extension invalide")
|
||||||
self.full_clean()
|
self.full_clean()
|
||||||
|
@ -361,9 +412,11 @@ class IpList(models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def need_infra(self):
|
def need_infra(self):
|
||||||
|
""" Permet de savoir si un user basique peut assigner cette ip ou non"""
|
||||||
return self.ip_type.need_infra
|
return self.ip_type.need_infra
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
""" Erreur si l'ip_type est incorrect"""
|
||||||
if not str(self.ipv4) in self.ip_type.ip_set_as_str:
|
if not str(self.ipv4) in self.ip_type.ip_set_as_str:
|
||||||
raise ValidationError("L'ipv4 et le range de l'iptype ne correspondent pas!")
|
raise ValidationError("L'ipv4 et le range de l'iptype ne correspondent pas!")
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue