| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514 |
- from unittest import skip
- from circuits.models import Circuit, CircuitTermination, ProviderNetwork
- from dcim.choices import CableLengthUnitChoices, CableProfileChoices
- from dcim.models import *
- from dcim.svg import CableTraceSVG
- from dcim.tests.utils import BaseCablePathTestCase
- from netbox.choices import DistanceUnitChoices
- class CablePathTestCase(BaseCablePathTestCase):
- """
- Test the creation of CablePaths for Cables with different profiles applied.
- Tests are numbered as follows:
- 1XX: Test direct connections using each profile
- 2XX: Topology tests replicated from the legacy test case and adapted to use profiles
- 3XX: Dynamic port mapping and termination changes
- """
- def test_101_cable_profile_single_1c1p(self):
- """
- [IF1] --C1-- [IF2]
- Cable profile: Single connector, single position
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- ]
- # Create cable 1
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- a_terminations=[interfaces[0]],
- b_terminations=[interfaces[1]],
- )
- cable1.clean()
- cable1.save()
- path1 = self.assertPathExists(
- (interfaces[0], cable1, interfaces[1]),
- is_complete=True,
- is_active=True
- )
- path2 = self.assertPathExists(
- (interfaces[1], cable1, interfaces[0]),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 2)
- interfaces[0].refresh_from_db()
- interfaces[1].refresh_from_db()
- self.assertPathIsSet(interfaces[0], path1)
- self.assertPathIsSet(interfaces[1], path2)
- self.assertEqual(interfaces[0].cable_connector, 1)
- self.assertEqual(interfaces[0].cable_positions, [1])
- self.assertEqual(interfaces[1].cable_connector, 1)
- self.assertEqual(interfaces[1].cable_positions, [1])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- # Delete cable 1
- cable1.delete()
- # Check that all CablePaths have been deleted
- self.assertEqual(CablePath.objects.count(), 0)
- def test_102_cable_profile_single_1c2p(self):
- """
- [IF1] --C1-- [FP1][RP1] --C3-- [RP2][FP3] --C4-- [IF3]
- [IF2] --C2-- [FP2] [FP4] --C5-- [IF4]
- Cable profile: Single connector, multiple positions
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- Interface.objects.create(device=self.device, name='Interface 4'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 2', positions=2),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1'),
- FrontPort.objects.create(device=self.device, name='Front Port 2'),
- FrontPort.objects.create(device=self.device, name='Front Port 3'),
- FrontPort.objects.create(device=self.device, name='Front Port 4'),
- ]
- PortMapping.objects.bulk_create([
- PortMapping(
- device=self.device,
- front_port=front_ports[0],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[1],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=2,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[2],
- front_port_position=1,
- rear_port=rear_ports[1],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[3],
- front_port_position=1,
- rear_port=rear_ports[1],
- rear_port_position=2,
- ),
- ])
- # Create cables
- cable1 = Cable(
- a_terminations=[interfaces[0]],
- b_terminations=[front_ports[0]],
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- a_terminations=[interfaces[1]],
- b_terminations=[front_ports[1]],
- )
- cable2.clean()
- cable2.save()
- cable3 = Cable(
- profile=CableProfileChoices.SINGLE_1C2P,
- a_terminations=[rear_ports[0]],
- b_terminations=[rear_ports[1]],
- )
- cable3.clean()
- cable3.save()
- cable4 = Cable(
- a_terminations=[interfaces[2]],
- b_terminations=[front_ports[2]],
- )
- cable4.clean()
- cable4.save()
- cable5 = Cable(
- a_terminations=[interfaces[3]],
- b_terminations=[front_ports[3]],
- )
- cable5.clean()
- cable5.save()
- path1 = self.assertPathExists(
- (
- interfaces[0], cable1, front_ports[0], rear_ports[0], cable3, rear_ports[1], front_ports[2], cable4,
- interfaces[2],
- ),
- is_complete=True,
- is_active=True
- )
- path2 = self.assertPathExists(
- (
- interfaces[1], cable2, front_ports[1], rear_ports[0], cable3, rear_ports[1], front_ports[3], cable5,
- interfaces[3],
- ),
- is_complete=True,
- is_active=True
- )
- path3 = self.assertPathExists(
- (
- interfaces[2], cable4, front_ports[2], rear_ports[1], cable3, rear_ports[0], front_ports[0], cable1,
- interfaces[0],
- ),
- is_complete=True,
- is_active=True
- )
- path4 = self.assertPathExists(
- (
- interfaces[3], cable5, front_ports[3], rear_ports[1], cable3, rear_ports[0], front_ports[1], cable2,
- interfaces[1],
- ),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 4)
- for iface in interfaces:
- iface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], path1)
- self.assertPathIsSet(interfaces[1], path2)
- self.assertPathIsSet(interfaces[2], path3)
- self.assertPathIsSet(interfaces[3], path4)
- for rear_port in rear_ports:
- rear_port.refresh_from_db()
- self.assertEqual(rear_ports[0].cable_connector, 1)
- self.assertEqual(rear_ports[0].cable_positions, [1, 2])
- self.assertEqual(rear_ports[1].cable_connector, 1)
- self.assertEqual(rear_ports[1].cable_positions, [1, 2])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_103_cable_profile_trunk_2c1p(self):
- """
- [IF1] --C1-- [IF3]
- [IF2] [IF4]
- Cable profile: Multiple connectors, single position
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- Interface.objects.create(device=self.device, name='Interface 4'),
- ]
- # Create cable 1
- cable1 = Cable(
- profile=CableProfileChoices.TRUNK_2C1P,
- a_terminations=[interfaces[0], interfaces[1]],
- b_terminations=[interfaces[2], interfaces[3]],
- )
- cable1.clean()
- cable1.save()
- path1 = self.assertPathExists(
- (interfaces[0], cable1, interfaces[2]),
- is_complete=True,
- is_active=True
- )
- path2 = self.assertPathExists(
- (interfaces[1], cable1, interfaces[3]),
- is_complete=True,
- is_active=True
- )
- path3 = self.assertPathExists(
- (interfaces[2], cable1, interfaces[0]),
- is_complete=True,
- is_active=True
- )
- path4 = self.assertPathExists(
- (interfaces[3], cable1, interfaces[1]),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 4)
- for interface in interfaces:
- interface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], path1)
- self.assertPathIsSet(interfaces[1], path2)
- self.assertPathIsSet(interfaces[2], path3)
- self.assertPathIsSet(interfaces[3], path4)
- self.assertEqual(interfaces[0].cable_connector, 1)
- self.assertEqual(interfaces[0].cable_positions, [1])
- self.assertEqual(interfaces[1].cable_connector, 2)
- self.assertEqual(interfaces[1].cable_positions, [1])
- self.assertEqual(interfaces[2].cable_connector, 1)
- self.assertEqual(interfaces[2].cable_positions, [1])
- self.assertEqual(interfaces[3].cable_connector, 2)
- self.assertEqual(interfaces[3].cable_positions, [1])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- # Delete cable 1
- cable1.delete()
- # Check that all CablePaths have been deleted
- self.assertEqual(CablePath.objects.count(), 0)
- def test_104_cable_profile_trunk_2c2p(self):
- """
- [IF1] --C1-- [FP1][RP1] --C9-- [RP3][FP5] --C5-- [IF5]
- [IF2] --C2-- [FP2] [FP6] --C6-- [IF6]
- [IF3] --C3-- [FP3][RP2] [RP4][FP7] --C7-- [IF7]
- [IF4] --C4-- [FP4] [FP8] --C8-- [IF8]
- Cable profile: Multiple connectors, multiple positions
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- Interface.objects.create(device=self.device, name='Interface 4'),
- Interface.objects.create(device=self.device, name='Interface 5'),
- Interface.objects.create(device=self.device, name='Interface 6'),
- Interface.objects.create(device=self.device, name='Interface 7'),
- Interface.objects.create(device=self.device, name='Interface 8'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 2', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 3', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 4', positions=2),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1'),
- FrontPort.objects.create(device=self.device, name='Front Port 2'),
- FrontPort.objects.create(device=self.device, name='Front Port 3'),
- FrontPort.objects.create(device=self.device, name='Front Port 4'),
- FrontPort.objects.create(device=self.device, name='Front Port 5'),
- FrontPort.objects.create(device=self.device, name='Front Port 6'),
- FrontPort.objects.create(device=self.device, name='Front Port 7'),
- FrontPort.objects.create(device=self.device, name='Front Port 8'),
- ]
- PortMapping.objects.bulk_create([
- PortMapping(
- device=self.device,
- front_port=front_ports[0],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[1],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=2,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[2],
- front_port_position=1,
- rear_port=rear_ports[1],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[3],
- front_port_position=1,
- rear_port=rear_ports[1],
- rear_port_position=2,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[4],
- front_port_position=1,
- rear_port=rear_ports[2],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[5],
- front_port_position=1,
- rear_port=rear_ports[2],
- rear_port_position=2,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[6],
- front_port_position=1,
- rear_port=rear_ports[3],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[7],
- front_port_position=1,
- rear_port=rear_ports[3],
- rear_port_position=2,
- ),
- ])
- # Create cables
- cable1 = Cable(a_terminations=[interfaces[0]], b_terminations=[front_ports[0]])
- cable1.clean()
- cable1.save()
- cable2 = Cable(a_terminations=[interfaces[1]], b_terminations=[front_ports[1]])
- cable2.clean()
- cable2.save()
- cable3 = Cable(a_terminations=[interfaces[2]], b_terminations=[front_ports[2]])
- cable3.clean()
- cable3.save()
- cable4 = Cable(a_terminations=[interfaces[3]], b_terminations=[front_ports[3]])
- cable4.clean()
- cable4.save()
- cable5 = Cable(a_terminations=[interfaces[4]], b_terminations=[front_ports[4]])
- cable5.clean()
- cable5.save()
- cable6 = Cable(a_terminations=[interfaces[5]], b_terminations=[front_ports[5]])
- cable6.clean()
- cable6.save()
- cable7 = Cable(a_terminations=[interfaces[6]], b_terminations=[front_ports[6]])
- cable7.clean()
- cable7.save()
- cable8 = Cable(a_terminations=[interfaces[7]], b_terminations=[front_ports[7]])
- cable8.clean()
- cable8.save()
- cable9 = Cable(
- profile=CableProfileChoices.TRUNK_2C2P,
- a_terminations=[rear_ports[0], rear_ports[1]],
- b_terminations=[rear_ports[2], rear_ports[3]]
- )
- cable9.clean()
- cable9.save()
- path1 = self.assertPathExists(
- (
- interfaces[0], cable1, front_ports[0], rear_ports[0], cable9, rear_ports[2], front_ports[4], cable5,
- interfaces[4],
- ),
- is_complete=True,
- is_active=True
- )
- path2 = self.assertPathExists(
- (
- interfaces[1], cable2, front_ports[1], rear_ports[0], cable9, rear_ports[2], front_ports[5], cable6,
- interfaces[5],
- ),
- is_complete=True,
- is_active=True
- )
- path3 = self.assertPathExists(
- (
- interfaces[2], cable3, front_ports[2], rear_ports[1], cable9, rear_ports[3], front_ports[6], cable7,
- interfaces[6],
- ),
- is_complete=True,
- is_active=True
- )
- path4 = self.assertPathExists(
- (
- interfaces[3], cable4, front_ports[3], rear_ports[1], cable9, rear_ports[3], front_ports[7], cable8,
- interfaces[7],
- ),
- is_complete=True,
- is_active=True
- )
- path5 = self.assertPathExists(
- (
- interfaces[4], cable5, front_ports[4], rear_ports[2], cable9, rear_ports[0], front_ports[0], cable1,
- interfaces[0],
- ),
- is_complete=True,
- is_active=True
- )
- path6 = self.assertPathExists(
- (
- interfaces[5], cable6, front_ports[5], rear_ports[2], cable9, rear_ports[0], front_ports[1], cable2,
- interfaces[1],
- ),
- is_complete=True,
- is_active=True
- )
- path7 = self.assertPathExists(
- (
- interfaces[6], cable7, front_ports[6], rear_ports[3], cable9, rear_ports[1], front_ports[2], cable3,
- interfaces[2],
- ),
- is_complete=True,
- is_active=True
- )
- path8 = self.assertPathExists(
- (
- interfaces[7], cable8, front_ports[7], rear_ports[3], cable9, rear_ports[1], front_ports[3], cable4,
- interfaces[3],
- ),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 8)
- for iface in interfaces:
- iface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], path1)
- self.assertPathIsSet(interfaces[1], path2)
- self.assertPathIsSet(interfaces[2], path3)
- self.assertPathIsSet(interfaces[3], path4)
- self.assertPathIsSet(interfaces[4], path5)
- self.assertPathIsSet(interfaces[5], path6)
- self.assertPathIsSet(interfaces[6], path7)
- self.assertPathIsSet(interfaces[7], path8)
- for rear_port in rear_ports:
- rear_port.refresh_from_db()
- self.assertEqual(rear_ports[0].cable_connector, 1)
- self.assertEqual(rear_ports[0].cable_positions, [1, 2])
- self.assertEqual(rear_ports[1].cable_connector, 2)
- self.assertEqual(rear_ports[1].cable_positions, [1, 2])
- self.assertEqual(rear_ports[2].cable_connector, 1)
- self.assertEqual(rear_ports[2].cable_positions, [1, 2])
- self.assertEqual(rear_ports[3].cable_connector, 2)
- self.assertEqual(rear_ports[3].cable_positions, [1, 2])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_105_cable_profile_breakout(self):
- """
- [IF1] --C1-- [FP1][RP1] --C2-- [IF5]
- [IF2] --C3-- [FP2] [IF6]
- [IF3] --C4-- [FP3] [IF7]
- [IF4] --C5-- [FP4] [IF8]
- Cable profile: 1:4 breakout
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- Interface.objects.create(device=self.device, name='Interface 4'),
- Interface.objects.create(device=self.device, name='Interface 5'),
- Interface.objects.create(device=self.device, name='Interface 6'),
- Interface.objects.create(device=self.device, name='Interface 7'),
- Interface.objects.create(device=self.device, name='Interface 8'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1'),
- FrontPort.objects.create(device=self.device, name='Front Port 2'),
- FrontPort.objects.create(device=self.device, name='Front Port 3'),
- FrontPort.objects.create(device=self.device, name='Front Port 4'),
- ]
- PortMapping.objects.bulk_create([
- PortMapping(
- device=self.device,
- front_port=front_ports[0],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[1],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=2,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[2],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=3,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[3],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=4,
- ),
- ])
- # Create cables
- cable1 = Cable(a_terminations=[interfaces[0]], b_terminations=[front_ports[0]])
- cable1.clean()
- cable1.save()
- cable2 = Cable(a_terminations=[interfaces[1]], b_terminations=[front_ports[1]])
- cable2.clean()
- cable2.save()
- cable3 = Cable(a_terminations=[interfaces[2]], b_terminations=[front_ports[2]])
- cable3.clean()
- cable3.save()
- cable4 = Cable(a_terminations=[interfaces[3]], b_terminations=[front_ports[3]])
- cable4.clean()
- cable4.save()
- cable5 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[rear_ports[0]],
- b_terminations=interfaces[4:8],
- )
- cable5.clean()
- cable5.save()
- path1 = self.assertPathExists(
- (interfaces[0], cable1, front_ports[0], rear_ports[0], cable5, interfaces[4]),
- is_complete=True,
- is_active=True
- )
- path2 = self.assertPathExists(
- (interfaces[1], cable2, front_ports[1], rear_ports[0], cable5, interfaces[5]),
- is_complete=True,
- is_active=True
- )
- path3 = self.assertPathExists(
- (interfaces[2], cable3, front_ports[2], rear_ports[0], cable5, interfaces[6]),
- is_complete=True,
- is_active=True
- )
- path4 = self.assertPathExists(
- (interfaces[3], cable4, front_ports[3], rear_ports[0], cable5, interfaces[7]),
- is_complete=True,
- is_active=True
- )
- path5 = self.assertPathExists(
- (interfaces[4], cable5, rear_ports[0], front_ports[0], cable1, interfaces[0]),
- is_complete=True,
- is_active=True
- )
- path6 = self.assertPathExists(
- (interfaces[5], cable5, rear_ports[0], front_ports[1], cable2, interfaces[1]),
- is_complete=True,
- is_active=True
- )
- path7 = self.assertPathExists(
- (interfaces[6], cable5, rear_ports[0], front_ports[2], cable3, interfaces[2]),
- is_complete=True,
- is_active=True
- )
- path8 = self.assertPathExists(
- (interfaces[7], cable5, rear_ports[0], front_ports[3], cable4, interfaces[3]),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 8)
- for interface in interfaces:
- interface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], path1)
- self.assertPathIsSet(interfaces[1], path2)
- self.assertPathIsSet(interfaces[2], path3)
- self.assertPathIsSet(interfaces[3], path4)
- self.assertPathIsSet(interfaces[4], path5)
- self.assertPathIsSet(interfaces[5], path6)
- self.assertPathIsSet(interfaces[6], path7)
- self.assertPathIsSet(interfaces[7], path8)
- self.assertEqual(interfaces[4].cable_connector, 1)
- self.assertEqual(interfaces[4].cable_positions, [1])
- self.assertEqual(interfaces[5].cable_connector, 2)
- self.assertEqual(interfaces[5].cable_positions, [1])
- self.assertEqual(interfaces[6].cable_connector, 3)
- self.assertEqual(interfaces[6].cable_positions, [1])
- self.assertEqual(interfaces[7].cable_connector, 4)
- self.assertEqual(interfaces[7].cable_positions, [1])
- rear_ports[0].refresh_from_db()
- self.assertEqual(rear_ports[0].cable_connector, 1)
- self.assertEqual(rear_ports[0].cable_positions, [1, 2, 3, 4])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_106_cable_profile_shuffle(self):
- """
- [IF1] --C1-- [FP1][RP1] --C17-- [RP3][FP9] --C9-- [IF9]
- [IF2] --C2-- [FP2] [FP10] --C10-- [IF10]
- [IF3] --C3-- [FP3] [FP11] --C11-- [IF11]
- [IF4] --C4-- [FP4] [FP12] --C12-- [IF12]
- [IF5] --C5-- [FP5][RP2] [RP4][FP13] --C13-- [IF9]
- [IF6] --C6-- [FP6] [FP14] --C14-- [IF10]
- [IF7] --C7-- [FP7] [FP15] --C15-- [IF11]
- [IF8] --C8-- [FP8] [FP16] --C16-- [IF12]
- Cable profile: Shuffle (2x2 MPO8)
- """
- interfaces = [
- # A side
- Interface.objects.create(device=self.device, name='Interface 1:1'),
- Interface.objects.create(device=self.device, name='Interface 1:2'),
- Interface.objects.create(device=self.device, name='Interface 1:3'),
- Interface.objects.create(device=self.device, name='Interface 1:4'),
- Interface.objects.create(device=self.device, name='Interface 2:1'),
- Interface.objects.create(device=self.device, name='Interface 2:2'),
- Interface.objects.create(device=self.device, name='Interface 2:3'),
- Interface.objects.create(device=self.device, name='Interface 2:4'),
- # B side
- Interface.objects.create(device=self.device, name='Interface 3:1'),
- Interface.objects.create(device=self.device, name='Interface 3:2'),
- Interface.objects.create(device=self.device, name='Interface 3:3'),
- Interface.objects.create(device=self.device, name='Interface 3:4'),
- Interface.objects.create(device=self.device, name='Interface 4:1'),
- Interface.objects.create(device=self.device, name='Interface 4:2'),
- Interface.objects.create(device=self.device, name='Interface 4:3'),
- Interface.objects.create(device=self.device, name='Interface 4:4'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4),
- RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4),
- RearPort.objects.create(device=self.device, name='Rear Port 3', positions=4),
- RearPort.objects.create(device=self.device, name='Rear Port 4', positions=4),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1'),
- FrontPort.objects.create(device=self.device, name='Front Port 2'),
- FrontPort.objects.create(device=self.device, name='Front Port 3'),
- FrontPort.objects.create(device=self.device, name='Front Port 4'),
- FrontPort.objects.create(device=self.device, name='Front Port 5'),
- FrontPort.objects.create(device=self.device, name='Front Port 6'),
- FrontPort.objects.create(device=self.device, name='Front Port 7'),
- FrontPort.objects.create(device=self.device, name='Front Port 8'),
- FrontPort.objects.create(device=self.device, name='Front Port 9'),
- FrontPort.objects.create(device=self.device, name='Front Port 10'),
- FrontPort.objects.create(device=self.device, name='Front Port 11'),
- FrontPort.objects.create(device=self.device, name='Front Port 12'),
- FrontPort.objects.create(device=self.device, name='Front Port 13'),
- FrontPort.objects.create(device=self.device, name='Front Port 14'),
- FrontPort.objects.create(device=self.device, name='Front Port 15'),
- FrontPort.objects.create(device=self.device, name='Front Port 16'),
- ]
- port_mappings = []
- for i, front_port in enumerate(front_ports):
- port_mappings.append(
- PortMapping(
- device=self.device,
- front_port=front_ports[i],
- front_port_position=1,
- rear_port=rear_ports[int(i / 4)],
- rear_port_position=(i % 4) + 1,
- ),
- )
- PortMapping.objects.bulk_create(port_mappings)
- # Create cables
- cables = []
- for interface, front_port in zip(interfaces, front_ports):
- cable = Cable(a_terminations=[interface], b_terminations=[front_port])
- cable.clean()
- cable.save()
- cables.append(cable)
- shuffle_cable = Cable(
- profile=CableProfileChoices.TRUNK_2C4P_SHUFFLE,
- a_terminations=rear_ports[0:2],
- b_terminations=rear_ports[2:4],
- )
- shuffle_cable.clean()
- shuffle_cable.save()
- paths = [
- # A-to-B paths
- self.assertPathExists(
- (
- interfaces[0], cables[0], front_ports[0], rear_ports[0], shuffle_cable, rear_ports[2],
- front_ports[8], cables[8], interfaces[8],
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interfaces[1], cables[1], front_ports[1], rear_ports[0], shuffle_cable, rear_ports[2],
- front_ports[9], cables[9], interfaces[9],
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interfaces[2], cables[2], front_ports[2], rear_ports[0], shuffle_cable, rear_ports[3],
- front_ports[12], cables[12], interfaces[12],
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interfaces[3], cables[3], front_ports[3], rear_ports[0], shuffle_cable, rear_ports[3],
- front_ports[13], cables[13], interfaces[13],
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interfaces[4], cables[4], front_ports[4], rear_ports[1], shuffle_cable, rear_ports[2],
- front_ports[10], cables[10], interfaces[10],
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interfaces[5], cables[5], front_ports[5], rear_ports[1], shuffle_cable, rear_ports[2],
- front_ports[11], cables[11], interfaces[11],
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interfaces[6], cables[6], front_ports[6], rear_ports[1], shuffle_cable, rear_ports[3],
- front_ports[14], cables[14], interfaces[14],
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interfaces[7], cables[7], front_ports[7], rear_ports[1], shuffle_cable, rear_ports[3],
- front_ports[15], cables[15], interfaces[15],
- ),
- is_complete=True,
- is_active=True
- ),
- ]
- self.assertEqual(CablePath.objects.count(), len(paths) * 2)
- for i, (interface, path) in enumerate(zip(interfaces, paths)):
- interface.refresh_from_db()
- self.assertPathIsSet(interface, path)
- for i, rear_port in enumerate(rear_ports):
- rear_port.refresh_from_db()
- self.assertEqual(rear_port.cable_connector, (i % 2) + 1)
- self.assertEqual(rear_port.cable_positions, [1, 2, 3, 4])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_107_duplex_interface_profiled_patch_through_trunk_with_splices(self):
- """
- Tests that a duplex interface (cable_positions=[1,2]) traces both positions through
- profiled cables and splice pass-throughs, producing a single CablePath with both
- strands visible.
- [IF1] -C1(1C2P)- [FP1(p=2)][RP1(p=2)] -C2(1C2P)- [RP2(p=2)]
- [FP2] -C3- [FP4][RP3(p=2)] -C4(1C2P)- [RP4(p=2)][FP6(p=2)]
- -C5(1C2P)- [IF2] / [FP3] -C6- [FP5]
- Cable profiles: C1=1C2P, C2=1C2P, C3/C6=unprofiled splices, C4=1C2P, C5=1C2P
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 2', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 3', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 4', positions=2),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1', positions=2), # Panel A duplex
- FrontPort.objects.create(device=self.device, name='Front Port 2'), # Splice A strand 1
- FrontPort.objects.create(device=self.device, name='Front Port 3'), # Splice A strand 2
- FrontPort.objects.create(device=self.device, name='Front Port 4'), # Splice B strand 1
- FrontPort.objects.create(device=self.device, name='Front Port 5'), # Splice B strand 2
- FrontPort.objects.create(device=self.device, name='Front Port 6', positions=2), # Panel B duplex
- ]
- PortMapping.objects.bulk_create([
- # Panel A: duplex FP1(pos=2) -> RP1(pos=2)
- PortMapping(
- device=self.device, front_port=front_ports[0], front_port_position=1,
- rear_port=rear_ports[0], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[0], front_port_position=2,
- rear_port=rear_ports[0], rear_port_position=2,
- ),
- # Splice A: FP2, FP3 -> RP2(pos=2)
- PortMapping(
- device=self.device, front_port=front_ports[1], front_port_position=1,
- rear_port=rear_ports[1], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[2], front_port_position=1,
- rear_port=rear_ports[1], rear_port_position=2,
- ),
- # Splice B: FP4, FP5 -> RP3(pos=2)
- PortMapping(
- device=self.device, front_port=front_ports[3], front_port_position=1,
- rear_port=rear_ports[2], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[4], front_port_position=1,
- rear_port=rear_ports[2], rear_port_position=2,
- ),
- # Panel B: duplex FP6(pos=2) -> RP4(pos=2)
- PortMapping(
- device=self.device, front_port=front_ports[5], front_port_position=1,
- rear_port=rear_ports[3], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[5], front_port_position=2,
- rear_port=rear_ports[3], rear_port_position=2,
- ),
- ])
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_1C2P,
- a_terminations=[interfaces[0]],
- b_terminations=[front_ports[0]],
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- profile=CableProfileChoices.SINGLE_1C2P,
- a_terminations=[rear_ports[0]],
- b_terminations=[rear_ports[1]],
- )
- cable2.clean()
- cable2.save()
- cable3 = Cable(
- a_terminations=[front_ports[1]],
- b_terminations=[front_ports[3]],
- )
- cable3.clean()
- cable3.save()
- cable4 = Cable(
- profile=CableProfileChoices.SINGLE_1C2P,
- a_terminations=[rear_ports[2]],
- b_terminations=[rear_ports[3]],
- )
- cable4.clean()
- cable4.save()
- cable5 = Cable(
- profile=CableProfileChoices.SINGLE_1C2P,
- a_terminations=[front_ports[5]],
- b_terminations=[interfaces[1]],
- )
- cable5.clean()
- cable5.save()
- cable6 = Cable(
- a_terminations=[front_ports[2]],
- b_terminations=[front_ports[4]],
- )
- cable6.clean()
- cable6.save()
- # Verify forward path: IF1 -> IF2 (both strands through splice)
- self.assertPathExists(
- (
- interfaces[0], cable1, front_ports[0],
- rear_ports[0], cable2, rear_ports[1],
- [front_ports[1], front_ports[2]], [cable3, cable6], [front_ports[3], front_ports[4]],
- rear_ports[2], cable4, rear_ports[3],
- front_ports[5], cable5, interfaces[1],
- ),
- is_complete=True,
- is_active=True
- )
- # Verify reverse path: IF2 -> IF1
- self.assertPathExists(
- (
- interfaces[1], cable5, front_ports[5],
- rear_ports[3], cable4, rear_ports[2],
- [front_ports[3], front_ports[4]], [cable3, cable6], [front_ports[1], front_ports[2]],
- rear_ports[1], cable2, rear_ports[0],
- front_ports[0], cable1, interfaces[0],
- ),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 2)
- # Verify cable positions on interfaces
- for iface in interfaces:
- iface.refresh_from_db()
- self.assertEqual(interfaces[0].cable_connector, 1)
- self.assertEqual(interfaces[0].cable_positions, [1, 2])
- self.assertEqual(interfaces[1].cable_connector, 1)
- self.assertEqual(interfaces[1].cable_positions, [1, 2])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_108_single_interface_two_frontports_unprofiled_through_trunk_with_splices(self):
- """
- Tests that positions seeded by PortMapping (not cable_positions) are preserved
- when crossing profiled cables.
- [IF1] -C1- [FP1,FP2][RP1(p=2)] -C2(1C2P)- [RP2(p=2)]
- [FP3] -C3- [FP5][RP3(p=2)] -C4(1C2P)- [RP4(p=2)]
- [FP7,FP8] -C5- [IF2] / [FP4] -C6- [FP6]
- PortMappings: FP1->RP1p1, FP2->RP1p2, FP3->RP2p1, FP4->RP2p2,
- FP5->RP3p1, FP6->RP3p2, FP7->RP4p1, FP8->RP4p2
- C1 is unprofiled (1 IF -> 2 FPs), C2/C4 are 1C2P trunks,
- C3/C6 are unprofiled splices, C5 is unprofiled (2 FPs -> 1 IF).
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 2', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 3', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 4', positions=2),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1'), # Panel A strand 1
- FrontPort.objects.create(device=self.device, name='Front Port 2'), # Panel A strand 2
- FrontPort.objects.create(device=self.device, name='Front Port 3'), # Splice A strand 1
- FrontPort.objects.create(device=self.device, name='Front Port 4'), # Splice A strand 2
- FrontPort.objects.create(device=self.device, name='Front Port 5'), # Splice B strand 1
- FrontPort.objects.create(device=self.device, name='Front Port 6'), # Splice B strand 2
- FrontPort.objects.create(device=self.device, name='Front Port 7'), # Panel B strand 1
- FrontPort.objects.create(device=self.device, name='Front Port 8'), # Panel B strand 2
- ]
- PortMapping.objects.bulk_create([
- # Panel A: FP1, FP2 -> RP1(pos=2)
- PortMapping(
- device=self.device, front_port=front_ports[0], front_port_position=1,
- rear_port=rear_ports[0], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[1], front_port_position=1,
- rear_port=rear_ports[0], rear_port_position=2,
- ),
- # Splice A: FP3, FP4 -> RP2(pos=2)
- PortMapping(
- device=self.device, front_port=front_ports[2], front_port_position=1,
- rear_port=rear_ports[1], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[3], front_port_position=1,
- rear_port=rear_ports[1], rear_port_position=2,
- ),
- # Splice B: FP5, FP6 -> RP3(pos=2)
- PortMapping(
- device=self.device, front_port=front_ports[4], front_port_position=1,
- rear_port=rear_ports[2], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[5], front_port_position=1,
- rear_port=rear_ports[2], rear_port_position=2,
- ),
- # Panel B: FP7, FP8 -> RP4(pos=2)
- PortMapping(
- device=self.device, front_port=front_ports[6], front_port_position=1,
- rear_port=rear_ports[3], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[7], front_port_position=1,
- rear_port=rear_ports[3], rear_port_position=2,
- ),
- ])
- # Create cables
- cable1 = Cable(
- a_terminations=[interfaces[0]],
- b_terminations=[front_ports[0], front_ports[1]],
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- profile=CableProfileChoices.SINGLE_1C2P,
- a_terminations=[rear_ports[0]],
- b_terminations=[rear_ports[1]],
- )
- cable2.clean()
- cable2.save()
- cable3 = Cable(
- a_terminations=[front_ports[2]],
- b_terminations=[front_ports[4]],
- )
- cable3.clean()
- cable3.save()
- cable4 = Cable(
- profile=CableProfileChoices.SINGLE_1C2P,
- a_terminations=[rear_ports[2]],
- b_terminations=[rear_ports[3]],
- )
- cable4.clean()
- cable4.save()
- cable5 = Cable(
- a_terminations=[front_ports[6], front_ports[7]],
- b_terminations=[interfaces[1]],
- )
- cable5.clean()
- cable5.save()
- cable6 = Cable(
- a_terminations=[front_ports[3]],
- b_terminations=[front_ports[5]],
- )
- cable6.clean()
- cable6.save()
- # Verify forward path: IF1 -> IF2 (both strands through splice)
- self.assertPathExists(
- (
- interfaces[0], cable1, [front_ports[0], front_ports[1]],
- rear_ports[0], cable2, rear_ports[1],
- [front_ports[2], front_ports[3]], [cable3, cable6], [front_ports[4], front_ports[5]],
- rear_ports[2], cable4, rear_ports[3],
- [front_ports[6], front_ports[7]], cable5, interfaces[1],
- ),
- is_complete=True,
- is_active=True
- )
- # Verify reverse path: IF2 -> IF1
- self.assertPathExists(
- (
- interfaces[1], cable5, [front_ports[6], front_ports[7]],
- rear_ports[3], cable4, rear_ports[2],
- [front_ports[4], front_ports[5]], [cable3, cable6], [front_ports[2], front_ports[3]],
- rear_ports[1], cable2, rear_ports[0],
- [front_ports[0], front_ports[1]], cable1, interfaces[0],
- ),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 2)
- # Verify cable positions are not set (unprofiled patch cables)
- for iface in interfaces:
- iface.refresh_from_db()
- self.assertIsNone(interfaces[0].cable_connector)
- self.assertIsNone(interfaces[0].cable_positions)
- self.assertIsNone(interfaces[1].cable_connector)
- self.assertIsNone(interfaces[1].cable_positions)
- def test_109_multiconnector_trunk_through_patch_panel(self):
- """
- Tests that a 4-position interface traces correctly through a patch panel
- that fans out to both connectors of a Trunk2C2P cable.
- [IF1] --C1(1C4P)-- [FP1(p=4)][RP1(p=2)] --C3(Trunk2C2P)-- [RP3(p=2)][FP5(p=4)] --C5(1C4P)-- [IF2]
- [RP2(p=2)] [RP4(p=2)]
- PortMappings (Panel A): FP1p1->RP1p1, FP1p2->RP1p2, FP1p3->RP2p1, FP1p4->RP2p2
- PortMappings (Panel B): FP5p1->RP3p1, FP5p2->RP3p2, FP5p3->RP4p1, FP5p4->RP4p2
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 2', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 3', positions=2),
- RearPort.objects.create(device=self.device, name='Rear Port 4', positions=2),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1', positions=4),
- FrontPort.objects.create(device=self.device, name='Front Port 5', positions=4),
- ]
- PortMapping.objects.bulk_create([
- # Panel A: FP1(p=4) -> RP1(p=2) and RP2(p=2)
- PortMapping(
- device=self.device, front_port=front_ports[0], front_port_position=1,
- rear_port=rear_ports[0], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[0], front_port_position=2,
- rear_port=rear_ports[0], rear_port_position=2,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[0], front_port_position=3,
- rear_port=rear_ports[1], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[0], front_port_position=4,
- rear_port=rear_ports[1], rear_port_position=2,
- ),
- # Panel B: FP5(p=4) -> RP3(p=2) and RP4(p=2)
- PortMapping(
- device=self.device, front_port=front_ports[1], front_port_position=1,
- rear_port=rear_ports[2], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[1], front_port_position=2,
- rear_port=rear_ports[2], rear_port_position=2,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[1], front_port_position=3,
- rear_port=rear_ports[3], rear_port_position=1,
- ),
- PortMapping(
- device=self.device, front_port=front_ports[1], front_port_position=4,
- rear_port=rear_ports[3], rear_port_position=2,
- ),
- ])
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_1C4P,
- a_terminations=[interfaces[0]],
- b_terminations=[front_ports[0]],
- )
- cable1.clean()
- cable1.save()
- cable3 = Cable(
- profile=CableProfileChoices.TRUNK_2C2P,
- a_terminations=[rear_ports[0], rear_ports[1]],
- b_terminations=[rear_ports[2], rear_ports[3]],
- )
- cable3.clean()
- cable3.save()
- cable5 = Cable(
- profile=CableProfileChoices.SINGLE_1C4P,
- a_terminations=[front_ports[1]],
- b_terminations=[interfaces[1]],
- )
- cable5.clean()
- cable5.save()
- # Verify forward path: IF1 -> IF2 (all 4 positions through trunk)
- self.assertPathExists(
- (
- interfaces[0], cable1, front_ports[0],
- [rear_ports[0], rear_ports[1]], cable3, [rear_ports[2], rear_ports[3]],
- front_ports[1], cable5, interfaces[1],
- ),
- is_complete=True,
- is_active=True
- )
- # Verify reverse path: IF2 -> IF1
- self.assertPathExists(
- (
- interfaces[1], cable5, front_ports[1],
- [rear_ports[2], rear_ports[3]], cable3, [rear_ports[0], rear_ports[1]],
- front_ports[0], cable1, interfaces[0],
- ),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 2)
- # Verify cable positions
- for iface in interfaces:
- iface.refresh_from_db()
- self.assertEqual(interfaces[0].cable_connector, 1)
- self.assertEqual(interfaces[0].cable_positions, [1, 2, 3, 4])
- self.assertEqual(interfaces[1].cable_connector, 1)
- self.assertEqual(interfaces[1].cable_positions, [1, 2, 3, 4])
- # Verify rear port connector assignments
- for rp in rear_ports:
- rp.refresh_from_db()
- self.assertEqual(rear_ports[0].cable_connector, 1)
- self.assertEqual(rear_ports[0].cable_positions, [1, 2])
- self.assertEqual(rear_ports[1].cable_connector, 2)
- self.assertEqual(rear_ports[1].cable_positions, [1, 2])
- self.assertEqual(rear_ports[2].cable_connector, 1)
- self.assertEqual(rear_ports[2].cable_positions, [1, 2])
- self.assertEqual(rear_ports[3].cable_connector, 2)
- self.assertEqual(rear_ports[3].cable_positions, [1, 2])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_110_partial_termination_profiled_trunk(self):
- """
- Tests that tracing through a partially terminated profiled cable
- produces a complete path for the connected pair and an incomplete
- path for the unconnected pair, without errors. Also verifies that
- attaching the missing termination completes the previously incomplete path.
- [IF1] --C1-- [IF3]
- [IF2] (empty)
- Cable profile: Trunk 2C1P with only one B-side termination.
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- ]
- # Create a 2-connector trunk cable with both A-side connectors
- # populated but only one B-side connector terminated.
- cable1 = Cable(
- profile=CableProfileChoices.TRUNK_2C1P,
- a_terminations=[interfaces[0], interfaces[1]],
- b_terminations=[interfaces[2]],
- )
- cable1.clean()
- cable1.save()
- # IF1 (connector 1) → IF3 (connector 1): complete path
- path1 = self.assertPathExists(
- (interfaces[0], cable1, interfaces[2]),
- is_complete=True,
- is_active=True,
- )
- # IF3 (connector 1) → IF1 (connector 1): complete path (reverse)
- path2 = self.assertPathExists(
- (interfaces[2], cable1, interfaces[0]),
- is_complete=True,
- is_active=True,
- )
- # IF2 (connector 2) has no B-side peer.
- # Tracing should stop at this segment, and the resulting path
- # should remain incomplete.
- # Verify via the origin's _path reference rather than matching
- # the exact path shape directly.
- interfaces[1].refresh_from_db()
- self.assertIsNotNone(interfaces[1]._path_id)
- path3 = CablePath.objects.get(pk=interfaces[1]._path_id)
- self.assertFalse(path3.is_complete)
- self.assertTrue(path3.is_active)
- for iface in interfaces:
- iface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], path1)
- self.assertPathIsSet(interfaces[2], path2)
- self.assertPathIsSet(interfaces[1], path3)
- # Verify connector/position assignments
- self.assertEqual(interfaces[0].cable_connector, 1)
- self.assertEqual(interfaces[0].cable_positions, [1])
- self.assertEqual(interfaces[1].cable_connector, 2)
- self.assertEqual(interfaces[1].cable_positions, [1])
- self.assertEqual(interfaces[2].cable_connector, 1)
- self.assertEqual(interfaces[2].cable_positions, [1])
- # Now attach the missing B-side termination and verify the
- # previously incomplete path becomes complete.
- interface4 = Interface.objects.create(device=self.device, name='Interface 4')
- cable1.b_terminations = [interfaces[2], interface4]
- cable1.clean()
- cable1.save()
- path4 = self.assertPathExists(
- (interfaces[1], cable1, interface4),
- is_complete=True,
- is_active=True,
- )
- path5 = self.assertPathExists(
- (interface4, cable1, interfaces[1]),
- is_complete=True,
- is_active=True,
- )
- interfaces[1].refresh_from_db()
- interface4.refresh_from_db()
- self.assertPathIsSet(interfaces[1], path4)
- self.assertPathIsSet(interface4, path5)
- self.assertEqual(interface4.cable_connector, 2)
- self.assertEqual(interface4.cable_positions, [1])
- def test_202_single_path_via_pass_through_with_breakouts(self):
- """
- [IF1] --C1-- [FP1] [RP1] --C2-- [IF3]
- [IF2] [IF4]
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- Interface.objects.create(device=self.device, name='Interface 4'),
- ]
- rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
- frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1', positions=4)
- PortMapping.objects.bulk_create([
- PortMapping(
- device=self.device,
- front_port=frontport1,
- front_port_position=1,
- rear_port=rearport1,
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport1,
- front_port_position=2,
- rear_port=rearport1,
- rear_port_position=2,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport1,
- front_port_position=3,
- rear_port=rearport1,
- rear_port_position=3,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport1,
- front_port_position=4,
- rear_port=rearport1,
- rear_port_position=4,
- ),
- ])
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[frontport1],
- b_terminations=[interfaces[0], interfaces[1]],
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[rearport1],
- b_terminations=[interfaces[2], interfaces[3]]
- )
- cable2.clean()
- cable2.save()
- paths = [
- self.assertPathExists(
- (interfaces[0], cable1, frontport1, rearport1, cable2, interfaces[2]),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (interfaces[1], cable1, frontport1, rearport1, cable2, interfaces[3]),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (interfaces[2], cable2, rearport1, frontport1, cable1, interfaces[0]),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (interfaces[3], cable2, rearport1, frontport1, cable1, interfaces[1]),
- is_complete=True,
- is_active=True
- ),
- ]
- self.assertEqual(CablePath.objects.count(), 4)
- for interface in interfaces:
- interface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], paths[0])
- self.assertPathIsSet(interfaces[1], paths[1])
- self.assertPathIsSet(interfaces[2], paths[2])
- self.assertPathIsSet(interfaces[3], paths[3])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_204_multiple_paths_via_pass_through_with_breakouts(self):
- """
- [IF1] --C1-- [FP1] [RP1] --C3-- [RP2] [FP3] --C4-- [IF5]
- [IF2] [IF6]
- [IF3] --C2-- [FP2] [FP4] --C5-- [IF7]
- [IF4] [IF8]
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- Interface.objects.create(device=self.device, name='Interface 4'),
- Interface.objects.create(device=self.device, name='Interface 5'),
- Interface.objects.create(device=self.device, name='Interface 6'),
- Interface.objects.create(device=self.device, name='Interface 7'),
- Interface.objects.create(device=self.device, name='Interface 8'),
- ]
- rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=8)
- rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=8)
- frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1', positions=4)
- frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2', positions=4)
- frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 2:1', positions=4)
- frontport4 = FrontPort.objects.create(device=self.device, name='Front Port 2:2', positions=4)
- PortMapping.objects.bulk_create([
- PortMapping(
- device=self.device,
- front_port=frontport1,
- front_port_position=1,
- rear_port=rearport1,
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport1,
- front_port_position=2,
- rear_port=rearport1,
- rear_port_position=2,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport2,
- front_port_position=1,
- rear_port=rearport1,
- rear_port_position=5,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport2,
- front_port_position=2,
- rear_port=rearport1,
- rear_port_position=6,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport3,
- front_port_position=1,
- rear_port=rearport2,
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport3,
- front_port_position=2,
- rear_port=rearport2,
- rear_port_position=2,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport4,
- front_port_position=1,
- rear_port=rearport2,
- rear_port_position=5,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport4,
- front_port_position=2,
- rear_port=rearport2,
- rear_port_position=6,
- ),
- ])
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[frontport1],
- b_terminations=[interfaces[0], interfaces[1]],
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[frontport2],
- b_terminations=[interfaces[2], interfaces[3]],
- )
- cable2.clean()
- cable2.save()
- cable3 = Cable(
- profile=CableProfileChoices.SINGLE_1C8P,
- a_terminations=[rearport1],
- b_terminations=[rearport2]
- )
- cable3.clean()
- cable3.save()
- cable4 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[frontport3],
- b_terminations=[interfaces[4], interfaces[5]],
- )
- cable4.clean()
- cable4.save()
- cable5 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[frontport4],
- b_terminations=[interfaces[6], interfaces[7]],
- )
- cable5.clean()
- cable5.save()
- paths = [
- self.assertPathExists(
- (
- interfaces[0], cable1, frontport1, rearport1, cable3, rearport2, frontport3, cable4,
- interfaces[4],
- ),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (
- interfaces[1], cable1, frontport1, rearport1, cable3, rearport2, frontport3, cable4,
- interfaces[5],
- ),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (
- interfaces[2], cable2, frontport2, rearport1, cable3, rearport2, frontport4, cable5,
- interfaces[6],
- ),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (
- interfaces[3], cable2, frontport2, rearport1, cable3, rearport2, frontport4, cable5,
- interfaces[7],
- ),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (
- interfaces[4], cable4, frontport3, rearport2, cable3, rearport1, frontport1, cable1,
- interfaces[0],
- ),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (
- interfaces[5], cable4, frontport3, rearport2, cable3, rearport1, frontport1, cable1,
- interfaces[1],
- ),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (
- interfaces[6], cable5, frontport4, rearport2, cable3, rearport1, frontport2, cable2,
- interfaces[2],
- ),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (
- interfaces[7], cable5, frontport4, rearport2, cable3, rearport1, frontport2, cable2,
- interfaces[3],
- ),
- is_complete=True,
- is_active=True,
- ),
- ]
- self.assertEqual(CablePath.objects.count(), 8)
- for interface in interfaces:
- interface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], paths[0])
- self.assertPathIsSet(interfaces[1], paths[1])
- self.assertPathIsSet(interfaces[2], paths[2])
- self.assertPathIsSet(interfaces[3], paths[3])
- self.assertPathIsSet(interfaces[4], paths[4])
- self.assertPathIsSet(interfaces[5], paths[5])
- self.assertPathIsSet(interfaces[6], paths[6])
- self.assertPathIsSet(interfaces[7], paths[7])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_212_interface_to_interface_via_circuit_with_breakouts(self):
- """
- [IF1] --C1-- [CT1] [CT2] --C2-- [IF3]
- [IF2] [IF4]
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- Interface.objects.create(device=self.device, name='Interface 4'),
- ]
- circuittermination1 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='A'
- )
- circuittermination2 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='Z'
- )
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[circuittermination1],
- b_terminations=[interfaces[0], interfaces[1]],
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C4P_4C1P,
- a_terminations=[circuittermination2],
- b_terminations=[interfaces[2], interfaces[3]]
- )
- cable2.clean()
- cable2.save()
- # Check for two complete paths in either direction
- paths = [
- self.assertPathExists(
- (interfaces[0], cable1, circuittermination1, circuittermination2, cable2, interfaces[2]),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (interfaces[1], cable1, circuittermination1, circuittermination2, cable2, interfaces[3]),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (interfaces[2], cable2, circuittermination2, circuittermination1, cable1, interfaces[0]),
- is_complete=True,
- is_active=True,
- ),
- self.assertPathExists(
- (interfaces[3], cable2, circuittermination2, circuittermination1, cable1, interfaces[1]),
- is_complete=True,
- is_active=True,
- ),
- ]
- self.assertEqual(CablePath.objects.count(), 4)
- for interface in interfaces:
- interface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], paths[0])
- self.assertPathIsSet(interfaces[1], paths[1])
- self.assertPathIsSet(interfaces[2], paths[2])
- self.assertPathIsSet(interfaces[3], paths[3])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- # TBD: Is this a topology we want to support?
- @skip("Test applicability TBD")
- def test_217_interface_to_interface_via_rear_ports(self):
- """
- [IF1] --C1-- [FP1] [RP1] --C2-- [RP3] [FP3] --C3-- [IF2]
- [FP2] [RP2] [RP4] [FP4]
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1'),
- RearPort.objects.create(device=self.device, name='Rear Port 2'),
- RearPort.objects.create(device=self.device, name='Rear Port 3'),
- RearPort.objects.create(device=self.device, name='Rear Port 4'),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1'),
- FrontPort.objects.create(device=self.device, name='Front Port 2'),
- FrontPort.objects.create(device=self.device, name='Front Port 3'),
- FrontPort.objects.create(device=self.device, name='Front Port 4'),
- ]
- PortMapping.objects.bulk_create([
- PortMapping(
- device=self.device,
- front_port=front_ports[0],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[1],
- front_port_position=1,
- rear_port=rear_ports[1],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[2],
- front_port_position=1,
- rear_port=rear_ports[2],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[3],
- front_port_position=1,
- rear_port=rear_ports[3],
- rear_port_position=1,
- ),
- ])
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_2C1P,
- a_terminations=[interfaces[0]],
- b_terminations=[front_ports[0], front_ports[1]]
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- a_terminations=[rear_ports[0], rear_ports[1]],
- b_terminations=[rear_ports[2], rear_ports[3]]
- )
- cable2.clean()
- cable2.save()
- cable3 = Cable(
- profile=CableProfileChoices.SINGLE_2C1P,
- a_terminations=[interfaces[1]],
- b_terminations=[front_ports[2], front_ports[3]]
- )
- cable3.clean()
- cable3.save()
- # Check for one complete path in either direction
- paths = [
- self.assertPathExists(
- (
- interfaces[0], cable1, (front_ports[0], front_ports[1]), (rear_ports[0], rear_ports[1]), cable2,
- (rear_ports[2], rear_ports[3]), (front_ports[2], front_ports[3]), cable3, interfaces[1]
- ),
- is_complete=True
- ),
- self.assertPathExists(
- (
- interfaces[1], cable3, (front_ports[2], front_ports[3]), (rear_ports[2], rear_ports[3]), cable2,
- (rear_ports[0], rear_ports[1]), (front_ports[0], front_ports[1]), cable1, interfaces[0]
- ),
- is_complete=True
- ),
- ]
- self.assertEqual(CablePath.objects.count(), 2)
- for interface in interfaces:
- interface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], paths[0])
- self.assertPathIsSet(interfaces[1], paths[1])
- # Test SVG generation
- CableTraceSVG(interfaces[0]).render()
- def test_223_single_path_via_multiple_pass_throughs_with_breakouts(self):
- """
- [IF1] --C1-- [FP1] [RP1] --C2-- [IF3]
- [IF2] [FP2] [RP2] [IF4]
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- Interface.objects.create(device=self.device, name='Interface 4'),
- ]
- rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
- rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
- frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
- frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
- PortMapping.objects.bulk_create([
- PortMapping(
- device=self.device,
- front_port=frontport1,
- front_port_position=1,
- rear_port=rearport1,
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=frontport2,
- front_port_position=1,
- rear_port=rearport2,
- rear_port_position=1,
- ),
- ])
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.TRUNK_2C2P,
- a_terminations=[interfaces[0], interfaces[1]],
- b_terminations=[frontport1, frontport2]
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- profile=CableProfileChoices.TRUNK_2C2P,
- a_terminations=[rearport1, rearport2],
- b_terminations=[interfaces[2], interfaces[3]]
- )
- cable2.clean()
- cable2.save()
- # Validate paths
- self.assertPathExists(
- (interfaces[0], cable1, frontport1, rearport1, cable2, interfaces[2]),
- is_complete=True,
- is_active=True
- )
- self.assertPathExists(
- (interfaces[1], cable1, frontport2, rearport2, cable2, interfaces[3]),
- is_complete=True,
- is_active=True
- )
- self.assertPathExists(
- (interfaces[2], cable2, rearport1, frontport1, cable1, interfaces[0]),
- is_complete=True,
- is_active=True
- )
- self.assertPathExists(
- (interfaces[3], cable2, rearport2, frontport2, cable1, interfaces[1]),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(CablePath.objects.count(), 4)
- def test_225_breakout_1c2p_2c1p_to_single_position_passthroughs(self):
- """
- Regression test for #22187: a 1C2P:2C1P breakout cable terminating on two
- single-position FrontPorts (each mapping 1:1 to a single-position RearPort)
- which are then connected to PathEndpoints via unprofiled cables.
- [IF1] --C1 (1C2P:2C1P)-- [FP1] [RP1] --C2 (unprofiled)-- [IF2]
- [FP2] [RP2] --C3 (unprofiled)-- [IF3]
- """
- interfaces = [
- Interface.objects.create(device=self.device, name='Interface 1'),
- Interface.objects.create(device=self.device, name='Interface 2'),
- Interface.objects.create(device=self.device, name='Interface 3'),
- ]
- rear_ports = [
- RearPort.objects.create(device=self.device, name='Rear Port 1'),
- RearPort.objects.create(device=self.device, name='Rear Port 2'),
- ]
- front_ports = [
- FrontPort.objects.create(device=self.device, name='Front Port 1'),
- FrontPort.objects.create(device=self.device, name='Front Port 2'),
- ]
- PortMapping.objects.bulk_create([
- PortMapping(
- device=self.device,
- front_port=front_ports[0],
- front_port_position=1,
- rear_port=rear_ports[0],
- rear_port_position=1,
- ),
- PortMapping(
- device=self.device,
- front_port=front_ports[1],
- front_port_position=1,
- rear_port=rear_ports[1],
- rear_port_position=1,
- ),
- ])
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.BREAKOUT_1C2P_2C1P,
- a_terminations=[interfaces[0]],
- b_terminations=[front_ports[0], front_ports[1]],
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- a_terminations=[rear_ports[0]],
- b_terminations=[interfaces[1]],
- )
- cable2.clean()
- cable2.save()
- cable3 = Cable(
- a_terminations=[rear_ports[1]],
- b_terminations=[interfaces[2]],
- )
- cable3.clean()
- cable3.save()
- # The breakout splits IF1's two positions into separate downstream cables,
- # so the forward path has FP1/FP2, RP1/RP2, and the two unprofiled cables
- # at the corresponding hops.
- path1 = self.assertPathExists(
- (
- interfaces[0],
- cable1,
- [front_ports[0], front_ports[1]],
- [rear_ports[0], rear_ports[1]],
- [cable2, cable3],
- [interfaces[1], interfaces[2]],
- ),
- is_complete=True,
- is_active=True,
- )
- path2 = self.assertPathExists(
- (interfaces[1], cable2, rear_ports[0], front_ports[0], cable1, interfaces[0]),
- is_complete=True,
- is_active=True,
- )
- path3 = self.assertPathExists(
- (interfaces[2], cable3, rear_ports[1], front_ports[1], cable1, interfaces[0]),
- is_complete=True,
- is_active=True,
- )
- self.assertEqual(CablePath.objects.count(), 3)
- for interface in interfaces:
- interface.refresh_from_db()
- self.assertPathIsSet(interfaces[0], path1)
- self.assertPathIsSet(interfaces[1], path2)
- self.assertPathIsSet(interfaces[2], path3)
- # Test SVG generation from both directions
- CableTraceSVG(interfaces[0]).render()
- CableTraceSVG(interfaces[1]).render()
- CableTraceSVG(interfaces[2]).render()
- def test_226_total_length_via_circuit(self):
- """
- [IF1] --C1-- [CT1] [CT2] --C2-- [IF2]
- """
- self.circuit.distance = 10
- self.circuit.distance_unit = DistanceUnitChoices.UNIT_KILOMETER
- self.circuit.save()
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- interface2 = Interface.objects.create(device=self.device, name='Interface 2')
- circuittermination1 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='A'
- )
- circuittermination2 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='Z'
- )
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[interface1],
- b_terminations=[circuittermination1]
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[circuittermination2],
- b_terminations=[interface2]
- )
- cable2.clean()
- cable2.save()
- # Check for complete paths in both directions
- paths = [
- self.assertPathExists(
- (interface1, cable1, circuittermination1, circuittermination2, cable2, interface2),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (interface2, cable2, circuittermination2, circuittermination1, cable1, interface1),
- is_complete=True,
- is_active=True
- ),
- ]
- # The crossed circuit's distance counts toward the total path length
- for path in paths:
- self.assertEqual(path.get_total_length(), (10400, True))
- # An unset circuit distance makes the total length non-definitive
- self.circuit.distance = None
- self.circuit.save()
- for path in paths:
- self.assertEqual(path.get_total_length(), (400, False))
- # A circuit distance of zero is a known value and remains definitive
- self.circuit.distance = 0
- self.circuit.distance_unit = DistanceUnitChoices.UNIT_KILOMETER
- self.circuit.save()
- for path in paths:
- self.assertEqual(path.get_total_length(), (400, True))
- def test_227_total_length_via_circuit_without_peer_termination(self):
- """
- [IF1] --C1-- [CT1]
- """
- self.circuit.distance = 10
- self.circuit.distance_unit = DistanceUnitChoices.UNIT_KILOMETER
- self.circuit.save()
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- circuittermination1 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='A'
- )
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[interface1],
- b_terminations=[circuittermination1]
- )
- cable1.clean()
- cable1.save()
- # The distance of a circuit which the path does not cross is excluded
- path = self.assertPathExists(
- (interface1, cable1, circuittermination1),
- is_complete=False
- )
- self.assertEqual(path.get_total_length(), (200, True))
- def test_228_total_length_via_multiple_circuits(self):
- """
- [IF1] --C1-- [CT1] [CT2] --C2-- [CT3] [CT4] --C3-- [IF2]
- """
- self.circuit.distance = 10
- self.circuit.distance_unit = DistanceUnitChoices.UNIT_KILOMETER
- self.circuit.save()
- circuit2 = Circuit.objects.create(
- provider=self.circuit.provider,
- type=self.circuit.type,
- cid='Circuit 2',
- distance=5,
- distance_unit=DistanceUnitChoices.UNIT_KILOMETER
- )
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- interface2 = Interface.objects.create(device=self.device, name='Interface 2')
- circuittermination1 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='A'
- )
- circuittermination2 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='Z'
- )
- circuittermination3 = CircuitTermination.objects.create(
- circuit=circuit2,
- termination=self.site,
- term_side='A'
- )
- circuittermination4 = CircuitTermination.objects.create(
- circuit=circuit2,
- termination=self.site,
- term_side='Z'
- )
- # Create cables
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[interface1],
- b_terminations=[circuittermination1]
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- length=100,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[circuittermination2],
- b_terminations=[circuittermination3]
- )
- cable2.clean()
- cable2.save()
- cable3 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[circuittermination4],
- b_terminations=[interface2]
- )
- cable3.clean()
- cable3.save()
- # Check for complete paths in both directions
- paths = [
- self.assertPathExists(
- (
- interface1, cable1, circuittermination1, circuittermination2, cable2, circuittermination3,
- circuittermination4, cable3, interface2,
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interface2, cable3, circuittermination4, circuittermination3, cable2, circuittermination2,
- circuittermination1, cable1, interface1,
- ),
- is_complete=True,
- is_active=True
- ),
- ]
- # Each crossed circuit adds its distance to the total path length
- for path in paths:
- self.assertEqual(path.get_total_length(), (15500, True))
- def test_229_total_length_via_circuit_to_site(self):
- """
- [IF1] --C1-- [CT1] [CT2] --> [Site2]
- """
- self.circuit.distance = 10
- self.circuit.distance_unit = DistanceUnitChoices.UNIT_KILOMETER
- self.circuit.save()
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- site2 = Site.objects.create(name='Site 2', slug='site-2')
- circuittermination1 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='A'
- )
- circuittermination2 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=site2,
- term_side='Z'
- )
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[interface1],
- b_terminations=[circuittermination1]
- )
- cable1.clean()
- cable1.save()
- # The distance of a circuit crossed to reach its far-side site counts toward the total length
- path = self.assertPathExists(
- (interface1, cable1, circuittermination1, circuittermination2, site2),
- is_active=True
- )
- self.assertEqual(path.get_total_length(), (10200, True))
- def test_230_total_length_via_circuit_to_providernetwork(self):
- """
- [IF1] --C1-- [CT1] [CT2] --> [PN1]
- """
- self.circuit.distance = 10
- self.circuit.distance_unit = DistanceUnitChoices.UNIT_KILOMETER
- self.circuit.save()
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- providernetwork = ProviderNetwork.objects.create(name='Provider Network 1', provider=self.circuit.provider)
- circuittermination1 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='A'
- )
- circuittermination2 = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=providernetwork,
- term_side='Z'
- )
- cable1 = Cable(
- profile=CableProfileChoices.SINGLE_1C1P,
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[interface1],
- b_terminations=[circuittermination1]
- )
- cable1.clean()
- cable1.save()
- # The distance of a circuit crossed to reach a provider network counts toward the total length
- path = self.assertPathExists(
- (interface1, cable1, circuittermination1, circuittermination2, providernetwork),
- is_complete=True,
- is_active=True
- )
- self.assertEqual(path.get_total_length(), (10200, True))
- def test_231_total_length_via_parallel_circuits(self):
- """
- [IF1] --C1-- [CT1_A] [CT1_Z] --C2-- [IF2]
- [CT2_A] [CT2_Z]
- """
- self.circuit.distance = 10
- self.circuit.distance_unit = DistanceUnitChoices.UNIT_KILOMETER
- self.circuit.save()
- circuit2 = Circuit.objects.create(
- provider=self.circuit.provider,
- type=self.circuit.type,
- cid='Circuit 2',
- distance=5,
- distance_unit=DistanceUnitChoices.UNIT_KILOMETER
- )
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- interface2 = Interface.objects.create(device=self.device, name='Interface 2')
- circuittermination1_A = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='A'
- )
- circuittermination1_Z = CircuitTermination.objects.create(
- circuit=self.circuit,
- termination=self.site,
- term_side='Z'
- )
- circuittermination2_A = CircuitTermination.objects.create(
- circuit=circuit2,
- termination=self.site,
- term_side='A'
- )
- circuittermination2_Z = CircuitTermination.objects.create(
- circuit=circuit2,
- termination=self.site,
- term_side='Z'
- )
- # Create cables
- cable1 = Cable(
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[interface1],
- b_terminations=[circuittermination1_A, circuittermination2_A]
- )
- cable1.clean()
- cable1.save()
- cable2 = Cable(
- length=200,
- length_unit=CableLengthUnitChoices.UNIT_METER,
- a_terminations=[circuittermination1_Z, circuittermination2_Z],
- b_terminations=[interface2]
- )
- cable2.clean()
- cable2.save()
- # Check for complete paths in both directions
- paths = [
- self.assertPathExists(
- (
- interface1, cable1, (circuittermination1_A, circuittermination2_A),
- (circuittermination1_Z, circuittermination2_Z), cable2, interface2,
- ),
- is_complete=True,
- is_active=True
- ),
- self.assertPathExists(
- (
- interface2, cable2, (circuittermination1_Z, circuittermination2_Z),
- (circuittermination1_A, circuittermination2_A), cable1, interface1,
- ),
- is_complete=True,
- is_active=True
- ),
- ]
- # Parallel circuits crossed in the same hop count only the longest distance
- for path in paths:
- self.assertEqual(path.get_total_length(), (10400, True))
- # An unset distance on one parallel circuit keeps the longest known distance but is non-definitive
- circuit2.distance = None
- circuit2.save()
- for path in paths:
- self.assertEqual(path.get_total_length(), (10400, False))
- def test_304_add_port_mapping_between_connected_ports(self):
- """
- [IF1] --C1-- [FP1] [RP1] --C2-- [IF2]
- """
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- interface2 = Interface.objects.create(device=self.device, name='Interface 2')
- frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
- rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
- cable1 = Cable(
- a_terminations=[interface1],
- b_terminations=[frontport1]
- )
- cable1.save()
- cable2 = Cable(
- a_terminations=[interface2],
- b_terminations=[rearport1]
- )
- cable2.save()
- # Check for incomplete paths
- self.assertPathExists(
- (interface1, cable1, frontport1),
- is_complete=False,
- is_active=True
- )
- self.assertPathExists(
- (interface2, cable2, rearport1),
- is_complete=False,
- is_active=True
- )
- # Create a PortMapping between frontport1 and rearport1
- PortMapping.objects.create(
- device=self.device,
- front_port=frontport1,
- front_port_position=1,
- rear_port=rearport1,
- rear_port_position=1,
- )
- # Check that paths are now complete
- self.assertPathExists(
- (interface1, cable1, frontport1, rearport1, cable2, interface2),
- is_complete=True,
- is_active=True
- )
- self.assertPathExists(
- (interface2, cable2, rearport1, frontport1, cable1, interface1),
- is_complete=True,
- is_active=True
- )
- def test_305_delete_port_mapping_between_connected_ports(self):
- """
- [IF1] --C1-- [FP1] [RP1] --C2-- [IF2]
- """
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- interface2 = Interface.objects.create(device=self.device, name='Interface 2')
- frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
- rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
- cable1 = Cable(
- a_terminations=[interface1],
- b_terminations=[frontport1]
- )
- cable1.save()
- cable2 = Cable(
- a_terminations=[interface2],
- b_terminations=[rearport1]
- )
- cable2.save()
- portmapping1 = PortMapping.objects.create(
- device=self.device,
- front_port=frontport1,
- front_port_position=1,
- rear_port=rearport1,
- rear_port_position=1,
- )
- # Check for complete paths
- self.assertPathExists(
- (interface1, cable1, frontport1, rearport1, cable2, interface2),
- is_complete=True,
- is_active=True
- )
- self.assertPathExists(
- (interface2, cable2, rearport1, frontport1, cable1, interface1),
- is_complete=True,
- is_active=True
- )
- # Delete the PortMapping between frontport1 and rearport1
- portmapping1.delete()
- # Check that paths are no longer complete
- self.assertPathExists(
- (interface1, cable1, frontport1),
- is_complete=False,
- is_active=True
- )
- self.assertPathExists(
- (interface2, cable2, rearport1),
- is_complete=False,
- is_active=True
- )
- def test_306_change_port_mapping_between_connected_ports(self):
- """
- [IF1] --C1-- [FP1] [RP1] --C3-- [IF3]
- [IF2] --C2-- [FP2] [RP3] --C4-- [IF4]
- """
- interface1 = Interface.objects.create(device=self.device, name='Interface 1')
- interface2 = Interface.objects.create(device=self.device, name='Interface 2')
- interface3 = Interface.objects.create(device=self.device, name='Interface 3')
- interface4 = Interface.objects.create(device=self.device, name='Interface 4')
- frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
- frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
- rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
- rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
- cable1 = Cable(
- a_terminations=[interface1],
- b_terminations=[frontport1]
- )
- cable1.save()
- cable2 = Cable(
- a_terminations=[interface2],
- b_terminations=[frontport2]
- )
- cable2.save()
- cable3 = Cable(
- a_terminations=[interface3],
- b_terminations=[rearport1]
- )
- cable3.save()
- cable4 = Cable(
- a_terminations=[interface4],
- b_terminations=[rearport2]
- )
- cable4.save()
- portmapping1 = PortMapping.objects.create(
- device=self.device,
- front_port=frontport1,
- front_port_position=1,
- rear_port=rearport1,
- rear_port_position=1,
- )
- # Verify expected initial paths
- self.assertPathExists(
- (interface1, cable1, frontport1, rearport1, cable3, interface3),
- is_complete=True,
- is_active=True
- )
- self.assertPathExists(
- (interface3, cable3, rearport1, frontport1, cable1, interface1),
- is_complete=True,
- is_active=True
- )
- # Delete and replace the PortMapping to connect interface1 to interface4
- portmapping1.delete()
- portmapping2 = PortMapping.objects.create(
- device=self.device,
- front_port=frontport1,
- front_port_position=1,
- rear_port=rearport2,
- rear_port_position=1,
- )
- # Verify expected new paths
- self.assertPathExists(
- (interface1, cable1, frontport1, rearport2, cable4, interface4),
- is_complete=True,
- is_active=True
- )
- self.assertPathExists(
- (interface4, cable4, rearport2, frontport1, cable1, interface1),
- is_complete=True,
- is_active=True
- )
- # Delete and replace the PortMapping to connect interface2 to interface4
- portmapping2.delete()
- PortMapping.objects.create(
- device=self.device,
- front_port=frontport2,
- front_port_position=1,
- rear_port=rearport2,
- rear_port_position=1,
- )
- # Verify expected new paths
- self.assertPathExists(
- (interface2, cable2, frontport2, rearport2, cable4, interface4),
- is_complete=True,
- is_active=True
- )
- self.assertPathExists(
- (interface4, cable4, rearport2, frontport2, cable2, interface2),
- is_complete=True,
- is_active=True
- )
|