test_cablepaths.py 118 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258
  1. from circuits.models import *
  2. from dcim.choices import CableEndChoices, LinkStatusChoices
  3. from dcim.models import *
  4. from dcim.svg import CableTraceSVG
  5. from dcim.tests.utils import BaseCablePathTestCase
  6. from utilities.exceptions import AbortRequest
  7. class LegacyCablePathTestCase(BaseCablePathTestCase):
  8. """
  9. Test NetBox's ability to trace and retrace CablePaths in response to data model changes, without cable profiles.
  10. Tests are numbered 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. 4XX: Test to exclude specific cable topologies
  15. """
  16. def _create_cable_raw(self, termination_a, termination_b, status=LinkStatusChoices.STATUS_CONNECTED):
  17. """
  18. Write a Cable and its terminations directly to the database, bypassing Cable.save(). Unprofiled
  19. cables only: the connector & positions a profile assigns are not replicated here.
  20. """
  21. cable = Cable(status=status)
  22. cable.save_base(raw=True)
  23. for termination, cable_end in (
  24. (termination_a, CableEndChoices.SIDE_A),
  25. (termination_b, CableEndChoices.SIDE_B),
  26. ):
  27. ct = CableTermination(cable=cable, cable_end=cable_end, termination=termination)
  28. ct.cache_related_objects()
  29. ct.save_base(raw=True)
  30. termination.cable = cable
  31. termination.cable_end = cable_end
  32. termination.save()
  33. return cable
  34. def test_101_interface_to_interface(self):
  35. """
  36. [IF1] --C1-- [IF2]
  37. """
  38. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  39. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  40. # Create cable 1
  41. cable1 = Cable(
  42. a_terminations=[interface1],
  43. b_terminations=[interface2]
  44. )
  45. cable1.save()
  46. path1 = self.assertPathExists(
  47. (interface1, cable1, interface2),
  48. is_complete=True,
  49. is_active=True
  50. )
  51. path2 = self.assertPathExists(
  52. (interface2, cable1, interface1),
  53. is_complete=True,
  54. is_active=True
  55. )
  56. self.assertEqual(CablePath.objects.count(), 2)
  57. interface1.refresh_from_db()
  58. interface2.refresh_from_db()
  59. self.assertPathIsSet(interface1, path1)
  60. self.assertPathIsSet(interface2, path2)
  61. # Test SVG generation
  62. CableTraceSVG(interface1).render()
  63. # Delete cable 1
  64. cable1.delete()
  65. # Check that all CablePaths have been deleted
  66. self.assertEqual(CablePath.objects.count(), 0)
  67. # Check that connected interfaces are fully cleaned up
  68. interface1.refresh_from_db()
  69. interface2.refresh_from_db()
  70. self.assertIsNone(interface1.cable_id)
  71. self.assertIsNone(interface1.cable_end)
  72. self.assertPathIsNotSet(interface1)
  73. self.assertIsNone(interface2.cable_id)
  74. self.assertIsNone(interface2.cable_end)
  75. self.assertPathIsNotSet(interface2)
  76. def test_102_consoleport_to_consoleserverport(self):
  77. """
  78. [CP1] --C1-- [CSP1]
  79. """
  80. consoleport1 = ConsolePort.objects.create(device=self.device, name='Console Port 1')
  81. consoleserverport1 = ConsoleServerPort.objects.create(device=self.device, name='Console Server Port 1')
  82. # Create cable 1
  83. cable1 = Cable(
  84. a_terminations=[consoleport1],
  85. b_terminations=[consoleserverport1]
  86. )
  87. cable1.save()
  88. path1 = self.assertPathExists(
  89. (consoleport1, cable1, consoleserverport1),
  90. is_complete=True,
  91. is_active=True
  92. )
  93. path2 = self.assertPathExists(
  94. (consoleserverport1, cable1, consoleport1),
  95. is_complete=True,
  96. is_active=True
  97. )
  98. self.assertEqual(CablePath.objects.count(), 2)
  99. consoleport1.refresh_from_db()
  100. consoleserverport1.refresh_from_db()
  101. self.assertPathIsSet(consoleport1, path1)
  102. self.assertPathIsSet(consoleserverport1, path2)
  103. # Test SVG generation
  104. CableTraceSVG(consoleport1).render()
  105. # Delete cable 1
  106. cable1.delete()
  107. # Check that all CablePaths have been deleted
  108. self.assertEqual(CablePath.objects.count(), 0)
  109. def test_103_powerport_to_poweroutlet(self):
  110. """
  111. [PP1] --C1-- [PO1]
  112. """
  113. powerport1 = PowerPort.objects.create(device=self.device, name='Power Port 1')
  114. poweroutlet1 = PowerOutlet.objects.create(device=self.device, name='Power Outlet 1')
  115. # Create cable 1
  116. cable1 = Cable(
  117. a_terminations=[powerport1],
  118. b_terminations=[poweroutlet1]
  119. )
  120. cable1.save()
  121. path1 = self.assertPathExists(
  122. (powerport1, cable1, poweroutlet1),
  123. is_complete=True,
  124. is_active=True
  125. )
  126. path2 = self.assertPathExists(
  127. (poweroutlet1, cable1, powerport1),
  128. is_complete=True,
  129. is_active=True
  130. )
  131. self.assertEqual(CablePath.objects.count(), 2)
  132. powerport1.refresh_from_db()
  133. poweroutlet1.refresh_from_db()
  134. self.assertPathIsSet(powerport1, path1)
  135. self.assertPathIsSet(poweroutlet1, path2)
  136. # Test SVG generation
  137. CableTraceSVG(powerport1).render()
  138. # Delete cable 1
  139. cable1.delete()
  140. # Check that all CablePaths have been deleted
  141. self.assertEqual(CablePath.objects.count(), 0)
  142. def test_104_powerport_to_powerfeed(self):
  143. """
  144. [PP1] --C1-- [PF1]
  145. """
  146. powerport1 = PowerPort.objects.create(device=self.device, name='Power Port 1')
  147. powerfeed1 = PowerFeed.objects.create(power_panel=self.powerpanel, name='Power Feed 1')
  148. # Create cable 1
  149. cable1 = Cable(
  150. a_terminations=[powerport1],
  151. b_terminations=[powerfeed1]
  152. )
  153. cable1.save()
  154. path1 = self.assertPathExists(
  155. (powerport1, cable1, powerfeed1),
  156. is_complete=True,
  157. is_active=True
  158. )
  159. path2 = self.assertPathExists(
  160. (powerfeed1, cable1, powerport1),
  161. is_complete=True,
  162. is_active=True
  163. )
  164. self.assertEqual(CablePath.objects.count(), 2)
  165. powerport1.refresh_from_db()
  166. powerfeed1.refresh_from_db()
  167. self.assertPathIsSet(powerport1, path1)
  168. self.assertPathIsSet(powerfeed1, path2)
  169. # Test SVG generation
  170. CableTraceSVG(powerport1).render()
  171. # Delete cable 1
  172. cable1.delete()
  173. # Check that all CablePaths have been deleted
  174. self.assertEqual(CablePath.objects.count(), 0)
  175. def test_120_single_interface_to_multi_interface(self):
  176. """
  177. [IF1] --C1-- [IF2]
  178. [IF3]
  179. """
  180. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  181. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  182. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  183. # Create cable 1
  184. cable1 = Cable(
  185. a_terminations=[interface1],
  186. b_terminations=[interface2, interface3]
  187. )
  188. cable1.save()
  189. path1 = self.assertPathExists(
  190. (interface1, cable1, (interface2, interface3)),
  191. is_complete=True,
  192. is_active=True
  193. )
  194. path2 = self.assertPathExists(
  195. ((interface2, interface3), cable1, interface1),
  196. is_complete=True,
  197. is_active=True
  198. )
  199. self.assertEqual(CablePath.objects.count(), 2)
  200. interface1.refresh_from_db()
  201. interface2.refresh_from_db()
  202. interface3.refresh_from_db()
  203. self.assertPathIsSet(interface1, path1)
  204. self.assertPathIsSet(interface2, path2)
  205. self.assertPathIsSet(interface3, path2)
  206. # Test SVG generation
  207. CableTraceSVG(interface1).render()
  208. # Delete cable 1
  209. cable1.delete()
  210. # Check that all CablePaths have been deleted
  211. self.assertEqual(CablePath.objects.count(), 0)
  212. interface1.refresh_from_db()
  213. interface2.refresh_from_db()
  214. interface3.refresh_from_db()
  215. self.assertPathIsNotSet(interface1)
  216. self.assertPathIsNotSet(interface2)
  217. self.assertPathIsNotSet(interface3)
  218. def test_121_multi_interface_to_multi_interface(self):
  219. """
  220. [IF1] --C1-- [IF3]
  221. [IF2] [IF4]
  222. """
  223. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  224. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  225. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  226. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  227. # Create cable 1
  228. cable1 = Cable(
  229. a_terminations=[interface1, interface2],
  230. b_terminations=[interface3, interface4]
  231. )
  232. cable1.save()
  233. path1 = self.assertPathExists(
  234. ((interface1, interface2), cable1, (interface3, interface4)),
  235. is_complete=True,
  236. is_active=True
  237. )
  238. path2 = self.assertPathExists(
  239. ((interface3, interface4), cable1, (interface1, interface2)),
  240. is_complete=True,
  241. is_active=True
  242. )
  243. self.assertEqual(CablePath.objects.count(), 2)
  244. interface1.refresh_from_db()
  245. interface2.refresh_from_db()
  246. interface3.refresh_from_db()
  247. interface4.refresh_from_db()
  248. self.assertPathIsSet(interface1, path1)
  249. self.assertPathIsSet(interface2, path1)
  250. self.assertPathIsSet(interface3, path2)
  251. self.assertPathIsSet(interface4, path2)
  252. # Test SVG generation
  253. CableTraceSVG(interface1).render()
  254. # Delete cable 1
  255. cable1.delete()
  256. # Check that all CablePaths have been deleted
  257. self.assertEqual(CablePath.objects.count(), 0)
  258. interface1.refresh_from_db()
  259. interface2.refresh_from_db()
  260. interface3.refresh_from_db()
  261. interface4.refresh_from_db()
  262. self.assertPathIsNotSet(interface1)
  263. self.assertPathIsNotSet(interface2)
  264. self.assertPathIsNotSet(interface3)
  265. self.assertPathIsNotSet(interface4)
  266. def test_201_single_path_via_pass_through(self):
  267. """
  268. [IF1] --C1-- [FP1] [RP1] --C2-- [IF2]
  269. """
  270. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  271. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  272. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  273. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  274. PortMapping.objects.create(
  275. device=self.device,
  276. front_port=frontport1,
  277. front_port_position=1,
  278. rear_port=rearport1,
  279. rear_port_position=1
  280. )
  281. # Create cable 1
  282. cable1 = Cable(
  283. a_terminations=[interface1],
  284. b_terminations=[frontport1]
  285. )
  286. cable1.save()
  287. self.assertPathExists(
  288. (interface1, cable1, frontport1, rearport1),
  289. is_complete=False
  290. )
  291. self.assertEqual(CablePath.objects.count(), 1)
  292. # Create cable 2
  293. cable2 = Cable(
  294. a_terminations=[rearport1],
  295. b_terminations=[interface2]
  296. )
  297. cable2.save()
  298. self.assertPathExists(
  299. (interface1, cable1, frontport1, rearport1, cable2, interface2),
  300. is_complete=True,
  301. is_active=True
  302. )
  303. self.assertPathExists(
  304. (interface2, cable2, rearport1, frontport1, cable1, interface1),
  305. is_complete=True,
  306. is_active=True
  307. )
  308. self.assertEqual(CablePath.objects.count(), 2)
  309. # Test SVG generation
  310. CableTraceSVG(interface1).render()
  311. # Delete cable 2
  312. cable2.delete()
  313. path1 = self.assertPathExists(
  314. (interface1, cable1, frontport1, rearport1),
  315. is_complete=False
  316. )
  317. self.assertEqual(CablePath.objects.count(), 1)
  318. interface1.refresh_from_db()
  319. interface2.refresh_from_db()
  320. self.assertPathIsSet(interface1, path1)
  321. self.assertPathIsNotSet(interface2)
  322. def test_202_single_path_via_pass_through_with_breakouts(self):
  323. """
  324. [IF1] --C1-- [FP1] [RP1] --C2-- [IF3]
  325. [IF2] [IF4]
  326. """
  327. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  328. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  329. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  330. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  331. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  332. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  333. PortMapping.objects.create(
  334. device=self.device,
  335. front_port=frontport1,
  336. front_port_position=1,
  337. rear_port=rearport1,
  338. rear_port_position=1
  339. )
  340. # Create cable 1
  341. cable1 = Cable(
  342. a_terminations=[interface1, interface2],
  343. b_terminations=[frontport1]
  344. )
  345. cable1.save()
  346. self.assertPathExists(
  347. ([interface1, interface2], cable1, frontport1, rearport1),
  348. is_complete=False
  349. )
  350. self.assertEqual(CablePath.objects.count(), 1)
  351. # Create cable 2
  352. cable2 = Cable(
  353. a_terminations=[rearport1],
  354. b_terminations=[interface3, interface4]
  355. )
  356. cable2.save()
  357. self.assertPathExists(
  358. ([interface1, interface2], cable1, frontport1, rearport1, cable2, [interface3, interface4]),
  359. is_complete=True,
  360. is_active=True
  361. )
  362. self.assertPathExists(
  363. ([interface3, interface4], cable2, rearport1, frontport1, cable1, [interface1, interface2]),
  364. is_complete=True,
  365. is_active=True
  366. )
  367. self.assertEqual(CablePath.objects.count(), 2)
  368. # Test SVG generation
  369. CableTraceSVG(interface1).render()
  370. # Delete cable 2
  371. cable2.delete()
  372. path1 = self.assertPathExists(
  373. ([interface1, interface2], cable1, frontport1, rearport1),
  374. is_complete=False
  375. )
  376. self.assertEqual(CablePath.objects.count(), 1)
  377. interface1.refresh_from_db()
  378. interface2.refresh_from_db()
  379. self.assertPathIsSet(interface1, path1)
  380. self.assertPathIsSet(interface2, path1)
  381. self.assertPathIsNotSet(interface3)
  382. self.assertPathIsNotSet(interface4)
  383. def test_203_multiple_paths_via_pass_through(self):
  384. """
  385. [IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [IF3]
  386. [IF2] --C2-- [FP1:2] [FP2:2] --C5-- [IF4]
  387. """
  388. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  389. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  390. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  391. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  392. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  393. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  394. frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
  395. frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
  396. frontport2_1 = FrontPort.objects.create(device=self.device, name='Front Port 2:1')
  397. frontport2_2 = FrontPort.objects.create(device=self.device, name='Front Port 2:2')
  398. PortMapping.objects.bulk_create([
  399. PortMapping(
  400. device=self.device,
  401. front_port=frontport1_1,
  402. front_port_position=1,
  403. rear_port=rearport1,
  404. rear_port_position=1,
  405. ),
  406. PortMapping(
  407. device=self.device,
  408. front_port=frontport1_2,
  409. front_port_position=1,
  410. rear_port=rearport1,
  411. rear_port_position=2,
  412. ),
  413. PortMapping(
  414. device=self.device,
  415. front_port=frontport2_1,
  416. front_port_position=1,
  417. rear_port=rearport2,
  418. rear_port_position=1,
  419. ),
  420. PortMapping(
  421. device=self.device,
  422. front_port=frontport2_2,
  423. front_port_position=1,
  424. rear_port=rearport2,
  425. rear_port_position=2,
  426. ),
  427. ])
  428. # Create cables 1-2
  429. cable1 = Cable(
  430. a_terminations=[interface1],
  431. b_terminations=[frontport1_1]
  432. )
  433. cable1.save()
  434. cable2 = Cable(
  435. a_terminations=[interface2],
  436. b_terminations=[frontport1_2]
  437. )
  438. cable2.save()
  439. self.assertPathExists(
  440. (interface1, cable1, frontport1_1, rearport1),
  441. is_complete=False
  442. )
  443. self.assertPathExists(
  444. (interface2, cable2, frontport1_2, rearport1),
  445. is_complete=False
  446. )
  447. self.assertEqual(CablePath.objects.count(), 2)
  448. # Create cable 3
  449. cable3 = Cable(
  450. a_terminations=[rearport1],
  451. b_terminations=[rearport2]
  452. )
  453. cable3.save()
  454. self.assertPathExists(
  455. (interface1, cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1),
  456. is_complete=False
  457. )
  458. self.assertPathExists(
  459. (interface2, cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2),
  460. is_complete=False
  461. )
  462. self.assertEqual(CablePath.objects.count(), 2)
  463. # Create cables 4-5
  464. cable4 = Cable(
  465. a_terminations=[frontport2_1],
  466. b_terminations=[interface3]
  467. )
  468. cable4.save()
  469. cable5 = Cable(
  470. a_terminations=[frontport2_2],
  471. b_terminations=[interface4]
  472. )
  473. cable5.save()
  474. path1 = self.assertPathExists(
  475. (interface1, cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1, cable4, interface3),
  476. is_complete=True,
  477. is_active=True
  478. )
  479. path2 = self.assertPathExists(
  480. (interface2, cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2, cable5, interface4),
  481. is_complete=True,
  482. is_active=True
  483. )
  484. path3 = self.assertPathExists(
  485. (interface3, cable4, frontport2_1, rearport2, cable3, rearport1, frontport1_1, cable1, interface1),
  486. is_complete=True,
  487. is_active=True
  488. )
  489. path4 = self.assertPathExists(
  490. (interface4, cable5, frontport2_2, rearport2, cable3, rearport1, frontport1_2, cable2, interface2),
  491. is_complete=True,
  492. is_active=True
  493. )
  494. self.assertEqual(CablePath.objects.count(), 4)
  495. # Test SVG generation
  496. CableTraceSVG(interface1).render()
  497. # Delete cable 3
  498. cable3.delete()
  499. # Check for four partial paths; one from each interface
  500. self.assertEqual(CablePath.objects.filter(is_complete=False).count(), 4)
  501. self.assertEqual(CablePath.objects.filter(is_complete=True).count(), 0)
  502. interface1.refresh_from_db()
  503. interface2.refresh_from_db()
  504. interface3.refresh_from_db()
  505. interface4.refresh_from_db()
  506. self.assertPathIsSet(interface1, path1)
  507. self.assertPathIsSet(interface2, path2)
  508. self.assertPathIsSet(interface3, path3)
  509. self.assertPathIsSet(interface4, path4)
  510. def test_204_multiple_paths_via_pass_through_with_breakouts(self):
  511. """
  512. [IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [IF4]
  513. [IF2] [IF5]
  514. [IF3] --C2-- [FP1:2] [FP2:2] --C5-- [IF6]
  515. [IF4] [IF7]
  516. """
  517. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  518. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  519. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  520. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  521. interface5 = Interface.objects.create(device=self.device, name='Interface 5')
  522. interface6 = Interface.objects.create(device=self.device, name='Interface 6')
  523. interface7 = Interface.objects.create(device=self.device, name='Interface 7')
  524. interface8 = Interface.objects.create(device=self.device, name='Interface 8')
  525. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  526. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  527. frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
  528. frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
  529. frontport2_1 = FrontPort.objects.create(device=self.device, name='Front Port 2:1')
  530. frontport2_2 = FrontPort.objects.create(device=self.device, name='Front Port 2:2')
  531. PortMapping.objects.bulk_create([
  532. PortMapping(
  533. device=self.device,
  534. front_port=frontport1_1,
  535. front_port_position=1,
  536. rear_port=rearport1,
  537. rear_port_position=1,
  538. ),
  539. PortMapping(
  540. device=self.device,
  541. front_port=frontport1_2,
  542. front_port_position=1,
  543. rear_port=rearport1,
  544. rear_port_position=2,
  545. ),
  546. PortMapping(
  547. device=self.device,
  548. front_port=frontport2_1,
  549. front_port_position=1,
  550. rear_port=rearport2,
  551. rear_port_position=1,
  552. ),
  553. PortMapping(
  554. device=self.device,
  555. front_port=frontport2_2,
  556. front_port_position=1,
  557. rear_port=rearport2,
  558. rear_port_position=2,
  559. ),
  560. ])
  561. # Create cables 1-2
  562. cable1 = Cable(
  563. a_terminations=[interface1, interface2],
  564. b_terminations=[frontport1_1]
  565. )
  566. cable1.save()
  567. cable2 = Cable(
  568. a_terminations=[interface3, interface4],
  569. b_terminations=[frontport1_2]
  570. )
  571. cable2.save()
  572. self.assertPathExists(
  573. ([interface1, interface2], cable1, frontport1_1, rearport1),
  574. is_complete=False
  575. )
  576. self.assertPathExists(
  577. ([interface3, interface4], cable2, frontport1_2, rearport1),
  578. is_complete=False
  579. )
  580. self.assertEqual(CablePath.objects.count(), 2)
  581. # Create cable 3
  582. cable3 = Cable(
  583. a_terminations=[rearport1],
  584. b_terminations=[rearport2]
  585. )
  586. cable3.save()
  587. self.assertPathExists(
  588. ([interface1, interface2], cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1),
  589. is_complete=False
  590. )
  591. self.assertPathExists(
  592. ([interface3, interface4], cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2),
  593. is_complete=False
  594. )
  595. self.assertEqual(CablePath.objects.count(), 2)
  596. # Create cables 4-5
  597. cable4 = Cable(
  598. a_terminations=[frontport2_1],
  599. b_terminations=[interface5, interface6]
  600. )
  601. cable4.save()
  602. cable5 = Cable(
  603. a_terminations=[frontport2_2],
  604. b_terminations=[interface7, interface8]
  605. )
  606. cable5.save()
  607. path1 = self.assertPathExists(
  608. (
  609. [interface1, interface2],
  610. cable1,
  611. frontport1_1,
  612. rearport1,
  613. cable3,
  614. rearport2,
  615. frontport2_1,
  616. cable4,
  617. [interface5, interface6],
  618. ),
  619. is_complete=True,
  620. is_active=True,
  621. )
  622. path2 = self.assertPathExists(
  623. (
  624. [interface3, interface4],
  625. cable2,
  626. frontport1_2,
  627. rearport1,
  628. cable3,
  629. rearport2,
  630. frontport2_2,
  631. cable5,
  632. [interface7, interface8],
  633. ),
  634. is_complete=True,
  635. is_active=True,
  636. )
  637. path3 = self.assertPathExists(
  638. (
  639. [interface5, interface6],
  640. cable4,
  641. frontport2_1,
  642. rearport2,
  643. cable3,
  644. rearport1,
  645. frontport1_1,
  646. cable1,
  647. [interface1, interface2],
  648. ),
  649. is_complete=True,
  650. is_active=True,
  651. )
  652. path4 = self.assertPathExists(
  653. (
  654. [interface7, interface8],
  655. cable5,
  656. frontport2_2,
  657. rearport2,
  658. cable3,
  659. rearport1,
  660. frontport1_2,
  661. cable2,
  662. [interface3, interface4],
  663. ),
  664. is_complete=True,
  665. is_active=True,
  666. )
  667. self.assertEqual(CablePath.objects.count(), 4)
  668. # Test SVG generation
  669. CableTraceSVG(interface1).render()
  670. # Delete cable 3
  671. cable3.delete()
  672. # Check for four partial paths; one from each interface
  673. self.assertEqual(CablePath.objects.filter(is_complete=False).count(), 4)
  674. self.assertEqual(CablePath.objects.filter(is_complete=True).count(), 0)
  675. interface1.refresh_from_db()
  676. interface2.refresh_from_db()
  677. interface3.refresh_from_db()
  678. interface4.refresh_from_db()
  679. interface5.refresh_from_db()
  680. interface6.refresh_from_db()
  681. interface7.refresh_from_db()
  682. interface8.refresh_from_db()
  683. self.assertPathIsSet(interface1, path1)
  684. self.assertPathIsSet(interface2, path1)
  685. self.assertPathIsSet(interface3, path2)
  686. self.assertPathIsSet(interface4, path2)
  687. self.assertPathIsSet(interface5, path3)
  688. self.assertPathIsSet(interface6, path3)
  689. self.assertPathIsSet(interface7, path4)
  690. self.assertPathIsSet(interface8, path4)
  691. def test_205_multiple_paths_via_nested_pass_throughs(self):
  692. """
  693. [IF1] --C1-- [FP1:1] [RP1] --C3-- [FP2] [RP2] --C4-- [RP3] [FP3] --C5-- [RP4] [FP4:1] --C6-- [IF3]
  694. [IF2] --C2-- [FP1:2] [FP4:2] --C7-- [IF4]
  695. """
  696. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  697. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  698. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  699. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  700. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  701. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  702. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3')
  703. rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4', positions=4)
  704. frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
  705. frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
  706. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  707. frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 3')
  708. frontport4_1 = FrontPort.objects.create(device=self.device, name='Front Port 4:1')
  709. frontport4_2 = FrontPort.objects.create(device=self.device, name='Front Port 4:2')
  710. PortMapping.objects.bulk_create([
  711. PortMapping(
  712. device=self.device,
  713. front_port=frontport1_1,
  714. front_port_position=1,
  715. rear_port=rearport1,
  716. rear_port_position=1,
  717. ),
  718. PortMapping(
  719. device=self.device,
  720. front_port=frontport1_2,
  721. front_port_position=1,
  722. rear_port=rearport1,
  723. rear_port_position=2,
  724. ),
  725. PortMapping(
  726. device=self.device,
  727. front_port=frontport2,
  728. front_port_position=1,
  729. rear_port=rearport2,
  730. rear_port_position=1,
  731. ),
  732. PortMapping(
  733. device=self.device,
  734. front_port=frontport3,
  735. front_port_position=1,
  736. rear_port=rearport3,
  737. rear_port_position=1,
  738. ),
  739. PortMapping(
  740. device=self.device,
  741. front_port=frontport4_1,
  742. front_port_position=1,
  743. rear_port=rearport4,
  744. rear_port_position=1,
  745. ),
  746. PortMapping(
  747. device=self.device,
  748. front_port=frontport4_2,
  749. front_port_position=1,
  750. rear_port=rearport4,
  751. rear_port_position=2,
  752. ),
  753. ])
  754. # Create cables 1-2, 6-7
  755. cable1 = Cable(
  756. a_terminations=[interface1],
  757. b_terminations=[frontport1_1]
  758. )
  759. cable1.save()
  760. cable2 = Cable(
  761. a_terminations=[interface2],
  762. b_terminations=[frontport1_2]
  763. )
  764. cable2.save()
  765. cable6 = Cable(
  766. a_terminations=[interface3],
  767. b_terminations=[frontport4_1]
  768. )
  769. cable6.save()
  770. cable7 = Cable(
  771. a_terminations=[interface4],
  772. b_terminations=[frontport4_2]
  773. )
  774. cable7.save()
  775. self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface
  776. # Create cables 3 and 5
  777. cable3 = Cable(
  778. a_terminations=[rearport1],
  779. b_terminations=[frontport2]
  780. )
  781. cable3.save()
  782. cable5 = Cable(
  783. a_terminations=[rearport4],
  784. b_terminations=[frontport3]
  785. )
  786. cable5.save()
  787. self.assertEqual(CablePath.objects.count(), 4) # Four (longer) partial paths; one from each interface
  788. # Create cable 4
  789. cable4 = Cable(
  790. a_terminations=[rearport2],
  791. b_terminations=[rearport3]
  792. )
  793. cable4.save()
  794. self.assertPathExists(
  795. (
  796. interface1, cable1, frontport1_1, rearport1, cable3, frontport2, rearport2, cable4, rearport3,
  797. frontport3, cable5, rearport4, frontport4_1, cable6, interface3,
  798. ),
  799. is_complete=True,
  800. is_active=True
  801. )
  802. self.assertPathExists(
  803. (
  804. interface2, cable2, frontport1_2, rearport1, cable3, frontport2, rearport2, cable4, rearport3,
  805. frontport3, cable5, rearport4, frontport4_2, cable7, interface4,
  806. ),
  807. is_complete=True,
  808. is_active=True
  809. )
  810. self.assertPathExists(
  811. (
  812. interface3, cable6, frontport4_1, rearport4, cable5, frontport3, rearport3, cable4, rearport2,
  813. frontport2, cable3, rearport1, frontport1_1, cable1, interface1,
  814. ),
  815. is_complete=True,
  816. is_active=True
  817. )
  818. self.assertPathExists(
  819. (
  820. interface4, cable7, frontport4_2, rearport4, cable5, frontport3, rearport3, cable4, rearport2,
  821. frontport2, cable3, rearport1, frontport1_2, cable2, interface2,
  822. ),
  823. is_complete=True,
  824. is_active=True
  825. )
  826. self.assertEqual(CablePath.objects.count(), 4)
  827. # Test SVG generation
  828. CableTraceSVG(interface1).render()
  829. # Delete cable 3
  830. cable3.delete()
  831. # Check for four partial paths; one from each interface
  832. self.assertEqual(CablePath.objects.filter(is_complete=False).count(), 4)
  833. self.assertEqual(CablePath.objects.filter(is_complete=True).count(), 0)
  834. def test_206_multiple_paths_via_multiple_pass_throughs(self):
  835. """
  836. [IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [FP3:1] [RP3] --C6-- [RP4] [FP4:1] --C7-- [IF3]
  837. [IF2] --C2-- [FP1:2] [FP2:1] --C5-- [FP3:1] [FP4:2] --C8-- [IF4]
  838. """
  839. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  840. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  841. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  842. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  843. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  844. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  845. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3', positions=4)
  846. rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4', positions=4)
  847. frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
  848. frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
  849. frontport2_1 = FrontPort.objects.create(device=self.device, name='Front Port 2:1')
  850. frontport2_2 = FrontPort.objects.create(device=self.device, name='Front Port 2:2')
  851. frontport3_1 = FrontPort.objects.create(device=self.device, name='Front Port 3:1')
  852. frontport3_2 = FrontPort.objects.create(device=self.device, name='Front Port 3:2')
  853. frontport4_1 = FrontPort.objects.create(device=self.device, name='Front Port 4:1')
  854. frontport4_2 = FrontPort.objects.create(device=self.device, name='Front Port 4:2')
  855. PortMapping.objects.bulk_create([
  856. PortMapping(
  857. device=self.device,
  858. front_port=frontport1_1,
  859. front_port_position=1,
  860. rear_port=rearport1,
  861. rear_port_position=1,
  862. ),
  863. PortMapping(
  864. device=self.device,
  865. front_port=frontport1_2,
  866. front_port_position=1,
  867. rear_port=rearport1,
  868. rear_port_position=2,
  869. ),
  870. PortMapping(
  871. device=self.device,
  872. front_port=frontport2_1,
  873. front_port_position=1,
  874. rear_port=rearport2,
  875. rear_port_position=1,
  876. ),
  877. PortMapping(
  878. device=self.device,
  879. front_port=frontport2_2,
  880. front_port_position=1,
  881. rear_port=rearport2,
  882. rear_port_position=2,
  883. ),
  884. PortMapping(
  885. device=self.device,
  886. front_port=frontport3_1,
  887. front_port_position=1,
  888. rear_port=rearport3,
  889. rear_port_position=1,
  890. ),
  891. PortMapping(
  892. device=self.device,
  893. front_port=frontport3_2,
  894. front_port_position=1,
  895. rear_port=rearport3,
  896. rear_port_position=2,
  897. ),
  898. PortMapping(
  899. device=self.device,
  900. front_port=frontport4_1,
  901. front_port_position=1,
  902. rear_port=rearport4,
  903. rear_port_position=1,
  904. ),
  905. PortMapping(
  906. device=self.device,
  907. front_port=frontport4_2,
  908. front_port_position=1,
  909. rear_port=rearport4,
  910. rear_port_position=2,
  911. ),
  912. ])
  913. # Create cables 1-3, 6-8
  914. cable1 = Cable(
  915. a_terminations=[interface1],
  916. b_terminations=[frontport1_1]
  917. )
  918. cable1.save()
  919. cable2 = Cable(
  920. a_terminations=[interface2],
  921. b_terminations=[frontport1_2]
  922. )
  923. cable2.save()
  924. cable3 = Cable(
  925. a_terminations=[rearport1],
  926. b_terminations=[rearport2]
  927. )
  928. cable3.save()
  929. cable6 = Cable(
  930. a_terminations=[rearport3],
  931. b_terminations=[rearport4]
  932. )
  933. cable6.save()
  934. cable7 = Cable(
  935. a_terminations=[interface3],
  936. b_terminations=[frontport4_1]
  937. )
  938. cable7.save()
  939. cable8 = Cable(
  940. a_terminations=[interface4],
  941. b_terminations=[frontport4_2]
  942. )
  943. cable8.save()
  944. self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface
  945. # Create cables 4 and 5
  946. cable4 = Cable(
  947. a_terminations=[frontport2_1],
  948. b_terminations=[frontport3_1]
  949. )
  950. cable4.save()
  951. cable5 = Cable(
  952. a_terminations=[frontport2_2],
  953. b_terminations=[frontport3_2]
  954. )
  955. cable5.save()
  956. self.assertPathExists(
  957. (
  958. interface1, cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1,
  959. cable4, frontport3_1, rearport3, cable6, rearport4, frontport4_1,
  960. cable7, interface3,
  961. ),
  962. is_complete=True,
  963. is_active=True
  964. )
  965. self.assertPathExists(
  966. (
  967. interface2, cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2,
  968. cable5, frontport3_2, rearport3, cable6, rearport4, frontport4_2,
  969. cable8, interface4,
  970. ),
  971. is_complete=True,
  972. is_active=True
  973. )
  974. self.assertPathExists(
  975. (
  976. interface3, cable7, frontport4_1, rearport4, cable6, rearport3, frontport3_1,
  977. cable4, frontport2_1, rearport2, cable3, rearport1, frontport1_1,
  978. cable1, interface1,
  979. ),
  980. is_complete=True,
  981. is_active=True
  982. )
  983. self.assertPathExists(
  984. (
  985. interface4, cable8, frontport4_2, rearport4, cable6, rearport3, frontport3_2,
  986. cable5, frontport2_2, rearport2, cable3, rearport1, frontport1_2,
  987. cable2, interface2,
  988. ),
  989. is_complete=True,
  990. is_active=True
  991. )
  992. self.assertEqual(CablePath.objects.count(), 4)
  993. # Test SVG generation
  994. CableTraceSVG(interface1).render()
  995. # Delete cable 5
  996. cable5.delete()
  997. # Check for two complete paths (IF1 <--> IF2) and two partial (IF3 <--> IF4)
  998. self.assertEqual(CablePath.objects.filter(is_complete=False).count(), 2)
  999. self.assertEqual(CablePath.objects.filter(is_complete=True).count(), 2)
  1000. def test_207_multiple_paths_via_patched_pass_throughs(self):
  1001. """
  1002. [IF1] --C1-- [FP1:1] [RP1] --C3-- [FP2] [RP2] --C4-- [RP3] [FP3:1] --C5-- [IF3]
  1003. [IF2] --C2-- [FP1:2] [FP3:2] --C6-- [IF4]
  1004. """
  1005. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1006. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1007. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  1008. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  1009. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  1010. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  1011. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3', positions=4)
  1012. frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
  1013. frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
  1014. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  1015. frontport3_1 = FrontPort.objects.create(device=self.device, name='Front Port 3:1')
  1016. frontport3_2 = FrontPort.objects.create(device=self.device, name='Front Port 3:2')
  1017. PortMapping.objects.bulk_create([
  1018. PortMapping(
  1019. device=self.device,
  1020. front_port=frontport1_1,
  1021. front_port_position=1,
  1022. rear_port=rearport1,
  1023. rear_port_position=1,
  1024. ),
  1025. PortMapping(
  1026. device=self.device,
  1027. front_port=frontport1_2,
  1028. front_port_position=1,
  1029. rear_port=rearport1,
  1030. rear_port_position=2,
  1031. ),
  1032. PortMapping(
  1033. device=self.device,
  1034. front_port=frontport2,
  1035. front_port_position=1,
  1036. rear_port=rearport2,
  1037. rear_port_position=1,
  1038. ),
  1039. PortMapping(
  1040. device=self.device,
  1041. front_port=frontport3_1,
  1042. front_port_position=1,
  1043. rear_port=rearport3,
  1044. rear_port_position=1,
  1045. ),
  1046. PortMapping(
  1047. device=self.device,
  1048. front_port=frontport3_2,
  1049. front_port_position=1,
  1050. rear_port=rearport3,
  1051. rear_port_position=2,
  1052. ),
  1053. ])
  1054. # Create cables 1-2, 5-6
  1055. cable1 = Cable(
  1056. a_terminations=[interface1],
  1057. b_terminations=[frontport1_1]
  1058. )
  1059. cable1.save()
  1060. cable2 = Cable(
  1061. a_terminations=[interface2],
  1062. b_terminations=[frontport1_2]
  1063. )
  1064. cable2.save()
  1065. cable5 = Cable(
  1066. a_terminations=[interface3],
  1067. b_terminations=[frontport3_1]
  1068. )
  1069. cable5.save()
  1070. cable6 = Cable(
  1071. a_terminations=[interface4],
  1072. b_terminations=[frontport3_2]
  1073. )
  1074. cable6.save()
  1075. self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface
  1076. # Create cables 3-4
  1077. cable3 = Cable(
  1078. a_terminations=[rearport1],
  1079. b_terminations=[frontport2]
  1080. )
  1081. cable3.save()
  1082. cable4 = Cable(
  1083. a_terminations=[rearport2],
  1084. b_terminations=[rearport3]
  1085. )
  1086. cable4.save()
  1087. self.assertPathExists(
  1088. (
  1089. interface1, cable1, frontport1_1, rearport1, cable3, frontport2, rearport2,
  1090. cable4, rearport3, frontport3_1, cable5, interface3,
  1091. ),
  1092. is_complete=True,
  1093. is_active=True
  1094. )
  1095. self.assertPathExists(
  1096. (
  1097. interface2, cable2, frontport1_2, rearport1, cable3, frontport2, rearport2,
  1098. cable4, rearport3, frontport3_2, cable6, interface4,
  1099. ),
  1100. is_complete=True,
  1101. is_active=True
  1102. )
  1103. self.assertPathExists(
  1104. (
  1105. interface3, cable5, frontport3_1, rearport3, cable4, rearport2, frontport2,
  1106. cable3, rearport1, frontport1_1, cable1, interface1,
  1107. ),
  1108. is_complete=True,
  1109. is_active=True
  1110. )
  1111. self.assertPathExists(
  1112. (
  1113. interface4, cable6, frontport3_2, rearport3, cable4, rearport2, frontport2,
  1114. cable3, rearport1, frontport1_2, cable2, interface2,
  1115. ),
  1116. is_complete=True,
  1117. is_active=True
  1118. )
  1119. self.assertEqual(CablePath.objects.count(), 4)
  1120. # Test SVG generation
  1121. CableTraceSVG(interface1).render()
  1122. # Delete cable 3
  1123. cable3.delete()
  1124. # Check for four partial paths; one from each interface
  1125. self.assertEqual(CablePath.objects.filter(is_complete=False).count(), 4)
  1126. self.assertEqual(CablePath.objects.filter(is_complete=True).count(), 0)
  1127. def test_208_unidirectional_split_paths(self):
  1128. """
  1129. [IF1] --C1-- [RP1] [FP1:1] --C2-- [IF2]
  1130. [FP1:2] --C3-- [IF3]
  1131. """
  1132. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1133. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1134. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  1135. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=2)
  1136. frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
  1137. frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
  1138. PortMapping.objects.bulk_create([
  1139. PortMapping(
  1140. device=self.device,
  1141. front_port=frontport1_1,
  1142. front_port_position=1,
  1143. rear_port=rearport1,
  1144. rear_port_position=1,
  1145. ),
  1146. PortMapping(
  1147. device=self.device,
  1148. front_port=frontport1_2,
  1149. front_port_position=1,
  1150. rear_port=rearport1,
  1151. rear_port_position=2,
  1152. ),
  1153. ])
  1154. # Create cables 1
  1155. cable1 = Cable(
  1156. a_terminations=[interface1],
  1157. b_terminations=[rearport1]
  1158. )
  1159. cable1.save()
  1160. self.assertPathExists(
  1161. (interface1, cable1, rearport1),
  1162. is_complete=False,
  1163. is_split=True
  1164. )
  1165. self.assertEqual(CablePath.objects.count(), 1)
  1166. # Create cables 2-3
  1167. cable2 = Cable(
  1168. a_terminations=[interface2],
  1169. b_terminations=[frontport1_1]
  1170. )
  1171. cable2.save()
  1172. cable3 = Cable(
  1173. a_terminations=[interface3],
  1174. b_terminations=[frontport1_2]
  1175. )
  1176. cable3.save()
  1177. self.assertPathExists(
  1178. (interface2, cable2, frontport1_1, rearport1, cable1, interface1),
  1179. is_complete=True,
  1180. is_active=True
  1181. )
  1182. self.assertPathExists(
  1183. (interface3, cable3, frontport1_2, rearport1, cable1, interface1),
  1184. is_complete=True,
  1185. is_active=True
  1186. )
  1187. self.assertEqual(CablePath.objects.count(), 3)
  1188. # Test SVG generation
  1189. CableTraceSVG(interface1).render()
  1190. # Delete cable 1
  1191. cable1.delete()
  1192. # Check that the partial path was deleted and the two complete paths are now partial
  1193. self.assertPathExists(
  1194. (interface2, cable2, frontport1_1, rearport1),
  1195. is_complete=False
  1196. )
  1197. self.assertPathExists(
  1198. (interface3, cable3, frontport1_2, rearport1),
  1199. is_complete=False
  1200. )
  1201. self.assertEqual(CablePath.objects.count(), 2)
  1202. def test_209_rearport_without_frontport(self):
  1203. """
  1204. [IF1] --C1-- [FP1] [RP1] --C2-- [RP2]
  1205. """
  1206. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1207. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  1208. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  1209. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  1210. PortMapping.objects.create(
  1211. front_port=frontport1, front_port_position=1, rear_port=rearport1, rear_port_position=1,
  1212. )
  1213. # Create cables
  1214. cable1 = Cable(
  1215. a_terminations=[interface1],
  1216. b_terminations=[frontport1]
  1217. )
  1218. cable1.save()
  1219. cable2 = Cable(
  1220. a_terminations=[rearport1],
  1221. b_terminations=[rearport2]
  1222. )
  1223. cable2.save()
  1224. self.assertPathExists(
  1225. (interface1, cable1, frontport1, rearport1, cable2, rearport2),
  1226. is_complete=False
  1227. )
  1228. self.assertEqual(CablePath.objects.count(), 1)
  1229. # Test SVG generation
  1230. CableTraceSVG(interface1).render()
  1231. def test_210_interface_to_circuittermination(self):
  1232. """
  1233. [IF1] --C1-- [CT1]
  1234. """
  1235. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1236. circuittermination1 = CircuitTermination.objects.create(
  1237. circuit=self.circuit,
  1238. termination=self.site,
  1239. term_side='A'
  1240. )
  1241. # Create cable 1
  1242. cable1 = Cable(
  1243. a_terminations=[interface1],
  1244. b_terminations=[circuittermination1]
  1245. )
  1246. cable1.save()
  1247. # Check for incomplete path
  1248. self.assertPathExists(
  1249. (interface1, cable1, circuittermination1),
  1250. is_complete=False
  1251. )
  1252. self.assertEqual(CablePath.objects.count(), 1)
  1253. # Test SVG generation
  1254. CableTraceSVG(interface1).render()
  1255. # Delete cable 1
  1256. cable1.delete()
  1257. self.assertEqual(CablePath.objects.count(), 0)
  1258. interface1.refresh_from_db()
  1259. self.assertPathIsNotSet(interface1)
  1260. def test_211_interface_to_interface_via_circuit(self):
  1261. """
  1262. [IF1] --C1-- [CT1] [CT2] --C2-- [IF2]
  1263. """
  1264. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1265. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1266. circuittermination1 = CircuitTermination.objects.create(
  1267. circuit=self.circuit,
  1268. termination=self.site,
  1269. term_side='A'
  1270. )
  1271. # Create cable 1
  1272. cable1 = Cable(
  1273. a_terminations=[interface1],
  1274. b_terminations=[circuittermination1]
  1275. )
  1276. cable1.save()
  1277. # Check for partial path from interface1
  1278. self.assertPathExists(
  1279. (interface1, cable1, circuittermination1),
  1280. is_complete=False
  1281. )
  1282. # Create CT2
  1283. circuittermination2 = CircuitTermination.objects.create(
  1284. circuit=self.circuit,
  1285. termination=self.site,
  1286. term_side='Z'
  1287. )
  1288. # Check for partial path to site
  1289. self.assertPathExists(
  1290. (interface1, cable1, circuittermination1, circuittermination2, self.site),
  1291. is_active=True
  1292. )
  1293. # Create cable 2
  1294. cable2 = Cable(
  1295. a_terminations=[circuittermination2],
  1296. b_terminations=[interface2]
  1297. )
  1298. cable2.save()
  1299. # Check for complete path in each direction
  1300. self.assertPathExists(
  1301. (interface1, cable1, circuittermination1, circuittermination2, cable2, interface2),
  1302. is_complete=True,
  1303. is_active=True
  1304. )
  1305. self.assertPathExists(
  1306. (interface2, cable2, circuittermination2, circuittermination1, cable1, interface1),
  1307. is_complete=True,
  1308. is_active=True
  1309. )
  1310. self.assertEqual(CablePath.objects.count(), 2)
  1311. # Test SVG generation
  1312. CableTraceSVG(interface1).render()
  1313. # Delete cable 2
  1314. cable2.delete()
  1315. path1 = self.assertPathExists(
  1316. (interface1, cable1, circuittermination1, circuittermination2, self.site),
  1317. is_active=True
  1318. )
  1319. self.assertEqual(CablePath.objects.count(), 1)
  1320. interface1.refresh_from_db()
  1321. interface2.refresh_from_db()
  1322. self.assertPathIsSet(interface1, path1)
  1323. self.assertPathIsNotSet(interface2)
  1324. def test_212_interface_to_interface_via_circuit_with_breakouts(self):
  1325. """
  1326. [IF1] --C1-- [CT1] [CT2] --C2-- [IF3]
  1327. [IF2] [IF4]
  1328. """
  1329. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1330. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1331. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  1332. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  1333. circuittermination1 = CircuitTermination.objects.create(
  1334. circuit=self.circuit,
  1335. termination=self.site,
  1336. term_side='A'
  1337. )
  1338. # Create cable 1
  1339. cable1 = Cable(
  1340. a_terminations=[interface1, interface2],
  1341. b_terminations=[circuittermination1]
  1342. )
  1343. cable1.save()
  1344. # Check for partial path from interface1
  1345. self.assertPathExists(
  1346. ([interface1, interface2], cable1, circuittermination1),
  1347. is_complete=False
  1348. )
  1349. # Create CT2
  1350. circuittermination2 = CircuitTermination.objects.create(
  1351. circuit=self.circuit,
  1352. termination=self.site,
  1353. term_side='Z'
  1354. )
  1355. # Check for partial path to site
  1356. self.assertPathExists(
  1357. ([interface1, interface2], cable1, circuittermination1, circuittermination2, self.site),
  1358. is_active=True
  1359. )
  1360. # Create cable 2
  1361. cable2 = Cable(
  1362. a_terminations=[circuittermination2],
  1363. b_terminations=[interface3, interface4]
  1364. )
  1365. cable2.save()
  1366. # Check for complete path in each direction
  1367. self.assertPathExists(
  1368. (
  1369. [interface1, interface2],
  1370. cable1,
  1371. circuittermination1,
  1372. circuittermination2,
  1373. cable2,
  1374. [interface3, interface4],
  1375. ),
  1376. is_complete=True,
  1377. is_active=True,
  1378. )
  1379. self.assertPathExists(
  1380. (
  1381. [interface3, interface4],
  1382. cable2,
  1383. circuittermination2,
  1384. circuittermination1,
  1385. cable1,
  1386. [interface1, interface2],
  1387. ),
  1388. is_complete=True,
  1389. is_active=True,
  1390. )
  1391. self.assertEqual(CablePath.objects.count(), 2)
  1392. # Test SVG generation
  1393. CableTraceSVG(interface1).render()
  1394. # Delete cable 2
  1395. cable2.delete()
  1396. path1 = self.assertPathExists(
  1397. ([interface1, interface2], cable1, circuittermination1, circuittermination2, self.site),
  1398. is_active=True
  1399. )
  1400. self.assertEqual(CablePath.objects.count(), 1)
  1401. interface1.refresh_from_db()
  1402. interface2.refresh_from_db()
  1403. interface3.refresh_from_db()
  1404. interface4.refresh_from_db()
  1405. self.assertPathIsSet(interface1, path1)
  1406. self.assertPathIsSet(interface2, path1)
  1407. self.assertPathIsNotSet(interface3)
  1408. self.assertPathIsNotSet(interface4)
  1409. def test_213_interface_to_site_via_circuit(self):
  1410. """
  1411. [IF1] --C1-- [CT1] [CT2] --> [Site2]
  1412. """
  1413. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1414. site2 = Site.objects.create(name='Site 2', slug='site-2')
  1415. circuittermination1 = CircuitTermination.objects.create(
  1416. circuit=self.circuit,
  1417. termination=self.site,
  1418. term_side='A'
  1419. )
  1420. circuittermination2 = CircuitTermination.objects.create(
  1421. circuit=self.circuit,
  1422. termination=site2,
  1423. term_side='Z'
  1424. )
  1425. # Create cable 1
  1426. cable1 = Cable(
  1427. a_terminations=[interface1],
  1428. b_terminations=[circuittermination1]
  1429. )
  1430. cable1.save()
  1431. self.assertPathExists(
  1432. (interface1, cable1, circuittermination1, circuittermination2, site2),
  1433. is_active=True
  1434. )
  1435. self.assertEqual(CablePath.objects.count(), 1)
  1436. # Test SVG generation
  1437. CableTraceSVG(interface1).render()
  1438. # Delete cable 1
  1439. cable1.delete()
  1440. self.assertEqual(CablePath.objects.count(), 0)
  1441. interface1.refresh_from_db()
  1442. self.assertPathIsNotSet(interface1)
  1443. def test_214_interface_to_providernetwork_via_circuit(self):
  1444. """
  1445. [IF1] --C1-- [CT1] [CT2] --> [PN1]
  1446. """
  1447. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1448. providernetwork = ProviderNetwork.objects.create(name='Provider Network 1', provider=self.circuit.provider)
  1449. circuittermination1 = CircuitTermination.objects.create(
  1450. circuit=self.circuit,
  1451. termination=self.site,
  1452. term_side='A'
  1453. )
  1454. circuittermination2 = CircuitTermination.objects.create(
  1455. circuit=self.circuit,
  1456. termination=providernetwork,
  1457. term_side='Z'
  1458. )
  1459. # Create cable 1
  1460. cable1 = Cable(
  1461. a_terminations=[interface1],
  1462. b_terminations=[circuittermination1]
  1463. )
  1464. cable1.save()
  1465. self.assertPathExists(
  1466. (interface1, cable1, circuittermination1, circuittermination2, providernetwork),
  1467. is_active=True
  1468. )
  1469. self.assertEqual(CablePath.objects.count(), 1)
  1470. self.assertTrue(CablePath.objects.first().is_complete)
  1471. # Test SVG generation
  1472. CableTraceSVG(interface1).render()
  1473. # Delete cable 1
  1474. cable1.delete()
  1475. self.assertEqual(CablePath.objects.count(), 0)
  1476. interface1.refresh_from_db()
  1477. self.assertPathIsNotSet(interface1)
  1478. def test_215_multiple_paths_via_circuit(self):
  1479. """
  1480. [IF1] --C1-- [FP1:1] [RP1] --C3-- [CT1] [CT2] --C4-- [RP2] [FP2:1] --C5-- [IF3]
  1481. [IF2] --C2-- [FP1:2] [FP2:2] --C6-- [IF4]
  1482. """
  1483. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1484. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1485. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  1486. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  1487. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  1488. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  1489. frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
  1490. frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
  1491. frontport2_1 = FrontPort.objects.create(device=self.device, name='Front Port 2:1')
  1492. frontport2_2 = FrontPort.objects.create(device=self.device, name='Front Port 2:2')
  1493. PortMapping.objects.bulk_create([
  1494. PortMapping(
  1495. device=self.device,
  1496. front_port=frontport1_1,
  1497. front_port_position=1,
  1498. rear_port=rearport1,
  1499. rear_port_position=1,
  1500. ),
  1501. PortMapping(
  1502. device=self.device,
  1503. front_port=frontport1_2,
  1504. front_port_position=1,
  1505. rear_port=rearport1,
  1506. rear_port_position=2,
  1507. ),
  1508. PortMapping(
  1509. device=self.device,
  1510. front_port=frontport2_1,
  1511. front_port_position=1,
  1512. rear_port=rearport2,
  1513. rear_port_position=1,
  1514. ),
  1515. PortMapping(
  1516. device=self.device,
  1517. front_port=frontport2_2,
  1518. front_port_position=1,
  1519. rear_port=rearport2,
  1520. rear_port_position=2,
  1521. ),
  1522. ])
  1523. circuittermination1 = CircuitTermination.objects.create(
  1524. circuit=self.circuit,
  1525. termination=self.site,
  1526. term_side='A'
  1527. )
  1528. circuittermination2 = CircuitTermination.objects.create(
  1529. circuit=self.circuit,
  1530. termination=self.site, term_side='Z'
  1531. )
  1532. # Create cables
  1533. cable1 = Cable(
  1534. a_terminations=[interface1],
  1535. b_terminations=[frontport1_1]
  1536. )
  1537. cable1.save()
  1538. cable2 = Cable(
  1539. a_terminations=[interface2],
  1540. b_terminations=[frontport1_2]
  1541. )
  1542. cable2.save()
  1543. cable3 = Cable(
  1544. a_terminations=[rearport1],
  1545. b_terminations=[circuittermination1]
  1546. )
  1547. cable3.save()
  1548. cable4 = Cable(
  1549. a_terminations=[rearport2],
  1550. b_terminations=[circuittermination2]
  1551. )
  1552. cable4.save()
  1553. cable5 = Cable(
  1554. a_terminations=[interface3],
  1555. b_terminations=[frontport2_1]
  1556. )
  1557. cable5.save()
  1558. cable6 = Cable(
  1559. a_terminations=[interface4],
  1560. b_terminations=[frontport2_2]
  1561. )
  1562. cable6.save()
  1563. self.assertPathExists(
  1564. (
  1565. interface1, cable1, frontport1_1, rearport1, cable3, circuittermination1, circuittermination2,
  1566. cable4, rearport2, frontport2_1, cable5, interface3,
  1567. ),
  1568. is_complete=True,
  1569. is_active=True
  1570. )
  1571. self.assertPathExists(
  1572. (
  1573. interface2, cable2, frontport1_2, rearport1, cable3, circuittermination1, circuittermination2,
  1574. cable4, rearport2, frontport2_2, cable6, interface4,
  1575. ),
  1576. is_complete=True,
  1577. is_active=True
  1578. )
  1579. self.assertPathExists(
  1580. (
  1581. interface3, cable5, frontport2_1, rearport2, cable4, circuittermination2, circuittermination1,
  1582. cable3, rearport1, frontport1_1, cable1, interface1,
  1583. ),
  1584. is_complete=True,
  1585. is_active=True
  1586. )
  1587. self.assertPathExists(
  1588. (
  1589. interface4, cable6, frontport2_2, rearport2, cable4, circuittermination2, circuittermination1,
  1590. cable3, rearport1, frontport1_2, cable2, interface2,
  1591. ),
  1592. is_complete=True,
  1593. is_active=True
  1594. )
  1595. self.assertEqual(CablePath.objects.count(), 4)
  1596. # Test SVG generation
  1597. CableTraceSVG(interface1).render()
  1598. # Delete cables 3-4
  1599. cable3.delete()
  1600. cable4.delete()
  1601. # Check for four partial paths; one from each interface
  1602. self.assertEqual(CablePath.objects.filter(is_complete=False).count(), 4)
  1603. self.assertEqual(CablePath.objects.filter(is_complete=True).count(), 0)
  1604. def test_216_interface_to_interface_via_multiple_circuits(self):
  1605. """
  1606. [IF1] --C1-- [CT1] [CT2] --C2-- [CT3] [CT4] --C3-- [IF2]
  1607. """
  1608. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1609. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1610. circuit2 = Circuit.objects.create(provider=self.circuit.provider, type=self.circuit.type, cid='Circuit 2')
  1611. circuittermination1 = CircuitTermination.objects.create(
  1612. circuit=self.circuit,
  1613. termination=self.site,
  1614. term_side='A'
  1615. )
  1616. circuittermination2 = CircuitTermination.objects.create(
  1617. circuit=self.circuit,
  1618. termination=self.site,
  1619. term_side='Z'
  1620. )
  1621. circuittermination3 = CircuitTermination.objects.create(
  1622. circuit=circuit2,
  1623. termination=self.site,
  1624. term_side='A'
  1625. )
  1626. circuittermination4 = CircuitTermination.objects.create(
  1627. circuit=circuit2,
  1628. termination=self.site,
  1629. term_side='Z'
  1630. )
  1631. # Create cables
  1632. cable1 = Cable(
  1633. a_terminations=[interface1],
  1634. b_terminations=[circuittermination1]
  1635. )
  1636. cable1.save()
  1637. cable2 = Cable(
  1638. a_terminations=[circuittermination2],
  1639. b_terminations=[circuittermination3]
  1640. )
  1641. cable2.save()
  1642. cable3 = Cable(
  1643. a_terminations=[circuittermination4],
  1644. b_terminations=[interface2]
  1645. )
  1646. cable3.save()
  1647. # Check for paths
  1648. self.assertPathExists(
  1649. (
  1650. interface1, cable1, circuittermination1, circuittermination2, cable2, circuittermination3,
  1651. circuittermination4, cable3, interface2,
  1652. ),
  1653. is_complete=True,
  1654. is_active=True
  1655. )
  1656. self.assertPathExists(
  1657. (
  1658. interface2, cable3, circuittermination4, circuittermination3, cable2, circuittermination2,
  1659. circuittermination1, cable1, interface1,
  1660. ),
  1661. is_complete=True,
  1662. is_active=True
  1663. )
  1664. self.assertEqual(CablePath.objects.count(), 2)
  1665. # Test SVG generation
  1666. CableTraceSVG(interface1).render()
  1667. # Delete cable 2
  1668. cable2.delete()
  1669. path1 = self.assertPathExists(
  1670. (interface1, cable1, circuittermination1, circuittermination2, self.site),
  1671. is_active=True
  1672. )
  1673. path2 = self.assertPathExists(
  1674. (interface2, cable3, circuittermination4, circuittermination3, self.site),
  1675. is_active=True
  1676. )
  1677. self.assertEqual(CablePath.objects.count(), 2)
  1678. interface1.refresh_from_db()
  1679. interface2.refresh_from_db()
  1680. self.assertPathIsSet(interface1, path1)
  1681. self.assertPathIsSet(interface2, path2)
  1682. def test_217_interface_to_interface_via_rear_ports(self):
  1683. """
  1684. [IF1] --C1-- [FP1] [RP1] --C2-- [RP3] [FP3] --C3-- [IF2]
  1685. [FP2] [RP2] [RP4] [FP4]
  1686. """
  1687. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1688. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1689. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  1690. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  1691. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3')
  1692. rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4')
  1693. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  1694. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  1695. frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 3')
  1696. frontport4 = FrontPort.objects.create(device=self.device, name='Front Port 4')
  1697. PortMapping.objects.bulk_create([
  1698. PortMapping(
  1699. device=self.device,
  1700. front_port=frontport1,
  1701. front_port_position=1,
  1702. rear_port=rearport1,
  1703. rear_port_position=1,
  1704. ),
  1705. PortMapping(
  1706. device=self.device,
  1707. front_port=frontport2,
  1708. front_port_position=1,
  1709. rear_port=rearport2,
  1710. rear_port_position=1,
  1711. ),
  1712. PortMapping(
  1713. device=self.device,
  1714. front_port=frontport3,
  1715. front_port_position=1,
  1716. rear_port=rearport3,
  1717. rear_port_position=1,
  1718. ),
  1719. PortMapping(
  1720. device=self.device,
  1721. front_port=frontport4,
  1722. front_port_position=1,
  1723. rear_port=rearport4,
  1724. rear_port_position=1,
  1725. ),
  1726. ])
  1727. # Create cables 1-2
  1728. cable1 = Cable(
  1729. a_terminations=[interface1],
  1730. b_terminations=[frontport1, frontport2]
  1731. )
  1732. cable1.save()
  1733. cable3 = Cable(
  1734. a_terminations=[interface2],
  1735. b_terminations=[frontport3, frontport4]
  1736. )
  1737. cable3.save()
  1738. self.assertPathExists(
  1739. (interface1, cable1, (frontport1, frontport2), (rearport1, rearport2)),
  1740. is_complete=False
  1741. )
  1742. self.assertPathExists(
  1743. (interface2, cable3, (frontport3, frontport4), (rearport3, rearport4)),
  1744. is_complete=False
  1745. )
  1746. self.assertEqual(CablePath.objects.count(), 2)
  1747. # Create cable 2
  1748. cable2 = Cable(
  1749. a_terminations=[rearport1, rearport2],
  1750. b_terminations=[rearport3, rearport4]
  1751. )
  1752. cable2.save()
  1753. path1 = self.assertPathExists(
  1754. (
  1755. interface1, cable1, (frontport1, frontport2), (rearport1, rearport2), cable2,
  1756. (rearport3, rearport4), (frontport3, frontport4), cable3, interface2
  1757. ),
  1758. is_complete=True
  1759. )
  1760. path2 = self.assertPathExists(
  1761. (
  1762. interface2, cable3, (frontport3, frontport4), (rearport3, rearport4), cable2,
  1763. (rearport1, rearport2), (frontport1, frontport2), cable1, interface1
  1764. ),
  1765. is_complete=True
  1766. )
  1767. self.assertEqual(CablePath.objects.count(), 2)
  1768. # Test SVG generation
  1769. CableTraceSVG(interface1).render()
  1770. # Delete cable 2
  1771. cable2.delete()
  1772. # Check for two partial paths; one from each interface
  1773. self.assertEqual(CablePath.objects.filter(is_complete=False).count(), 2)
  1774. self.assertEqual(CablePath.objects.filter(is_complete=True).count(), 0)
  1775. interface1.refresh_from_db()
  1776. interface2.refresh_from_db()
  1777. self.assertPathIsSet(interface1, path1)
  1778. self.assertPathIsSet(interface2, path2)
  1779. def test_218_interfaces_to_interfaces_via_multiposition_rear_ports(self):
  1780. """
  1781. [IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [IF3]
  1782. [FP1:2] [FP2:2]
  1783. [IF2] --C2-- [FP1:3] [FP2:3] --C5-- [IF4]
  1784. [FP1:4] [FP2:4]
  1785. """
  1786. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1787. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1788. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  1789. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  1790. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
  1791. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
  1792. frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
  1793. frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
  1794. frontport1_3 = FrontPort.objects.create(device=self.device, name='Front Port 1:3')
  1795. frontport1_4 = FrontPort.objects.create(device=self.device, name='Front Port 1:4')
  1796. frontport2_1 = FrontPort.objects.create(device=self.device, name='Front Port 2:1')
  1797. frontport2_2 = FrontPort.objects.create(device=self.device, name='Front Port 2:2')
  1798. frontport2_3 = FrontPort.objects.create(device=self.device, name='Front Port 2:3')
  1799. frontport2_4 = FrontPort.objects.create(device=self.device, name='Front Port 2:4')
  1800. PortMapping.objects.bulk_create([
  1801. PortMapping(
  1802. device=self.device,
  1803. front_port=frontport1_1,
  1804. front_port_position=1,
  1805. rear_port=rearport1,
  1806. rear_port_position=1,
  1807. ),
  1808. PortMapping(
  1809. device=self.device,
  1810. front_port=frontport1_2,
  1811. front_port_position=1,
  1812. rear_port=rearport1,
  1813. rear_port_position=2,
  1814. ),
  1815. PortMapping(
  1816. device=self.device,
  1817. front_port=frontport1_3,
  1818. front_port_position=1,
  1819. rear_port=rearport1,
  1820. rear_port_position=3,
  1821. ),
  1822. PortMapping(
  1823. device=self.device,
  1824. front_port=frontport1_4,
  1825. front_port_position=1,
  1826. rear_port=rearport1,
  1827. rear_port_position=4,
  1828. ),
  1829. PortMapping(
  1830. device=self.device,
  1831. front_port=frontport2_1,
  1832. front_port_position=1,
  1833. rear_port=rearport2,
  1834. rear_port_position=1,
  1835. ),
  1836. PortMapping(
  1837. device=self.device,
  1838. front_port=frontport2_2,
  1839. front_port_position=1,
  1840. rear_port=rearport2,
  1841. rear_port_position=2,
  1842. ),
  1843. PortMapping(
  1844. device=self.device,
  1845. front_port=frontport2_3,
  1846. front_port_position=1,
  1847. rear_port=rearport2,
  1848. rear_port_position=3,
  1849. ),
  1850. PortMapping(
  1851. device=self.device,
  1852. front_port=frontport2_4,
  1853. front_port_position=1,
  1854. rear_port=rearport2,
  1855. rear_port_position=4,
  1856. ),
  1857. ])
  1858. # Create cables 1-2
  1859. cable1 = Cable(
  1860. a_terminations=[interface1],
  1861. b_terminations=[frontport1_1, frontport1_2]
  1862. )
  1863. cable1.save()
  1864. cable2 = Cable(
  1865. a_terminations=[interface2],
  1866. b_terminations=[frontport1_3, frontport1_4]
  1867. )
  1868. cable2.save()
  1869. self.assertPathExists(
  1870. (interface1, cable1, (frontport1_1, frontport1_2), rearport1),
  1871. is_complete=False
  1872. )
  1873. self.assertPathExists(
  1874. (interface2, cable2, (frontport1_3, frontport1_4), rearport1),
  1875. is_complete=False
  1876. )
  1877. self.assertEqual(CablePath.objects.count(), 2)
  1878. # Create cable 3
  1879. cable3 = Cable(
  1880. a_terminations=[rearport1],
  1881. b_terminations=[rearport2]
  1882. )
  1883. cable3.save()
  1884. self.assertPathExists(
  1885. (
  1886. interface1,
  1887. cable1,
  1888. (frontport1_1, frontport1_2),
  1889. rearport1,
  1890. cable3,
  1891. rearport2,
  1892. (frontport2_1, frontport2_2),
  1893. ),
  1894. is_complete=False,
  1895. )
  1896. self.assertPathExists(
  1897. (
  1898. interface2,
  1899. cable2,
  1900. (frontport1_3, frontport1_4),
  1901. rearport1,
  1902. cable3,
  1903. rearport2,
  1904. (frontport2_3, frontport2_4),
  1905. ),
  1906. is_complete=False,
  1907. )
  1908. self.assertEqual(CablePath.objects.count(), 2)
  1909. # Create cables 4-5
  1910. cable4 = Cable(a_terminations=[frontport2_1, frontport2_2], b_terminations=[interface3])
  1911. cable4.save()
  1912. cable5 = Cable(a_terminations=[frontport2_3, frontport2_4], b_terminations=[interface4])
  1913. cable5.save()
  1914. path1 = self.assertPathExists(
  1915. (
  1916. interface1,
  1917. cable1,
  1918. (frontport1_1, frontport1_2),
  1919. rearport1,
  1920. cable3,
  1921. rearport2,
  1922. (frontport2_1, frontport2_2),
  1923. cable4,
  1924. interface3,
  1925. ),
  1926. is_complete=True,
  1927. is_active=True,
  1928. )
  1929. path2 = self.assertPathExists(
  1930. (
  1931. interface2,
  1932. cable2,
  1933. (frontport1_3, frontport1_4),
  1934. rearport1,
  1935. cable3,
  1936. rearport2,
  1937. (frontport2_3, frontport2_4),
  1938. cable5,
  1939. interface4,
  1940. ),
  1941. is_complete=True,
  1942. is_active=True,
  1943. )
  1944. path3 = self.assertPathExists(
  1945. (
  1946. interface3,
  1947. cable4,
  1948. (frontport2_1, frontport2_2),
  1949. rearport2,
  1950. cable3,
  1951. rearport1,
  1952. (frontport1_1, frontport1_2),
  1953. cable1,
  1954. interface1,
  1955. ),
  1956. is_complete=True,
  1957. is_active=True,
  1958. )
  1959. path4 = self.assertPathExists(
  1960. (
  1961. interface4,
  1962. cable5,
  1963. (frontport2_3, frontport2_4),
  1964. rearport2,
  1965. cable3,
  1966. rearport1,
  1967. (frontport1_3, frontport1_4),
  1968. cable2,
  1969. interface2,
  1970. ),
  1971. is_complete=True,
  1972. is_active=True,
  1973. )
  1974. self.assertEqual(CablePath.objects.count(), 4)
  1975. # Test SVG generation
  1976. CableTraceSVG(interface1).render()
  1977. # Delete cable 3
  1978. cable3.delete()
  1979. # Check for four partial paths; one from each interface
  1980. self.assertEqual(CablePath.objects.filter(is_complete=False).count(), 4)
  1981. self.assertEqual(CablePath.objects.filter(is_complete=True).count(), 0)
  1982. interface1.refresh_from_db()
  1983. interface2.refresh_from_db()
  1984. interface3.refresh_from_db()
  1985. interface4.refresh_from_db()
  1986. self.assertPathIsSet(interface1, path1)
  1987. self.assertPathIsSet(interface2, path2)
  1988. self.assertPathIsSet(interface3, path3)
  1989. self.assertPathIsSet(interface4, path4)
  1990. def test_219_interface_to_interface_duplex_via_multiple_rearports(self):
  1991. """
  1992. [IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- [IF2]
  1993. [FP3] [RP3] --C4-- [RP4] [FP4]
  1994. """
  1995. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  1996. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  1997. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  1998. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  1999. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3')
  2000. rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4')
  2001. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2002. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  2003. frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 3')
  2004. frontport4 = FrontPort.objects.create(device=self.device, name='Front Port 4')
  2005. PortMapping.objects.bulk_create([
  2006. PortMapping(
  2007. device=self.device,
  2008. front_port=frontport1,
  2009. front_port_position=1,
  2010. rear_port=rearport1,
  2011. rear_port_position=1,
  2012. ),
  2013. PortMapping(
  2014. device=self.device,
  2015. front_port=frontport2,
  2016. front_port_position=1,
  2017. rear_port=rearport2,
  2018. rear_port_position=1,
  2019. ),
  2020. PortMapping(
  2021. device=self.device,
  2022. front_port=frontport3,
  2023. front_port_position=1,
  2024. rear_port=rearport3,
  2025. rear_port_position=1,
  2026. ),
  2027. PortMapping(
  2028. device=self.device,
  2029. front_port=frontport4,
  2030. front_port_position=1,
  2031. rear_port=rearport4,
  2032. rear_port_position=1,
  2033. ),
  2034. ])
  2035. cable2 = Cable(
  2036. a_terminations=[rearport1],
  2037. b_terminations=[rearport2]
  2038. )
  2039. cable2.save()
  2040. cable4 = Cable(
  2041. a_terminations=[rearport3],
  2042. b_terminations=[rearport4]
  2043. )
  2044. cable4.save()
  2045. self.assertEqual(CablePath.objects.count(), 0)
  2046. # Create cable1
  2047. cable1 = Cable(
  2048. a_terminations=[interface1],
  2049. b_terminations=[frontport1, frontport3]
  2050. )
  2051. cable1.save()
  2052. self.assertPathExists(
  2053. (
  2054. interface1, cable1, (frontport1, frontport3), (rearport1, rearport3), (cable2, cable4),
  2055. (rearport2, rearport4), (frontport2, frontport4)
  2056. ),
  2057. is_complete=False
  2058. )
  2059. self.assertEqual(CablePath.objects.count(), 1)
  2060. # Create cable 3
  2061. cable3 = Cable(
  2062. a_terminations=[frontport2, frontport4],
  2063. b_terminations=[interface2]
  2064. )
  2065. cable3.save()
  2066. self.assertPathExists(
  2067. (
  2068. interface1, cable1, (frontport1, frontport3), (rearport1, rearport3), (cable2, cable4),
  2069. (rearport2, rearport4), (frontport2, frontport4), cable3, interface2
  2070. ),
  2071. is_complete=True,
  2072. is_active=True
  2073. )
  2074. self.assertPathExists(
  2075. (
  2076. interface2, cable3, (frontport2, frontport4), (rearport2, rearport4), (cable2, cable4),
  2077. (rearport1, rearport3), (frontport1, frontport3), cable1, interface1
  2078. ),
  2079. is_complete=True,
  2080. is_active=True
  2081. )
  2082. self.assertEqual(CablePath.objects.count(), 2)
  2083. # Test SVG generation
  2084. CableTraceSVG(interface1).render()
  2085. def test_220_interface_to_interface_duplex_via_multiple_front_and_rear_ports(self):
  2086. """
  2087. [IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- [IF2]
  2088. [IF2] --C5-- [FP3] [RP3] --C4-- [RP4] [FP4]
  2089. """
  2090. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2091. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2092. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  2093. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2094. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  2095. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3')
  2096. rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4')
  2097. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2098. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  2099. frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 3')
  2100. frontport4 = FrontPort.objects.create(device=self.device, name='Front Port 4')
  2101. PortMapping.objects.bulk_create([
  2102. PortMapping(
  2103. device=self.device,
  2104. front_port=frontport1,
  2105. front_port_position=1,
  2106. rear_port=rearport1,
  2107. rear_port_position=1,
  2108. ),
  2109. PortMapping(
  2110. device=self.device,
  2111. front_port=frontport2,
  2112. front_port_position=1,
  2113. rear_port=rearport2,
  2114. rear_port_position=1,
  2115. ),
  2116. PortMapping(
  2117. device=self.device,
  2118. front_port=frontport3,
  2119. front_port_position=1,
  2120. rear_port=rearport3,
  2121. rear_port_position=1,
  2122. ),
  2123. PortMapping(
  2124. device=self.device,
  2125. front_port=frontport4,
  2126. front_port_position=1,
  2127. rear_port=rearport4,
  2128. rear_port_position=1,
  2129. ),
  2130. ])
  2131. cable2 = Cable(
  2132. a_terminations=[rearport1],
  2133. b_terminations=[rearport2]
  2134. )
  2135. cable2.save()
  2136. cable4 = Cable(
  2137. a_terminations=[rearport3],
  2138. b_terminations=[rearport4]
  2139. )
  2140. cable4.save()
  2141. self.assertEqual(CablePath.objects.count(), 0)
  2142. # Create cable1
  2143. cable1 = Cable(
  2144. a_terminations=[interface1],
  2145. b_terminations=[frontport1]
  2146. )
  2147. cable1.save()
  2148. self.assertPathExists(
  2149. (
  2150. interface1, cable1, frontport1, rearport1, cable2, rearport2, frontport2
  2151. ),
  2152. is_complete=False
  2153. )
  2154. # Create cable1
  2155. cable5 = Cable(
  2156. a_terminations=[interface3],
  2157. b_terminations=[frontport3]
  2158. )
  2159. cable5.save()
  2160. self.assertPathExists(
  2161. (
  2162. interface3, cable5, frontport3, rearport3, cable4, rearport4, frontport4
  2163. ),
  2164. is_complete=False
  2165. )
  2166. self.assertEqual(CablePath.objects.count(), 2)
  2167. # Create cable 3
  2168. cable3 = Cable(
  2169. a_terminations=[frontport2, frontport4],
  2170. b_terminations=[interface2]
  2171. )
  2172. cable3.save()
  2173. self.assertPathExists(
  2174. (
  2175. interface2, cable3, (frontport2, frontport4), (rearport2, rearport4), (cable2, cable4),
  2176. (rearport1, rearport3), (frontport1, frontport3), (cable1, cable5), (interface1, interface3)
  2177. ),
  2178. is_complete=True,
  2179. is_active=True
  2180. )
  2181. self.assertPathExists(
  2182. (
  2183. interface1, cable1, frontport1, rearport1, cable2, rearport2, frontport2, cable3, interface2
  2184. ),
  2185. is_complete=True,
  2186. is_active=True
  2187. )
  2188. self.assertPathExists(
  2189. (
  2190. interface3, cable5, frontport3, rearport3, cable4, rearport4, frontport4, cable3, interface2
  2191. ),
  2192. is_complete=True,
  2193. is_active=True
  2194. )
  2195. self.assertEqual(CablePath.objects.count(), 3)
  2196. # Test SVG generation
  2197. CableTraceSVG(interface1).render()
  2198. def test_221_non_symmetric_paths(self):
  2199. """
  2200. [IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- -------------------------------------- [IF2]
  2201. [IF2] --C5-- [FP3] [RP3] --C4-- [RP4] [FP4] --C6-- [FP5] [RP5] --C7-- [RP6] [FP6] --C3---/
  2202. """
  2203. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2204. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2205. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  2206. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2207. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  2208. rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3')
  2209. rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4')
  2210. rearport5 = RearPort.objects.create(device=self.device, name='Rear Port 5')
  2211. rearport6 = RearPort.objects.create(device=self.device, name='Rear Port 6')
  2212. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2213. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  2214. frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 3')
  2215. frontport4 = FrontPort.objects.create(device=self.device, name='Front Port 4')
  2216. frontport5 = FrontPort.objects.create(device=self.device, name='Front Port 5')
  2217. frontport6 = FrontPort.objects.create(device=self.device, name='Front Port 6')
  2218. PortMapping.objects.bulk_create([
  2219. PortMapping(
  2220. device=self.device,
  2221. front_port=frontport1,
  2222. front_port_position=1,
  2223. rear_port=rearport1,
  2224. rear_port_position=1,
  2225. ),
  2226. PortMapping(
  2227. device=self.device,
  2228. front_port=frontport2,
  2229. front_port_position=1,
  2230. rear_port=rearport2,
  2231. rear_port_position=1,
  2232. ),
  2233. PortMapping(
  2234. device=self.device,
  2235. front_port=frontport3,
  2236. front_port_position=1,
  2237. rear_port=rearport3,
  2238. rear_port_position=1,
  2239. ),
  2240. PortMapping(
  2241. device=self.device,
  2242. front_port=frontport4,
  2243. front_port_position=1,
  2244. rear_port=rearport4,
  2245. rear_port_position=1,
  2246. ),
  2247. PortMapping(
  2248. device=self.device,
  2249. front_port=frontport5,
  2250. front_port_position=1,
  2251. rear_port=rearport5,
  2252. rear_port_position=1,
  2253. ),
  2254. PortMapping(
  2255. device=self.device,
  2256. front_port=frontport6,
  2257. front_port_position=1,
  2258. rear_port=rearport6,
  2259. rear_port_position=1,
  2260. ),
  2261. ])
  2262. cable2 = Cable(
  2263. a_terminations=[rearport1],
  2264. b_terminations=[rearport2],
  2265. label='C2'
  2266. )
  2267. cable2.save()
  2268. cable4 = Cable(
  2269. a_terminations=[rearport3],
  2270. b_terminations=[rearport4],
  2271. label='C4'
  2272. )
  2273. cable4.save()
  2274. cable6 = Cable(
  2275. a_terminations=[frontport4],
  2276. b_terminations=[frontport5],
  2277. label='C6'
  2278. )
  2279. cable6.save()
  2280. cable7 = Cable(
  2281. a_terminations=[rearport5],
  2282. b_terminations=[rearport6],
  2283. label='C7'
  2284. )
  2285. cable7.save()
  2286. self.assertEqual(CablePath.objects.count(), 0)
  2287. # Create cable1
  2288. cable1 = Cable(
  2289. a_terminations=[interface1],
  2290. b_terminations=[frontport1],
  2291. label='C1'
  2292. )
  2293. cable1.save()
  2294. self.assertPathExists(
  2295. (
  2296. interface1, cable1, frontport1, rearport1, cable2, rearport2, frontport2
  2297. ),
  2298. is_complete=False
  2299. )
  2300. # Create cable1
  2301. cable5 = Cable(
  2302. a_terminations=[interface3],
  2303. b_terminations=[frontport3],
  2304. label='C5'
  2305. )
  2306. cable5.save()
  2307. self.assertPathExists(
  2308. (
  2309. interface3, cable5, frontport3, rearport3, cable4, rearport4, frontport4, cable6, frontport5, rearport5,
  2310. cable7, rearport6, frontport6
  2311. ),
  2312. is_complete=False
  2313. )
  2314. self.assertEqual(CablePath.objects.count(), 2)
  2315. # Create cable 3
  2316. cable3 = Cable(
  2317. a_terminations=[frontport2, frontport6],
  2318. b_terminations=[interface2],
  2319. label='C3'
  2320. )
  2321. cable3.save()
  2322. self.assertPathExists(
  2323. (
  2324. interface2, cable3, (frontport2, frontport6), (rearport2, rearport6), (cable2, cable7),
  2325. (rearport1, rearport5), (frontport1, frontport5), (cable1, cable6)
  2326. ),
  2327. is_complete=False,
  2328. is_split=True
  2329. )
  2330. self.assertPathExists(
  2331. (
  2332. interface1, cable1, frontport1, rearport1, cable2, rearport2, frontport2, cable3, interface2
  2333. ),
  2334. is_complete=True,
  2335. is_active=True
  2336. )
  2337. self.assertPathExists(
  2338. (
  2339. interface3, cable5, frontport3, rearport3, cable4, rearport4, frontport4, cable6, frontport5, rearport5,
  2340. cable7, rearport6, frontport6, cable3, interface2
  2341. ),
  2342. is_complete=True,
  2343. is_active=True
  2344. )
  2345. self.assertEqual(CablePath.objects.count(), 3)
  2346. # Test SVG generation
  2347. CableTraceSVG(interface1).render()
  2348. def test_222_single_path_via_multiple_singleposition_rear_ports(self):
  2349. """
  2350. [IF1] --C1-- [FP1] [RP1] --C2-- [IF2]
  2351. [FP2] [RP2]
  2352. """
  2353. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2354. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2355. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2356. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  2357. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2358. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  2359. PortMapping.objects.bulk_create([
  2360. PortMapping(
  2361. device=self.device,
  2362. front_port=frontport1,
  2363. front_port_position=1,
  2364. rear_port=rearport1,
  2365. rear_port_position=1,
  2366. ),
  2367. PortMapping(
  2368. device=self.device,
  2369. front_port=frontport2,
  2370. front_port_position=1,
  2371. rear_port=rearport2,
  2372. rear_port_position=1,
  2373. ),
  2374. ])
  2375. cable1 = Cable(
  2376. a_terminations=[interface1],
  2377. b_terminations=[frontport1, frontport2]
  2378. )
  2379. cable1.save()
  2380. self.assertEqual(CablePath.objects.count(), 1)
  2381. cable2 = Cable(
  2382. a_terminations=[rearport1, rearport2],
  2383. b_terminations=[interface2]
  2384. )
  2385. cable2.save()
  2386. self.assertEqual(CablePath.objects.count(), 2)
  2387. self.assertPathExists(
  2388. (interface1, cable1, (frontport1, frontport2), (rearport1, rearport2), cable2, interface2),
  2389. is_complete=True
  2390. )
  2391. self.assertPathExists(
  2392. (interface2, cable2, (rearport1, rearport2), (frontport1, frontport2), cable1, interface1),
  2393. is_complete=True
  2394. )
  2395. # Test SVG generation both directions
  2396. CableTraceSVG(interface1).render()
  2397. CableTraceSVG(interface2).render()
  2398. def test_223_interface_to_interface_via_multiple_circuit_terminations(self):
  2399. provider = Provider.objects.first()
  2400. circuit_type = CircuitType.objects.first()
  2401. circuit1 = self.circuit
  2402. circuit2 = Circuit.objects.create(provider=provider, type=circuit_type, cid='Circuit 2')
  2403. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2404. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2405. circuittermination1_A = CircuitTermination.objects.create(
  2406. circuit=circuit1,
  2407. termination=self.site,
  2408. term_side='A'
  2409. )
  2410. circuittermination1_Z = CircuitTermination.objects.create(
  2411. circuit=circuit1,
  2412. termination=self.site,
  2413. term_side='Z'
  2414. )
  2415. circuittermination2_A = CircuitTermination.objects.create(
  2416. circuit=circuit2,
  2417. termination=self.site,
  2418. term_side='A'
  2419. )
  2420. circuittermination2_Z = CircuitTermination.objects.create(
  2421. circuit=circuit2,
  2422. termination=self.site,
  2423. term_side='Z'
  2424. )
  2425. # Create cables
  2426. cable1 = Cable(
  2427. a_terminations=[interface1],
  2428. b_terminations=[circuittermination1_A, circuittermination2_A]
  2429. )
  2430. cable2 = Cable(
  2431. a_terminations=[interface2],
  2432. b_terminations=[circuittermination1_Z, circuittermination2_Z]
  2433. )
  2434. cable1.save()
  2435. cable2.save()
  2436. self.assertEqual(CablePath.objects.count(), 2)
  2437. path1 = self.assertPathExists(
  2438. (
  2439. interface1,
  2440. cable1,
  2441. (circuittermination1_A, circuittermination2_A),
  2442. (circuittermination1_Z, circuittermination2_Z),
  2443. cable2,
  2444. interface2
  2445. ),
  2446. is_active=True,
  2447. is_complete=True,
  2448. )
  2449. interface1.refresh_from_db()
  2450. self.assertPathIsSet(interface1, path1)
  2451. path2 = self.assertPathExists(
  2452. (
  2453. interface2,
  2454. cable2,
  2455. (circuittermination1_Z, circuittermination2_Z),
  2456. (circuittermination1_A, circuittermination2_A),
  2457. cable1,
  2458. interface1
  2459. ),
  2460. is_active=True,
  2461. is_complete=True,
  2462. )
  2463. interface2.refresh_from_db()
  2464. self.assertPathIsSet(interface2, path2)
  2465. def test_224_single_path_via_multiple_pass_throughs_with_breakouts(self):
  2466. """
  2467. [IF1] --C1-- [FP1] [RP1] --C2-- [IF3]
  2468. [IF2] [FP2] [RP2] [IF4]
  2469. """
  2470. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2471. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2472. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  2473. interface4 = Interface.objects.create(device=self.device, name='Interface 4')
  2474. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2475. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  2476. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2477. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  2478. PortMapping.objects.bulk_create([
  2479. PortMapping(
  2480. device=self.device,
  2481. front_port=frontport1,
  2482. front_port_position=1,
  2483. rear_port=rearport1,
  2484. rear_port_position=1,
  2485. ),
  2486. PortMapping(
  2487. device=self.device,
  2488. front_port=frontport2,
  2489. front_port_position=1,
  2490. rear_port=rearport2,
  2491. rear_port_position=1,
  2492. ),
  2493. ])
  2494. # Create cables
  2495. cable1 = Cable(
  2496. a_terminations=[interface1, interface2],
  2497. b_terminations=[frontport1, frontport2]
  2498. )
  2499. cable1.save()
  2500. cable2 = Cable(
  2501. a_terminations=[rearport1, rearport2],
  2502. b_terminations=[interface3, interface4]
  2503. )
  2504. cable2.save()
  2505. # Validate paths
  2506. self.assertPathExists(
  2507. (
  2508. [interface1, interface2], cable1, [frontport1, frontport2],
  2509. [rearport1, rearport2], cable2, [interface3, interface4],
  2510. ),
  2511. is_complete=True,
  2512. is_active=True
  2513. )
  2514. self.assertPathExists(
  2515. (
  2516. [interface3, interface4], cable2, [rearport1, rearport2],
  2517. [frontport1, frontport2], cable1, [interface1, interface2],
  2518. ),
  2519. is_complete=True,
  2520. is_active=True
  2521. )
  2522. self.assertEqual(CablePath.objects.count(), 2)
  2523. def test_225_circuittermination_origin_passive_network(self):
  2524. """
  2525. [CT1] --C1-- [RP1] [FP1]
  2526. A CircuitTermination cabled into a passive (FrontPort/RearPort-only) device can become a
  2527. CablePath origin. Unlike PathEndpoint origins, CircuitTermination has no `_path` back-reference
  2528. field, so saving and deleting such a path must not attempt to write it (see #22825).
  2529. """
  2530. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2531. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2532. PortMapping.objects.create(
  2533. device=self.device, front_port=frontport1, front_port_position=1,
  2534. rear_port=rearport1, rear_port_position=1,
  2535. )
  2536. circuittermination1 = CircuitTermination.objects.create(
  2537. circuit=self.circuit,
  2538. termination=self.site,
  2539. term_side='A'
  2540. )
  2541. cable1 = Cable(
  2542. a_terminations=[circuittermination1],
  2543. b_terminations=[rearport1]
  2544. )
  2545. cable1.save()
  2546. # Re-fetch so the in-memory instance reflects the cable set above (from_origin reads .cable).
  2547. circuittermination1.refresh_from_db()
  2548. # A path traced from the CircuitTermination origin must save without raising FieldDoesNotExist
  2549. # on the missing `_path` field.
  2550. cablepath = CablePath.from_origin([circuittermination1])
  2551. cablepath.save()
  2552. self.assertEqual(cablepath.origin_type.model_class(), CircuitTermination)
  2553. self.assertEqual(cablepath.origins, [circuittermination1])
  2554. # Deleting the path must likewise not attempt to clear a nonexistent `_path` field.
  2555. cablepath.delete()
  2556. self.assertIsNone(CablePath.objects.filter(pk=cablepath.pk).first())
  2557. def test_301_create_path_via_existing_cable(self):
  2558. """
  2559. [IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- [IF2]
  2560. """
  2561. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2562. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2563. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2564. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  2565. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2566. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  2567. PortMapping.objects.bulk_create([
  2568. PortMapping(
  2569. device=self.device,
  2570. front_port=frontport1,
  2571. front_port_position=1,
  2572. rear_port=rearport1,
  2573. rear_port_position=1,
  2574. ),
  2575. PortMapping(
  2576. device=self.device,
  2577. front_port=frontport2,
  2578. front_port_position=1,
  2579. rear_port=rearport2,
  2580. rear_port_position=1,
  2581. ),
  2582. ])
  2583. # Create cable 2
  2584. cable2 = Cable(
  2585. a_terminations=[rearport1],
  2586. b_terminations=[rearport2]
  2587. )
  2588. cable2.save()
  2589. self.assertEqual(CablePath.objects.count(), 0)
  2590. # Create cable1
  2591. cable1 = Cable(
  2592. a_terminations=[interface1],
  2593. b_terminations=[frontport1]
  2594. )
  2595. cable1.save()
  2596. self.assertPathExists(
  2597. (interface1, cable1, frontport1, rearport1, cable2, rearport2, frontport2),
  2598. is_complete=False
  2599. )
  2600. self.assertEqual(CablePath.objects.count(), 1)
  2601. # Create cable 3
  2602. cable3 = Cable(
  2603. a_terminations=[frontport2],
  2604. b_terminations=[interface2]
  2605. )
  2606. cable3.save()
  2607. self.assertPathExists(
  2608. (interface1, cable1, frontport1, rearport1, cable2, rearport2, frontport2, cable3, interface2),
  2609. is_complete=True,
  2610. is_active=True
  2611. )
  2612. self.assertPathExists(
  2613. (interface2, cable3, frontport2, rearport2, cable2, rearport1, frontport1, cable1, interface1),
  2614. is_complete=True,
  2615. is_active=True
  2616. )
  2617. self.assertEqual(CablePath.objects.count(), 2)
  2618. def test_302_update_path_on_cable_status_change(self):
  2619. """
  2620. [IF1] --C1-- [FP1] [RP1] --C2-- [IF2]
  2621. """
  2622. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2623. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2624. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2625. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2626. PortMapping.objects.bulk_create([
  2627. PortMapping(
  2628. device=self.device,
  2629. front_port=frontport1,
  2630. front_port_position=1,
  2631. rear_port=rearport1,
  2632. rear_port_position=1,
  2633. ),
  2634. ])
  2635. # Create cables 1 and 2
  2636. cable1 = Cable(
  2637. a_terminations=[interface1],
  2638. b_terminations=[frontport1]
  2639. )
  2640. cable1.save()
  2641. cable2 = Cable(
  2642. a_terminations=[rearport1],
  2643. b_terminations=[interface2]
  2644. )
  2645. cable2.save()
  2646. self.assertEqual(CablePath.objects.filter(is_active=True).count(), 2)
  2647. self.assertEqual(CablePath.objects.count(), 2)
  2648. # Change cable 2's status to "planned"
  2649. cable2 = Cable.objects.get(pk=cable2.pk) # Rebuild object to ditch A/B terminations set earlier
  2650. cable2.status = LinkStatusChoices.STATUS_PLANNED
  2651. cable2.save()
  2652. self.assertPathExists(
  2653. (interface1, cable1, frontport1, rearport1, cable2, interface2),
  2654. is_complete=True,
  2655. is_active=False
  2656. )
  2657. self.assertPathExists(
  2658. (interface2, cable2, rearport1, frontport1, cable1, interface1),
  2659. is_complete=True,
  2660. is_active=False
  2661. )
  2662. self.assertEqual(CablePath.objects.count(), 2)
  2663. # Change cable 2's status to "connected"
  2664. cable2 = Cable.objects.get(pk=cable2.pk)
  2665. cable2.status = LinkStatusChoices.STATUS_CONNECTED
  2666. cable2.save()
  2667. self.assertPathExists(
  2668. (interface1, cable1, frontport1, rearport1, cable2, interface2),
  2669. is_complete=True,
  2670. is_active=True
  2671. )
  2672. self.assertPathExists(
  2673. (interface2, cable2, rearport1, frontport1, cable1, interface1),
  2674. is_complete=True,
  2675. is_active=True
  2676. )
  2677. self.assertEqual(CablePath.objects.count(), 2)
  2678. def test_303_remove_termination_from_existing_cable(self):
  2679. """
  2680. [IF1] --C1-- [IF2]
  2681. [IF3]
  2682. """
  2683. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2684. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2685. interface3 = Interface.objects.create(device=self.device, name='Interface 3')
  2686. cable1 = Cable(
  2687. a_terminations=[interface1],
  2688. b_terminations=[interface2, interface3]
  2689. )
  2690. cable1.save()
  2691. self.assertPathExists(
  2692. (interface1, cable1, [interface2, interface3]),
  2693. is_complete=True,
  2694. is_active=True
  2695. )
  2696. self.assertPathExists(
  2697. ([interface2, interface3], cable1, interface1),
  2698. is_complete=True,
  2699. is_active=True
  2700. )
  2701. # Remove the termination to interface 3
  2702. cable1 = Cable.objects.first()
  2703. cable1.b_terminations = [interface2]
  2704. cable1.save()
  2705. self.assertPathExists(
  2706. (interface1, cable1, interface2),
  2707. is_complete=True,
  2708. is_active=True
  2709. )
  2710. self.assertPathExists(
  2711. (interface2, cable1, interface1),
  2712. is_complete=True,
  2713. is_active=True
  2714. )
  2715. # Verify _path is cleared on removed interface (#21127)
  2716. interface3.refresh_from_db()
  2717. self.assertPathIsNotSet(interface3)
  2718. def test_304_retrace_cable_created_without_save(self):
  2719. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2720. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2721. cable = self._create_cable_raw(interface1, interface2)
  2722. self.assertEqual(CablePath.objects.count(), 0)
  2723. cable.update_dependent_objects()
  2724. self.assertPathExists((interface1, cable, interface2), is_complete=True, is_active=True)
  2725. self.assertPathExists((interface2, cable, interface1), is_complete=True, is_active=True)
  2726. self.assertEqual(CablePath.objects.count(), 2)
  2727. def test_305_retrace_cable_extends_incomplete_path(self):
  2728. """
  2729. [IF1] --C1-- [FP1] [RP1] --C2-- [IF2], with C2 written raw. Retracing from a termination which is not
  2730. itself a path endpoint must extend the existing incomplete path.
  2731. """
  2732. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2733. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2734. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2735. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2736. PortMapping.objects.create(
  2737. device=self.device,
  2738. front_port=frontport1,
  2739. front_port_position=1,
  2740. rear_port=rearport1,
  2741. rear_port_position=1
  2742. )
  2743. cable1 = Cable(a_terminations=[interface1], b_terminations=[frontport1])
  2744. cable1.save()
  2745. self.assertPathExists((interface1, cable1, frontport1, rearport1), is_complete=False)
  2746. cable2 = self._create_cable_raw(rearport1, interface2)
  2747. self.assertEqual(CablePath.objects.count(), 1)
  2748. cable2.update_dependent_objects()
  2749. self.assertPathExists(
  2750. (interface1, cable1, frontport1, rearport1, cable2, interface2),
  2751. is_complete=True,
  2752. is_active=True
  2753. )
  2754. self.assertPathExists(
  2755. (interface2, cable2, rearport1, frontport1, cable1, interface1),
  2756. is_complete=True,
  2757. is_active=True
  2758. )
  2759. self.assertEqual(CablePath.objects.count(), 2)
  2760. def test_306_retrace_cable_status_from_database(self):
  2761. """
  2762. A raw write leaves no in-memory record of the Cable's status, so path activity must come from the
  2763. stored value.
  2764. """
  2765. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2766. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2767. cable = self._create_cable_raw(interface1, interface2, status=LinkStatusChoices.STATUS_PLANNED)
  2768. cable.update_dependent_objects()
  2769. self.assertPathExists((interface1, cable, interface2), is_complete=True, is_active=False)
  2770. self.assertPathExists((interface2, cable, interface1), is_complete=True, is_active=False)
  2771. self.assertEqual(CablePath.objects.count(), 2)
  2772. def test_307_retrace_cable_preserves_path_via_pass_through(self):
  2773. """
  2774. [IF1] --C1-- [FP1] [RP1] --C2-- [IF2]. Retracing C1, whose B side is not a path endpoint, must
  2775. preserve the reverse path originating at IF2.
  2776. """
  2777. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2778. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2779. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2780. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2781. PortMapping.objects.create(
  2782. device=self.device,
  2783. front_port=frontport1,
  2784. front_port_position=1,
  2785. rear_port=rearport1,
  2786. rear_port_position=1
  2787. )
  2788. cable1 = Cable(a_terminations=[interface1], b_terminations=[frontport1])
  2789. cable1.save()
  2790. cable2 = Cable(a_terminations=[rearport1], b_terminations=[interface2])
  2791. cable2.save()
  2792. self.assertEqual(CablePath.objects.count(), 2)
  2793. Cable.objects.get(pk=cable1.pk).update_dependent_objects()
  2794. self.assertPathExists(
  2795. (interface1, cable1, frontport1, rearport1, cable2, interface2),
  2796. is_complete=True,
  2797. is_active=True
  2798. )
  2799. self.assertPathExists(
  2800. (interface2, cable2, rearport1, frontport1, cable1, interface1),
  2801. is_complete=True,
  2802. is_active=True
  2803. )
  2804. self.assertEqual(CablePath.objects.count(), 2)
  2805. def test_308_retrace_midspan_cable_preserves_paths(self):
  2806. """
  2807. [IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- [IF2]. Retracing C2, which originates nothing
  2808. itself (both sides are rear ports), must preserve both paths.
  2809. """
  2810. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2811. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2812. ports = {}
  2813. for i in (1, 2):
  2814. ports[f'rear{i}'] = RearPort.objects.create(device=self.device, name=f'Rear Port {i}')
  2815. ports[f'front{i}'] = FrontPort.objects.create(device=self.device, name=f'Front Port {i}')
  2816. PortMapping.objects.create(
  2817. device=self.device,
  2818. front_port=ports[f'front{i}'],
  2819. front_port_position=1,
  2820. rear_port=ports[f'rear{i}'],
  2821. rear_port_position=1
  2822. )
  2823. cable1 = Cable(a_terminations=[interface1], b_terminations=[ports['front1']])
  2824. cable1.save()
  2825. cable2 = Cable(a_terminations=[ports['rear1']], b_terminations=[ports['rear2']])
  2826. cable2.save()
  2827. cable3 = Cable(a_terminations=[ports['front2']], b_terminations=[interface2])
  2828. cable3.save()
  2829. self.assertEqual(CablePath.objects.count(), 2)
  2830. # Twice: with no path endpoint of its own, every path this Cable carries is restored from the
  2831. # origins of the paths it replaces, so a repeat call must neither duplicate nor drop them
  2832. for _ in range(2):
  2833. Cable.objects.get(pk=cable2.pk).update_dependent_objects()
  2834. self.assertPathExists(
  2835. (
  2836. interface1, cable1, ports['front1'], ports['rear1'], cable2, ports['rear2'], ports['front2'],
  2837. cable3, interface2
  2838. ),
  2839. is_complete=True,
  2840. is_active=True
  2841. )
  2842. self.assertPathExists(
  2843. (
  2844. interface2, cable3, ports['front2'], ports['rear2'], cable2, ports['rear1'], ports['front1'],
  2845. cable1, interface1
  2846. ),
  2847. is_complete=True,
  2848. is_active=True
  2849. )
  2850. self.assertEqual(CablePath.objects.count(), 2)
  2851. def test_309_retrace_cable_preserves_path_via_circuit(self):
  2852. """
  2853. [IF1] --C1-- [CT1] [CT2] --C2-- [IF2]. Retracing C1, whose B side is a circuit termination, must
  2854. preserve the reverse path originating at IF2.
  2855. """
  2856. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2857. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2858. circuittermination1 = CircuitTermination.objects.create(
  2859. circuit=self.circuit, termination=self.site, term_side='A'
  2860. )
  2861. circuittermination2 = CircuitTermination.objects.create(
  2862. circuit=self.circuit, termination=self.site, term_side='Z'
  2863. )
  2864. cable1 = Cable(a_terminations=[interface1], b_terminations=[circuittermination1])
  2865. cable1.save()
  2866. cable2 = Cable(a_terminations=[circuittermination2], b_terminations=[interface2])
  2867. cable2.save()
  2868. self.assertEqual(CablePath.objects.count(), 2)
  2869. Cable.objects.get(pk=cable1.pk).update_dependent_objects()
  2870. self.assertPathExists(
  2871. (interface1, cable1, circuittermination1, circuittermination2, cable2, interface2),
  2872. is_complete=True,
  2873. is_active=True
  2874. )
  2875. self.assertPathExists(
  2876. (interface2, cable2, circuittermination2, circuittermination1, cable1, interface1),
  2877. is_complete=True,
  2878. is_active=True
  2879. )
  2880. self.assertEqual(CablePath.objects.count(), 2)
  2881. def test_310_retrace_cable_is_idempotent(self):
  2882. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2883. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2884. cable = Cable(a_terminations=[interface1], b_terminations=[interface2])
  2885. cable.save()
  2886. self.assertEqual(CablePath.objects.count(), 2)
  2887. cable.update_dependent_objects()
  2888. path1 = self.assertPathExists((interface1, cable, interface2), is_complete=True, is_active=True)
  2889. path2 = self.assertPathExists((interface2, cable, interface1), is_complete=True, is_active=True)
  2890. self.assertEqual(CablePath.objects.count(), 2)
  2891. interface1.refresh_from_db()
  2892. interface2.refresh_from_db()
  2893. self.assertPathIsSet(interface1, path1)
  2894. self.assertPathIsSet(interface2, path2)
  2895. def test_401_exclude_midspan_devices(self):
  2896. """
  2897. [IF1] --C1-- [FP1][Test Device][RP1] --C2-- [RP2][Test Device][FP2] --C3-- [IF2]
  2898. [FP3][Test mid-span Device][RP3] --C4-- [RP4][Test mid-span Device][FP4] /
  2899. """
  2900. device = Device.objects.create(
  2901. site=self.site,
  2902. device_type=self.device.device_type,
  2903. role=self.device.role,
  2904. name='Test mid-span Device'
  2905. )
  2906. interface1 = Interface.objects.create(device=self.device, name='Interface 1')
  2907. interface2 = Interface.objects.create(device=self.device, name='Interface 2')
  2908. rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
  2909. rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
  2910. rearport3 = RearPort.objects.create(device=device, name='Rear Port 3')
  2911. rearport4 = RearPort.objects.create(device=device, name='Rear Port 4')
  2912. frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
  2913. frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
  2914. frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 3')
  2915. frontport4 = FrontPort.objects.create(device=self.device, name='Front Port 4')
  2916. PortMapping.objects.bulk_create([
  2917. PortMapping(
  2918. device=self.device,
  2919. front_port=frontport1,
  2920. front_port_position=1,
  2921. rear_port=rearport1,
  2922. rear_port_position=1,
  2923. ),
  2924. PortMapping(
  2925. device=self.device,
  2926. front_port=frontport2,
  2927. front_port_position=1,
  2928. rear_port=rearport2,
  2929. rear_port_position=1,
  2930. ),
  2931. PortMapping(
  2932. device=self.device,
  2933. front_port=frontport3,
  2934. front_port_position=1,
  2935. rear_port=rearport3,
  2936. rear_port_position=1,
  2937. ),
  2938. PortMapping(
  2939. device=self.device,
  2940. front_port=frontport4,
  2941. front_port_position=1,
  2942. rear_port=rearport4,
  2943. rear_port_position=1,
  2944. ),
  2945. ])
  2946. cable2 = Cable(
  2947. a_terminations=[rearport1],
  2948. b_terminations=[rearport2],
  2949. label='C2'
  2950. )
  2951. cable2.save()
  2952. cable4 = Cable(
  2953. a_terminations=[rearport3],
  2954. b_terminations=[rearport4],
  2955. label='C4'
  2956. )
  2957. cable4.save()
  2958. self.assertEqual(CablePath.objects.count(), 0)
  2959. # Create cable1
  2960. cable1 = Cable(
  2961. a_terminations=[interface1],
  2962. b_terminations=[frontport1, frontport3],
  2963. label='C1'
  2964. )
  2965. with self.assertRaises(AbortRequest):
  2966. cable1.save()
  2967. self.assertPathDoesNotExist(
  2968. (
  2969. interface1, cable1, (frontport1, frontport3), (rearport1, rearport3), (cable2, cable4),
  2970. (rearport2, rearport4), (frontport2, frontport4)
  2971. ),
  2972. is_complete=False
  2973. )
  2974. self.assertEqual(CablePath.objects.count(), 0)
  2975. # Create cable 3
  2976. cable3 = Cable(
  2977. a_terminations=[frontport2, frontport4],
  2978. b_terminations=[interface2],
  2979. label='C3'
  2980. )
  2981. with self.assertRaises(AbortRequest):
  2982. cable3.save()
  2983. self.assertPathDoesNotExist(
  2984. (
  2985. interface2, cable3, (frontport2, frontport4), (rearport2, rearport4), (cable2, cable4),
  2986. (rearport1, rearport3), (frontport1, frontport2), cable1, interface1
  2987. ),
  2988. is_complete=True,
  2989. is_active=True
  2990. )
  2991. self.assertPathDoesNotExist(
  2992. (
  2993. interface1, cable1, (frontport1, frontport3), (rearport1, rearport3), (cable2, cable4),
  2994. (rearport2, rearport4), (frontport2, frontport4), cable3, interface2
  2995. ),
  2996. is_complete=True,
  2997. is_active=True
  2998. )
  2999. self.assertEqual(CablePath.objects.count(), 0)
  3000. def test_402_exclude_circuit_loopback(self):
  3001. interface = Interface.objects.create(device=self.device, name='Interface 1')
  3002. circuittermination1 = CircuitTermination.objects.create(
  3003. circuit=self.circuit,
  3004. termination=self.site,
  3005. term_side='A'
  3006. )
  3007. circuittermination2 = CircuitTermination.objects.create(
  3008. circuit=self.circuit,
  3009. termination=self.site,
  3010. term_side='Z'
  3011. )
  3012. # Create cables
  3013. cable = Cable(
  3014. a_terminations=[interface],
  3015. b_terminations=[circuittermination1, circuittermination2]
  3016. )
  3017. cable.save()
  3018. path = self.assertPathExists(
  3019. (interface, cable, (circuittermination1, circuittermination2)),
  3020. is_active=True,
  3021. is_complete=False,
  3022. is_split=True
  3023. )
  3024. self.assertEqual(CablePath.objects.count(), 1)
  3025. interface.refresh_from_db()
  3026. self.assertPathIsSet(interface, path)