test_models.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. from django.core.exceptions import ValidationError
  2. from django.test import TestCase
  3. from circuits.models import *
  4. from dcim.choices import *
  5. from dcim.models import *
  6. from tenancy.models import Tenant
  7. class RackTestCase(TestCase):
  8. def setUp(self):
  9. self.site1 = Site.objects.create(
  10. name='TestSite1',
  11. slug='test-site-1'
  12. )
  13. self.site2 = Site.objects.create(
  14. name='TestSite2',
  15. slug='test-site-2'
  16. )
  17. self.group1 = RackGroup.objects.create(
  18. name='TestGroup1',
  19. slug='test-group-1',
  20. site=self.site1
  21. )
  22. self.group2 = RackGroup.objects.create(
  23. name='TestGroup2',
  24. slug='test-group-2',
  25. site=self.site2
  26. )
  27. self.rack = Rack.objects.create(
  28. name='TestRack1',
  29. facility_id='A101',
  30. site=self.site1,
  31. group=self.group1,
  32. u_height=42
  33. )
  34. self.manufacturer = Manufacturer.objects.create(
  35. name='Acme',
  36. slug='acme'
  37. )
  38. self.device_type = {
  39. 'ff2048': DeviceType.objects.create(
  40. manufacturer=self.manufacturer,
  41. model='FrameForwarder 2048',
  42. slug='ff2048'
  43. ),
  44. 'cc5000': DeviceType.objects.create(
  45. manufacturer=self.manufacturer,
  46. model='CurrentCatapult 5000',
  47. slug='cc5000',
  48. u_height=0
  49. ),
  50. }
  51. self.role = {
  52. 'Server': DeviceRole.objects.create(
  53. name='Server',
  54. slug='server',
  55. ),
  56. 'Switch': DeviceRole.objects.create(
  57. name='Switch',
  58. slug='switch',
  59. ),
  60. 'Console Server': DeviceRole.objects.create(
  61. name='Console Server',
  62. slug='console-server',
  63. ),
  64. 'PDU': DeviceRole.objects.create(
  65. name='PDU',
  66. slug='pdu',
  67. ),
  68. }
  69. def test_rack_device_outside_height(self):
  70. rack1 = Rack(
  71. name='TestRack2',
  72. facility_id='A102',
  73. site=self.site1,
  74. u_height=42
  75. )
  76. rack1.save()
  77. device1 = Device(
  78. name='TestSwitch1',
  79. device_type=DeviceType.objects.get(manufacturer__slug='acme', slug='ff2048'),
  80. device_role=DeviceRole.objects.get(slug='switch'),
  81. site=self.site1,
  82. rack=rack1,
  83. position=43,
  84. face=DeviceFaceChoices.FACE_FRONT,
  85. )
  86. device1.save()
  87. with self.assertRaises(ValidationError):
  88. rack1.clean()
  89. def test_rack_group_site(self):
  90. rack_invalid_group = Rack(
  91. name='TestRack2',
  92. facility_id='A102',
  93. site=self.site1,
  94. u_height=42,
  95. group=self.group2
  96. )
  97. rack_invalid_group.save()
  98. with self.assertRaises(ValidationError):
  99. rack_invalid_group.clean()
  100. def test_mount_single_device(self):
  101. device1 = Device(
  102. name='TestSwitch1',
  103. device_type=DeviceType.objects.get(manufacturer__slug='acme', slug='ff2048'),
  104. device_role=DeviceRole.objects.get(slug='switch'),
  105. site=self.site1,
  106. rack=self.rack,
  107. position=10,
  108. face=DeviceFaceChoices.FACE_REAR,
  109. )
  110. device1.save()
  111. # Validate rack height
  112. self.assertEqual(list(self.rack.units), list(reversed(range(1, 43))))
  113. # Validate inventory (front face)
  114. rack1_inventory_front = self.rack.get_rack_units(face=DeviceFaceChoices.FACE_FRONT)
  115. self.assertEqual(rack1_inventory_front[-10]['device'], device1)
  116. del(rack1_inventory_front[-10])
  117. for u in rack1_inventory_front:
  118. self.assertIsNone(u['device'])
  119. # Validate inventory (rear face)
  120. rack1_inventory_rear = self.rack.get_rack_units(face=DeviceFaceChoices.FACE_REAR)
  121. self.assertEqual(rack1_inventory_rear[-10]['device'], device1)
  122. del(rack1_inventory_rear[-10])
  123. for u in rack1_inventory_rear:
  124. self.assertIsNone(u['device'])
  125. def test_mount_zero_ru(self):
  126. pdu = Device.objects.create(
  127. name='TestPDU',
  128. device_role=self.role.get('PDU'),
  129. device_type=self.device_type.get('cc5000'),
  130. site=self.site1,
  131. rack=self.rack,
  132. position=None,
  133. face='',
  134. )
  135. self.assertTrue(pdu)
  136. class DeviceTestCase(TestCase):
  137. def setUp(self):
  138. self.site = Site.objects.create(name='Test Site 1', slug='test-site-1')
  139. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  140. self.device_type = DeviceType.objects.create(
  141. manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
  142. )
  143. self.device_role = DeviceRole.objects.create(
  144. name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
  145. )
  146. # Create DeviceType components
  147. ConsolePortTemplate(
  148. device_type=self.device_type,
  149. name='Console Port 1'
  150. ).save()
  151. ConsoleServerPortTemplate(
  152. device_type=self.device_type,
  153. name='Console Server Port 1'
  154. ).save()
  155. ppt = PowerPortTemplate(
  156. device_type=self.device_type,
  157. name='Power Port 1',
  158. maximum_draw=1000,
  159. allocated_draw=500
  160. )
  161. ppt.save()
  162. PowerOutletTemplate(
  163. device_type=self.device_type,
  164. name='Power Outlet 1',
  165. power_port=ppt,
  166. feed_leg=PowerOutletFeedLegChoices.FEED_LEG_A
  167. ).save()
  168. InterfaceTemplate(
  169. device_type=self.device_type,
  170. name='Interface 1',
  171. type=InterfaceTypeChoices.TYPE_1GE_FIXED,
  172. mgmt_only=True
  173. ).save()
  174. rpt = RearPortTemplate(
  175. device_type=self.device_type,
  176. name='Rear Port 1',
  177. type=PortTypeChoices.TYPE_8P8C,
  178. positions=8
  179. )
  180. rpt.save()
  181. FrontPortTemplate(
  182. device_type=self.device_type,
  183. name='Front Port 1',
  184. type=PortTypeChoices.TYPE_8P8C,
  185. rear_port=rpt,
  186. rear_port_position=2
  187. ).save()
  188. DeviceBayTemplate(
  189. device_type=self.device_type,
  190. name='Device Bay 1'
  191. ).save()
  192. def test_device_creation(self):
  193. """
  194. Ensure that all Device components are copied automatically from the DeviceType.
  195. """
  196. d = Device(
  197. site=self.site,
  198. device_type=self.device_type,
  199. device_role=self.device_role,
  200. name='Test Device 1'
  201. )
  202. d.save()
  203. ConsolePort.objects.get(
  204. device=d,
  205. name='Console Port 1'
  206. )
  207. ConsoleServerPort.objects.get(
  208. device=d,
  209. name='Console Server Port 1'
  210. )
  211. pp = PowerPort.objects.get(
  212. device=d,
  213. name='Power Port 1',
  214. maximum_draw=1000,
  215. allocated_draw=500
  216. )
  217. PowerOutlet.objects.get(
  218. device=d,
  219. name='Power Outlet 1',
  220. power_port=pp,
  221. feed_leg=PowerOutletFeedLegChoices.FEED_LEG_A
  222. )
  223. Interface.objects.get(
  224. device=d,
  225. name='Interface 1',
  226. type=InterfaceTypeChoices.TYPE_1GE_FIXED,
  227. mgmt_only=True
  228. )
  229. rp = RearPort.objects.get(
  230. device=d,
  231. name='Rear Port 1',
  232. type=PortTypeChoices.TYPE_8P8C,
  233. positions=8
  234. )
  235. FrontPort.objects.get(
  236. device=d,
  237. name='Front Port 1',
  238. type=PortTypeChoices.TYPE_8P8C,
  239. rear_port=rp,
  240. rear_port_position=2
  241. )
  242. DeviceBay.objects.get(
  243. device=d,
  244. name='Device Bay 1'
  245. )
  246. def test_multiple_unnamed_devices(self):
  247. device1 = Device(
  248. site=self.site,
  249. device_type=self.device_type,
  250. device_role=self.device_role,
  251. name=''
  252. )
  253. device1.save()
  254. device2 = Device(
  255. site=device1.site,
  256. device_type=device1.device_type,
  257. device_role=device1.device_role,
  258. name=''
  259. )
  260. device2.full_clean()
  261. device2.save()
  262. self.assertEqual(Device.objects.filter(name='').count(), 2)
  263. def test_device_duplicate_names(self):
  264. device1 = Device(
  265. site=self.site,
  266. device_type=self.device_type,
  267. device_role=self.device_role,
  268. name='Test Device 1'
  269. )
  270. device1.save()
  271. device2 = Device(
  272. site=device1.site,
  273. device_type=device1.device_type,
  274. device_role=device1.device_role,
  275. name=device1.name
  276. )
  277. # Two devices assigned to the same Site and no Tenant should fail validation
  278. with self.assertRaises(ValidationError):
  279. device2.full_clean()
  280. tenant = Tenant.objects.create(name='Test Tenant 1', slug='test-tenant-1')
  281. device1.tenant = tenant
  282. device1.save()
  283. device2.tenant = tenant
  284. # Two devices assigned to the same Site and the same Tenant should fail validation
  285. with self.assertRaises(ValidationError):
  286. device2.full_clean()
  287. device2.tenant = None
  288. # Two devices assigned to the same Site and different Tenants should pass validation
  289. device2.full_clean()
  290. device2.save()
  291. class CableTestCase(TestCase):
  292. def setUp(self):
  293. site = Site.objects.create(name='Test Site 1', slug='test-site-1')
  294. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  295. devicetype = DeviceType.objects.create(
  296. manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
  297. )
  298. devicerole = DeviceRole.objects.create(
  299. name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
  300. )
  301. self.device1 = Device.objects.create(
  302. device_type=devicetype, device_role=devicerole, name='TestDevice1', site=site
  303. )
  304. self.device2 = Device.objects.create(
  305. device_type=devicetype, device_role=devicerole, name='TestDevice2', site=site
  306. )
  307. self.interface1 = Interface.objects.create(device=self.device1, name='eth0')
  308. self.interface2 = Interface.objects.create(device=self.device2, name='eth0')
  309. self.cable = Cable(termination_a=self.interface1, termination_b=self.interface2)
  310. self.cable.save()
  311. self.power_port1 = PowerPort.objects.create(device=self.device2, name='psu1')
  312. self.patch_pannel = Device.objects.create(
  313. device_type=devicetype, device_role=devicerole, name='TestPatchPannel', site=site
  314. )
  315. self.rear_port = RearPort.objects.create(device=self.patch_pannel, name='R1', type=1000)
  316. self.front_port = FrontPort.objects.create(
  317. device=self.patch_pannel, name='F1', type=1000, rear_port=self.rear_port
  318. )
  319. def test_cable_creation(self):
  320. """
  321. When a new Cable is created, it must be cached on either termination point.
  322. """
  323. interface1 = Interface.objects.get(pk=self.interface1.pk)
  324. self.assertEqual(self.cable.termination_a, interface1)
  325. interface2 = Interface.objects.get(pk=self.interface2.pk)
  326. self.assertEqual(self.cable.termination_b, interface2)
  327. def test_cable_deletion(self):
  328. """
  329. When a Cable is deleted, the `cable` field on its termination points must be nullified. The str() method
  330. should still return the PK of the string even after being nullified.
  331. """
  332. self.cable.delete()
  333. self.assertIsNone(self.cable.pk)
  334. self.assertNotEqual(str(self.cable), '#None')
  335. interface1 = Interface.objects.get(pk=self.interface1.pk)
  336. self.assertIsNone(interface1.cable)
  337. interface2 = Interface.objects.get(pk=self.interface2.pk)
  338. self.assertIsNone(interface2.cable)
  339. def test_cabletermination_deletion(self):
  340. """
  341. When a CableTermination object is deleted, its attached Cable (if any) must also be deleted.
  342. """
  343. self.interface1.delete()
  344. cable = Cable.objects.filter(pk=self.cable.pk).first()
  345. self.assertIsNone(cable)
  346. def test_cable_validates_compatibale_types(self):
  347. """
  348. The clean method should have a check to ensure only compatible port types can be connected by a cable
  349. """
  350. # An interface cannot be connected to a power port
  351. cable = Cable(termination_a=self.interface1, termination_b=self.power_port1)
  352. with self.assertRaises(ValidationError):
  353. cable.clean()
  354. def test_cable_cannot_have_the_same_terminination_on_both_ends(self):
  355. """
  356. A cable cannot be made with the same A and B side terminations
  357. """
  358. cable = Cable(termination_a=self.interface1, termination_b=self.interface1)
  359. with self.assertRaises(ValidationError):
  360. cable.clean()
  361. def test_cable_front_port_cannot_connect_to_corresponding_rear_port(self):
  362. """
  363. A cable cannot connect a front port to its corresponding rear port
  364. """
  365. cable = Cable(termination_a=self.front_port, termination_b=self.rear_port)
  366. with self.assertRaises(ValidationError):
  367. cable.clean()
  368. def test_cable_cannot_terminate_to_an_existing_connection(self):
  369. """
  370. Either side of a cable cannot be terminated when that side already has a connection
  371. """
  372. # Try to create a cable with the same interface terminations
  373. cable = Cable(termination_a=self.interface2, termination_b=self.interface1)
  374. with self.assertRaises(ValidationError):
  375. cable.clean()
  376. def test_cable_cannot_terminate_to_a_virtual_inteface(self):
  377. """
  378. A cable cannot terminate to a virtual interface
  379. """
  380. virtual_interface = Interface(device=self.device1, name="V1", type=InterfaceTypeChoices.TYPE_VIRTUAL)
  381. cable = Cable(termination_a=self.interface2, termination_b=virtual_interface)
  382. with self.assertRaises(ValidationError):
  383. cable.clean()
  384. def test_cable_cannot_terminate_to_a_wireless_inteface(self):
  385. """
  386. A cable cannot terminate to a wireless interface
  387. """
  388. wireless_interface = Interface(device=self.device1, name="W1", type=InterfaceTypeChoices.TYPE_80211A)
  389. cable = Cable(termination_a=self.interface2, termination_b=wireless_interface)
  390. with self.assertRaises(ValidationError):
  391. cable.clean()
  392. class CablePathTestCase(TestCase):
  393. @classmethod
  394. def setUpTestData(cls):
  395. site = Site.objects.create(name='Site 1', slug='site-1')
  396. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  397. devicetype = DeviceType.objects.create(
  398. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  399. )
  400. devicerole = DeviceRole.objects.create(
  401. name='Device Role 1', slug='device-role-1', color='ff0000'
  402. )
  403. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  404. circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
  405. circuit = Circuit.objects.create(provider=provider, type=circuittype, cid='1')
  406. CircuitTermination.objects.bulk_create((
  407. CircuitTermination(circuit=circuit, site=site, term_side='A', port_speed=1000),
  408. CircuitTermination(circuit=circuit, site=site, term_side='Z', port_speed=1000),
  409. ))
  410. # Create four network devices with four interfaces each
  411. devices = (
  412. Device(device_type=devicetype, device_role=devicerole, name='Device 1', site=site),
  413. Device(device_type=devicetype, device_role=devicerole, name='Device 2', site=site),
  414. Device(device_type=devicetype, device_role=devicerole, name='Device 3', site=site),
  415. Device(device_type=devicetype, device_role=devicerole, name='Device 4', site=site),
  416. )
  417. Device.objects.bulk_create(devices)
  418. for device in devices:
  419. Interface.objects.bulk_create((
  420. Interface(device=device, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  421. Interface(device=device, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  422. Interface(device=device, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  423. Interface(device=device, name='Interface 4', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  424. ))
  425. # Create four patch panels, each with one rear port and four front ports
  426. patch_panels = (
  427. Device(device_type=devicetype, device_role=devicerole, name='Panel 1', site=site),
  428. Device(device_type=devicetype, device_role=devicerole, name='Panel 2', site=site),
  429. Device(device_type=devicetype, device_role=devicerole, name='Panel 3', site=site),
  430. Device(device_type=devicetype, device_role=devicerole, name='Panel 4', site=site),
  431. )
  432. Device.objects.bulk_create(patch_panels)
  433. for patch_panel in patch_panels:
  434. rearport = RearPort.objects.create(device=patch_panel, name='Rear Port 1', positions=4, type=PortTypeChoices.TYPE_8P8C)
  435. FrontPort.objects.bulk_create((
  436. FrontPort(device=patch_panel, name='Front Port 1', rear_port=rearport, rear_port_position=1, type=PortTypeChoices.TYPE_8P8C),
  437. FrontPort(device=patch_panel, name='Front Port 2', rear_port=rearport, rear_port_position=2, type=PortTypeChoices.TYPE_8P8C),
  438. FrontPort(device=patch_panel, name='Front Port 3', rear_port=rearport, rear_port_position=3, type=PortTypeChoices.TYPE_8P8C),
  439. FrontPort(device=patch_panel, name='Front Port 4', rear_port=rearport, rear_port_position=4, type=PortTypeChoices.TYPE_8P8C),
  440. ))
  441. def test_direct_connection(self):
  442. """
  443. [Device 1] ----- [Device 2]
  444. Iface1 Iface1
  445. """
  446. # Create cable
  447. cable = Cable(
  448. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  449. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  450. )
  451. cable.save()
  452. # Retrieve endpoints
  453. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  454. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  455. # Validate connections
  456. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  457. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  458. self.assertTrue(endpoint_a.connection_status)
  459. self.assertTrue(endpoint_b.connection_status)
  460. # Delete cable
  461. cable.delete()
  462. # Refresh endpoints
  463. endpoint_a.refresh_from_db()
  464. endpoint_b.refresh_from_db()
  465. # Check that connections have been nullified
  466. self.assertIsNone(endpoint_a.connected_endpoint)
  467. self.assertIsNone(endpoint_b.connected_endpoint)
  468. self.assertIsNone(endpoint_a.connection_status)
  469. self.assertIsNone(endpoint_b.connection_status)
  470. def test_connection_via_patch(self):
  471. """
  472. 1 2 3
  473. [Device 1] ----- [Panel 1] ----- [Panel 2] ----- [Device 2]
  474. Iface1 FP1 RP1 RP1 FP1 Iface1
  475. """
  476. # Create cables
  477. cable1 = Cable(
  478. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  479. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  480. )
  481. cable1.save()
  482. cable2 = Cable(
  483. termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  484. termination_b=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1')
  485. )
  486. cable2.save()
  487. cable3 = Cable(
  488. termination_a=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1'),
  489. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  490. )
  491. cable3.save()
  492. # Retrieve endpoints
  493. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  494. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  495. # Validate connections
  496. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  497. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  498. self.assertTrue(endpoint_a.connection_status)
  499. self.assertTrue(endpoint_b.connection_status)
  500. # Delete cable 2
  501. cable2.delete()
  502. # Refresh endpoints
  503. endpoint_a.refresh_from_db()
  504. endpoint_b.refresh_from_db()
  505. # Check that connections have been nullified
  506. self.assertIsNone(endpoint_a.connected_endpoint)
  507. self.assertIsNone(endpoint_b.connected_endpoint)
  508. self.assertIsNone(endpoint_a.connection_status)
  509. self.assertIsNone(endpoint_b.connection_status)
  510. def test_connection_via_multiple_patches(self):
  511. """
  512. 1 2 3 4 5
  513. [Device 1] ----- [Panel 1] ----- [Panel 2] ----- [Panel 3] ----- [Panel 4] ----- [Device 2]
  514. Iface1 FP1 RP1 RP1 FP1 FP1 RP1 RP1 FP1 Iface1
  515. """
  516. # Create cables
  517. cable1 = Cable(
  518. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  519. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  520. )
  521. cable1.save()
  522. cable2 = Cable(
  523. termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  524. termination_b=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1')
  525. )
  526. cable2.save()
  527. cable3 = Cable(
  528. termination_a=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1'),
  529. termination_b=FrontPort.objects.get(device__name='Panel 3', name='Front Port 1')
  530. )
  531. cable3.save()
  532. cable4 = Cable(
  533. termination_a=RearPort.objects.get(device__name='Panel 3', name='Rear Port 1'),
  534. termination_b=RearPort.objects.get(device__name='Panel 4', name='Rear Port 1')
  535. )
  536. cable4.save()
  537. cable5 = Cable(
  538. termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 1'),
  539. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  540. )
  541. cable5.save()
  542. # Retrieve endpoints
  543. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  544. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  545. # Validate connections
  546. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  547. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  548. self.assertTrue(endpoint_a.connection_status)
  549. self.assertTrue(endpoint_b.connection_status)
  550. # Delete cable 3
  551. cable3.delete()
  552. # Refresh endpoints
  553. endpoint_a.refresh_from_db()
  554. endpoint_b.refresh_from_db()
  555. # Check that connections have been nullified
  556. self.assertIsNone(endpoint_a.connected_endpoint)
  557. self.assertIsNone(endpoint_b.connected_endpoint)
  558. self.assertIsNone(endpoint_a.connection_status)
  559. self.assertIsNone(endpoint_b.connection_status)
  560. def test_connection_via_stacked_rear_ports(self):
  561. """
  562. 1 2 3 4 5
  563. [Device 1] ----- [Panel 1] ----- [Panel 2] ----- [Panel 3] ----- [Panel 4] ----- [Device 2]
  564. Iface1 FP1 RP1 FP1 RP1 RP1 FP1 RP1 FP1 Iface1
  565. """
  566. # Create cables
  567. cable1 = Cable(
  568. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  569. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  570. )
  571. cable1.save()
  572. cable2 = Cable(
  573. termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  574. termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1')
  575. )
  576. cable2.save()
  577. cable3 = Cable(
  578. termination_a=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1'),
  579. termination_b=RearPort.objects.get(device__name='Panel 3', name='Rear Port 1')
  580. )
  581. cable3.save()
  582. cable4 = Cable(
  583. termination_a=FrontPort.objects.get(device__name='Panel 3', name='Front Port 1'),
  584. termination_b=RearPort.objects.get(device__name='Panel 4', name='Rear Port 1')
  585. )
  586. cable4.save()
  587. cable5 = Cable(
  588. termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 1'),
  589. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  590. )
  591. cable5.save()
  592. # Retrieve endpoints
  593. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  594. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  595. # Validate connections
  596. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  597. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  598. self.assertTrue(endpoint_a.connection_status)
  599. self.assertTrue(endpoint_b.connection_status)
  600. # Delete cable 3
  601. cable3.delete()
  602. # Refresh endpoints
  603. endpoint_a.refresh_from_db()
  604. endpoint_b.refresh_from_db()
  605. # Check that connections have been nullified
  606. self.assertIsNone(endpoint_a.connected_endpoint)
  607. self.assertIsNone(endpoint_b.connected_endpoint)
  608. self.assertIsNone(endpoint_a.connection_status)
  609. self.assertIsNone(endpoint_b.connection_status)
  610. def test_connection_via_circuit(self):
  611. """
  612. 1 2
  613. [Device 1] ----- [Circuit] ----- [Device 2]
  614. Iface1 A Z Iface1
  615. """
  616. # Create cables
  617. cable1 = Cable(
  618. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  619. termination_b=CircuitTermination.objects.get(term_side='A')
  620. )
  621. cable1.save()
  622. cable2 = Cable(
  623. termination_a=CircuitTermination.objects.get(term_side='Z'),
  624. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  625. )
  626. cable2.save()
  627. # Retrieve endpoints
  628. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  629. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  630. # Validate connections
  631. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  632. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  633. self.assertTrue(endpoint_a.connection_status)
  634. self.assertTrue(endpoint_b.connection_status)
  635. # Delete circuit
  636. circuit = Circuit.objects.first().delete()
  637. # Refresh endpoints
  638. endpoint_a.refresh_from_db()
  639. endpoint_b.refresh_from_db()
  640. # Check that connections have been nullified
  641. self.assertIsNone(endpoint_a.connected_endpoint)
  642. self.assertIsNone(endpoint_b.connected_endpoint)
  643. self.assertIsNone(endpoint_a.connection_status)
  644. self.assertIsNone(endpoint_b.connection_status)
  645. def test_connection_via_patched_circuit(self):
  646. """
  647. 1 2 3 4
  648. [Device 1] ----- [Panel 1] ----- [Circuit] ----- [Panel 2] ----- [Device 2]
  649. Iface1 FP1 RP1 A Z RP1 FP1 Iface1
  650. """
  651. # Create cables
  652. cable1 = Cable(
  653. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  654. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  655. )
  656. cable1.save()
  657. cable2 = Cable(
  658. termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  659. termination_b=CircuitTermination.objects.get(term_side='A')
  660. )
  661. cable2.save()
  662. cable3 = Cable(
  663. termination_a=CircuitTermination.objects.get(term_side='Z'),
  664. termination_b=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1')
  665. )
  666. cable3.save()
  667. cable4 = Cable(
  668. termination_a=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1'),
  669. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  670. )
  671. cable4.save()
  672. # Retrieve endpoints
  673. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  674. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  675. # Validate connections
  676. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  677. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  678. self.assertTrue(endpoint_a.connection_status)
  679. self.assertTrue(endpoint_b.connection_status)
  680. # Delete circuit
  681. circuit = Circuit.objects.first().delete()
  682. # Refresh endpoints
  683. endpoint_a.refresh_from_db()
  684. endpoint_b.refresh_from_db()
  685. # Check that connections have been nullified
  686. self.assertIsNone(endpoint_a.connected_endpoint)
  687. self.assertIsNone(endpoint_b.connected_endpoint)
  688. self.assertIsNone(endpoint_a.connection_status)
  689. self.assertIsNone(endpoint_b.connection_status)