test_cablepaths.py 53 KB

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