mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
348 lines
13 KiB
Python
348 lines
13 KiB
Python
from django.test import TestCase
|
|
|
|
from dcim.constants import *
|
|
from dcim.models import *
|
|
|
|
|
|
class RackTestCase(TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
self.site1 = Site.objects.create(
|
|
name='TestSite1',
|
|
slug='test-site-1'
|
|
)
|
|
self.site2 = Site.objects.create(
|
|
name='TestSite2',
|
|
slug='test-site-2'
|
|
)
|
|
self.group1 = RackGroup.objects.create(
|
|
name='TestGroup1',
|
|
slug='test-group-1',
|
|
site=self.site1
|
|
)
|
|
self.group2 = RackGroup.objects.create(
|
|
name='TestGroup2',
|
|
slug='test-group-2',
|
|
site=self.site2
|
|
)
|
|
self.rack = Rack.objects.create(
|
|
name='TestRack1',
|
|
facility_id='A101',
|
|
site=self.site1,
|
|
group=self.group1,
|
|
u_height=42
|
|
)
|
|
self.manufacturer = Manufacturer.objects.create(
|
|
name='Acme',
|
|
slug='acme'
|
|
)
|
|
|
|
self.device_type = {
|
|
'ff2048': DeviceType.objects.create(
|
|
manufacturer=self.manufacturer,
|
|
model='FrameForwarder 2048',
|
|
slug='ff2048'
|
|
),
|
|
'cc5000': DeviceType.objects.create(
|
|
manufacturer=self.manufacturer,
|
|
model='CurrentCatapult 5000',
|
|
slug='cc5000',
|
|
u_height=0
|
|
),
|
|
}
|
|
self.role = {
|
|
'Server': DeviceRole.objects.create(
|
|
name='Server',
|
|
slug='server',
|
|
),
|
|
'Switch': DeviceRole.objects.create(
|
|
name='Switch',
|
|
slug='switch',
|
|
),
|
|
'Console Server': DeviceRole.objects.create(
|
|
name='Console Server',
|
|
slug='console-server',
|
|
),
|
|
'PDU': DeviceRole.objects.create(
|
|
name='PDU',
|
|
slug='pdu',
|
|
),
|
|
|
|
}
|
|
|
|
def test_rack_device_outside_height(self):
|
|
|
|
rack1 = Rack(
|
|
name='TestRack2',
|
|
facility_id='A102',
|
|
site=self.site1,
|
|
u_height=42
|
|
)
|
|
rack1.save()
|
|
|
|
device1 = Device(
|
|
name='TestSwitch1',
|
|
device_type=DeviceType.objects.get(manufacturer__slug='acme', slug='ff2048'),
|
|
device_role=DeviceRole.objects.get(slug='switch'),
|
|
site=self.site1,
|
|
rack=rack1,
|
|
position=43,
|
|
face=RACK_FACE_FRONT,
|
|
)
|
|
device1.save()
|
|
|
|
with self.assertRaises(ValidationError):
|
|
rack1.clean()
|
|
|
|
def test_rack_group_site(self):
|
|
|
|
rack_invalid_group = Rack(
|
|
name='TestRack2',
|
|
facility_id='A102',
|
|
site=self.site1,
|
|
u_height=42,
|
|
group=self.group2
|
|
)
|
|
rack_invalid_group.save()
|
|
|
|
with self.assertRaises(ValidationError):
|
|
rack_invalid_group.clean()
|
|
|
|
def test_mount_single_device(self):
|
|
|
|
device1 = Device(
|
|
name='TestSwitch1',
|
|
device_type=DeviceType.objects.get(manufacturer__slug='acme', slug='ff2048'),
|
|
device_role=DeviceRole.objects.get(slug='switch'),
|
|
site=self.site1,
|
|
rack=self.rack,
|
|
position=10,
|
|
face=RACK_FACE_REAR,
|
|
)
|
|
device1.save()
|
|
|
|
# Validate rack height
|
|
self.assertEqual(list(self.rack.units), list(reversed(range(1, 43))))
|
|
|
|
# Validate inventory (front face)
|
|
rack1_inventory_front = self.rack.get_front_elevation()
|
|
self.assertEqual(rack1_inventory_front[-10]['device'], device1)
|
|
del(rack1_inventory_front[-10])
|
|
for u in rack1_inventory_front:
|
|
self.assertIsNone(u['device'])
|
|
|
|
# Validate inventory (rear face)
|
|
rack1_inventory_rear = self.rack.get_rear_elevation()
|
|
self.assertEqual(rack1_inventory_rear[-10]['device'], device1)
|
|
del(rack1_inventory_rear[-10])
|
|
for u in rack1_inventory_rear:
|
|
self.assertIsNone(u['device'])
|
|
|
|
def test_mount_zero_ru(self):
|
|
pdu = Device.objects.create(
|
|
name='TestPDU',
|
|
device_role=self.role.get('PDU'),
|
|
device_type=self.device_type.get('cc5000'),
|
|
site=self.site1,
|
|
rack=self.rack,
|
|
position=None,
|
|
face=None,
|
|
)
|
|
self.assertTrue(pdu)
|
|
|
|
|
|
class CableTestCase(TestCase):
|
|
|
|
def setUp(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')
|
|
devicetype = DeviceType.objects.create(
|
|
manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
|
|
)
|
|
devicerole = DeviceRole.objects.create(
|
|
name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
|
|
)
|
|
self.device1 = Device.objects.create(
|
|
device_type=devicetype, device_role=devicerole, name='TestDevice1', site=site
|
|
)
|
|
self.device2 = Device.objects.create(
|
|
device_type=devicetype, device_role=devicerole, name='TestDevice2', site=site
|
|
)
|
|
self.interface1 = Interface.objects.create(device=self.device1, name='eth0')
|
|
self.interface2 = Interface.objects.create(device=self.device2, name='eth0')
|
|
self.cable = Cable(termination_a=self.interface1, termination_b=self.interface2)
|
|
self.cable.save()
|
|
|
|
self.power_port1 = PowerPort.objects.create(device=self.device2, name='psu1')
|
|
self.patch_pannel = Device.objects.create(
|
|
device_type=devicetype, device_role=devicerole, name='TestPatchPannel', site=site
|
|
)
|
|
self.rear_port = RearPort.objects.create(device=self.patch_pannel, name='R1', type=1000)
|
|
self.front_port = FrontPort.objects.create(
|
|
device=self.patch_pannel, name='F1', type=1000, rear_port=self.rear_port
|
|
)
|
|
|
|
def test_cable_creation(self):
|
|
"""
|
|
When a new Cable is created, it must be cached on either termination point.
|
|
"""
|
|
interface1 = Interface.objects.get(pk=self.interface1.pk)
|
|
self.assertEqual(self.cable.termination_a, interface1)
|
|
interface2 = Interface.objects.get(pk=self.interface2.pk)
|
|
self.assertEqual(self.cable.termination_b, interface2)
|
|
|
|
def test_cable_deletion(self):
|
|
"""
|
|
When a Cable is deleted, the `cable` field on its termination points must be nullified.
|
|
"""
|
|
self.cable.delete()
|
|
interface1 = Interface.objects.get(pk=self.interface1.pk)
|
|
self.assertIsNone(interface1.cable)
|
|
interface2 = Interface.objects.get(pk=self.interface2.pk)
|
|
self.assertIsNone(interface2.cable)
|
|
|
|
def test_cabletermination_deletion(self):
|
|
"""
|
|
When a CableTermination object is deleted, its attached Cable (if any) must also be deleted.
|
|
"""
|
|
self.interface1.delete()
|
|
cable = Cable.objects.filter(pk=self.cable.pk).first()
|
|
self.assertIsNone(cable)
|
|
|
|
def test_cable_validates_compatibale_types(self):
|
|
"""
|
|
The clean method should have a check to ensure only compatiable port types can be connected by a cable
|
|
"""
|
|
# An interface cannot be connected to a power port
|
|
cable = Cable(termination_a=self.interface1, termination_b=self.power_port1)
|
|
with self.assertRaises(ValidationError):
|
|
cable.clean()
|
|
|
|
def test_cable_cannot_have_the_same_terminination_on_both_ends(self):
|
|
"""
|
|
A cable cannot be made with the same A and B side terminations
|
|
"""
|
|
cable = Cable(termination_a=self.interface1, termination_b=self.interface1)
|
|
with self.assertRaises(ValidationError):
|
|
cable.clean()
|
|
|
|
def test_cable_front_port_cannot_connect_to_corresponding_rear_port(self):
|
|
"""
|
|
A cable cannot connect a front port to its sorresponding rear port
|
|
"""
|
|
cable = Cable(termination_a=self.front_port, termination_b=self.rear_port)
|
|
with self.assertRaises(ValidationError):
|
|
cable.clean()
|
|
|
|
def test_cable_cannot_be_connected_to_an_existing_connection(self):
|
|
"""
|
|
Either side of a cable cannot be terminated when that side aready has a connection
|
|
"""
|
|
# Try to create a cable with the same interface terminations
|
|
cable = Cable(termination_a=self.interface2, termination_b=self.interface1)
|
|
with self.assertRaises(ValidationError):
|
|
cable.clean()
|
|
|
|
def test_cable_cannot_connect_to_a_virtual_inteface(self):
|
|
"""
|
|
A cable connection cannot include a virtual interface
|
|
"""
|
|
virtual_interface = Interface(device=self.device1, name="V1", form_factor=0)
|
|
cable = Cable(termination_a=self.interface2, termination_b=virtual_interface)
|
|
with self.assertRaises(ValidationError):
|
|
cable.clean()
|
|
|
|
|
|
class CablePathTestCase(TestCase):
|
|
|
|
def setUp(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')
|
|
devicetype = DeviceType.objects.create(
|
|
manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
|
|
)
|
|
devicerole = DeviceRole.objects.create(
|
|
name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
|
|
)
|
|
self.device1 = Device.objects.create(
|
|
device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
|
|
)
|
|
self.device2 = Device.objects.create(
|
|
device_type=devicetype, device_role=devicerole, name='Test Device 2', site=site
|
|
)
|
|
self.interface1 = Interface.objects.create(device=self.device1, name='eth0')
|
|
self.interface2 = Interface.objects.create(device=self.device2, name='eth0')
|
|
self.panel1 = Device.objects.create(
|
|
device_type=devicetype, device_role=devicerole, name='Test Panel 1', site=site
|
|
)
|
|
self.panel2 = Device.objects.create(
|
|
device_type=devicetype, device_role=devicerole, name='Test Panel 2', site=site
|
|
)
|
|
self.rear_port1 = RearPort.objects.create(
|
|
device=self.panel1, name='Rear Port 1', type=PORT_TYPE_8P8C
|
|
)
|
|
self.front_port1 = FrontPort.objects.create(
|
|
device=self.panel1, name='Front Port 1', type=PORT_TYPE_8P8C, rear_port=self.rear_port1
|
|
)
|
|
self.rear_port2 = RearPort.objects.create(
|
|
device=self.panel2, name='Rear Port 2', type=PORT_TYPE_8P8C
|
|
)
|
|
self.front_port2 = FrontPort.objects.create(
|
|
device=self.panel2, name='Front Port 2', type=PORT_TYPE_8P8C, rear_port=self.rear_port2
|
|
)
|
|
|
|
def test_path_completion(self):
|
|
|
|
# First segment
|
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1)
|
|
cable1.save()
|
|
interface1 = Interface.objects.get(pk=self.interface1.pk)
|
|
self.assertIsNone(interface1.connected_endpoint)
|
|
self.assertIsNone(interface1.connection_status)
|
|
|
|
# Second segment
|
|
cable2 = Cable(termination_a=self.rear_port1, termination_b=self.rear_port2)
|
|
cable2.save()
|
|
interface1 = Interface.objects.get(pk=self.interface1.pk)
|
|
self.assertIsNone(interface1.connected_endpoint)
|
|
self.assertIsNone(interface1.connection_status)
|
|
|
|
# Third segment
|
|
cable3 = Cable(termination_a=self.front_port2, termination_b=self.interface2, status=CONNECTION_STATUS_PLANNED)
|
|
cable3.save()
|
|
interface1 = Interface.objects.get(pk=self.interface1.pk)
|
|
self.assertEqual(interface1.connected_endpoint, self.interface2)
|
|
self.assertEqual(interface1.connection_status, CONNECTION_STATUS_PLANNED)
|
|
|
|
# Switch third segment from planned to connected
|
|
cable3.status = CONNECTION_STATUS_CONNECTED
|
|
cable3.save()
|
|
interface1 = Interface.objects.get(pk=self.interface1.pk)
|
|
self.assertEqual(interface1.connected_endpoint, self.interface2)
|
|
self.assertEqual(interface1.connection_status, CONNECTION_STATUS_CONNECTED)
|
|
|
|
def test_path_teardown(self):
|
|
|
|
# Build the path
|
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1)
|
|
cable1.save()
|
|
cable2 = Cable(termination_a=self.rear_port1, termination_b=self.rear_port2)
|
|
cable2.save()
|
|
cable3 = Cable(termination_a=self.front_port2, termination_b=self.interface2)
|
|
cable3.save()
|
|
interface1 = Interface.objects.get(pk=self.interface1.pk)
|
|
self.assertEqual(interface1.connected_endpoint, self.interface2)
|
|
self.assertEqual(interface1.connection_status, CONNECTION_STATUS_CONNECTED)
|
|
|
|
# Remove a cable
|
|
cable2.delete()
|
|
interface1 = Interface.objects.get(pk=self.interface1.pk)
|
|
self.assertIsNone(interface1.connected_endpoint)
|
|
self.assertIsNone(interface1.connection_status)
|
|
interface2 = Interface.objects.get(pk=self.interface2.pk)
|
|
self.assertIsNone(interface2.connected_endpoint)
|
|
self.assertIsNone(interface2.connection_status)
|