mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Merge pull request #3412 from netbox-community/3405-bugfix
Move device component creation logic out of Device model
This commit is contained in:
commit
f18c3be745
@ -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)
|
v2.6.2 (2019-08-02)
|
||||||
|
|
||||||
## Enhancements
|
## Enhancements
|
||||||
|
@ -31,6 +31,12 @@ class ComponentTemplateModel(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
def instantiate(self, device):
|
||||||
|
"""
|
||||||
|
Instantiate a new component on the specified Device.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
def log_change(self, user, request_id, action):
|
def log_change(self, user, request_id, action):
|
||||||
"""
|
"""
|
||||||
Log an ObjectChange including the parent DeviceType.
|
Log an ObjectChange including the parent DeviceType.
|
||||||
@ -1010,6 +1016,12 @@ class ConsolePortTemplate(ComponentTemplateModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def instantiate(self, device):
|
||||||
|
return ConsolePort(
|
||||||
|
device=device,
|
||||||
|
name=self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ConsoleServerPortTemplate(ComponentTemplateModel):
|
class ConsoleServerPortTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
@ -1033,6 +1045,12 @@ class ConsoleServerPortTemplate(ComponentTemplateModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def instantiate(self, device):
|
||||||
|
return ConsoleServerPort(
|
||||||
|
device=device,
|
||||||
|
name=self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PowerPortTemplate(ComponentTemplateModel):
|
class PowerPortTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
@ -1068,6 +1086,14 @@ class PowerPortTemplate(ComponentTemplateModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
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):
|
class PowerOutletTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
@ -1112,6 +1138,18 @@ class PowerOutletTemplate(ComponentTemplateModel):
|
|||||||
"Parent power port ({}) must belong to the same device type".format(self.power_port)
|
"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):
|
class InterfaceTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
@ -1159,6 +1197,14 @@ class InterfaceTemplate(ComponentTemplateModel):
|
|||||||
"""
|
"""
|
||||||
self.type = value
|
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):
|
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):
|
class RearPortTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
@ -1243,6 +1302,14 @@ class RearPortTemplate(ComponentTemplateModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def instantiate(self, device):
|
||||||
|
return RearPort(
|
||||||
|
device=device,
|
||||||
|
name=self.name,
|
||||||
|
type=self.type,
|
||||||
|
positions=self.positions
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DeviceBayTemplate(ComponentTemplateModel):
|
class DeviceBayTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
@ -1266,6 +1333,12 @@ class DeviceBayTemplate(ComponentTemplateModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def instantiate(self, device):
|
||||||
|
return DeviceBay(
|
||||||
|
device=device,
|
||||||
|
name=self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Devices
|
# 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 this is a new Device, instantiate all of the related components per the DeviceType definition
|
||||||
if is_new:
|
if is_new:
|
||||||
ConsolePort.objects.bulk_create(
|
ConsolePort.objects.bulk_create(
|
||||||
[ConsolePort(device=self, name=template.name) for template in
|
[x.instantiate(self) for x in self.device_type.consoleport_templates.all()]
|
||||||
self.device_type.consoleport_templates.all()]
|
|
||||||
)
|
)
|
||||||
ConsoleServerPort.objects.bulk_create(
|
ConsoleServerPort.objects.bulk_create(
|
||||||
[ConsoleServerPort(device=self, name=template.name) for template in
|
[x.instantiate(self) for x in self.device_type.consoleserverport_templates.all()]
|
||||||
self.device_type.consoleserverport_templates.all()]
|
|
||||||
)
|
)
|
||||||
PowerPort.objects.bulk_create(
|
PowerPort.objects.bulk_create(
|
||||||
[PowerPort(device=self, name=template.name) for template in
|
[x.instantiate(self) for x in self.device_type.powerport_templates.all()]
|
||||||
self.device_type.powerport_templates.all()]
|
|
||||||
)
|
)
|
||||||
PowerOutlet.objects.bulk_create(
|
PowerOutlet.objects.bulk_create(
|
||||||
[PowerOutlet(device=self, name=template.name) for template in
|
[x.instantiate(self) for x in self.device_type.poweroutlet_templates.all()]
|
||||||
self.device_type.poweroutlet_templates.all()]
|
|
||||||
)
|
)
|
||||||
Interface.objects.bulk_create(
|
Interface.objects.bulk_create(
|
||||||
[Interface(device=self, name=template.name, type=template.type,
|
[x.instantiate(self) for x in self.device_type.interface_templates.all()]
|
||||||
mgmt_only=template.mgmt_only) for template 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.objects.bulk_create(
|
||||||
[DeviceBay(device=self, name=template.name) for template in
|
[x.instantiate(self) for x in self.device_type.device_bay_templates.all()]
|
||||||
self.device_type.device_bay_templates.all()]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Update Site and Rack assignment for any child Devices
|
# Update Site and Rack assignment for any child Devices
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from dcim.constants import *
|
|
||||||
from dcim.models import *
|
from dcim.models import *
|
||||||
|
|
||||||
|
|
||||||
@ -152,6 +151,137 @@ class RackTestCase(TestCase):
|
|||||||
self.assertTrue(pdu)
|
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):
|
class CableTestCase(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user