test_models.py 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  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. Device(device_type=devicetype, device_role=devicerole, name='Panel 5', site=site),
  432. )
  433. Device.objects.bulk_create(patch_panels)
  434. # Create patch panels with 4 positions
  435. for patch_panel in patch_panels[:4]:
  436. rearport = RearPort.objects.create(device=patch_panel, name='Rear Port 1', positions=4, type=PortTypeChoices.TYPE_8P8C)
  437. FrontPort.objects.bulk_create((
  438. FrontPort(device=patch_panel, name='Front Port 1', rear_port=rearport, rear_port_position=1, type=PortTypeChoices.TYPE_8P8C),
  439. FrontPort(device=patch_panel, name='Front Port 2', rear_port=rearport, rear_port_position=2, type=PortTypeChoices.TYPE_8P8C),
  440. FrontPort(device=patch_panel, name='Front Port 3', rear_port=rearport, rear_port_position=3, type=PortTypeChoices.TYPE_8P8C),
  441. FrontPort(device=patch_panel, name='Front Port 4', rear_port=rearport, rear_port_position=4, type=PortTypeChoices.TYPE_8P8C),
  442. ))
  443. # Create a 1-on-1 patch panel
  444. for patch_panel in patch_panels[4:]:
  445. rearport = RearPort.objects.create(device=patch_panel, name='Rear Port 1', positions=1, type=PortTypeChoices.TYPE_8P8C)
  446. FrontPort.objects.create(device=patch_panel, name='Front Port 1', rear_port=rearport, rear_port_position=1, type=PortTypeChoices.TYPE_8P8C)
  447. def test_direct_connection(self):
  448. """
  449. Test a direct connection between two interfaces.
  450. [Device 1] ----- [Device 2]
  451. Iface1 Iface1
  452. """
  453. # Create cable
  454. cable = Cable(
  455. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  456. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  457. )
  458. cable.save()
  459. # Retrieve endpoints
  460. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  461. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  462. # Validate connections
  463. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  464. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  465. self.assertTrue(endpoint_a.connection_status)
  466. self.assertTrue(endpoint_b.connection_status)
  467. # Delete cable
  468. cable.delete()
  469. # Refresh endpoints
  470. endpoint_a.refresh_from_db()
  471. endpoint_b.refresh_from_db()
  472. # Check that connections have been nullified
  473. self.assertIsNone(endpoint_a.connected_endpoint)
  474. self.assertIsNone(endpoint_b.connected_endpoint)
  475. self.assertIsNone(endpoint_a.connection_status)
  476. self.assertIsNone(endpoint_b.connection_status)
  477. def test_connection_via_single_rear_port(self):
  478. """
  479. Test a connection which passes through a single front/rear port pair.
  480. 1 2
  481. [Device 1] ----- [Panel 1] ----- [Device 2]
  482. Iface1 FP1 RP1 Iface1
  483. TODO: Panel 1's rear port has multiple front ports. Should this even work?
  484. """
  485. # Create cables (FP first, RP second)
  486. cable1 = Cable(
  487. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  488. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  489. )
  490. cable1.full_clean()
  491. cable1.save()
  492. cable2 = Cable(
  493. termination_b=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  494. termination_a=Interface.objects.get(device__name='Device 2', name='Interface 1')
  495. )
  496. cable2.full_clean()
  497. cable2.save()
  498. # Retrieve endpoints
  499. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  500. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  501. # Validate connections
  502. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  503. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  504. self.assertTrue(endpoint_a.connection_status)
  505. self.assertTrue(endpoint_b.connection_status)
  506. # Delete cable 1
  507. cable1.delete()
  508. # Refresh endpoints
  509. endpoint_a.refresh_from_db()
  510. endpoint_b.refresh_from_db()
  511. # Check that connections have been nullified
  512. self.assertIsNone(endpoint_a.connected_endpoint)
  513. self.assertIsNone(endpoint_b.connected_endpoint)
  514. self.assertIsNone(endpoint_a.connection_status)
  515. self.assertIsNone(endpoint_b.connection_status)
  516. def test_connection_via_one_on_one_port(self):
  517. """
  518. Test a connection which passes through a rear port with exactly one front port.
  519. 1 2
  520. [Device 1] ----- [Panel 5] ----- [Device 2]
  521. Iface1 FP1 RP1 Iface1
  522. """
  523. # Create cables (FP first, RP second)
  524. cable1 = Cable(
  525. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  526. termination_b=FrontPort.objects.get(device__name='Panel 5', name='Front Port 1')
  527. )
  528. cable1.full_clean()
  529. cable1.save()
  530. cable2 = Cable(
  531. termination_b=RearPort.objects.get(device__name='Panel 5', name='Rear Port 1'),
  532. termination_a=Interface.objects.get(device__name='Device 2', name='Interface 1')
  533. )
  534. cable2.full_clean()
  535. cable2.save()
  536. # Retrieve endpoints
  537. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  538. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  539. # Validate connections
  540. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  541. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  542. self.assertTrue(endpoint_a.connection_status)
  543. self.assertTrue(endpoint_b.connection_status)
  544. # Delete cable 1
  545. cable1.delete()
  546. # Refresh endpoints
  547. endpoint_a.refresh_from_db()
  548. endpoint_b.refresh_from_db()
  549. # Check that connections have been nullified
  550. self.assertIsNone(endpoint_a.connected_endpoint)
  551. self.assertIsNone(endpoint_b.connected_endpoint)
  552. self.assertIsNone(endpoint_a.connection_status)
  553. self.assertIsNone(endpoint_b.connection_status)
  554. # Recreate cable 1 to test creating the cables in reverse order (RP first, FP second)
  555. cable1 = Cable(
  556. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  557. termination_b=FrontPort.objects.get(device__name='Panel 5', name='Front Port 1')
  558. )
  559. cable1.full_clean()
  560. cable1.save()
  561. # Refresh endpoints
  562. endpoint_a.refresh_from_db()
  563. endpoint_b.refresh_from_db()
  564. # Validate connections
  565. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  566. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  567. self.assertTrue(endpoint_a.connection_status)
  568. self.assertTrue(endpoint_b.connection_status)
  569. # Delete cable 2
  570. cable2.delete()
  571. # Refresh endpoints
  572. endpoint_a.refresh_from_db()
  573. endpoint_b.refresh_from_db()
  574. # Check that connections have been nullified
  575. self.assertIsNone(endpoint_a.connected_endpoint)
  576. self.assertIsNone(endpoint_b.connected_endpoint)
  577. self.assertIsNone(endpoint_a.connection_status)
  578. self.assertIsNone(endpoint_b.connection_status)
  579. def test_connection_via_nested_one_on_one_port(self):
  580. """
  581. Test a connection which passes through a single front/rear port pair between two multi-port MUXes.
  582. Test two connections via patched rear ports:
  583. Device 1 <---> Device 2
  584. Device 3 <---> Device 4
  585. 1 2
  586. [Device 1] -----------+ +----------- [Device 2]
  587. Iface1 | | Iface1
  588. FP1 | 3 4 | FP1
  589. [Panel 1] ----- [Panel 5] ----- [Panel 2]
  590. FP2 | RP1 RP1 FP1 RP1 | FP2
  591. Iface1 | | Iface1
  592. [Device 3] -----------+ +----------- [Device 4]
  593. 5 6
  594. """
  595. # Create cables (Panel 5 RP first, FP second)
  596. cable1 = Cable(
  597. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  598. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  599. )
  600. cable1.full_clean()
  601. cable1.save()
  602. cable2 = Cable(
  603. termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1'),
  604. termination_a=Interface.objects.get(device__name='Device 2', name='Interface 1')
  605. )
  606. cable2.full_clean()
  607. cable2.save()
  608. cable3 = Cable(
  609. termination_b=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  610. termination_a=RearPort.objects.get(device__name='Panel 5', name='Rear Port 1')
  611. )
  612. cable3.full_clean()
  613. cable3.save()
  614. cable4 = Cable(
  615. termination_b=FrontPort.objects.get(device__name='Panel 5', name='Front Port 1'),
  616. termination_a=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1')
  617. )
  618. cable4.full_clean()
  619. cable4.save()
  620. cable5 = Cable(
  621. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 2'),
  622. termination_a=Interface.objects.get(device__name='Device 3', name='Interface 1')
  623. )
  624. cable5.full_clean()
  625. cable5.save()
  626. cable6 = Cable(
  627. termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 2'),
  628. termination_a=Interface.objects.get(device__name='Device 4', name='Interface 1')
  629. )
  630. cable6.full_clean()
  631. cable6.save()
  632. # Retrieve endpoints
  633. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  634. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  635. endpoint_c = Interface.objects.get(device__name='Device 3', name='Interface 1')
  636. endpoint_d = Interface.objects.get(device__name='Device 4', name='Interface 1')
  637. # Validate connections
  638. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  639. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  640. self.assertEqual(endpoint_c.connected_endpoint, endpoint_d)
  641. self.assertEqual(endpoint_d.connected_endpoint, endpoint_c)
  642. self.assertTrue(endpoint_a.connection_status)
  643. self.assertTrue(endpoint_b.connection_status)
  644. self.assertTrue(endpoint_c.connection_status)
  645. self.assertTrue(endpoint_d.connection_status)
  646. # Delete cable 3
  647. cable3.delete()
  648. # Refresh endpoints
  649. endpoint_a.refresh_from_db()
  650. endpoint_b.refresh_from_db()
  651. endpoint_c.refresh_from_db()
  652. endpoint_d.refresh_from_db()
  653. # Check that connections have been nullified
  654. self.assertIsNone(endpoint_a.connected_endpoint)
  655. self.assertIsNone(endpoint_b.connected_endpoint)
  656. self.assertIsNone(endpoint_c.connected_endpoint)
  657. self.assertIsNone(endpoint_d.connected_endpoint)
  658. self.assertIsNone(endpoint_a.connection_status)
  659. self.assertIsNone(endpoint_b.connection_status)
  660. self.assertIsNone(endpoint_c.connection_status)
  661. self.assertIsNone(endpoint_d.connection_status)
  662. # Recreate cable 3 to test reverse order (Panel 5 FP first, RP second)
  663. cable3 = Cable(
  664. termination_b=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  665. termination_a=RearPort.objects.get(device__name='Panel 5', name='Rear Port 1')
  666. )
  667. cable3.full_clean()
  668. cable3.save()
  669. # Refresh endpoints
  670. endpoint_a.refresh_from_db()
  671. endpoint_b.refresh_from_db()
  672. endpoint_c.refresh_from_db()
  673. endpoint_d.refresh_from_db()
  674. # Validate connections
  675. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  676. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  677. self.assertEqual(endpoint_c.connected_endpoint, endpoint_d)
  678. self.assertEqual(endpoint_d.connected_endpoint, endpoint_c)
  679. self.assertTrue(endpoint_a.connection_status)
  680. self.assertTrue(endpoint_b.connection_status)
  681. self.assertTrue(endpoint_c.connection_status)
  682. self.assertTrue(endpoint_d.connection_status)
  683. # Delete cable 4
  684. cable4.delete()
  685. # Refresh endpoints
  686. endpoint_a.refresh_from_db()
  687. endpoint_b.refresh_from_db()
  688. endpoint_c.refresh_from_db()
  689. endpoint_d.refresh_from_db()
  690. # Check that connections have been nullified
  691. self.assertIsNone(endpoint_a.connected_endpoint)
  692. self.assertIsNone(endpoint_b.connected_endpoint)
  693. self.assertIsNone(endpoint_c.connected_endpoint)
  694. self.assertIsNone(endpoint_d.connected_endpoint)
  695. self.assertIsNone(endpoint_a.connection_status)
  696. self.assertIsNone(endpoint_b.connection_status)
  697. self.assertIsNone(endpoint_c.connection_status)
  698. self.assertIsNone(endpoint_d.connection_status)
  699. def test_connections_via_patch(self):
  700. """
  701. Test two connections via patched rear ports:
  702. Device 1 <---> Device 2
  703. Device 3 <---> Device 4
  704. 1 2
  705. [Device 1] -----------+ +----------- [Device 2]
  706. Iface1 | | Iface1
  707. FP1 | 3 | FP1
  708. [Panel 1] ----- [Panel 2]
  709. FP2 | RP1 RP1 | FP2
  710. Iface1 | | Iface1
  711. [Device 3] -----------+ +----------- [Device 4]
  712. 4 5
  713. """
  714. # Create cables
  715. cable1 = Cable(
  716. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  717. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  718. )
  719. cable1.full_clean()
  720. cable1.save()
  721. cable2 = Cable(
  722. termination_a=Interface.objects.get(device__name='Device 2', name='Interface 1'),
  723. termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1')
  724. )
  725. cable2.full_clean()
  726. cable2.save()
  727. cable3 = Cable(
  728. termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  729. termination_b=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1')
  730. )
  731. cable3.full_clean()
  732. cable3.save()
  733. cable4 = Cable(
  734. termination_a=Interface.objects.get(device__name='Device 3', name='Interface 1'),
  735. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 2')
  736. )
  737. cable4.full_clean()
  738. cable4.save()
  739. cable5 = Cable(
  740. termination_a=Interface.objects.get(device__name='Device 4', name='Interface 1'),
  741. termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 2')
  742. )
  743. cable5.full_clean()
  744. cable5.save()
  745. # Retrieve endpoints
  746. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  747. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  748. endpoint_c = Interface.objects.get(device__name='Device 3', name='Interface 1')
  749. endpoint_d = Interface.objects.get(device__name='Device 4', name='Interface 1')
  750. # Validate connections
  751. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  752. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  753. self.assertEqual(endpoint_c.connected_endpoint, endpoint_d)
  754. self.assertEqual(endpoint_d.connected_endpoint, endpoint_c)
  755. self.assertTrue(endpoint_a.connection_status)
  756. self.assertTrue(endpoint_b.connection_status)
  757. self.assertTrue(endpoint_c.connection_status)
  758. self.assertTrue(endpoint_d.connection_status)
  759. # Delete cable 3
  760. cable3.delete()
  761. # Refresh endpoints
  762. endpoint_a.refresh_from_db()
  763. endpoint_b.refresh_from_db()
  764. endpoint_c.refresh_from_db()
  765. endpoint_d.refresh_from_db()
  766. # Check that connections have been nullified
  767. self.assertIsNone(endpoint_a.connected_endpoint)
  768. self.assertIsNone(endpoint_b.connected_endpoint)
  769. self.assertIsNone(endpoint_c.connected_endpoint)
  770. self.assertIsNone(endpoint_d.connected_endpoint)
  771. self.assertIsNone(endpoint_a.connection_status)
  772. self.assertIsNone(endpoint_b.connection_status)
  773. self.assertIsNone(endpoint_c.connection_status)
  774. self.assertIsNone(endpoint_d.connection_status)
  775. def test_connections_via_multiple_patches(self):
  776. """
  777. Test two connections via patched rear ports:
  778. Device 1 <---> Device 2
  779. Device 3 <---> Device 4
  780. 1 2 3
  781. [Device 1] -----------+ +---------------+ +----------- [Device 2]
  782. Iface1 | | | | Iface1
  783. FP1 | 4 | FP1 FP1 | 5 | FP1
  784. [Panel 1] ----- [Panel 2] [Panel 3] ----- [Panel 4]
  785. FP2 | RP1 RP1 | FP2 FP2 | RP1 RP1 | FP2
  786. Iface1 | | | | Iface1
  787. [Device 3] -----------+ +---------------+ +----------- [Device 4]
  788. 6 7 8
  789. """
  790. # Create cables
  791. cable1 = Cable(
  792. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  793. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  794. )
  795. cable1.full_clean()
  796. cable1.save()
  797. cable2 = Cable(
  798. termination_a=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1'),
  799. termination_b=FrontPort.objects.get(device__name='Panel 3', name='Front Port 1')
  800. )
  801. cable2.full_clean()
  802. cable2.save()
  803. cable3 = Cable(
  804. termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 1'),
  805. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  806. )
  807. cable3.full_clean()
  808. cable3.save()
  809. cable4 = Cable(
  810. termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  811. termination_b=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1')
  812. )
  813. cable4.full_clean()
  814. cable4.save()
  815. cable5 = Cable(
  816. termination_a=RearPort.objects.get(device__name='Panel 3', name='Rear Port 1'),
  817. termination_b=RearPort.objects.get(device__name='Panel 4', name='Rear Port 1')
  818. )
  819. cable5.full_clean()
  820. cable5.save()
  821. cable6 = Cable(
  822. termination_a=Interface.objects.get(device__name='Device 3', name='Interface 1'),
  823. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 2')
  824. )
  825. cable6.full_clean()
  826. cable6.save()
  827. cable7 = Cable(
  828. termination_a=FrontPort.objects.get(device__name='Panel 2', name='Front Port 2'),
  829. termination_b=FrontPort.objects.get(device__name='Panel 3', name='Front Port 2')
  830. )
  831. cable7.full_clean()
  832. cable7.save()
  833. cable8 = Cable(
  834. termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 2'),
  835. termination_b=Interface.objects.get(device__name='Device 4', name='Interface 1')
  836. )
  837. cable8.full_clean()
  838. cable8.save()
  839. # Retrieve endpoints
  840. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  841. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  842. endpoint_c = Interface.objects.get(device__name='Device 3', name='Interface 1')
  843. endpoint_d = Interface.objects.get(device__name='Device 4', name='Interface 1')
  844. # Validate connections
  845. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  846. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  847. self.assertEqual(endpoint_c.connected_endpoint, endpoint_d)
  848. self.assertEqual(endpoint_d.connected_endpoint, endpoint_c)
  849. self.assertTrue(endpoint_a.connection_status)
  850. self.assertTrue(endpoint_b.connection_status)
  851. self.assertTrue(endpoint_c.connection_status)
  852. self.assertTrue(endpoint_d.connection_status)
  853. # Delete cables 4 and 5
  854. cable4.delete()
  855. cable5.delete()
  856. # Refresh endpoints
  857. endpoint_a.refresh_from_db()
  858. endpoint_b.refresh_from_db()
  859. endpoint_c.refresh_from_db()
  860. endpoint_d.refresh_from_db()
  861. # Check that connections have been nullified
  862. self.assertIsNone(endpoint_a.connected_endpoint)
  863. self.assertIsNone(endpoint_b.connected_endpoint)
  864. self.assertIsNone(endpoint_c.connected_endpoint)
  865. self.assertIsNone(endpoint_d.connected_endpoint)
  866. self.assertIsNone(endpoint_a.connection_status)
  867. self.assertIsNone(endpoint_b.connection_status)
  868. self.assertIsNone(endpoint_c.connection_status)
  869. self.assertIsNone(endpoint_d.connection_status)
  870. def test_connections_via_nested_rear_ports(self):
  871. """
  872. Test two connections via nested rear ports:
  873. Device 1 <---> Device 2
  874. Device 3 <---> Device 4
  875. 1 2
  876. [Device 1] -----------+ +----------- [Device 2]
  877. Iface1 | | Iface1
  878. FP1 | 3 4 5 | FP1
  879. [Panel 1] ----- [Panel 2] ----- [Panel 3] ----- [Panel 4]
  880. FP2 | RP1 FP1 RP1 RP1 FP1 RP1 | FP2
  881. Iface1 | | Iface1
  882. [Device 3] -----------+ +----------- [Device 4]
  883. 6 7
  884. """
  885. # Create cables
  886. cable1 = Cable(
  887. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  888. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  889. )
  890. cable1.full_clean()
  891. cable1.save()
  892. cable2 = Cable(
  893. termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 1'),
  894. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  895. )
  896. cable2.full_clean()
  897. cable2.save()
  898. cable3 = Cable(
  899. termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  900. termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1')
  901. )
  902. cable3.full_clean()
  903. cable3.save()
  904. cable4 = Cable(
  905. termination_a=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1'),
  906. termination_b=RearPort.objects.get(device__name='Panel 3', name='Rear Port 1')
  907. )
  908. cable4.full_clean()
  909. cable4.save()
  910. cable5 = Cable(
  911. termination_a=FrontPort.objects.get(device__name='Panel 3', name='Front Port 1'),
  912. termination_b=RearPort.objects.get(device__name='Panel 4', name='Rear Port 1')
  913. )
  914. cable5.full_clean()
  915. cable5.save()
  916. cable6 = Cable(
  917. termination_a=Interface.objects.get(device__name='Device 3', name='Interface 1'),
  918. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 2')
  919. )
  920. cable6.full_clean()
  921. cable6.save()
  922. cable7 = Cable(
  923. termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 2'),
  924. termination_b=Interface.objects.get(device__name='Device 4', name='Interface 1')
  925. )
  926. cable7.full_clean()
  927. cable7.save()
  928. # Retrieve endpoints
  929. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  930. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  931. endpoint_c = Interface.objects.get(device__name='Device 3', name='Interface 1')
  932. endpoint_d = Interface.objects.get(device__name='Device 4', name='Interface 1')
  933. # Validate connections
  934. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  935. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  936. self.assertEqual(endpoint_c.connected_endpoint, endpoint_d)
  937. self.assertEqual(endpoint_d.connected_endpoint, endpoint_c)
  938. self.assertTrue(endpoint_a.connection_status)
  939. self.assertTrue(endpoint_b.connection_status)
  940. self.assertTrue(endpoint_c.connection_status)
  941. self.assertTrue(endpoint_d.connection_status)
  942. # Delete cable 4
  943. cable4.delete()
  944. # Refresh endpoints
  945. endpoint_a.refresh_from_db()
  946. endpoint_b.refresh_from_db()
  947. endpoint_c.refresh_from_db()
  948. endpoint_d.refresh_from_db()
  949. # Check that connections have been nullified
  950. self.assertIsNone(endpoint_a.connected_endpoint)
  951. self.assertIsNone(endpoint_b.connected_endpoint)
  952. self.assertIsNone(endpoint_c.connected_endpoint)
  953. self.assertIsNone(endpoint_d.connected_endpoint)
  954. self.assertIsNone(endpoint_a.connection_status)
  955. self.assertIsNone(endpoint_b.connection_status)
  956. self.assertIsNone(endpoint_c.connection_status)
  957. self.assertIsNone(endpoint_d.connection_status)
  958. def test_connection_via_circuit(self):
  959. """
  960. 1 2
  961. [Device 1] ----- [Circuit] ----- [Device 2]
  962. Iface1 A Z Iface1
  963. """
  964. # Create cables
  965. cable1 = Cable(
  966. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  967. termination_b=CircuitTermination.objects.get(term_side='A')
  968. )
  969. cable1.full_clean()
  970. cable1.save()
  971. cable2 = Cable(
  972. termination_a=CircuitTermination.objects.get(term_side='Z'),
  973. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  974. )
  975. cable2.full_clean()
  976. cable2.save()
  977. # Retrieve endpoints
  978. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  979. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  980. # Validate connections
  981. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  982. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  983. self.assertTrue(endpoint_a.connection_status)
  984. self.assertTrue(endpoint_b.connection_status)
  985. # Delete circuit
  986. circuit = Circuit.objects.first().delete()
  987. # Refresh endpoints
  988. endpoint_a.refresh_from_db()
  989. endpoint_b.refresh_from_db()
  990. # Check that connections have been nullified
  991. self.assertIsNone(endpoint_a.connected_endpoint)
  992. self.assertIsNone(endpoint_b.connected_endpoint)
  993. self.assertIsNone(endpoint_a.connection_status)
  994. self.assertIsNone(endpoint_b.connection_status)
  995. def test_connection_via_patched_circuit(self):
  996. """
  997. 1 2 3 4
  998. [Device 1] ----- [Panel 1] ----- [Circuit] ----- [Panel 2] ----- [Device 2]
  999. Iface1 FP1 RP1 A Z RP1 FP1 Iface1
  1000. """
  1001. # Create cables
  1002. cable1 = Cable(
  1003. termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'),
  1004. termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1')
  1005. )
  1006. cable1.full_clean()
  1007. cable1.save()
  1008. cable2 = Cable(
  1009. termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'),
  1010. termination_b=CircuitTermination.objects.get(term_side='A')
  1011. )
  1012. cable2.full_clean()
  1013. cable2.save()
  1014. cable3 = Cable(
  1015. termination_a=CircuitTermination.objects.get(term_side='Z'),
  1016. termination_b=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1')
  1017. )
  1018. cable3.full_clean()
  1019. cable3.save()
  1020. cable4 = Cable(
  1021. termination_a=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1'),
  1022. termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1')
  1023. )
  1024. cable4.full_clean()
  1025. cable4.save()
  1026. # Retrieve endpoints
  1027. endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1')
  1028. endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1')
  1029. # Validate connections
  1030. self.assertEqual(endpoint_a.connected_endpoint, endpoint_b)
  1031. self.assertEqual(endpoint_b.connected_endpoint, endpoint_a)
  1032. self.assertTrue(endpoint_a.connection_status)
  1033. self.assertTrue(endpoint_b.connection_status)
  1034. # Delete circuit
  1035. circuit = Circuit.objects.first().delete()
  1036. # Refresh endpoints
  1037. endpoint_a.refresh_from_db()
  1038. endpoint_b.refresh_from_db()
  1039. # Check that connections have been nullified
  1040. self.assertIsNone(endpoint_a.connected_endpoint)
  1041. self.assertIsNone(endpoint_b.connected_endpoint)
  1042. self.assertIsNone(endpoint_a.connection_status)
  1043. self.assertIsNone(endpoint_b.connection_status)