mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Cache each CablePath on its originating endpoint
This commit is contained in:
20
netbox/circuits/migrations/0021_cablepath.py
Normal file
20
netbox/circuits/migrations/0021_cablepath.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 3.1 on 2020-10-02 19:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('dcim', '0120_cablepath'),
|
||||||
|
('circuits', '0020_custom_field_data'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='circuittermination',
|
||||||
|
name='_path',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'),
|
||||||
|
),
|
||||||
|
]
|
@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1 on 2020-10-02 15:49
|
# Generated by Django 3.1 on 2020-10-02 19:43
|
||||||
|
|
||||||
import dcim.fields
|
import dcim.fields
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
@ -28,4 +28,34 @@ class Migration(migrations.Migration):
|
|||||||
'unique_together': {('origin_type', 'origin_id')},
|
'unique_together': {('origin_type', 'origin_id')},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='consoleport',
|
||||||
|
name='_path',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='consoleserverport',
|
||||||
|
name='_path',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='interface',
|
||||||
|
name='_path',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='powerfeed',
|
||||||
|
name='_path',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='poweroutlet',
|
||||||
|
name='_path',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='powerport',
|
||||||
|
name='_path',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -126,38 +126,30 @@ class CableTermination(models.Model):
|
|||||||
|
|
||||||
class PathEndpoint(models.Model):
|
class PathEndpoint(models.Model):
|
||||||
"""
|
"""
|
||||||
Any object which may serve as either endpoint of a CablePath.
|
Any object which may serve as the originating endpoint of a CablePath.
|
||||||
"""
|
"""
|
||||||
_paths = GenericRelation(
|
_path = models.ForeignKey(
|
||||||
to='dcim.CablePath',
|
to='dcim.CablePath',
|
||||||
content_type_field='origin_type',
|
on_delete=models.SET_NULL,
|
||||||
object_id_field='origin_id',
|
null=True,
|
||||||
related_query_name='%(class)s'
|
blank=True
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
def trace(self):
|
def trace(self):
|
||||||
if self.path is None:
|
if self._path is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Construct the complete path
|
# Construct the complete path
|
||||||
path = [self, *[path_node_to_object(obj) for obj in self.path.path], self.path.destination]
|
path = [self, *[path_node_to_object(obj) for obj in self._path.path], self._path.destination]
|
||||||
assert not len(path) % 3, f"Invalid path length for CablePath #{self.pk}: {len(self.path)} elements in path"
|
assert not len(path) % 3,\
|
||||||
|
f"Invalid path length for CablePath #{self.pk}: {len(self._path.path)} elements in path"
|
||||||
|
|
||||||
# Return the path as a list of three-tuples (A termination, cable, B termination)
|
# Return the path as a list of three-tuples (A termination, cable, B termination)
|
||||||
return list(zip(*[iter(path)] * 3))
|
return list(zip(*[iter(path)] * 3))
|
||||||
|
|
||||||
@property
|
|
||||||
def path(self):
|
|
||||||
"""
|
|
||||||
Return the _complete_ CablePath associated with this origin point, if any.
|
|
||||||
"""
|
|
||||||
if not hasattr(self, '_path'):
|
|
||||||
self._path = self._paths.filter(destination_id__isnull=False).first()
|
|
||||||
return self._path
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Console ports
|
# Console ports
|
||||||
|
@ -1204,6 +1204,13 @@ class CablePath(models.Model):
|
|||||||
path = ', '.join([str(path_node_to_object(node)) for node in self.path])
|
path = ', '.join([str(path_node_to_object(node)) for node in self.path])
|
||||||
return f"Path #{self.pk}: {self.origin} to {self.destination} via ({path})"
|
return f"Path #{self.pk}: {self.origin} to {self.destination} via ({path})"
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
# Record a direct reference to this CablePath on its originating object
|
||||||
|
model = self.origin._meta.model
|
||||||
|
model.objects.filter(pk=self.origin.pk).update(_path=self.pk)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Virtual chassis
|
# Virtual chassis
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db.models.signals import post_save, pre_delete
|
from django.db.models.signals import post_save, post_delete, pre_delete
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ def update_connected_endpoints(instance, created, **kwargs):
|
|||||||
rebuild_paths(instance)
|
rebuild_paths(instance)
|
||||||
|
|
||||||
|
|
||||||
@receiver(pre_delete, sender=Cable)
|
@receiver(post_delete, sender=Cable)
|
||||||
def nullify_connected_endpoints(instance, **kwargs):
|
def nullify_connected_endpoints(instance, **kwargs):
|
||||||
"""
|
"""
|
||||||
When a Cable is deleted, check for and update its two connected endpoints
|
When a Cable is deleted, check for and update its two connected endpoints
|
||||||
@ -108,18 +108,15 @@ def nullify_connected_endpoints(instance, **kwargs):
|
|||||||
instance.termination_b.cable = None
|
instance.termination_b.cable = None
|
||||||
instance.termination_b.save()
|
instance.termination_b.save()
|
||||||
|
|
||||||
# Delete any dependent cable paths
|
# Delete and retrace any dependent cable paths
|
||||||
cable_paths = CablePath.objects.filter(path__contains=[object_to_path_node(instance)])
|
for cablepath in CablePath.objects.filter(path__contains=[object_to_path_node(instance)]):
|
||||||
retrace_queue = [cp.origin for cp in cable_paths]
|
path, destination, is_connected = trace_path(cablepath.origin)
|
||||||
deleted, _ = cable_paths.delete()
|
if path:
|
||||||
logger.info(f'Deleted {deleted} cable paths')
|
CablePath.objects.filter(pk=cablepath.pk).update(
|
||||||
|
path=path,
|
||||||
# Retrace cable paths from the origins of deleted paths
|
destination_type=ContentType.objects.get_for_model(destination) if destination else None,
|
||||||
for origin in retrace_queue:
|
destination_id=destination.pk if destination else None,
|
||||||
# Delete and recreate all CablePaths for this origin point
|
is_connected=is_connected
|
||||||
# TODO: We can probably be smarter about skipping unchanged paths
|
)
|
||||||
CablePath.objects.filter(
|
else:
|
||||||
origin_type=ContentType.objects.get_for_model(origin),
|
cablepath.delete()
|
||||||
origin_id=origin.pk
|
|
||||||
).delete()
|
|
||||||
create_cablepath(origin)
|
|
||||||
|
@ -132,6 +132,8 @@ class CablePathTestCase(TestCase):
|
|||||||
:param path: Sequence of objects comprising the intermediate path (optional)
|
:param path: Sequence of objects comprising the intermediate path (optional)
|
||||||
:param is_connected: Boolean indicating whether the end-to-end path is complete and active (optional)
|
:param is_connected: Boolean indicating whether the end-to-end path is complete and active (optional)
|
||||||
:param msg: Custom failure message (optional)
|
:param msg: Custom failure message (optional)
|
||||||
|
|
||||||
|
:return: The matching CablePath (if any)
|
||||||
"""
|
"""
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'origin_type': ContentType.objects.get_for_model(origin),
|
'origin_type': ContentType.objects.get_for_model(origin),
|
||||||
@ -152,7 +154,34 @@ class CablePathTestCase(TestCase):
|
|||||||
msg = f"Missing path from {origin} to {destination}"
|
msg = f"Missing path from {origin} to {destination}"
|
||||||
else:
|
else:
|
||||||
msg = f"Missing partial path originating from {origin}"
|
msg = f"Missing partial path originating from {origin}"
|
||||||
self.assertEqual(CablePath.objects.filter(**kwargs).count(), 1, msg=msg)
|
|
||||||
|
cablepath = CablePath.objects.filter(**kwargs).first()
|
||||||
|
self.assertIsNotNone(cablepath, msg=msg)
|
||||||
|
|
||||||
|
return cablepath
|
||||||
|
|
||||||
|
def assertPathIsSet(self, origin, cablepath, msg=None):
|
||||||
|
"""
|
||||||
|
Assert that a specific CablePath instance is set as the path on the origin.
|
||||||
|
|
||||||
|
:param origin: The originating path endpoint
|
||||||
|
:param cablepath: The CablePath instance originating from this endpoint
|
||||||
|
:param msg: Custom failure message (optional)
|
||||||
|
"""
|
||||||
|
if msg is None:
|
||||||
|
msg = f"Path #{cablepath.pk} not set on originating endpoint {origin}"
|
||||||
|
self.assertEqual(origin._path_id, cablepath.pk, msg=msg)
|
||||||
|
|
||||||
|
def assertPathIsNotSet(self, origin, msg=None):
|
||||||
|
"""
|
||||||
|
Assert that a specific CablePath instance is set as the path on the origin.
|
||||||
|
|
||||||
|
:param origin: The originating path endpoint
|
||||||
|
:param msg: Custom failure message (optional)
|
||||||
|
"""
|
||||||
|
if msg is None:
|
||||||
|
msg = f"Path #{origin._path_id} set as origin on {origin}; should be None!"
|
||||||
|
self.assertIsNone(origin._path_id, msg=msg)
|
||||||
|
|
||||||
def test_101_interface_to_interface(self):
|
def test_101_interface_to_interface(self):
|
||||||
"""
|
"""
|
||||||
@ -161,19 +190,23 @@ class CablePathTestCase(TestCase):
|
|||||||
# Create cable 1
|
# Create cable 1
|
||||||
cable1 = Cable(termination_a=self.interface1, termination_b=self.interface2)
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.interface2)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
self.assertPathExists(
|
path1 = self.assertPathExists(
|
||||||
origin=self.interface1,
|
origin=self.interface1,
|
||||||
destination=self.interface2,
|
destination=self.interface2,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertPathExists(
|
path2 = self.assertPathExists(
|
||||||
origin=self.interface2,
|
origin=self.interface2,
|
||||||
destination=self.interface1,
|
destination=self.interface1,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertEqual(CablePath.objects.count(), 2)
|
self.assertEqual(CablePath.objects.count(), 2)
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
self.assertPathIsSet(self.interface1, path1)
|
||||||
|
self.assertPathIsSet(self.interface2, path2)
|
||||||
|
|
||||||
# Delete cable 1
|
# Delete cable 1
|
||||||
cable1.delete()
|
cable1.delete()
|
||||||
@ -181,26 +214,30 @@ class CablePathTestCase(TestCase):
|
|||||||
# Check that all CablePaths have been deleted
|
# Check that all CablePaths have been deleted
|
||||||
self.assertEqual(CablePath.objects.count(), 0)
|
self.assertEqual(CablePath.objects.count(), 0)
|
||||||
|
|
||||||
def test_103_consoleport_to_consoleserverport(self):
|
def test_102_consoleport_to_consoleserverport(self):
|
||||||
"""
|
"""
|
||||||
[CP1] --C1-- [CSP1]
|
[CP1] --C1-- [CSP1]
|
||||||
"""
|
"""
|
||||||
# Create cable 1
|
# Create cable 1
|
||||||
cable1 = Cable(termination_a=self.consoleport1, termination_b=self.consoleserverport1)
|
cable1 = Cable(termination_a=self.consoleport1, termination_b=self.consoleserverport1)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
self.assertPathExists(
|
path1 = self.assertPathExists(
|
||||||
origin=self.consoleport1,
|
origin=self.consoleport1,
|
||||||
destination=self.consoleserverport1,
|
destination=self.consoleserverport1,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertPathExists(
|
path2 = self.assertPathExists(
|
||||||
origin=self.consoleserverport1,
|
origin=self.consoleserverport1,
|
||||||
destination=self.consoleport1,
|
destination=self.consoleport1,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertEqual(CablePath.objects.count(), 2)
|
self.assertEqual(CablePath.objects.count(), 2)
|
||||||
|
self.consoleport1.refresh_from_db()
|
||||||
|
self.consoleserverport1.refresh_from_db()
|
||||||
|
self.assertPathIsSet(self.consoleport1, path1)
|
||||||
|
self.assertPathIsSet(self.consoleserverport1, path2)
|
||||||
|
|
||||||
# Delete cable 1
|
# Delete cable 1
|
||||||
cable1.delete()
|
cable1.delete()
|
||||||
@ -208,26 +245,30 @@ class CablePathTestCase(TestCase):
|
|||||||
# Check that all CablePaths have been deleted
|
# Check that all CablePaths have been deleted
|
||||||
self.assertEqual(CablePath.objects.count(), 0)
|
self.assertEqual(CablePath.objects.count(), 0)
|
||||||
|
|
||||||
def test_104_powerport_to_poweroutlet(self):
|
def test_103_powerport_to_poweroutlet(self):
|
||||||
"""
|
"""
|
||||||
[PP1] --C1-- [PO1]
|
[PP1] --C1-- [PO1]
|
||||||
"""
|
"""
|
||||||
# Create cable 1
|
# Create cable 1
|
||||||
cable1 = Cable(termination_a=self.powerport1, termination_b=self.poweroutlet1)
|
cable1 = Cable(termination_a=self.powerport1, termination_b=self.poweroutlet1)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
self.assertPathExists(
|
path1 = self.assertPathExists(
|
||||||
origin=self.powerport1,
|
origin=self.powerport1,
|
||||||
destination=self.poweroutlet1,
|
destination=self.poweroutlet1,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertPathExists(
|
path2 = self.assertPathExists(
|
||||||
origin=self.poweroutlet1,
|
origin=self.poweroutlet1,
|
||||||
destination=self.powerport1,
|
destination=self.powerport1,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertEqual(CablePath.objects.count(), 2)
|
self.assertEqual(CablePath.objects.count(), 2)
|
||||||
|
self.powerport1.refresh_from_db()
|
||||||
|
self.poweroutlet1.refresh_from_db()
|
||||||
|
self.assertPathIsSet(self.powerport1, path1)
|
||||||
|
self.assertPathIsSet(self.poweroutlet1, path2)
|
||||||
|
|
||||||
# Delete cable 1
|
# Delete cable 1
|
||||||
cable1.delete()
|
cable1.delete()
|
||||||
@ -235,26 +276,30 @@ class CablePathTestCase(TestCase):
|
|||||||
# Check that all CablePaths have been deleted
|
# Check that all CablePaths have been deleted
|
||||||
self.assertEqual(CablePath.objects.count(), 0)
|
self.assertEqual(CablePath.objects.count(), 0)
|
||||||
|
|
||||||
def test_105_powerport_to_powerfeed(self):
|
def test_104_powerport_to_powerfeed(self):
|
||||||
"""
|
"""
|
||||||
[PP1] --C1-- [PF1]
|
[PP1] --C1-- [PF1]
|
||||||
"""
|
"""
|
||||||
# Create cable 1
|
# Create cable 1
|
||||||
cable1 = Cable(termination_a=self.powerport1, termination_b=self.powerfeed1)
|
cable1 = Cable(termination_a=self.powerport1, termination_b=self.powerfeed1)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
self.assertPathExists(
|
path1 = self.assertPathExists(
|
||||||
origin=self.powerport1,
|
origin=self.powerport1,
|
||||||
destination=self.powerfeed1,
|
destination=self.powerfeed1,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertPathExists(
|
path2 = self.assertPathExists(
|
||||||
origin=self.powerfeed1,
|
origin=self.powerfeed1,
|
||||||
destination=self.powerport1,
|
destination=self.powerport1,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertEqual(CablePath.objects.count(), 2)
|
self.assertEqual(CablePath.objects.count(), 2)
|
||||||
|
self.powerport1.refresh_from_db()
|
||||||
|
self.powerfeed1.refresh_from_db()
|
||||||
|
self.assertPathIsSet(self.powerport1, path1)
|
||||||
|
self.assertPathIsSet(self.powerfeed1, path2)
|
||||||
|
|
||||||
# Delete cable 1
|
# Delete cable 1
|
||||||
cable1.delete()
|
cable1.delete()
|
||||||
@ -262,26 +307,30 @@ class CablePathTestCase(TestCase):
|
|||||||
# Check that all CablePaths have been deleted
|
# Check that all CablePaths have been deleted
|
||||||
self.assertEqual(CablePath.objects.count(), 0)
|
self.assertEqual(CablePath.objects.count(), 0)
|
||||||
|
|
||||||
def test_106_interface_to_circuittermination(self):
|
def test_105_interface_to_circuittermination(self):
|
||||||
"""
|
"""
|
||||||
[PP1] --C1-- [CT1A]
|
[PP1] --C1-- [CT1A]
|
||||||
"""
|
"""
|
||||||
# Create cable 1
|
# Create cable 1
|
||||||
cable1 = Cable(termination_a=self.interface1, termination_b=self.circuittermination1_A)
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.circuittermination1_A)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
self.assertPathExists(
|
path1 = self.assertPathExists(
|
||||||
origin=self.interface1,
|
origin=self.interface1,
|
||||||
destination=self.circuittermination1_A,
|
destination=self.circuittermination1_A,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertPathExists(
|
path2 = self.assertPathExists(
|
||||||
origin=self.circuittermination1_A,
|
origin=self.circuittermination1_A,
|
||||||
destination=self.interface1,
|
destination=self.interface1,
|
||||||
path=(cable1,),
|
path=(cable1,),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertEqual(CablePath.objects.count(), 2)
|
self.assertEqual(CablePath.objects.count(), 2)
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.circuittermination1_A.refresh_from_db()
|
||||||
|
self.assertPathIsSet(self.interface1, path1)
|
||||||
|
self.assertPathIsSet(self.circuittermination1_A, path2)
|
||||||
|
|
||||||
# Delete cable 1
|
# Delete cable 1
|
||||||
cable1.delete()
|
cable1.delete()
|
||||||
@ -293,6 +342,9 @@ class CablePathTestCase(TestCase):
|
|||||||
"""
|
"""
|
||||||
[IF1] --C1-- [FP5] [RP5] --C2-- [IF2]
|
[IF1] --C1-- [FP5] [RP5] --C2-- [IF2]
|
||||||
"""
|
"""
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
|
||||||
# Create cable 1
|
# Create cable 1
|
||||||
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port5_1)
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port5_1)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
@ -323,19 +375,28 @@ class CablePathTestCase(TestCase):
|
|||||||
|
|
||||||
# Delete cable 2
|
# Delete cable 2
|
||||||
cable2.delete()
|
cable2.delete()
|
||||||
self.assertPathExists(
|
path1 = self.assertPathExists(
|
||||||
origin=self.interface1,
|
origin=self.interface1,
|
||||||
destination=None,
|
destination=None,
|
||||||
path=(cable1, self.front_port5_1, self.rear_port5),
|
path=(cable1, self.front_port5_1, self.rear_port5),
|
||||||
is_connected=False
|
is_connected=False
|
||||||
)
|
)
|
||||||
self.assertEqual(CablePath.objects.count(), 1)
|
self.assertEqual(CablePath.objects.count(), 1)
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
self.assertPathIsSet(self.interface1, path1)
|
||||||
|
self.assertPathIsNotSet(self.interface2)
|
||||||
|
|
||||||
def test_202_multiple_paths_via_pass_through(self):
|
def test_202_multiple_paths_via_pass_through(self):
|
||||||
"""
|
"""
|
||||||
[IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [IF3]
|
[IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [IF3]
|
||||||
[IF2] --C2-- [FP1:2] [FP2:2] --C5-- [IF4]
|
[IF2] --C2-- [FP1:2] [FP2:2] --C5-- [IF4]
|
||||||
"""
|
"""
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
self.interface3.refresh_from_db()
|
||||||
|
self.interface4.refresh_from_db()
|
||||||
|
|
||||||
# Create cables 1-2
|
# Create cables 1-2
|
||||||
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1_1)
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1_1)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
@ -377,7 +438,7 @@ class CablePathTestCase(TestCase):
|
|||||||
cable4.save()
|
cable4.save()
|
||||||
cable5 = Cable(termination_a=self.front_port2_2, termination_b=self.interface4)
|
cable5 = Cable(termination_a=self.front_port2_2, termination_b=self.interface4)
|
||||||
cable5.save()
|
cable5.save()
|
||||||
self.assertPathExists(
|
path1 = self.assertPathExists(
|
||||||
origin=self.interface1,
|
origin=self.interface1,
|
||||||
destination=self.interface3,
|
destination=self.interface3,
|
||||||
path=(
|
path=(
|
||||||
@ -386,7 +447,7 @@ class CablePathTestCase(TestCase):
|
|||||||
),
|
),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertPathExists(
|
path2 = self.assertPathExists(
|
||||||
origin=self.interface2,
|
origin=self.interface2,
|
||||||
destination=self.interface4,
|
destination=self.interface4,
|
||||||
path=(
|
path=(
|
||||||
@ -395,7 +456,7 @@ class CablePathTestCase(TestCase):
|
|||||||
),
|
),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertPathExists(
|
path3 = self.assertPathExists(
|
||||||
origin=self.interface3,
|
origin=self.interface3,
|
||||||
destination=self.interface1,
|
destination=self.interface1,
|
||||||
path=(
|
path=(
|
||||||
@ -404,7 +465,7 @@ class CablePathTestCase(TestCase):
|
|||||||
),
|
),
|
||||||
is_connected=True
|
is_connected=True
|
||||||
)
|
)
|
||||||
self.assertPathExists(
|
path4 = self.assertPathExists(
|
||||||
origin=self.interface4,
|
origin=self.interface4,
|
||||||
destination=self.interface2,
|
destination=self.interface2,
|
||||||
path=(
|
path=(
|
||||||
@ -421,12 +482,25 @@ class CablePathTestCase(TestCase):
|
|||||||
# Check for four partial paths; one from each interface
|
# Check for four partial paths; one from each interface
|
||||||
self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4)
|
self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4)
|
||||||
self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0)
|
self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0)
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
self.interface3.refresh_from_db()
|
||||||
|
self.interface4.refresh_from_db()
|
||||||
|
self.assertPathIsSet(self.interface1, path1)
|
||||||
|
self.assertPathIsSet(self.interface2, path2)
|
||||||
|
self.assertPathIsSet(self.interface3, path3)
|
||||||
|
self.assertPathIsSet(self.interface4, path4)
|
||||||
|
|
||||||
def test_203_multiple_paths_via_nested_pass_throughs(self):
|
def test_203_multiple_paths_via_nested_pass_throughs(self):
|
||||||
"""
|
"""
|
||||||
[IF1] --C1-- [FP1:1] [RP1] --C3-- [FP2:1] [RP2] --C4-- [RP3] [FP3:1] --C5-- [RP4] [FP4:1] --C6-- [IF3]
|
[IF1] --C1-- [FP1:1] [RP1] --C3-- [FP2:1] [RP2] --C4-- [RP3] [FP3:1] --C5-- [RP4] [FP4:1] --C6-- [IF3]
|
||||||
[IF2] --C2-- [FP1:2] [FP4:2] --C7-- [IF4]
|
[IF2] --C2-- [FP1:2] [FP4:2] --C7-- [IF4]
|
||||||
"""
|
"""
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
self.interface3.refresh_from_db()
|
||||||
|
self.interface4.refresh_from_db()
|
||||||
|
|
||||||
# Create cables 1-2, 6-7
|
# Create cables 1-2, 6-7
|
||||||
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1_1)
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1_1)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
@ -502,6 +576,11 @@ class CablePathTestCase(TestCase):
|
|||||||
[IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [FP3:1] [RP3] --C6-- [RP4] [FP4:1] --C7-- [IF3]
|
[IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [FP3:1] [RP3] --C6-- [RP4] [FP4:1] --C7-- [IF3]
|
||||||
[IF2] --C2-- [FP1:2] [FP2:1] --C5-- [FP3:1] [FP4:2] --C8-- [IF4]
|
[IF2] --C2-- [FP1:2] [FP2:1] --C5-- [FP3:1] [FP4:2] --C8-- [IF4]
|
||||||
"""
|
"""
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
self.interface3.refresh_from_db()
|
||||||
|
self.interface4.refresh_from_db()
|
||||||
|
|
||||||
# Create cables 1-3, 6-8
|
# Create cables 1-3, 6-8
|
||||||
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1_1)
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1_1)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
@ -576,6 +655,11 @@ class CablePathTestCase(TestCase):
|
|||||||
[IF1] --C1-- [FP1:1] [RP1] --C3-- [FP5] [RP5] --C4-- [RP2] [FP2:1] --C5-- [IF3]
|
[IF1] --C1-- [FP1:1] [RP1] --C3-- [FP5] [RP5] --C4-- [RP2] [FP2:1] --C5-- [IF3]
|
||||||
[IF2] --C2-- [FP1:2] [FP2:2] --C6-- [IF4]
|
[IF2] --C2-- [FP1:2] [FP2:2] --C6-- [IF4]
|
||||||
"""
|
"""
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
self.interface3.refresh_from_db()
|
||||||
|
self.interface4.refresh_from_db()
|
||||||
|
|
||||||
# Create cables 1-2, 5-6
|
# Create cables 1-2, 5-6
|
||||||
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1_1) # IF1 -> FP1:1
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port1_1) # IF1 -> FP1:1
|
||||||
cable1.save()
|
cable1.save()
|
||||||
@ -641,6 +725,9 @@ class CablePathTestCase(TestCase):
|
|||||||
"""
|
"""
|
||||||
[IF1] --C1-- [FP5] [RP5] --C2-- [RP6] [FP6] --C3-- [IF2]
|
[IF1] --C1-- [FP5] [RP5] --C2-- [RP6] [FP6] --C3-- [IF2]
|
||||||
"""
|
"""
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
|
||||||
# Create cable 2
|
# Create cable 2
|
||||||
cable2 = Cable(termination_a=self.rear_port5, termination_b=self.rear_port6)
|
cable2 = Cable(termination_a=self.rear_port5, termination_b=self.rear_port6)
|
||||||
cable2.save()
|
cable2.save()
|
||||||
@ -684,6 +771,9 @@ class CablePathTestCase(TestCase):
|
|||||||
"""
|
"""
|
||||||
[IF1] --C1-- [FP5] [RP5] --C2-- [IF2]
|
[IF1] --C1-- [FP5] [RP5] --C2-- [IF2]
|
||||||
"""
|
"""
|
||||||
|
self.interface1.refresh_from_db()
|
||||||
|
self.interface2.refresh_from_db()
|
||||||
|
|
||||||
# Create cables 1 and 2
|
# Create cables 1 and 2
|
||||||
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port5_1)
|
cable1 = Cable(termination_a=self.interface1, termination_b=self.front_port5_1)
|
||||||
cable1.save()
|
cable1.save()
|
||||||
|
Reference in New Issue
Block a user