test_cablepaths.py 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  1. from django.contrib.contenttypes.models import ContentType
  2. from django.test import TestCase
  3. from circuits.models import *
  4. from dcim.choices import CableStatusChoices
  5. from dcim.models import *
  6. from dcim.utils import object_to_path_node
  7. class CablePathTestCase(TestCase):
  8. """
  9. Test NetBox's ability to trace and retrace CablePaths in response to data model changes. Tests are numbered
  10. as follows:
  11. 1XX: Test direct connections between different endpoint types
  12. 2XX: Test different cable topologies
  13. 3XX: Test responses to changes in existing objects
  14. """
  15. @classmethod
  16. def setUpTestData(cls):
  17. # Create a single device that will hold all components
  18. cls.site = Site.objects.create(name='Site', slug='site')
  19. manufacturer = Manufacturer.objects.create(name='Generic', slug='generic')
  20. device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Test Device')
  21. device_role = DeviceRole.objects.create(name='Device Role', slug='device-role')
  22. cls.device = Device.objects.create(site=cls.site, device_type=device_type, device_role=device_role, name='Test Device')
  23. cls.powerpanel = PowerPanel.objects.create(site=cls.site, name='Power Panel')
  24. provider = Provider.objects.create(name='Provider', slug='provider')
  25. circuit_type = CircuitType.objects.create(name='Circuit Type', slug='circuit-type')
  26. cls.circuit = Circuit.objects.create(provider=provider, type=circuit_type, cid='Circuit 1')
  27. def assertPathExists(self, origin, destination, path=None, is_active=None, msg=None):
  28. """
  29. Assert that a CablePath from origin to destination with a specific intermediate path exists.
  30. :param origin: Originating endpoint
  31. :param destination: Terminating endpoint, or None
  32. :param path: Sequence of objects comprising the intermediate path (optional)
  33. :param is_active: Boolean indicating whether the end-to-end path is complete and active (optional)
  34. :param msg: Custom failure message (optional)
  35. :return: The matching CablePath (if any)
  36. """
  37. kwargs = {
  38. 'origin_type': ContentType.objects.get_for_model(origin),
  39. 'origin_id': origin.pk,
  40. }
  41. if destination is not None:
  42. kwargs['destination_type'] = ContentType.objects.get_for_model(destination)
  43. kwargs['destination_id'] = destination.pk
  44. else:
  45. kwargs['destination_type__isnull'] = True
  46. kwargs['destination_id__isnull'] = True
  47. if path is not None:
  48. kwargs['path'] = [object_to_path_node(obj) for obj in path]
  49. if is_active is not None:
  50. kwargs['is_active'] = is_active
  51. if msg is None:
  52. if destination is not None:
  53. msg = f"Missing path from {origin} to {destination}"
  54. else:
  55. msg = f"Missing partial path originating from {origin}"
  56. cablepath = CablePath.objects.filter(**kwargs).first()
  57. self.assertIsNotNone(cablepath, msg=msg)
  58. return cablepath
  59. def assertPathIsSet(self, origin, cablepath, msg=None):
  60. """
  61. Assert that a specific CablePath instance is set as the path on the origin.
  62. :param origin: The originating path endpoint
  63. :param cablepath: The CablePath instance originating from this endpoint
  64. :param msg: Custom failure message (optional)
  65. """
  66. if msg is None:
  67. msg = f"Path #{cablepath.pk} not set on originating endpoint {origin}"
  68. self.assertEqual(origin._path_id, cablepath.pk, msg=msg)
  69. def assertPathIsNotSet(self, origin, msg=None):
  70. """
  71. Assert that a specific CablePath instance is set as the path on the origin.
  72. :param origin: The originating path endpoint
  73. :param msg: Custom failure message (optional)
  74. """
  75. if msg is None:
  76. msg = f"Path #{origin._path_id} set as origin on {origin}; should be None!"
  77. self.assertIsNone(origin._path_id, msg=msg)
  78. def test_101_interface_to_interface(self):
  79. """
  80. [IF1] --C1-- [IF2]
  81. """
  82. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  83. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  84. # Create cable 1
  85. cable1 = Cable(termination_a=interface1, termination_b=interface2)
  86. cable1.save()
  87. path1 = self.assertPathExists(
  88. origin=interface1,
  89. destination=interface2,
  90. path=(cable1,),
  91. is_active=True
  92. )
  93. path2 = self.assertPathExists(
  94. origin=interface2,
  95. destination=interface1,
  96. path=(cable1,),
  97. is_active=True
  98. )
  99. self.assertEqual(CablePath.objects.count(), 2)
  100. interface1.refresh_from_db()
  101. interface2.refresh_from_db()
  102. self.assertPathIsSet(interface1, path1)
  103. self.assertPathIsSet(interface2, path2)
  104. # Delete cable 1
  105. cable1.delete()
  106. # Check that all CablePaths have been deleted
  107. self.assertEqual(CablePath.objects.count(), 0)
  108. def test_102_consoleport_to_consoleserverport(self):
  109. """
  110. [CP1] --C1-- [CSP1]
  111. """
  112. consoleport1 = ConsolePort.objects.create(device=self.device, name='Console Port 1')
  113. consoleserverport1 = ConsoleServerPort.objects.create(device=self.device, name='Console Server Port 1')
  114. # Create cable 1
  115. cable1 = Cable(termination_a=consoleport1, termination_b=consoleserverport1)
  116. cable1.save()
  117. path1 = self.assertPathExists(
  118. origin=consoleport1,
  119. destination=consoleserverport1,
  120. path=(cable1,),
  121. is_active=True
  122. )
  123. path2 = self.assertPathExists(
  124. origin=consoleserverport1,
  125. destination=consoleport1,
  126. path=(cable1,),
  127. is_active=True
  128. )
  129. self.assertEqual(CablePath.objects.count(), 2)
  130. consoleport1.refresh_from_db()
  131. consoleserverport1.refresh_from_db()
  132. self.assertPathIsSet(consoleport1, path1)
  133. self.assertPathIsSet(consoleserverport1, path2)
  134. # Delete cable 1
  135. cable1.delete()
  136. # Check that all CablePaths have been deleted
  137. self.assertEqual(CablePath.objects.count(), 0)
  138. def test_103_powerport_to_poweroutlet(self):
  139. """
  140. [PP1] --C1-- [PO1]
  141. """
  142. powerport1 = PowerPort.objects.create(device=self.device, name='Power Port 1')
  143. poweroutlet1 = PowerOutlet.objects.create(device=self.device, name='Power Outlet 1')
  144. # Create cable 1
  145. cable1 = Cable(termination_a=powerport1, termination_b=poweroutlet1)
  146. cable1.save()
  147. path1 = self.assertPathExists(
  148. origin=powerport1,
  149. destination=poweroutlet1,
  150. path=(cable1,),
  151. is_active=True
  152. )
  153. path2 = self.assertPathExists(
  154. origin=poweroutlet1,
  155. destination=powerport1,
  156. path=(cable1,),
  157. is_active=True
  158. )
  159. self.assertEqual(CablePath.objects.count(), 2)
  160. powerport1.refresh_from_db()
  161. poweroutlet1.refresh_from_db()
  162. self.assertPathIsSet(powerport1, path1)
  163. self.assertPathIsSet(poweroutlet1, path2)
  164. # Delete cable 1
  165. cable1.delete()
  166. # Check that all CablePaths have been deleted
  167. self.assertEqual(CablePath.objects.count(), 0)
  168. def test_104_powerport_to_powerfeed(self):
  169. """
  170. [PP1] --C1-- [PF1]
  171. """
  172. powerport1 = PowerPort.objects.create(device=self.device, name='Power Port 1')
  173. powerfeed1 = PowerFeed.objects.create(power_panel=self.powerpanel, name='Power Feed 1')
  174. # Create cable 1
  175. cable1 = Cable(termination_a=powerport1, termination_b=powerfeed1)
  176. cable1.save()
  177. path1 = self.assertPathExists(
  178. origin=powerport1,
  179. destination=powerfeed1,
  180. path=(cable1,),
  181. is_active=True
  182. )
  183. path2 = self.assertPathExists(
  184. origin=powerfeed1,
  185. destination=powerport1,
  186. path=(cable1,),
  187. is_active=True
  188. )
  189. self.assertEqual(CablePath.objects.count(), 2)
  190. powerport1.refresh_from_db()
  191. powerfeed1.refresh_from_db()
  192. self.assertPathIsSet(powerport1, path1)
  193. self.assertPathIsSet(powerfeed1, path2)
  194. # Delete cable 1
  195. cable1.delete()
  196. # Check that all CablePaths have been deleted
  197. self.assertEqual(CablePath.objects.count(), 0)
  198. def test_201_single_path_via_pass_through(self):
  199. """
  200. [IF1] --C1-- [FP1] [RP1] --C2-- [IF2]
  201. """
  202. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  203. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  204. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1)
  205. frontport1 = FrontPort.objects.create(
  206. device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1
  207. )
  208. # Create cable 1
  209. cable1 = Cable(termination_a=interface1, termination_b=frontport1)
  210. cable1.save()
  211. self.assertPathExists(
  212. origin=interface1,
  213. destination=None,
  214. path=(cable1, frontport1, rearport1),
  215. is_active=False
  216. )
  217. self.assertEqual(CablePath.objects.count(), 1)
  218. # Create cable 2
  219. cable2 = Cable(termination_a=rearport1, termination_b=interface2)
  220. cable2.save()
  221. self.assertPathExists(
  222. origin=interface1,
  223. destination=interface2,
  224. path=(cable1, frontport1, rearport1, cable2),
  225. is_active=True
  226. )
  227. self.assertPathExists(
  228. origin=interface2,
  229. destination=interface1,
  230. path=(cable2, rearport1, frontport1, cable1),
  231. is_active=True
  232. )
  233. self.assertEqual(CablePath.objects.count(), 2)
  234. # Delete cable 2
  235. cable2.delete()
  236. path1 = self.assertPathExists(
  237. origin=interface1,
  238. destination=None,
  239. path=(cable1, frontport1, rearport1),
  240. is_active=False
  241. )
  242. self.assertEqual(CablePath.objects.count(), 1)
  243. interface1.refresh_from_db()
  244. interface2.refresh_from_db()
  245. self.assertPathIsSet(interface1, path1)
  246. self.assertPathIsNotSet(interface2)
  247. def test_202_multiple_paths_via_pass_through(self):
  248. """
  249. [IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [IF3]
  250. [IF2] --C2-- [FP1:2] [FP2:2] --C5-- [IF4]
  251. """
  252. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  253. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  254. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  255. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  256. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  257. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  258. frontport1_1 = FrontPort.objects.create(
  259. device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1
  260. )
  261. frontport1_2 = FrontPort.objects.create(
  262. device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2
  263. )
  264. frontport2_1 = FrontPort.objects.create(
  265. device=self.device, name='Front Port 2:1', rear_port=rearport2, rear_port_position=1
  266. )
  267. frontport2_2 = FrontPort.objects.create(
  268. device=self.device, name='Front Port 2:2', rear_port=rearport2, rear_port_position=2
  269. )
  270. # Create cables 1-2
  271. cable1 = Cable(termination_a=interface1, termination_b=frontport1_1)
  272. cable1.save()
  273. cable2 = Cable(termination_a=interface2, termination_b=frontport1_2)
  274. cable2.save()
  275. self.assertPathExists(
  276. origin=interface1,
  277. destination=None,
  278. path=(cable1, frontport1_1, rearport1),
  279. is_active=False
  280. )
  281. self.assertPathExists(
  282. origin=interface2,
  283. destination=None,
  284. path=(cable2, frontport1_2, rearport1),
  285. is_active=False
  286. )
  287. self.assertEqual(CablePath.objects.count(), 2)
  288. # Create cable 3
  289. cable3 = Cable(termination_a=rearport1, termination_b=rearport2)
  290. cable3.save()
  291. self.assertPathExists(
  292. origin=interface1,
  293. destination=None,
  294. path=(cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1),
  295. is_active=False
  296. )
  297. self.assertPathExists(
  298. origin=interface2,
  299. destination=None,
  300. path=(cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2),
  301. is_active=False
  302. )
  303. self.assertEqual(CablePath.objects.count(), 2)
  304. # Create cables 4-5
  305. cable4 = Cable(termination_a=frontport2_1, termination_b=interface3)
  306. cable4.save()
  307. cable5 = Cable(termination_a=frontport2_2, termination_b=interface4)
  308. cable5.save()
  309. path1 = self.assertPathExists(
  310. origin=interface1,
  311. destination=interface3,
  312. path=(
  313. cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1,
  314. cable4,
  315. ),
  316. is_active=True
  317. )
  318. path2 = self.assertPathExists(
  319. origin=interface2,
  320. destination=interface4,
  321. path=(
  322. cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2,
  323. cable5,
  324. ),
  325. is_active=True
  326. )
  327. path3 = self.assertPathExists(
  328. origin=interface3,
  329. destination=interface1,
  330. path=(
  331. cable4, frontport2_1, rearport2, cable3, rearport1, frontport1_1,
  332. cable1
  333. ),
  334. is_active=True
  335. )
  336. path4 = self.assertPathExists(
  337. origin=interface4,
  338. destination=interface2,
  339. path=(
  340. cable5, frontport2_2, rearport2, cable3, rearport1, frontport1_2,
  341. cable2
  342. ),
  343. is_active=True
  344. )
  345. self.assertEqual(CablePath.objects.count(), 4)
  346. # Delete cable 3
  347. cable3.delete()
  348. # Check for four partial paths; one from each interface
  349. self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4)
  350. self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0)
  351. interface1.refresh_from_db()
  352. interface2.refresh_from_db()
  353. interface3.refresh_from_db()
  354. interface4.refresh_from_db()
  355. self.assertPathIsSet(interface1, path1)
  356. self.assertPathIsSet(interface2, path2)
  357. self.assertPathIsSet(interface3, path3)
  358. self.assertPathIsSet(interface4, path4)
  359. def test_203_multiple_paths_via_nested_pass_throughs(self):
  360. """
  361. [IF1] --C1-- [FP1:1] [RP1] --C3-- [FP2] [RP2] --C4-- [RP3] [FP3] --C5-- [RP4] [FP4:1] --C6-- [IF3]
  362. [IF2] --C2-- [FP1:2] [FP4:2] --C7-- [IF4]
  363. """
  364. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  365. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  366. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  367. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  368. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  369. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1)
  370. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3', positions=1)
  371. rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4', positions=4)
  372. frontport1_1 = FrontPort.objects.create(
  373. device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1
  374. )
  375. frontport1_2 = FrontPort.objects.create(
  376. device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2
  377. )
  378. frontport2 = FrontPort.objects.create(
  379. device=self.device, name='Front Port 2', rear_port=rearport2, rear_port_position=1
  380. )
  381. frontport3 = FrontPort.objects.create(
  382. device=self.device, name='Front Port 3', rear_port=rearport3, rear_port_position=1
  383. )
  384. frontport4_1 = FrontPort.objects.create(
  385. device=self.device, name='Front Port 4:1', rear_port=rearport4, rear_port_position=1
  386. )
  387. frontport4_2 = FrontPort.objects.create(
  388. device=self.device, name='Front Port 4:2', rear_port=rearport4, rear_port_position=2
  389. )
  390. # Create cables 1-2, 6-7
  391. cable1 = Cable(termination_a=interface1, termination_b=frontport1_1)
  392. cable1.save()
  393. cable2 = Cable(termination_a=interface2, termination_b=frontport1_2)
  394. cable2.save()
  395. cable6 = Cable(termination_a=interface3, termination_b=frontport4_1)
  396. cable6.save()
  397. cable7 = Cable(termination_a=interface4, termination_b=frontport4_2)
  398. cable7.save()
  399. self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface
  400. # Create cables 3 and 5
  401. cable3 = Cable(termination_a=rearport1, termination_b=frontport2)
  402. cable3.save()
  403. cable5 = Cable(termination_a=rearport4, termination_b=frontport3)
  404. cable5.save()
  405. self.assertEqual(CablePath.objects.count(), 4) # Four (longer) partial paths; one from each interface
  406. # Create cable 4
  407. cable4 = Cable(termination_a=rearport2, termination_b=rearport3)
  408. cable4.save()
  409. self.assertPathExists(
  410. origin=interface1,
  411. destination=interface3,
  412. path=(
  413. cable1, frontport1_1, rearport1, cable3, frontport2, rearport2,
  414. cable4, rearport3, frontport3, cable5, rearport4, frontport4_1,
  415. cable6
  416. ),
  417. is_active=True
  418. )
  419. self.assertPathExists(
  420. origin=interface2,
  421. destination=interface4,
  422. path=(
  423. cable2, frontport1_2, rearport1, cable3, frontport2, rearport2,
  424. cable4, rearport3, frontport3, cable5, rearport4, frontport4_2,
  425. cable7
  426. ),
  427. is_active=True
  428. )
  429. self.assertPathExists(
  430. origin=interface3,
  431. destination=interface1,
  432. path=(
  433. cable6, frontport4_1, rearport4, cable5, frontport3, rearport3,
  434. cable4, rearport2, frontport2, cable3, rearport1, frontport1_1,
  435. cable1
  436. ),
  437. is_active=True
  438. )
  439. self.assertPathExists(
  440. origin=interface4,
  441. destination=interface2,
  442. path=(
  443. cable7, frontport4_2, rearport4, cable5, frontport3, rearport3,
  444. cable4, rearport2, frontport2, cable3, rearport1, frontport1_2,
  445. cable2
  446. ),
  447. is_active=True
  448. )
  449. self.assertEqual(CablePath.objects.count(), 4)
  450. # Delete cable 3
  451. cable3.delete()
  452. # Check for four partial paths; one from each interface
  453. self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4)
  454. self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0)
  455. def test_204_multiple_paths_via_multiple_pass_throughs(self):
  456. """
  457. [IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [FP3:1] [RP3] --C6-- [RP4] [FP4:1] --C7-- [IF3]
  458. [IF2] --C2-- [FP1:2] [FP2:1] --C5-- [FP3:1] [FP4:2] --C8-- [IF4]
  459. """
  460. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  461. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  462. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  463. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  464. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  465. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  466. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3', positions=4)
  467. rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4', positions=4)
  468. frontport1_1 = FrontPort.objects.create(
  469. device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1
  470. )
  471. frontport1_2 = FrontPort.objects.create(
  472. device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2
  473. )
  474. frontport2_1 = FrontPort.objects.create(
  475. device=self.device, name='Front Port 2:1', rear_port=rearport2, rear_port_position=1
  476. )
  477. frontport2_2 = FrontPort.objects.create(
  478. device=self.device, name='Front Port 2:2', rear_port=rearport2, rear_port_position=2
  479. )
  480. frontport3_1 = FrontPort.objects.create(
  481. device=self.device, name='Front Port 3:1', rear_port=rearport3, rear_port_position=1
  482. )
  483. frontport3_2 = FrontPort.objects.create(
  484. device=self.device, name='Front Port 3:2', rear_port=rearport3, rear_port_position=2
  485. )
  486. frontport4_1 = FrontPort.objects.create(
  487. device=self.device, name='Front Port 4:1', rear_port=rearport4, rear_port_position=1
  488. )
  489. frontport4_2 = FrontPort.objects.create(
  490. device=self.device, name='Front Port 4:2', rear_port=rearport4, rear_port_position=2
  491. )
  492. # Create cables 1-3, 6-8
  493. cable1 = Cable(termination_a=interface1, termination_b=frontport1_1)
  494. cable1.save()
  495. cable2 = Cable(termination_a=interface2, termination_b=frontport1_2)
  496. cable2.save()
  497. cable3 = Cable(termination_a=rearport1, termination_b=rearport2)
  498. cable3.save()
  499. cable6 = Cable(termination_a=rearport3, termination_b=rearport4)
  500. cable6.save()
  501. cable7 = Cable(termination_a=interface3, termination_b=frontport4_1)
  502. cable7.save()
  503. cable8 = Cable(termination_a=interface4, termination_b=frontport4_2)
  504. cable8.save()
  505. self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface
  506. # Create cables 4 and 5
  507. cable4 = Cable(termination_a=frontport2_1, termination_b=frontport3_1)
  508. cable4.save()
  509. cable5 = Cable(termination_a=frontport2_2, termination_b=frontport3_2)
  510. cable5.save()
  511. self.assertPathExists(
  512. origin=interface1,
  513. destination=interface3,
  514. path=(
  515. cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1,
  516. cable4, frontport3_1, rearport3, cable6, rearport4, frontport4_1,
  517. cable7
  518. ),
  519. is_active=True
  520. )
  521. self.assertPathExists(
  522. origin=interface2,
  523. destination=interface4,
  524. path=(
  525. cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2,
  526. cable5, frontport3_2, rearport3, cable6, rearport4, frontport4_2,
  527. cable8
  528. ),
  529. is_active=True
  530. )
  531. self.assertPathExists(
  532. origin=interface3,
  533. destination=interface1,
  534. path=(
  535. cable7, frontport4_1, rearport4, cable6, rearport3, frontport3_1,
  536. cable4, frontport2_1, rearport2, cable3, rearport1, frontport1_1,
  537. cable1
  538. ),
  539. is_active=True
  540. )
  541. self.assertPathExists(
  542. origin=interface4,
  543. destination=interface2,
  544. path=(
  545. cable8, frontport4_2, rearport4, cable6, rearport3, frontport3_2,
  546. cable5, frontport2_2, rearport2, cable3, rearport1, frontport1_2,
  547. cable2
  548. ),
  549. is_active=True
  550. )
  551. self.assertEqual(CablePath.objects.count(), 4)
  552. # Delete cable 5
  553. cable5.delete()
  554. # Check for two complete paths (IF1 <--> IF2) and two partial (IF3 <--> IF4)
  555. self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 2)
  556. self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 2)
  557. def test_205_multiple_paths_via_patched_pass_throughs(self):
  558. """
  559. [IF1] --C1-- [FP1:1] [RP1] --C3-- [FP2] [RP2] --C4-- [RP3] [FP3:1] --C5-- [IF3]
  560. [IF2] --C2-- [FP1:2] [FP3:2] --C6-- [IF4]
  561. """
  562. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  563. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  564. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  565. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  566. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  567. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 5', positions=1)
  568. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  569. frontport1_1 = FrontPort.objects.create(
  570. device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1
  571. )
  572. frontport1_2 = FrontPort.objects.create(
  573. device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2
  574. )
  575. frontport2 = FrontPort.objects.create(
  576. device=self.device, name='Front Port 5', rear_port=rearport2, rear_port_position=1
  577. )
  578. frontport3_1 = FrontPort.objects.create(
  579. device=self.device, name='Front Port 2:1', rear_port=rearport3, rear_port_position=1
  580. )
  581. frontport3_2 = FrontPort.objects.create(
  582. device=self.device, name='Front Port 2:2', rear_port=rearport3, rear_port_position=2
  583. )
  584. # Create cables 1-2, 5-6
  585. cable1 = Cable(termination_a=interface1, termination_b=frontport1_1) # IF1 -> FP1:1
  586. cable1.save()
  587. cable2 = Cable(termination_a=interface2, termination_b=frontport1_2) # IF2 -> FP1:2
  588. cable2.save()
  589. cable5 = Cable(termination_a=interface3, termination_b=frontport3_1) # IF3 -> FP3:1
  590. cable5.save()
  591. cable6 = Cable(termination_a=interface4, termination_b=frontport3_2) # IF4 -> FP3:2
  592. cable6.save()
  593. self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface
  594. # Create cables 3-4
  595. cable3 = Cable(termination_a=rearport1, termination_b=frontport2) # RP1 -> FP2
  596. cable3.save()
  597. cable4 = Cable(termination_a=rearport2, termination_b=rearport3) # RP2 -> RP3
  598. cable4.save()
  599. self.assertPathExists(
  600. origin=interface1,
  601. destination=interface3,
  602. path=(
  603. cable1, frontport1_1, rearport1, cable3, frontport2, rearport2,
  604. cable4, rearport3, frontport3_1, cable5
  605. ),
  606. is_active=True
  607. )
  608. self.assertPathExists(
  609. origin=interface2,
  610. destination=interface4,
  611. path=(
  612. cable2, frontport1_2, rearport1, cable3, frontport2, rearport2,
  613. cable4, rearport3, frontport3_2, cable6
  614. ),
  615. is_active=True
  616. )
  617. self.assertPathExists(
  618. origin=interface3,
  619. destination=interface1,
  620. path=(
  621. cable5, frontport3_1, rearport3, cable4, rearport2, frontport2,
  622. cable3, rearport1, frontport1_1, cable1
  623. ),
  624. is_active=True
  625. )
  626. self.assertPathExists(
  627. origin=interface4,
  628. destination=interface2,
  629. path=(
  630. cable6, frontport3_2, rearport3, cable4, rearport2, frontport2,
  631. cable3, rearport1, frontport1_2, cable2
  632. ),
  633. is_active=True
  634. )
  635. self.assertEqual(CablePath.objects.count(), 4)
  636. # Delete cable 3
  637. cable3.delete()
  638. # Check for four partial paths; one from each interface
  639. self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4)
  640. self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0)
  641. def test_206_unidirectional_split_paths(self):
  642. """
  643. [IF1] --C1-- [RP1] [FP1:1] --C2-- [IF2]
  644. [FP1:2] --C3-- [IF3]
  645. """
  646. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  647. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  648. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  649. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  650. frontport1_1 = FrontPort.objects.create(
  651. device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1
  652. )
  653. frontport1_2 = FrontPort.objects.create(
  654. device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2
  655. )
  656. # Create cables 1
  657. cable1 = Cable(termination_a=interface1, termination_b=rearport1)
  658. cable1.save()
  659. self.assertPathExists(
  660. origin=interface1,
  661. destination=None,
  662. path=(cable1, rearport1),
  663. is_active=False
  664. )
  665. self.assertEqual(CablePath.objects.count(), 1)
  666. # Create cables 2-3
  667. cable2 = Cable(termination_a=interface2, termination_b=frontport1_1)
  668. cable2.save()
  669. cable3 = Cable(termination_a=interface3, termination_b=frontport1_2)
  670. cable3.save()
  671. self.assertPathExists(
  672. origin=interface2,
  673. destination=interface1,
  674. path=(cable2, frontport1_1, rearport1, cable1),
  675. is_active=True
  676. )
  677. self.assertPathExists(
  678. origin=interface3,
  679. destination=interface1,
  680. path=(cable3, frontport1_2, rearport1, cable1),
  681. is_active=True
  682. )
  683. self.assertEqual(CablePath.objects.count(), 3)
  684. # Delete cable 1
  685. cable1.delete()
  686. # Check that the partial path was deleted and the two complete paths are now partial
  687. self.assertPathExists(
  688. origin=interface2,
  689. destination=None,
  690. path=(cable2, frontport1_1, rearport1),
  691. is_active=False
  692. )
  693. self.assertPathExists(
  694. origin=interface3,
  695. destination=None,
  696. path=(cable3, frontport1_2, rearport1),
  697. is_active=False
  698. )
  699. self.assertEqual(CablePath.objects.count(), 2)
  700. def test_207_rearport_without_frontport(self):
  701. """
  702. [IF1] --C1-- [FP1] [RP1] --C2-- [RP2]
  703. """
  704. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  705. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1)
  706. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1)
  707. frontport1 = FrontPort.objects.create(
  708. device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1
  709. )
  710. # Create cables
  711. cable1 = Cable(termination_a=interface1, termination_b=frontport1)
  712. cable1.save()
  713. cable2 = Cable(termination_a=rearport1, termination_b=rearport2)
  714. cable2.save()
  715. self.assertPathExists(
  716. origin=interface1,
  717. destination=None,
  718. path=(cable1, frontport1, rearport1, cable2, rearport2),
  719. is_active=False
  720. )
  721. self.assertEqual(CablePath.objects.count(), 1)
  722. def test_208_circuittermination(self):
  723. """
  724. [IF1] --C1-- [CT1]
  725. """
  726. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  727. circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A')
  728. # Create cable 1
  729. cable1 = Cable(termination_a=interface1, termination_b=circuittermination1)
  730. cable1.save()
  731. # Check for incomplete path
  732. self.assertPathExists(
  733. origin=interface1,
  734. destination=None,
  735. path=(cable1, circuittermination1),
  736. is_active=False
  737. )
  738. self.assertEqual(CablePath.objects.count(), 1)
  739. # Delete cable 1
  740. cable1.delete()
  741. self.assertEqual(CablePath.objects.count(), 0)
  742. interface1.refresh_from_db()
  743. self.assertPathIsNotSet(interface1)
  744. def test_209_circuit_to_interface(self):
  745. """
  746. [IF1] --C1-- [CT1] [CT2] --C2-- [IF2]
  747. """
  748. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  749. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  750. circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A')
  751. # Create cable 1
  752. cable1 = Cable(termination_a=interface1, termination_b=circuittermination1)
  753. cable1.save()
  754. # Check for partial path from interface1
  755. self.assertPathExists(
  756. origin=interface1,
  757. destination=None,
  758. path=(cable1, circuittermination1),
  759. is_active=False
  760. )
  761. # Create CT2
  762. circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='Z')
  763. # Check for partial path to site
  764. self.assertPathExists(
  765. origin=interface1,
  766. destination=self.site,
  767. path=(cable1, circuittermination1, circuittermination2),
  768. is_active=True
  769. )
  770. # Create cable 2
  771. cable2 = Cable(termination_a=circuittermination2, termination_b=interface2)
  772. cable2.save()
  773. # Check for complete path in each direction
  774. self.assertPathExists(
  775. origin=interface1,
  776. destination=interface2,
  777. path=(cable1, circuittermination1, circuittermination2, cable2),
  778. is_active=True
  779. )
  780. self.assertPathExists(
  781. origin=interface2,
  782. destination=interface1,
  783. path=(cable2, circuittermination2, circuittermination1, cable1),
  784. is_active=True
  785. )
  786. self.assertEqual(CablePath.objects.count(), 2)
  787. # Delete cable 2
  788. cable2.delete()
  789. path1 = self.assertPathExists(
  790. origin=interface1,
  791. destination=self.site,
  792. path=(cable1, circuittermination1, circuittermination2),
  793. is_active=True
  794. )
  795. self.assertEqual(CablePath.objects.count(), 1)
  796. interface1.refresh_from_db()
  797. interface2.refresh_from_db()
  798. self.assertPathIsSet(interface1, path1)
  799. self.assertPathIsNotSet(interface2)
  800. def test_210_circuit_to_site(self):
  801. """
  802. [IF1] --C1-- [CT1] [CT2] --> [Site2]
  803. """
  804. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  805. site2 = Site.objects.create(name='Site 2', slug='site-2')
  806. circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A')
  807. circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=site2, term_side='Z')
  808. # Create cable 1
  809. cable1 = Cable(termination_a=interface1, termination_b=circuittermination1)
  810. cable1.save()
  811. self.assertPathExists(
  812. origin=interface1,
  813. destination=site2,
  814. path=(cable1, circuittermination1, circuittermination2),
  815. is_active=True
  816. )
  817. self.assertEqual(CablePath.objects.count(), 1)
  818. # Delete cable 1
  819. cable1.delete()
  820. self.assertEqual(CablePath.objects.count(), 0)
  821. interface1.refresh_from_db()
  822. self.assertPathIsNotSet(interface1)
  823. def test_211_circuit_to_providernetwork(self):
  824. """
  825. [IF1] --C1-- [CT1] [CT2] --> [PN1]
  826. """
  827. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  828. providernetwork = ProviderNetwork.objects.create(name='Provider Network 1', provider=self.circuit.provider)
  829. circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A')
  830. circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, provider_network=providernetwork, term_side='Z')
  831. # Create cable 1
  832. cable1 = Cable(termination_a=interface1, termination_b=circuittermination1)
  833. cable1.save()
  834. self.assertPathExists(
  835. origin=interface1,
  836. destination=providernetwork,
  837. path=(cable1, circuittermination1, circuittermination2),
  838. is_active=True
  839. )
  840. self.assertEqual(CablePath.objects.count(), 1)
  841. # Delete cable 1
  842. cable1.delete()
  843. self.assertEqual(CablePath.objects.count(), 0)
  844. interface1.refresh_from_db()
  845. self.assertPathIsNotSet(interface1)
  846. def test_212_multiple_paths_via_circuit(self):
  847. """
  848. [IF1] --C1-- [FP1:1] [RP1] --C3-- [CT1] [CT2] --C4-- [RP2] [FP2:1] --C5-- [IF3]
  849. [IF2] --C2-- [FP1:2] [FP2:2] --C6-- [IF4]
  850. """
  851. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  852. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  853. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  854. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  855. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  856. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  857. frontport1_1 = FrontPort.objects.create(
  858. device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1
  859. )
  860. frontport1_2 = FrontPort.objects.create(
  861. device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2
  862. )
  863. frontport2_1 = FrontPort.objects.create(
  864. device=self.device, name='Front Port 2:1', rear_port=rearport2, rear_port_position=1
  865. )
  866. frontport2_2 = FrontPort.objects.create(
  867. device=self.device, name='Front Port 2:2', rear_port=rearport2, rear_port_position=2
  868. )
  869. circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A')
  870. circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='Z')
  871. # Create cables
  872. cable1 = Cable(termination_a=interface1, termination_b=frontport1_1) # IF1 -> FP1:1
  873. cable1.save()
  874. cable2 = Cable(termination_a=interface2, termination_b=frontport1_2) # IF2 -> FP1:2
  875. cable2.save()
  876. cable3 = Cable(termination_a=rearport1, termination_b=circuittermination1) # RP1 -> CT1
  877. cable3.save()
  878. cable4 = Cable(termination_a=rearport2, termination_b=circuittermination2) # RP2 -> CT2
  879. cable4.save()
  880. cable5 = Cable(termination_a=interface3, termination_b=frontport2_1) # IF3 -> FP2:1
  881. cable5.save()
  882. cable6 = Cable(termination_a=interface4, termination_b=frontport2_2) # IF4 -> FP2:2
  883. cable6.save()
  884. self.assertPathExists(
  885. origin=interface1,
  886. destination=interface3,
  887. path=(
  888. cable1, frontport1_1, rearport1, cable3, circuittermination1, circuittermination2,
  889. cable4, rearport2, frontport2_1, cable5
  890. ),
  891. is_active=True
  892. )
  893. self.assertPathExists(
  894. origin=interface2,
  895. destination=interface4,
  896. path=(
  897. cable2, frontport1_2, rearport1, cable3, circuittermination1, circuittermination2,
  898. cable4, rearport2, frontport2_2, cable6
  899. ),
  900. is_active=True
  901. )
  902. self.assertPathExists(
  903. origin=interface3,
  904. destination=interface1,
  905. path=(
  906. cable5, frontport2_1, rearport2, cable4, circuittermination2, circuittermination1,
  907. cable3, rearport1, frontport1_1, cable1
  908. ),
  909. is_active=True
  910. )
  911. self.assertPathExists(
  912. origin=interface4,
  913. destination=interface2,
  914. path=(
  915. cable6, frontport2_2, rearport2, cable4, circuittermination2, circuittermination1,
  916. cable3, rearport1, frontport1_2, cable2
  917. ),
  918. is_active=True
  919. )
  920. self.assertEqual(CablePath.objects.count(), 4)
  921. # Delete cables 3-4
  922. cable3.delete()
  923. cable4.delete()
  924. # Check for four partial paths; one from each interface
  925. self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4)
  926. self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0)
  927. def test_213_multiple_circuits_to_interface(self):
  928. """
  929. [IF1] --C1-- [CT1] [CT2] --C2-- [CT3] [CT4] --C3-- [IF2]
  930. """
  931. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  932. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  933. circuit2 = Circuit.objects.create(provider=self.circuit.provider, type=self.circuit.type, cid='Circuit 2')
  934. circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A')
  935. circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='Z')
  936. circuittermination3 = CircuitTermination.objects.create(circuit=circuit2, site=self.site, term_side='A')
  937. circuittermination4 = CircuitTermination.objects.create(circuit=circuit2, site=self.site, term_side='Z')
  938. # Create cables
  939. cable1 = Cable(termination_a=interface1, termination_b=circuittermination1)
  940. cable1.save()
  941. cable2 = Cable(termination_a=circuittermination2, termination_b=circuittermination3)
  942. cable2.save()
  943. cable3 = Cable(termination_a=circuittermination4, termination_b=interface2)
  944. cable3.save()
  945. # Check for paths
  946. self.assertPathExists(
  947. origin=interface1,
  948. destination=interface2,
  949. path=(
  950. cable1, circuittermination1, circuittermination2, cable2, circuittermination3, circuittermination4,
  951. cable3
  952. ),
  953. is_active=True
  954. )
  955. self.assertPathExists(
  956. origin=interface2,
  957. destination=interface1,
  958. path=(
  959. cable3, circuittermination4, circuittermination3, cable2, circuittermination2, circuittermination1,
  960. cable1
  961. ),
  962. is_active=True
  963. )
  964. self.assertEqual(CablePath.objects.count(), 2)
  965. # Delete cable 2
  966. cable2.delete()
  967. path1 = self.assertPathExists(
  968. origin=interface1,
  969. destination=self.site,
  970. path=(cable1, circuittermination1, circuittermination2),
  971. is_active=True
  972. )
  973. path2 = self.assertPathExists(
  974. origin=interface2,
  975. destination=self.site,
  976. path=(cable3, circuittermination4, circuittermination3),
  977. is_active=True
  978. )
  979. self.assertEqual(CablePath.objects.count(), 2)
  980. interface1.refresh_from_db()
  981. interface2.refresh_from_db()
  982. self.assertPathIsSet(interface1, path1)
  983. self.assertPathIsSet(interface2, path2)
  984. def test_301_create_path_via_existing_cable(self):
  985. """
  986. [IF1] --C1-- [FP1] [RP2] --C2-- [RP2] [FP2] --C3-- [IF2]
  987. """
  988. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  989. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  990. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1)
  991. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1)
  992. frontport1 = FrontPort.objects.create(
  993. device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1
  994. )
  995. frontport2 = FrontPort.objects.create(
  996. device=self.device, name='Front Port 2', rear_port=rearport2, rear_port_position=1
  997. )
  998. # Create cable 2
  999. cable2 = Cable(termination_a=rearport1, termination_b=rearport2)
  1000. cable2.save()
  1001. self.assertEqual(CablePath.objects.count(), 0)
  1002. # Create cable1
  1003. cable1 = Cable(termination_a=interface1, termination_b=frontport1)
  1004. cable1.save()
  1005. self.assertPathExists(
  1006. origin=interface1,
  1007. destination=None,
  1008. path=(cable1, frontport1, rearport1, cable2, rearport2, frontport2),
  1009. is_active=False
  1010. )
  1011. self.assertEqual(CablePath.objects.count(), 1)
  1012. # Create cable 3
  1013. cable3 = Cable(termination_a=frontport2, termination_b=interface2)
  1014. cable3.save()
  1015. self.assertPathExists(
  1016. origin=interface1,
  1017. destination=interface2,
  1018. path=(cable1, frontport1, rearport1, cable2, rearport2, frontport2, cable3),
  1019. is_active=True
  1020. )
  1021. self.assertPathExists(
  1022. origin=interface2,
  1023. destination=interface1,
  1024. path=(cable3, frontport2, rearport2, cable2, rearport1, frontport1, cable1),
  1025. is_active=True
  1026. )
  1027. self.assertEqual(CablePath.objects.count(), 2)
  1028. def test_302_update_path_on_cable_status_change(self):
  1029. """
  1030. [IF1] --C1-- [FP1] [RP1] --C2-- [IF2]
  1031. """
  1032. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1033. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1034. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1)
  1035. frontport1 = FrontPort.objects.create(
  1036. device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1
  1037. )
  1038. # Create cables 1 and 2
  1039. cable1 = Cable(termination_a=interface1, termination_b=frontport1)
  1040. cable1.save()
  1041. cable2 = Cable(termination_a=rearport1, termination_b=interface2)
  1042. cable2.save()
  1043. self.assertEqual(CablePath.objects.filter(is_active=True).count(), 2)
  1044. self.assertEqual(CablePath.objects.count(), 2)
  1045. # Change cable 2's status to "planned"
  1046. cable2.status = CableStatusChoices.STATUS_PLANNED
  1047. cable2.save()
  1048. self.assertPathExists(
  1049. origin=interface1,
  1050. destination=interface2,
  1051. path=(cable1, frontport1, rearport1, cable2),
  1052. is_active=False
  1053. )
  1054. self.assertPathExists(
  1055. origin=interface2,
  1056. destination=interface1,
  1057. path=(cable2, rearport1, frontport1, cable1),
  1058. is_active=False
  1059. )
  1060. self.assertEqual(CablePath.objects.count(), 2)
  1061. # Change cable 2's status to "connected"
  1062. cable2 = Cable.objects.get(pk=cable2.pk)
  1063. cable2.status = CableStatusChoices.STATUS_CONNECTED
  1064. cable2.save()
  1065. self.assertPathExists(
  1066. origin=interface1,
  1067. destination=interface2,
  1068. path=(cable1, frontport1, rearport1, cable2),
  1069. is_active=True
  1070. )
  1071. self.assertPathExists(
  1072. origin=interface2,
  1073. destination=interface1,
  1074. path=(cable2, rearport1, frontport1, cable1),
  1075. is_active=True
  1076. )
  1077. self.assertEqual(CablePath.objects.count(), 2)