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

Merge pull request #3412 from netbox-community/3405-bugfix

Move device component creation logic out of Device model
This commit is contained in:
Jeremy Stretch
2019-08-08 21:16:11 -04:00
committed by GitHub
3 changed files with 224 additions and 30 deletions

View File

@ -1,3 +1,11 @@
v2.6.3 (FUTURE)
## Bug Fixes
* [#3405](https://github.com/netbox-community/netbox/issues/3405) - Fix population of power port/outlet details on device creation
---
v2.6.2 (2019-08-02)
## Enhancements

View File

@ -31,6 +31,12 @@ class ComponentTemplateModel(models.Model):
class Meta:
abstract = True
def instantiate(self, device):
"""
Instantiate a new component on the specified Device.
"""
raise NotImplementedError()
def log_change(self, user, request_id, action):
"""
Log an ObjectChange including the parent DeviceType.
@ -1010,6 +1016,12 @@ class ConsolePortTemplate(ComponentTemplateModel):
def __str__(self):
return self.name
def instantiate(self, device):
return ConsolePort(
device=device,
name=self.name
)
class ConsoleServerPortTemplate(ComponentTemplateModel):
"""
@ -1033,6 +1045,12 @@ class ConsoleServerPortTemplate(ComponentTemplateModel):
def __str__(self):
return self.name
def instantiate(self, device):
return ConsoleServerPort(
device=device,
name=self.name
)
class PowerPortTemplate(ComponentTemplateModel):
"""
@ -1068,6 +1086,14 @@ class PowerPortTemplate(ComponentTemplateModel):
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):
"""
@ -1112,6 +1138,18 @@ class PowerOutletTemplate(ComponentTemplateModel):
"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):
"""
@ -1159,6 +1197,14 @@ class InterfaceTemplate(ComponentTemplateModel):
"""
self.type = value
def instantiate(self, device):
return Interface(
device=device,
name=self.name,
type=self.type,
mgmt_only=self.mgmt_only
)
class FrontPortTemplate(ComponentTemplateModel):
"""
@ -1213,6 +1259,19 @@ class FrontPortTemplate(ComponentTemplateModel):
)
)
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):
"""
@ -1243,6 +1302,14 @@ class RearPortTemplate(ComponentTemplateModel):
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):
"""
@ -1266,6 +1333,12 @@ class DeviceBayTemplate(ComponentTemplateModel):
def __str__(self):
return self.name
def instantiate(self, device):
return DeviceBay(
device=device,
name=self.name
)
#
# Devices
@ -1640,45 +1713,28 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
# If this is a new Device, instantiate all of the related components per the DeviceType definition
if is_new:
ConsolePort.objects.bulk_create(
[ConsolePort(device=self, name=template.name) for template in
self.device_type.consoleport_templates.all()]
[x.instantiate(self) for x in self.device_type.consoleport_templates.all()]
)
ConsoleServerPort.objects.bulk_create(
[ConsoleServerPort(device=self, name=template.name) for template in
self.device_type.consoleserverport_templates.all()]
[x.instantiate(self) for x in self.device_type.consoleserverport_templates.all()]
)
PowerPort.objects.bulk_create(
[PowerPort(device=self, name=template.name) for template in
self.device_type.powerport_templates.all()]
[x.instantiate(self) for x in self.device_type.powerport_templates.all()]
)
PowerOutlet.objects.bulk_create(
[PowerOutlet(device=self, name=template.name) for template in
self.device_type.poweroutlet_templates.all()]
[x.instantiate(self) for x in self.device_type.poweroutlet_templates.all()]
)
Interface.objects.bulk_create(
[Interface(device=self, name=template.name, type=template.type,
mgmt_only=template.mgmt_only) for template in self.device_type.interface_templates.all()]
[x.instantiate(self) for x in self.device_type.interface_templates.all()]
)
RearPort.objects.bulk_create(
[x.instantiate(self) for x in self.device_type.rearport_templates.all()]
)
FrontPort.objects.bulk_create(
[x.instantiate(self) for x in self.device_type.frontport_templates.all()]
)
RearPort.objects.bulk_create([
RearPort(
device=self,
name=template.name,
type=template.type,
positions=template.positions
) for template in self.device_type.rearport_templates.all()
])
FrontPort.objects.bulk_create([
FrontPort(
device=self,
name=template.name,
type=template.type,
rear_port=RearPort.objects.get(device=self, name=template.rear_port.name),
rear_port_position=template.rear_port_position,
) for template in self.device_type.frontport_templates.all()
])
DeviceBay.objects.bulk_create(
[DeviceBay(device=self, name=template.name) for template in
self.device_type.device_bay_templates.all()]
[x.instantiate(self) for x in self.device_type.device_bay_templates.all()]
)
# Update Site and Rack assignment for any child Devices

View File

@ -1,6 +1,5 @@
from django.test import TestCase
from dcim.constants import *
from dcim.models import *
@ -152,6 +151,137 @@ class RackTestCase(TestCase):
self.assertTrue(pdu)
class DeviceTestCase(TestCase):
def setUp(self):
self.site = Site.objects.create(name='Test Site 1', slug='test-site-1')
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
self.device_type = DeviceType.objects.create(
manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
)
self.device_role = DeviceRole.objects.create(
name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
)
# Create DeviceType components
ConsolePortTemplate(
device_type=self.device_type,
name='Console Port 1'
).save()
ConsoleServerPortTemplate(
device_type=self.device_type,
name='Console Server Port 1'
).save()
ppt = PowerPortTemplate(
device_type=self.device_type,
name='Power Port 1',
maximum_draw=1000,
allocated_draw=500
)
ppt.save()
PowerOutletTemplate(
device_type=self.device_type,
name='Power Outlet 1',
power_port=ppt,
feed_leg=POWERFEED_LEG_A
).save()
InterfaceTemplate(
device_type=self.device_type,
name='Interface 1',
type=IFACE_TYPE_1GE_FIXED,
mgmt_only=True
).save()
rpt = RearPortTemplate(
device_type=self.device_type,
name='Rear Port 1',
type=PORT_TYPE_8P8C,
positions=8
)
rpt.save()
FrontPortTemplate(
device_type=self.device_type,
name='Front Port 1',
type=PORT_TYPE_8P8C,
rear_port=rpt,
rear_port_position=2
).save()
DeviceBayTemplate(
device_type=self.device_type,
name='Device Bay 1'
).save()
def test_device_creation(self):
"""
Ensure that all Device components are copied automatically from the DeviceType.
"""
d = Device(
site=self.site,
device_type=self.device_type,
device_role=self.device_role,
name='Test Device 1'
)
d.save()
ConsolePort.objects.get(
device=d,
name='Console Port 1'
)
ConsoleServerPort.objects.get(
device=d,
name='Console Server Port 1'
)
pp = PowerPort.objects.get(
device=d,
name='Power Port 1',
maximum_draw=1000,
allocated_draw=500
)
PowerOutlet.objects.get(
device=d,
name='Power Outlet 1',
power_port=pp,
feed_leg=POWERFEED_LEG_A
)
Interface.objects.get(
device=d,
name='Interface 1',
type=IFACE_TYPE_1GE_FIXED,
mgmt_only=True
)
rp = RearPort.objects.get(
device=d,
name='Rear Port 1',
type=PORT_TYPE_8P8C,
positions=8
)
FrontPort.objects.get(
device=d,
name='Front Port 1',
type=PORT_TYPE_8P8C,
rear_port=rp,
rear_port_position=2
)
DeviceBay.objects.get(
device=d,
name='Device Bay 1'
)
class CableTestCase(TestCase):
def setUp(self):