| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- from django.core.exceptions import ValidationError
- from django.test import TestCase
- from circuits.models import *
- from dcim.choices import *
- from dcim.models import *
- from tenancy.models import Tenant
- class LocationTestCase(TestCase):
- def test_change_location_site(self):
- """
- Check that all child Locations and Racks get updated when a Location is moved to a new Site. Topology:
- Site A
- - Location A1
- - Location A2
- - Rack 2
- - Device 2
- - Rack 1
- - Device 1
- """
- manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
- device_type = DeviceType.objects.create(
- manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
- )
- device_role = DeviceRole.objects.create(
- name='Device Role 1', slug='device-role-1', color='ff0000'
- )
- site_a = Site.objects.create(name='Site A', slug='site-a')
- site_b = Site.objects.create(name='Site B', slug='site-b')
- location_a1 = Location(site=site_a, name='Location A1', slug='location-a1')
- location_a1.save()
- location_a2 = Location(site=site_a, parent=location_a1, name='Location A2', slug='location-a2')
- location_a2.save()
- rack1 = Rack.objects.create(site=site_a, location=location_a1, name='Rack 1')
- rack2 = Rack.objects.create(site=site_a, location=location_a2, name='Rack 2')
- device1 = Device.objects.create(
- site=site_a,
- location=location_a1,
- name='Device 1',
- device_type=device_type,
- device_role=device_role
- )
- device2 = Device.objects.create(
- site=site_a,
- location=location_a2,
- name='Device 2',
- device_type=device_type,
- device_role=device_role
- )
- powerpanel1 = PowerPanel.objects.create(site=site_a, location=location_a1, name='Power Panel 1')
- # Move Location A1 to Site B
- location_a1.site = site_b
- location_a1.save()
- # Check that all objects within Location A1 now belong to Site B
- self.assertEqual(Location.objects.get(pk=location_a1.pk).site, site_b)
- self.assertEqual(Location.objects.get(pk=location_a2.pk).site, site_b)
- self.assertEqual(Rack.objects.get(pk=rack1.pk).site, site_b)
- self.assertEqual(Rack.objects.get(pk=rack2.pk).site, site_b)
- self.assertEqual(Device.objects.get(pk=device1.pk).site, site_b)
- self.assertEqual(Device.objects.get(pk=device2.pk).site, site_b)
- self.assertEqual(PowerPanel.objects.get(pk=powerpanel1.pk).site, site_b)
- 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.location1 = Location.objects.create(
- name='TestGroup1',
- slug='test-group-1',
- site=self.site1
- )
- self.location2 = Location.objects.create(
- name='TestGroup2',
- slug='test-group-2',
- site=self.site2
- )
- self.rack = Rack.objects.create(
- name='TestRack1',
- facility_id='A101',
- site=self.site1,
- location=self.location1,
- 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=DeviceFaceChoices.FACE_FRONT,
- )
- device1.save()
- with self.assertRaises(ValidationError):
- rack1.clean()
- def test_location_site(self):
- rack_invalid_location = Rack(
- name='TestRack2',
- facility_id='A102',
- site=self.site1,
- u_height=42,
- location=self.location2
- )
- rack_invalid_location.save()
- with self.assertRaises(ValidationError):
- rack_invalid_location.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=DeviceFaceChoices.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_rack_units(face=DeviceFaceChoices.FACE_FRONT)
- 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_rack_units(face=DeviceFaceChoices.FACE_REAR)
- 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='',
- )
- self.assertTrue(pdu)
- def test_change_rack_site(self):
- """
- Check that child Devices get updated when a Rack is moved to a new Site.
- """
- site_a = Site.objects.create(name='Site A', slug='site-a')
- site_b = Site.objects.create(name='Site B', slug='site-b')
- manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
- device_type = DeviceType.objects.create(
- manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
- )
- device_role = DeviceRole.objects.create(
- name='Device Role 1', slug='device-role-1', color='ff0000'
- )
- # Create Rack1 in Site A
- rack1 = Rack.objects.create(site=site_a, name='Rack 1')
- # Create Device1 in Rack1
- device1 = Device.objects.create(site=site_a, rack=rack1, device_type=device_type, device_role=device_role)
- # Move Rack1 to Site B
- rack1.site = site_b
- rack1.save()
- # Check that Device1 is now assigned to Site B
- self.assertEqual(Device.objects.get(pk=device1.pk).site, site_b)
- 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=PowerOutletFeedLegChoices.FEED_LEG_A
- ).save()
- InterfaceTemplate(
- device_type=self.device_type,
- name='Interface 1',
- type=InterfaceTypeChoices.TYPE_1GE_FIXED,
- mgmt_only=True
- ).save()
- rpt = RearPortTemplate(
- device_type=self.device_type,
- name='Rear Port 1',
- type=PortTypeChoices.TYPE_8P8C,
- positions=8
- )
- rpt.save()
- FrontPortTemplate(
- device_type=self.device_type,
- name='Front Port 1',
- type=PortTypeChoices.TYPE_8P8C,
- rear_port=rpt,
- rear_port_position=2
- ).save()
- ModuleBayTemplate(
- device_type=self.device_type,
- name='Module Bay 1'
- ).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=PowerOutletFeedLegChoices.FEED_LEG_A
- )
- Interface.objects.get(
- device=d,
- name='Interface 1',
- type=InterfaceTypeChoices.TYPE_1GE_FIXED,
- mgmt_only=True
- )
- rp = RearPort.objects.get(
- device=d,
- name='Rear Port 1',
- type=PortTypeChoices.TYPE_8P8C,
- positions=8
- )
- FrontPort.objects.get(
- device=d,
- name='Front Port 1',
- type=PortTypeChoices.TYPE_8P8C,
- rear_port=rp,
- rear_port_position=2
- )
- ModuleBay.objects.get(
- device=d,
- name='Module Bay 1'
- )
- DeviceBay.objects.get(
- device=d,
- name='Device Bay 1'
- )
- def test_multiple_unnamed_devices(self):
- device1 = Device(
- site=self.site,
- device_type=self.device_type,
- device_role=self.device_role,
- name=''
- )
- device1.save()
- device2 = Device(
- site=device1.site,
- device_type=device1.device_type,
- device_role=device1.device_role,
- name=''
- )
- device2.full_clean()
- device2.save()
- self.assertEqual(Device.objects.filter(name='').count(), 2)
- def test_device_duplicate_names(self):
- device1 = Device(
- site=self.site,
- device_type=self.device_type,
- device_role=self.device_role,
- name='Test Device 1'
- )
- device1.save()
- device2 = Device(
- site=device1.site,
- device_type=device1.device_type,
- device_role=device1.device_role,
- name=device1.name
- )
- # Two devices assigned to the same Site and no Tenant should fail validation
- with self.assertRaises(ValidationError):
- device2.full_clean()
- tenant = Tenant.objects.create(name='Test Tenant 1', slug='test-tenant-1')
- device1.tenant = tenant
- device1.save()
- device2.tenant = tenant
- # Two devices assigned to the same Site and the same Tenant should fail validation
- with self.assertRaises(ValidationError):
- device2.full_clean()
- device2.tenant = None
- # Two devices assigned to the same Site and different Tenants should pass validation
- device2.full_clean()
- device2.save()
- 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.interface3 = Interface.objects.create(device=self.device2, name='eth1')
- 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_port1 = RearPort.objects.create(device=self.patch_pannel, name='RP1', type='8p8c')
- self.front_port1 = FrontPort.objects.create(
- device=self.patch_pannel, name='FP1', type='8p8c', rear_port=self.rear_port1, rear_port_position=1
- )
- self.rear_port2 = RearPort.objects.create(device=self.patch_pannel, name='RP2', type='8p8c', positions=2)
- self.front_port2 = FrontPort.objects.create(
- device=self.patch_pannel, name='FP2', type='8p8c', rear_port=self.rear_port2, rear_port_position=1
- )
- self.rear_port3 = RearPort.objects.create(device=self.patch_pannel, name='RP3', type='8p8c', positions=3)
- self.front_port3 = FrontPort.objects.create(
- device=self.patch_pannel, name='FP3', type='8p8c', rear_port=self.rear_port3, rear_port_position=1
- )
- self.rear_port4 = RearPort.objects.create(device=self.patch_pannel, name='RP4', type='8p8c', positions=3)
- self.front_port4 = FrontPort.objects.create(
- device=self.patch_pannel, name='FP4', type='8p8c', rear_port=self.rear_port4, rear_port_position=1
- )
- self.provider = Provider.objects.create(name='Provider 1', slug='provider-1')
- provider_network = ProviderNetwork.objects.create(name='Provider Network 1', provider=self.provider)
- self.circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
- self.circuit1 = Circuit.objects.create(provider=self.provider, type=self.circuittype, cid='1')
- self.circuit2 = Circuit.objects.create(provider=self.provider, type=self.circuittype, cid='2')
- self.circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit1, site=site, term_side='A')
- self.circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit1, site=site, term_side='Z')
- self.circuittermination3 = CircuitTermination.objects.create(circuit=self.circuit2, provider_network=provider_network, term_side='A')
- 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)
- interface2 = Interface.objects.get(pk=self.interface2.pk)
- self.assertEqual(self.cable.termination_a, interface1)
- self.assertEqual(interface1._link_peer, interface2)
- self.assertEqual(self.cable.termination_b, interface2)
- self.assertEqual(interface2._link_peer, interface1)
- def test_cable_deletion(self):
- """
- When a Cable is deleted, the `cable` field on its termination points must be nullified. The str() method
- should still return the PK of the string even after being nullified.
- """
- self.cable.delete()
- self.assertIsNone(self.cable.pk)
- self.assertNotEqual(str(self.cable), '#None')
- interface1 = Interface.objects.get(pk=self.interface1.pk)
- self.assertIsNone(interface1.cable)
- self.assertIsNone(interface1._link_peer)
- interface2 = Interface.objects.get(pk=self.interface2.pk)
- self.assertIsNone(interface2.cable)
- self.assertIsNone(interface2._link_peer)
- 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_compatible_types(self):
- """
- The clean method should have a check to ensure only compatible 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 corresponding rear port
- """
- cable = Cable(termination_a=self.front_port1, termination_b=self.rear_port1)
- with self.assertRaises(ValidationError):
- cable.clean()
- def test_cable_cannot_terminate_to_an_existing_connection(self):
- """
- Either side of a cable cannot be terminated when that side already 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_terminate_to_a_provider_network_circuittermination(self):
- """
- Neither side of a cable can be terminated to a CircuitTermination which is attached to a ProviderNetwork
- """
- cable = Cable(termination_a=self.interface3, termination_b=self.circuittermination3)
- with self.assertRaises(ValidationError):
- cable.clean()
- def test_rearport_connections(self):
- """
- Test various combinations of RearPort connections.
- """
- # Connecting a single-position RearPort to a multi-position RearPort is ok
- Cable(termination_a=self.rear_port1, termination_b=self.rear_port2).full_clean()
- # Connecting a single-position RearPort to an Interface is ok
- Cable(termination_a=self.rear_port1, termination_b=self.interface3).full_clean()
- # Connecting a single-position RearPort to a CircuitTermination is ok
- Cable(termination_a=self.rear_port1, termination_b=self.circuittermination1).full_clean()
- # Connecting a multi-position RearPort to another RearPort with the same number of positions is ok
- Cable(termination_a=self.rear_port3, termination_b=self.rear_port4).full_clean()
- # Connecting a multi-position RearPort to an Interface is ok
- Cable(termination_a=self.rear_port2, termination_b=self.interface3).full_clean()
- # Connecting a multi-position RearPort to a CircuitTermination is ok
- Cable(termination_a=self.rear_port2, termination_b=self.circuittermination1).full_clean()
- # Connecting a two-position RearPort to a three-position RearPort is NOT ok
- with self.assertRaises(
- ValidationError,
- msg='Connecting a 2-position RearPort to a 3-position RearPort should fail'
- ):
- Cable(termination_a=self.rear_port2, termination_b=self.rear_port3).full_clean()
- def test_cable_cannot_terminate_to_a_virtual_interface(self):
- """
- A cable cannot terminate to a virtual interface
- """
- virtual_interface = Interface(device=self.device1, name="V1", type=InterfaceTypeChoices.TYPE_VIRTUAL)
- cable = Cable(termination_a=self.interface2, termination_b=virtual_interface)
- with self.assertRaises(ValidationError):
- cable.clean()
- def test_cable_cannot_terminate_to_a_wireless_interface(self):
- """
- A cable cannot terminate to a wireless interface
- """
- wireless_interface = Interface(device=self.device1, name="W1", type=InterfaceTypeChoices.TYPE_80211A)
- cable = Cable(termination_a=self.interface2, termination_b=wireless_interface)
- with self.assertRaises(ValidationError):
- cable.clean()
|