1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Extend ObjectChange to optionally indicate a related object (e.g. a parent device)

This commit is contained in:
Jeremy Stretch
2018-06-22 15:05:40 -04:00
parent 6c1b5fdf3a
commit 2d198403c7
8 changed files with 136 additions and 43 deletions

View File

@ -18,16 +18,41 @@ from taggit.managers import TaggableManager
from timezone_field import TimeZoneField
from circuits.models import Circuit
from extras.models import CustomFieldModel
from extras.models import CustomFieldModel, ObjectChange
from extras.rpc import RPC_CLIENTS
from utilities.fields import ColorField, NullableCharField
from utilities.managers import NaturalOrderByManager
from utilities.models import ChangeLoggedModel
from utilities.utils import serialize_object
from .constants import *
from .fields import ASNField, MACAddressField
from .querysets import InterfaceQuerySet
class ComponentModel(models.Model):
class Meta:
abstract = True
def get_component_parent(self):
raise NotImplementedError(
"ComponentModel must implement get_component_parent()"
)
def log_change(self, user, request_id, action):
"""
Log an ObjectChange including the parent Device.
"""
ObjectChange(
user=user,
request_id=request_id,
changed_object=self,
related_object=self.get_component_parent(),
action=action,
object_data=serialize_object(self)
).save()
#
# Regions
#
@ -866,7 +891,7 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel):
@python_2_unicode_compatible
class ConsolePortTemplate(models.Model):
class ConsolePortTemplate(ComponentModel):
"""
A template for a ConsolePort to be created for a new Device.
"""
@ -886,9 +911,12 @@ class ConsolePortTemplate(models.Model):
def __str__(self):
return self.name
def get_component_parent(self):
return self.device_type
@python_2_unicode_compatible
class ConsoleServerPortTemplate(models.Model):
class ConsoleServerPortTemplate(ComponentModel):
"""
A template for a ConsoleServerPort to be created for a new Device.
"""
@ -908,9 +936,12 @@ class ConsoleServerPortTemplate(models.Model):
def __str__(self):
return self.name
def get_component_parent(self):
return self.device_type
@python_2_unicode_compatible
class PowerPortTemplate(models.Model):
class PowerPortTemplate(ComponentModel):
"""
A template for a PowerPort to be created for a new Device.
"""
@ -930,9 +961,12 @@ class PowerPortTemplate(models.Model):
def __str__(self):
return self.name
def get_component_parent(self):
return self.device_type
@python_2_unicode_compatible
class PowerOutletTemplate(models.Model):
class PowerOutletTemplate(ComponentModel):
"""
A template for a PowerOutlet to be created for a new Device.
"""
@ -952,9 +986,12 @@ class PowerOutletTemplate(models.Model):
def __str__(self):
return self.name
def get_component_parent(self):
return self.device_type
@python_2_unicode_compatible
class InterfaceTemplate(models.Model):
class InterfaceTemplate(ComponentModel):
"""
A template for a physical data interface on a new Device.
"""
@ -984,9 +1021,12 @@ class InterfaceTemplate(models.Model):
def __str__(self):
return self.name
def get_component_parent(self):
return self.device_type
@python_2_unicode_compatible
class DeviceBayTemplate(models.Model):
class DeviceBayTemplate(ComponentModel):
"""
A template for a DeviceBay to be created for a new parent Device.
"""
@ -1006,6 +1046,9 @@ class DeviceBayTemplate(models.Model):
def __str__(self):
return self.name
def get_component_parent(self):
return self.device_type
#
# Devices
@ -1502,7 +1545,7 @@ class Device(ChangeLoggedModel, CustomFieldModel):
#
@python_2_unicode_compatible
class ConsolePort(models.Model):
class ConsolePort(ComponentModel):
"""
A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts.
"""
@ -1539,6 +1582,9 @@ class ConsolePort(models.Model):
def get_absolute_url(self):
return self.device.get_absolute_url()
def get_component_parent(self):
return self.device
def to_csv(self):
return (
self.cs_port.device.identifier if self.cs_port else None,
@ -1564,7 +1610,7 @@ class ConsoleServerPortManager(models.Manager):
@python_2_unicode_compatible
class ConsoleServerPort(models.Model):
class ConsoleServerPort(ComponentModel):
"""
A physical port within a Device (typically a designated console server) which provides access to ConsolePorts.
"""
@ -1588,6 +1634,9 @@ class ConsoleServerPort(models.Model):
def get_absolute_url(self):
return self.device.get_absolute_url()
def get_component_parent(self):
return self.device
def clean(self):
# Check that the parent device's DeviceType is a console server
@ -1605,7 +1654,7 @@ class ConsoleServerPort(models.Model):
#
@python_2_unicode_compatible
class PowerPort(models.Model):
class PowerPort(ComponentModel):
"""
A physical power supply (intake) port within a Device. PowerPorts connect to PowerOutlets.
"""
@ -1641,6 +1690,9 @@ class PowerPort(models.Model):
def get_absolute_url(self):
return self.device.get_absolute_url()
def get_component_parent(self):
return self.device
def to_csv(self):
return (
self.power_outlet.device.identifier if self.power_outlet else None,
@ -1666,7 +1718,7 @@ class PowerOutletManager(models.Manager):
@python_2_unicode_compatible
class PowerOutlet(models.Model):
class PowerOutlet(ComponentModel):
"""
A physical power outlet (output) within a Device which provides power to a PowerPort.
"""
@ -1690,6 +1742,9 @@ class PowerOutlet(models.Model):
def get_absolute_url(self):
return self.device.get_absolute_url()
def get_component_parent(self):
return self.device
def clean(self):
# Check that the parent device's DeviceType is a PDU
@ -1707,7 +1762,7 @@ class PowerOutlet(models.Model):
#
@python_2_unicode_compatible
class Interface(models.Model):
class Interface(ComponentModel):
"""
A network interface within a Device or VirtualMachine. A physical Interface can connect to exactly one other
Interface via the creation of an InterfaceConnection.
@ -1797,6 +1852,9 @@ class Interface(models.Model):
def get_absolute_url(self):
return self.parent.get_absolute_url()
def get_component_parent(self):
return self.device or self.virtual_machine
def clean(self):
# Check that the parent device's DeviceType is a network device
@ -1867,6 +1925,7 @@ class Interface(models.Model):
return super(Interface, self).save(*args, **kwargs)
# TODO: Replace `parent` with get_component_parent() (from ComponentModel)
@property
def parent(self):
return self.device or self.virtual_machine
@ -1977,7 +2036,7 @@ class InterfaceConnection(models.Model):
#
@python_2_unicode_compatible
class DeviceBay(models.Model):
class DeviceBay(ComponentModel):
"""
An empty space within a Device which can house a child device
"""
@ -2008,6 +2067,9 @@ class DeviceBay(models.Model):
def get_absolute_url(self):
return self.device.get_absolute_url()
def get_component_parent(self):
return self.device
def clean(self):
# Validate that the parent Device can have DeviceBays
@ -2026,7 +2088,7 @@ class DeviceBay(models.Model):
#
@python_2_unicode_compatible
class InventoryItem(models.Model):
class InventoryItem(ComponentModel):
"""
An InventoryItem represents a serialized piece of hardware within a Device, such as a line card or power supply.
InventoryItems are used only for inventory purposes.
@ -2095,6 +2157,9 @@ class InventoryItem(models.Model):
def get_absolute_url(self):
return self.device.get_absolute_url()
def get_component_parent(self):
return self.device
def to_csv(self):
return (
self.device.name or '{' + self.device.pk + '}',