mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-08 16:48:16 -06:00
implemented a new device type for rack furniture with tests
This commit is contained in:
parent
3e9cec3e8e
commit
880d9f1713
@ -269,8 +269,8 @@ class DeviceTypeSerializer(CustomFieldModelSerializer):
|
||||
model = DeviceType
|
||||
fields = [
|
||||
'id', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'interface_ordering',
|
||||
'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments', 'custom_fields',
|
||||
'instance_count',
|
||||
'is_console_server', 'is_pdu', 'is_network_device', 'is_rack_furniture', 'subdevice_role', 'comments',
|
||||
'custom_fields', 'instance_count',
|
||||
]
|
||||
|
||||
|
||||
@ -289,7 +289,8 @@ class WritableDeviceTypeSerializer(CustomFieldModelSerializer):
|
||||
model = DeviceType
|
||||
fields = [
|
||||
'id', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'interface_ordering',
|
||||
'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments', 'custom_fields',
|
||||
'is_console_server', 'is_pdu', 'is_network_device', 'is_rack_furniture', 'subdevice_role', 'comments',
|
||||
'custom_fields',
|
||||
]
|
||||
|
||||
|
||||
|
@ -512,8 +512,11 @@ class DeviceTypeForm(BootstrapMixin, CustomFieldForm):
|
||||
|
||||
class Meta:
|
||||
model = DeviceType
|
||||
fields = ['manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'is_console_server',
|
||||
'is_pdu', 'is_network_device', 'subdevice_role', 'interface_ordering', 'comments']
|
||||
fields = [
|
||||
'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'is_console_server',
|
||||
'is_pdu', 'is_network_device', 'is_rack_furniture', 'subdevice_role', 'interface_ordering',
|
||||
'comments'
|
||||
]
|
||||
labels = {
|
||||
'interface_ordering': 'Order interfaces by',
|
||||
}
|
||||
@ -562,6 +565,9 @@ class DeviceTypeBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||
is_network_device = forms.NullBooleanField(
|
||||
required=False, widget=BulkEditNullBooleanSelect, label='Is a network device'
|
||||
)
|
||||
is_rack_furniture = forms.NullBooleanField(
|
||||
required=False, widget=BulkEditNullBooleanSelect, label='Is rack furniture'
|
||||
)
|
||||
|
||||
class Meta:
|
||||
nullable_fields = []
|
||||
@ -582,6 +588,9 @@ class DeviceTypeFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
is_network_device = forms.BooleanField(
|
||||
required=False, label='Is a network device', widget=forms.CheckboxInput(attrs={'value': 'True'})
|
||||
)
|
||||
is_rack_furniture = forms.BooleanField(
|
||||
required=False, label='Is rack furniture', widget=forms.CheckboxInput(attrs={'value': 'True'})
|
||||
)
|
||||
subdevice_role = forms.NullBooleanField(
|
||||
required=False, label='Subdevice role', widget=forms.Select(choices=(
|
||||
('', '---------'),
|
||||
|
20
netbox/dcim/migrations/0056_devicetype_is_rack_furniture.py
Normal file
20
netbox/dcim/migrations/0056_devicetype_is_rack_furniture.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.13 on 2018-07-02 03:30
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dcim', '0055_virtualchassis_ordering'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='devicetype',
|
||||
name='is_rack_furniture',
|
||||
field=models.BooleanField(default=False, help_text='This type of device is for rack furniture such as shelves or blanks', verbose_name='Is rack furniture'),
|
||||
),
|
||||
]
|
@ -548,6 +548,11 @@ class DeviceType(models.Model, CustomFieldModel):
|
||||
help_text="This type of device has power outlets")
|
||||
is_network_device = models.BooleanField(default=True, verbose_name='Is a network device',
|
||||
help_text="This type of device has network interfaces")
|
||||
is_rack_furniture = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name="Is rack furniture",
|
||||
help_text="This type of device is for rack furniture such as shelves or blanks",
|
||||
)
|
||||
subdevice_role = models.NullBooleanField(default=None, verbose_name='Parent/child status',
|
||||
choices=SUBDEVICE_ROLE_CHOICES,
|
||||
help_text="Parent devices house child devices in device bays. Select "
|
||||
@ -557,7 +562,7 @@ class DeviceType(models.Model, CustomFieldModel):
|
||||
|
||||
csv_headers = [
|
||||
'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'is_console_server',
|
||||
'is_pdu', 'is_network_device', 'subdevice_role', 'interface_ordering', 'comments',
|
||||
'is_pdu', 'is_network_device', 'is_rack_furniture', 'subdevice_role', 'interface_ordering', 'comments',
|
||||
]
|
||||
|
||||
class Meta:
|
||||
@ -590,6 +595,7 @@ class DeviceType(models.Model, CustomFieldModel):
|
||||
self.is_console_server,
|
||||
self.is_pdu,
|
||||
self.is_network_device,
|
||||
self.is_rack_furniture,
|
||||
self.get_subdevice_role_display() if self.subdevice_role else None,
|
||||
self.get_interface_ordering_display(),
|
||||
self.comments,
|
||||
@ -629,6 +635,37 @@ class DeviceType(models.Model, CustomFieldModel):
|
||||
"device before declassifying it as a network device."
|
||||
})
|
||||
|
||||
if self.is_rack_furniture and (self.is_console_server or self.is_pdu or self.is_network_device):
|
||||
raise ValidationError({
|
||||
'is_rack_furniture': "Rack furniture device types cannot simultaneously be any other device type."
|
||||
})
|
||||
|
||||
if self.is_rack_furniture and self.subdevice_role:
|
||||
raise ValidationError({
|
||||
'is_rack_furniture': "Rack furniture device types cannot be a parent or child device type."
|
||||
})
|
||||
|
||||
if self.is_rack_furniture and self.interface_templates.count():
|
||||
# Rack furniture device types cannot have management interfaces
|
||||
raise ValidationError({
|
||||
'is_rack_furniture': "Must delete all interface templates associated with this "
|
||||
"device before classifying it as rack furniture."
|
||||
})
|
||||
|
||||
if self.is_rack_furniture and self.power_port_templates.count():
|
||||
# Rack furniture device types cannot have power ports
|
||||
raise ValidationError({
|
||||
'is_rack_furniture': "Must delete all power ports associated with this "
|
||||
"device before classifying it as rack furniture."
|
||||
})
|
||||
|
||||
if self.is_rack_furniture and self.console_port_templates.count():
|
||||
# Rack furniture device types cannot have power ports
|
||||
raise ValidationError({
|
||||
'is_rack_furniture': "Must delete all console ports associated with this "
|
||||
"device before classifying it as rack furniture."
|
||||
})
|
||||
|
||||
if self.subdevice_role != SUBDEVICE_ROLE_PARENT and self.device_bay_templates.count():
|
||||
raise ValidationError({
|
||||
'subdevice_role': "Must delete all device bay templates associated with this device before "
|
||||
@ -668,6 +705,17 @@ class ConsolePortTemplate(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Validate model
|
||||
"""
|
||||
|
||||
# Rack furniture device types cannot have console ports
|
||||
if self.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have console ports."
|
||||
)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class ConsoleServerPortTemplate(models.Model):
|
||||
@ -684,6 +732,14 @@ class ConsoleServerPortTemplate(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def clean(self):
|
||||
|
||||
# Rack furniture device types cannot have console ports
|
||||
if self.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have console server ports."
|
||||
)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class PowerPortTemplate(models.Model):
|
||||
@ -700,6 +756,17 @@ class PowerPortTemplate(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Validate model
|
||||
"""
|
||||
|
||||
# Rack furniture device types cannot have power ports
|
||||
if self.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have power ports."
|
||||
)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class PowerOutletTemplate(models.Model):
|
||||
@ -716,6 +783,14 @@ class PowerOutletTemplate(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def clean(self):
|
||||
|
||||
# Rack furniture device types cannot have power outlets
|
||||
if self.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have power outlets."
|
||||
)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class InterfaceTemplate(models.Model):
|
||||
@ -736,6 +811,17 @@ class InterfaceTemplate(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Validate model
|
||||
"""
|
||||
|
||||
# Rack furniture device types cannot have interfaces
|
||||
if self.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have interfaces."
|
||||
)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class DeviceBayTemplate(models.Model):
|
||||
@ -1003,6 +1089,11 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
|
||||
pass
|
||||
|
||||
# Validate primary IP addresses
|
||||
if self.device_type.is_rack_furniture and (self.primary_ip4 or self.primary_ip6):
|
||||
# Rack furniture device types cannot have an assigned primary IP
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have an assigned primary IP address."
|
||||
)
|
||||
vc_interfaces = self.vc_interfaces.all()
|
||||
if self.primary_ip4:
|
||||
if self.primary_ip4.interface in vc_interfaces:
|
||||
@ -1033,12 +1124,24 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
|
||||
"to {}.".format(self.platform.manufacturer, self.device_type.manufacturer)
|
||||
})
|
||||
|
||||
# Rack furniture device types cannot be assigned to a cluster
|
||||
if self.cluster and self.device_type.is_rack_furniture:
|
||||
raise ValidationError({
|
||||
'cluster': "Rack furniture device types cannot be assigned to a cluster."
|
||||
})
|
||||
|
||||
# A Device can only be assigned to a Cluster in the same Site (or no Site)
|
||||
if self.cluster and self.cluster.site is not None and self.cluster.site != self.site:
|
||||
raise ValidationError({
|
||||
'cluster': "The assigned cluster belongs to a different site ({})".format(self.cluster.site)
|
||||
})
|
||||
|
||||
# Rack furniture device types cannot be assigned to a virtual chassis
|
||||
if self.virtual_chassis and self.device_type.is_rack_furniture:
|
||||
raise ValidationError({
|
||||
'virtual_chassis': "Rack furniture device types cannot be assigned to a virtual chassis."
|
||||
})
|
||||
|
||||
# Validate virtual chassis assignment
|
||||
if self.virtual_chassis and self.vc_position is None:
|
||||
raise ValidationError({
|
||||
@ -1201,6 +1304,17 @@ class ConsolePort(models.Model):
|
||||
self.get_connection_status_display(),
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Validate model
|
||||
"""
|
||||
|
||||
# Rack furniture device types cannot have console ports
|
||||
if self.device.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have console ports."
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Console server ports
|
||||
@ -1246,7 +1360,6 @@ class ConsoleServerPort(models.Model):
|
||||
device_type.manufacturer, device_type
|
||||
))
|
||||
|
||||
|
||||
#
|
||||
# Power ports
|
||||
#
|
||||
@ -1283,6 +1396,17 @@ class PowerPort(models.Model):
|
||||
self.get_connection_status_display(),
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Validate model
|
||||
"""
|
||||
|
||||
# Rack furniture device types cannot have power ports
|
||||
if self.device.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have power ports."
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Power outlets
|
||||
|
@ -326,6 +326,7 @@ class DeviceTypeTable(BaseTable):
|
||||
is_console_server = tables.BooleanColumn(verbose_name='CS')
|
||||
is_pdu = tables.BooleanColumn(verbose_name='PDU')
|
||||
is_network_device = tables.BooleanColumn(verbose_name='Net')
|
||||
is_rack_furniture = tables.BooleanColumn(verbose_name='RF')
|
||||
subdevice_role = tables.TemplateColumn(
|
||||
template_code=SUBDEVICE_ROLE_TEMPLATE,
|
||||
verbose_name='Subdevice Role'
|
||||
@ -339,7 +340,7 @@ class DeviceTypeTable(BaseTable):
|
||||
model = DeviceType
|
||||
fields = (
|
||||
'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'is_console_server', 'is_pdu',
|
||||
'is_network_device', 'subdevice_role', 'instance_count',
|
||||
'is_network_device', 'is_rack_furniture', 'subdevice_role', 'instance_count',
|
||||
)
|
||||
|
||||
|
||||
|
@ -260,3 +260,139 @@ class InterfaceTestCase(TestCase):
|
||||
list(Interface.objects.all().order_naturally()),
|
||||
[interface4, interface3, interface5, interface2, interface1, interface6]
|
||||
)
|
||||
|
||||
|
||||
class RackFurnitureDeviceTypeCase(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.manufacturer = Manufacturer.objects.create(
|
||||
name='Acme',
|
||||
slug='acme'
|
||||
)
|
||||
self.rack_furniture_type = DeviceType.objects.create(
|
||||
manufacturer=self.manufacturer,
|
||||
model='The Best Shelf 9000',
|
||||
slug='rf9000',
|
||||
is_network_device=False,
|
||||
is_rack_furniture=True,
|
||||
)
|
||||
|
||||
def test_rack_furniture_cs_port_template(self):
|
||||
cs_port_template = ConsoleServerPortTemplate(
|
||||
device_type=self.rack_furniture_type,
|
||||
name="CS Port Template"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
cs_port_template.clean()
|
||||
|
||||
def test_rack_furniture_console_port_template(self):
|
||||
console_port_template = ConsolePortTemplate(
|
||||
device_type=self.rack_furniture_type,
|
||||
name="Console Port Template"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
console_port_template.clean()
|
||||
|
||||
def test_rack_furniture_power_port_template(self):
|
||||
power_port_template = PowerPortTemplate(
|
||||
device_type=self.rack_furniture_type,
|
||||
name="Power Port Template"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
power_port_template.clean()
|
||||
|
||||
def test_rack_furniture_power_outlet_template(self):
|
||||
power_outlet_template = PowerOutletTemplate(
|
||||
device_type=self.rack_furniture_type,
|
||||
name="Power Outlet Template"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
power_outlet_template.clean()
|
||||
|
||||
def test_rack_furniture_interface_template(self):
|
||||
interface_template = InterfaceTemplate(
|
||||
device_type=self.rack_furniture_type,
|
||||
name="Interface Template"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
interface_template.clean()
|
||||
|
||||
|
||||
class RackFurnitureDeviceCase(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.manufacturer = Manufacturer.objects.create(
|
||||
name='Acme',
|
||||
slug='acme'
|
||||
)
|
||||
self.rack_furniture_type = DeviceType.objects.create(
|
||||
manufacturer=self.manufacturer,
|
||||
model='The Best Shelf 9000',
|
||||
slug='rf9000',
|
||||
is_network_device=False,
|
||||
is_rack_furniture=True,
|
||||
)
|
||||
self.site = Site.objects.create(
|
||||
name="Site 1",
|
||||
slug="site-1"
|
||||
)
|
||||
self.role = DeviceRole.objects.create(
|
||||
name='RF',
|
||||
slug='rf'
|
||||
)
|
||||
self.rack_furniture = Device.objects.create(
|
||||
name="1U Blank",
|
||||
device_type=self.rack_furniture_type,
|
||||
site=self.site,
|
||||
device_role=self.role,
|
||||
)
|
||||
|
||||
def test_rack_furniture_cs_port(self):
|
||||
cs_port = ConsoleServerPort(
|
||||
device=self.rack_furniture,
|
||||
name="CS Port"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
cs_port.clean()
|
||||
|
||||
def test_rack_furniture_console_port(self):
|
||||
console_port = ConsolePort(
|
||||
device=self.rack_furniture,
|
||||
name="Console Port"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
console_port.clean()
|
||||
|
||||
def test_rack_furniture_power_port(self):
|
||||
power_port = PowerPort(
|
||||
device=self.rack_furniture,
|
||||
name="Power Port"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
power_port.clean()
|
||||
|
||||
def test_rack_furniture_power_outlet(self):
|
||||
power_outlet = PowerOutlet(
|
||||
device=self.rack_furniture,
|
||||
name="Power Outlet"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
power_outlet.clean()
|
||||
|
||||
def test_rack_furniture_interface(self):
|
||||
interface = Interface(
|
||||
device=self.rack_furniture,
|
||||
name="Interface"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
interface.clean()
|
||||
|
@ -684,3 +684,9 @@ class Service(CreatedUpdatedModel):
|
||||
raise ValidationError("A service cannot be associated with both a device and a virtual machine.")
|
||||
if not self.device and not self.virtual_machine:
|
||||
raise ValidationError("A service must be associated with either a device or a virtual machine.")
|
||||
|
||||
# rack furniture cannot have assgined services
|
||||
if self.device and self.device.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have services."
|
||||
)
|
||||
|
@ -4,7 +4,10 @@ import netaddr
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
from ipam.models import IPAddress, Prefix, VRF
|
||||
from ipam.models import IPAddress, Prefix, VRF, Service
|
||||
from ipam.models import IP_PROTOCOL_TCP
|
||||
from dcim.models import Manufacturer, DeviceType, Device, Site, DeviceRole
|
||||
|
||||
|
||||
|
||||
class TestPrefix(TestCase):
|
||||
@ -59,3 +62,43 @@ class TestIPAddress(TestCase):
|
||||
IPAddress.objects.create(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24'))
|
||||
duplicate_ip = IPAddress(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24'))
|
||||
self.assertRaises(ValidationError, duplicate_ip.clean)
|
||||
|
||||
|
||||
class ServiceCase(TestCase):
|
||||
|
||||
def test_rack_funiture_no_assign(self):
|
||||
manufacturer = Manufacturer.objects.create(
|
||||
name='Acme',
|
||||
slug='acme'
|
||||
)
|
||||
rack_furniture_type = DeviceType.objects.create(
|
||||
manufacturer=manufacturer,
|
||||
model='The Best Shelf 9000',
|
||||
slug='rf9000',
|
||||
is_network_device=False,
|
||||
is_rack_furniture=True,
|
||||
)
|
||||
site = Site.objects.create(
|
||||
name="Site 1",
|
||||
slug="site-1"
|
||||
)
|
||||
role = DeviceRole.objects.create(
|
||||
name='RF',
|
||||
slug='rf'
|
||||
)
|
||||
rack_furniture = Device.objects.create(
|
||||
name="1U Blank",
|
||||
device_type=rack_furniture_type,
|
||||
site=site,
|
||||
device_role=role,
|
||||
)
|
||||
|
||||
s = Service(
|
||||
name="Service",
|
||||
protocol=IP_PROTOCOL_TCP,
|
||||
port=80,
|
||||
device=rack_furniture
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
s.clean()
|
||||
|
@ -304,6 +304,17 @@ class Secret(CreatedUpdatedModel):
|
||||
def get_absolute_url(self):
|
||||
return reverse('secrets:secret', args=[self.pk])
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Validate model
|
||||
"""
|
||||
|
||||
# rack furniture cannot have assigned secrets
|
||||
if self.device.device_type.is_rack_furniture:
|
||||
raise ValidationError(
|
||||
"Rack furniture device types cannot have secrets."
|
||||
)
|
||||
|
||||
def _pad(self, s):
|
||||
"""
|
||||
Prepend the length of the plaintext (2B) and pad with garbage to a multiple of 16B (minimum of 64B).
|
||||
|
@ -8,6 +8,7 @@ from django.test import TestCase
|
||||
|
||||
from secrets.hashers import SecretValidationHasher
|
||||
from secrets.models import UserKey, Secret, encrypt_master_key, decrypt_master_key, generate_random_key
|
||||
from dcim.models import Manufacturer, DeviceType, Device, Site, DeviceRole
|
||||
|
||||
|
||||
class UserKeyTestCase(TestCase):
|
||||
@ -131,3 +132,39 @@ class SecretTestCase(TestCase):
|
||||
self.assertEqual(duplicate_ivs, [], "One or more duplicate IVs found!")
|
||||
duplicate_ciphertexts = [i for i, x in enumerate(ciphertexts) if ciphertexts.count(x) > 1]
|
||||
self.assertEqual(duplicate_ciphertexts, [], "One or more duplicate ciphertexts (first blocks) found!")
|
||||
|
||||
def test_03_rack_funiture_no_assign(self):
|
||||
manufacturer = Manufacturer.objects.create(
|
||||
name='Acme',
|
||||
slug='acme'
|
||||
)
|
||||
rack_furniture_type = DeviceType.objects.create(
|
||||
manufacturer=manufacturer,
|
||||
model='The Best Shelf 9000',
|
||||
slug='rf9000',
|
||||
is_network_device=False,
|
||||
is_rack_furniture=True,
|
||||
)
|
||||
site = Site.objects.create(
|
||||
name="Site 1",
|
||||
slug="site-1"
|
||||
)
|
||||
role = DeviceRole.objects.create(
|
||||
name='RF',
|
||||
slug='rf'
|
||||
)
|
||||
rack_furniture = Device.objects.create(
|
||||
name="1U Blank",
|
||||
device_type=rack_furniture_type,
|
||||
site=site,
|
||||
device_role=role,
|
||||
)
|
||||
|
||||
plaintext = "FooBar123"
|
||||
secret_key = generate_random_key()
|
||||
s = Secret(plaintext=plaintext)
|
||||
s.encrypt(secret_key)
|
||||
s.device = rack_furniture
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
s.clean()
|
||||
|
@ -165,6 +165,7 @@
|
||||
<span class="label label-{{ device.get_status_class }}">{{ device.get_status_display }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% if not device.device_type.is_rack_furniture %}
|
||||
<tr>
|
||||
<td>Primary IPv4</td>
|
||||
<td>
|
||||
@ -195,6 +196,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if device.cluster %}
|
||||
<tr>
|
||||
<td>Cluster</td>
|
||||
@ -226,6 +228,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{% if not device.device_type.is_rack_furniture %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Console / Power</strong>
|
||||
@ -327,6 +330,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Images</strong>
|
||||
|
@ -56,7 +56,7 @@
|
||||
<div class="panel-body">
|
||||
{% render_field form.status %}
|
||||
{% render_field form.platform %}
|
||||
{% if obj.pk %}
|
||||
{% if obj.pk and not obj.device_type.is_rack_furniture %}
|
||||
{% render_field form.primary_ip4 %}
|
||||
{% render_field form.primary_ip6 %}
|
||||
{% endif %}
|
||||
|
@ -69,10 +69,12 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if not devicetype.is_rack_furniture %}
|
||||
<tr>
|
||||
<td>Interface Ordering</td>
|
||||
<td>{{ devicetype.get_interface_ordering_display }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td>Instances</td>
|
||||
<td><a href="{% url 'dcim:device_list' %}?device_type_id={{ devicetype.pk }}">{{ devicetype.instances.count }}</a></td>
|
||||
@ -123,6 +125,19 @@
|
||||
<small class="text-muted">This device {% if devicetype.is_network_device %}has{% else %}does not have{% endif %} network interfaces</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-right">
|
||||
{% if devicetype.is_rack_furniture %}
|
||||
<i class="glyphicon glyphicon-ok text-success" title="Yes"></i>
|
||||
{% else %}
|
||||
<i class="glyphicon glyphicon-remove text-danger" title="No"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<strong>Rack Furniture</strong><br />
|
||||
<small class="text-muted">This device {% if devicetype.is_rack_furniture %}is{% else %}is not{% endif %} rack furniture</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-right">
|
||||
{% if devicetype.subdevice_role == True %}
|
||||
@ -163,6 +178,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
{% if not devicetype.is_rack_furniture %}
|
||||
{% include 'dcim/inc/devicetype_component_table.html' with table=consoleport_table title='Console Ports' add_url='dcim:devicetype_add_consoleport' delete_url='dcim:devicetype_delete_consoleport' %}
|
||||
{% include 'dcim/inc/devicetype_component_table.html' with table=powerport_table title='Power Ports' add_url='dcim:devicetype_add_powerport' delete_url='dcim:devicetype_delete_powerport' %}
|
||||
{% if devicetype.is_parent_device or devicebay_table.rows %}
|
||||
@ -177,6 +193,7 @@
|
||||
{% if devicetype.is_pdu or poweroutlet_table.rows %}
|
||||
{% include 'dcim/inc/devicetype_component_table.html' with table=poweroutlet_table title='Power Outlets' add_url='dcim:devicetype_add_poweroutlet' delete_url='dcim:devicetype_delete_poweroutlet' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -20,6 +20,7 @@
|
||||
{% render_field form.is_console_server %}
|
||||
{% render_field form.is_pdu %}
|
||||
{% render_field form.is_network_device %}
|
||||
{% render_field form.is_rack_furniture %}
|
||||
{% render_field form.subdevice_role %}
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user