| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- from django.core.exceptions import ValidationError
- from django.core.validators import MaxValueValidator, MinValueValidator
- from django.db import models
- from dcim.choices import *
- from dcim.constants import *
- from dcim.managers import InterfaceManager
- from extras.models import ObjectChange
- from utilities.managers import NaturalOrderingManager
- from utilities.utils import serialize_object
- from .device_components import (
- ConsolePort, ConsoleServerPort, DeviceBay, FrontPort, Interface, PowerOutlet, PowerPort, RearPort,
- )
- __all__ = (
- 'ConsolePortTemplate',
- 'ConsoleServerPortTemplate',
- 'DeviceBayTemplate',
- 'FrontPortTemplate',
- 'InterfaceTemplate',
- 'PowerOutletTemplate',
- 'PowerPortTemplate',
- 'RearPortTemplate',
- )
- class ComponentTemplateModel(models.Model):
- class Meta:
- abstract = True
- def instantiate(self, device):
- """
- Instantiate a new component on the specified Device.
- """
- raise NotImplementedError()
- def to_objectchange(self, action):
- return ObjectChange(
- changed_object=self,
- object_repr=str(self),
- action=action,
- related_object=self.device_type,
- object_data=serialize_object(self)
- )
- class ConsolePortTemplate(ComponentTemplateModel):
- """
- A template for a ConsolePort to be created for a new Device.
- """
- device_type = models.ForeignKey(
- to='dcim.DeviceType',
- on_delete=models.CASCADE,
- related_name='consoleport_templates'
- )
- name = models.CharField(
- max_length=50
- )
- type = models.CharField(
- max_length=50,
- choices=ConsolePortTypeChoices,
- blank=True
- )
- objects = NaturalOrderingManager()
- class Meta:
- ordering = ['device_type', 'name']
- unique_together = ['device_type', 'name']
- def __str__(self):
- return self.name
- def instantiate(self, device):
- return ConsolePort(
- device=device,
- name=self.name,
- type=self.type
- )
- class ConsoleServerPortTemplate(ComponentTemplateModel):
- """
- A template for a ConsoleServerPort to be created for a new Device.
- """
- device_type = models.ForeignKey(
- to='dcim.DeviceType',
- on_delete=models.CASCADE,
- related_name='consoleserverport_templates'
- )
- name = models.CharField(
- max_length=50
- )
- type = models.CharField(
- max_length=50,
- choices=ConsolePortTypeChoices,
- blank=True
- )
- objects = NaturalOrderingManager()
- class Meta:
- ordering = ['device_type', 'name']
- unique_together = ['device_type', 'name']
- def __str__(self):
- return self.name
- def instantiate(self, device):
- return ConsoleServerPort(
- device=device,
- name=self.name,
- type=self.type
- )
- class PowerPortTemplate(ComponentTemplateModel):
- """
- A template for a PowerPort to be created for a new Device.
- """
- device_type = models.ForeignKey(
- to='dcim.DeviceType',
- on_delete=models.CASCADE,
- related_name='powerport_templates'
- )
- name = models.CharField(
- max_length=50
- )
- type = models.CharField(
- max_length=50,
- choices=PowerPortTypeChoices,
- blank=True
- )
- maximum_draw = models.PositiveSmallIntegerField(
- blank=True,
- null=True,
- validators=[MinValueValidator(1)],
- help_text="Maximum power draw (watts)"
- )
- allocated_draw = models.PositiveSmallIntegerField(
- blank=True,
- null=True,
- validators=[MinValueValidator(1)],
- help_text="Allocated power draw (watts)"
- )
- objects = NaturalOrderingManager()
- class Meta:
- ordering = ['device_type', 'name']
- unique_together = ['device_type', 'name']
- def __str__(self):
- return self.name
- def instantiate(self, device):
- return PowerPort(
- device=device,
- name=self.name,
- maximum_draw=self.maximum_draw,
- allocated_draw=self.allocated_draw
- )
- class PowerOutletTemplate(ComponentTemplateModel):
- """
- A template for a PowerOutlet to be created for a new Device.
- """
- device_type = models.ForeignKey(
- to='dcim.DeviceType',
- on_delete=models.CASCADE,
- related_name='poweroutlet_templates'
- )
- name = models.CharField(
- max_length=50
- )
- type = models.CharField(
- max_length=50,
- choices=PowerOutletTypeChoices,
- blank=True
- )
- power_port = models.ForeignKey(
- to='dcim.PowerPortTemplate',
- on_delete=models.SET_NULL,
- blank=True,
- null=True,
- related_name='poweroutlet_templates'
- )
- feed_leg = models.CharField(
- max_length=50,
- choices=PowerOutletFeedLegChoices,
- blank=True,
- help_text="Phase (for three-phase feeds)"
- )
- objects = NaturalOrderingManager()
- class Meta:
- ordering = ['device_type', 'name']
- unique_together = ['device_type', 'name']
- def __str__(self):
- return self.name
- def clean(self):
- # Validate power port assignment
- if self.power_port and self.power_port.device_type != self.device_type:
- raise ValidationError(
- "Parent power port ({}) must belong to the same device type".format(self.power_port)
- )
- def instantiate(self, device):
- if self.power_port:
- power_port = PowerPort.objects.get(device=device, name=self.power_port.name)
- else:
- power_port = None
- return PowerOutlet(
- device=device,
- name=self.name,
- power_port=power_port,
- feed_leg=self.feed_leg
- )
- class InterfaceTemplate(ComponentTemplateModel):
- """
- A template for a physical data interface on a new Device.
- """
- device_type = models.ForeignKey(
- to='dcim.DeviceType',
- on_delete=models.CASCADE,
- related_name='interface_templates'
- )
- name = models.CharField(
- max_length=64
- )
- type = models.CharField(
- max_length=50,
- choices=InterfaceTypeChoices
- )
- mgmt_only = models.BooleanField(
- default=False,
- verbose_name='Management only'
- )
- objects = InterfaceManager()
- class Meta:
- ordering = ['device_type', 'name']
- unique_together = ['device_type', 'name']
- def __str__(self):
- return self.name
- def instantiate(self, device):
- return Interface(
- device=device,
- name=self.name,
- type=self.type,
- mgmt_only=self.mgmt_only
- )
- class FrontPortTemplate(ComponentTemplateModel):
- """
- Template for a pass-through port on the front of a new Device.
- """
- device_type = models.ForeignKey(
- to='dcim.DeviceType',
- on_delete=models.CASCADE,
- related_name='frontport_templates'
- )
- name = models.CharField(
- max_length=64
- )
- type = models.CharField(
- max_length=50,
- choices=PortTypeChoices
- )
- rear_port = models.ForeignKey(
- to='dcim.RearPortTemplate',
- on_delete=models.CASCADE,
- related_name='frontport_templates'
- )
- rear_port_position = models.PositiveSmallIntegerField(
- default=1,
- validators=[MinValueValidator(1), MaxValueValidator(64)]
- )
- objects = NaturalOrderingManager()
- class Meta:
- ordering = ['device_type', 'name']
- unique_together = [
- ['device_type', 'name'],
- ['rear_port', 'rear_port_position'],
- ]
- def __str__(self):
- return self.name
- def clean(self):
- # Validate rear port assignment
- if self.rear_port.device_type != self.device_type:
- raise ValidationError(
- "Rear port ({}) must belong to the same device type".format(self.rear_port)
- )
- # Validate rear port position assignment
- if self.rear_port_position > self.rear_port.positions:
- raise ValidationError(
- "Invalid rear port position ({}); rear port {} has only {} positions".format(
- self.rear_port_position, self.rear_port.name, self.rear_port.positions
- )
- )
- def instantiate(self, device):
- if self.rear_port:
- rear_port = RearPort.objects.get(device=device, name=self.rear_port.name)
- else:
- rear_port = None
- return FrontPort(
- device=device,
- name=self.name,
- type=self.type,
- rear_port=rear_port,
- rear_port_position=self.rear_port_position
- )
- class RearPortTemplate(ComponentTemplateModel):
- """
- Template for a pass-through port on the rear of a new Device.
- """
- device_type = models.ForeignKey(
- to='dcim.DeviceType',
- on_delete=models.CASCADE,
- related_name='rearport_templates'
- )
- name = models.CharField(
- max_length=64
- )
- type = models.CharField(
- max_length=50,
- choices=PortTypeChoices
- )
- positions = models.PositiveSmallIntegerField(
- default=1,
- validators=[MinValueValidator(1), MaxValueValidator(64)]
- )
- objects = NaturalOrderingManager()
- class Meta:
- ordering = ['device_type', 'name']
- unique_together = ['device_type', 'name']
- def __str__(self):
- return self.name
- def instantiate(self, device):
- return RearPort(
- device=device,
- name=self.name,
- type=self.type,
- positions=self.positions
- )
- class DeviceBayTemplate(ComponentTemplateModel):
- """
- A template for a DeviceBay to be created for a new parent Device.
- """
- device_type = models.ForeignKey(
- to='dcim.DeviceType',
- on_delete=models.CASCADE,
- related_name='device_bay_templates'
- )
- name = models.CharField(
- max_length=50
- )
- objects = NaturalOrderingManager()
- class Meta:
- ordering = ['device_type', 'name']
- unique_together = ['device_type', 'name']
- def __str__(self):
- return self.name
- def instantiate(self, device):
- return DeviceBay(
- device=device,
- name=self.name
- )
|