mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
Remove legacy connected endpoint fields
This commit is contained in:
parent
f8800b8303
commit
079c42291c
@ -46,9 +46,7 @@ class CircuitTypeViewSet(ModelViewSet):
|
||||
|
||||
class CircuitViewSet(CustomFieldModelViewSet):
|
||||
queryset = Circuit.objects.prefetch_related(
|
||||
Prefetch('terminations', queryset=CircuitTermination.objects.prefetch_related(
|
||||
'site', 'connected_endpoint__device'
|
||||
)),
|
||||
Prefetch('terminations', queryset=CircuitTermination.objects.prefetch_related('site')),
|
||||
'type', 'tenant', 'provider',
|
||||
).prefetch_related('tags')
|
||||
serializer_class = serializers.CircuitSerializer
|
||||
@ -61,7 +59,7 @@ class CircuitViewSet(CustomFieldModelViewSet):
|
||||
|
||||
class CircuitTerminationViewSet(ModelViewSet):
|
||||
queryset = CircuitTermination.objects.prefetch_related(
|
||||
'circuit', 'site', 'connected_endpoint__device', 'cable'
|
||||
'circuit', 'site', 'cable'
|
||||
)
|
||||
serializer_class = serializers.CircuitTerminationSerializer
|
||||
filterset_class = filters.CircuitTerminationFilterSet
|
||||
|
17
netbox/circuits/migrations/0022_drop_connected_endpoint.py
Normal file
17
netbox/circuits/migrations/0022_drop_connected_endpoint.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Generated by Django 3.1 on 2020-10-05 13:56
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('circuits', '0021_cablepath'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='circuittermination',
|
||||
name='connected_endpoint',
|
||||
),
|
||||
]
|
@ -248,13 +248,6 @@ class CircuitTermination(PathEndpoint, CableTermination):
|
||||
on_delete=models.PROTECT,
|
||||
related_name='circuit_terminations'
|
||||
)
|
||||
connected_endpoint = models.OneToOneField(
|
||||
to='dcim.Interface',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='+',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
connection_status = models.BooleanField(
|
||||
choices=CONNECTION_STATUS_CHOICES,
|
||||
blank=True,
|
||||
|
@ -131,7 +131,7 @@ class CircuitView(ObjectView):
|
||||
circuit = get_object_or_404(self.queryset, pk=pk)
|
||||
|
||||
termination_a = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related(
|
||||
'site__region', 'connected_endpoint__device'
|
||||
'site__region'
|
||||
).filter(
|
||||
circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_A
|
||||
).first()
|
||||
@ -139,7 +139,7 @@ class CircuitView(ObjectView):
|
||||
termination_a.ip_addresses = termination_a.connected_endpoint.ip_addresses.restrict(request.user, 'view')
|
||||
|
||||
termination_z = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related(
|
||||
'site__region', 'connected_endpoint__device'
|
||||
'site__region'
|
||||
).filter(
|
||||
circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_Z
|
||||
).first()
|
||||
|
@ -34,8 +34,7 @@ class ConnectedEndpointSerializer(ValidatedModelSerializer):
|
||||
|
||||
def get_connected_endpoint_type(self, obj):
|
||||
if obj.path is not None:
|
||||
destination = obj.path.destination
|
||||
return f'{destination._meta.app_label}.{destination._meta.model_name}'
|
||||
return f'{obj.connected_endpoint._meta.app_label}.{obj.connected_endpoint._meta.model_name}'
|
||||
return None
|
||||
|
||||
@swagger_serializer_method(serializer_or_field=serializers.DictField)
|
||||
@ -44,7 +43,7 @@ class ConnectedEndpointSerializer(ValidatedModelSerializer):
|
||||
Return the appropriate serializer for the type of connected object.
|
||||
"""
|
||||
if obj.path is not None:
|
||||
serializer = get_serializer_for_model(obj.path.destination, prefix='Nested')
|
||||
serializer = get_serializer_for_model(obj.connected_endpoint, prefix='Nested')
|
||||
context = {'request': self.context['request']}
|
||||
return serializer(obj.path.destination, context=context).data
|
||||
return None
|
||||
|
@ -470,37 +470,31 @@ class DeviceViewSet(CustomFieldModelViewSet):
|
||||
#
|
||||
|
||||
class ConsolePortViewSet(PathEndpointMixin, ModelViewSet):
|
||||
queryset = ConsolePort.objects.prefetch_related('device', 'connected_endpoint__device', 'cable', 'tags')
|
||||
queryset = ConsolePort.objects.prefetch_related('device', '_path', 'cable', 'tags')
|
||||
serializer_class = serializers.ConsolePortSerializer
|
||||
filterset_class = filters.ConsolePortFilterSet
|
||||
|
||||
|
||||
class ConsoleServerPortViewSet(PathEndpointMixin, ModelViewSet):
|
||||
queryset = ConsoleServerPort.objects.prefetch_related('device', 'connected_endpoint__device', 'cable', 'tags')
|
||||
queryset = ConsoleServerPort.objects.prefetch_related('device', '_path', 'cable', 'tags')
|
||||
serializer_class = serializers.ConsoleServerPortSerializer
|
||||
filterset_class = filters.ConsoleServerPortFilterSet
|
||||
|
||||
|
||||
class PowerPortViewSet(PathEndpointMixin, ModelViewSet):
|
||||
queryset = PowerPort.objects.prefetch_related(
|
||||
'device', '_connected_poweroutlet__device', '_connected_powerfeed', 'cable', 'tags'
|
||||
)
|
||||
queryset = PowerPort.objects.prefetch_related('device', '_path', 'cable', 'tags')
|
||||
serializer_class = serializers.PowerPortSerializer
|
||||
filterset_class = filters.PowerPortFilterSet
|
||||
|
||||
|
||||
class PowerOutletViewSet(PathEndpointMixin, ModelViewSet):
|
||||
queryset = PowerOutlet.objects.prefetch_related('device', 'connected_endpoint__device', 'cable', 'tags')
|
||||
queryset = PowerOutlet.objects.prefetch_related('device', '_path', 'cable', 'tags')
|
||||
serializer_class = serializers.PowerOutletSerializer
|
||||
filterset_class = filters.PowerOutletFilterSet
|
||||
|
||||
|
||||
class InterfaceViewSet(PathEndpointMixin, ModelViewSet):
|
||||
queryset = Interface.objects.prefetch_related(
|
||||
'device', '_connected_interface', '_connected_circuittermination', 'cable', 'ip_addresses', 'tags'
|
||||
).filter(
|
||||
device__isnull=False
|
||||
)
|
||||
queryset = Interface.objects.prefetch_related('device', '_path', 'cable', 'ip_addresses', 'tags')
|
||||
serializer_class = serializers.InterfaceSerializer
|
||||
filterset_class = filters.InterfaceFilterSet
|
||||
|
||||
@ -534,32 +528,26 @@ class InventoryItemViewSet(ModelViewSet):
|
||||
#
|
||||
|
||||
class ConsoleConnectionViewSet(ListModelMixin, GenericViewSet):
|
||||
queryset = ConsolePort.objects.prefetch_related(
|
||||
'device', 'connected_endpoint__device'
|
||||
).filter(
|
||||
connected_endpoint__isnull=False
|
||||
queryset = ConsolePort.objects.prefetch_related('device', '_path').filter(
|
||||
_path__destination_id__isnull=False
|
||||
)
|
||||
serializer_class = serializers.ConsolePortSerializer
|
||||
filterset_class = filters.ConsoleConnectionFilterSet
|
||||
|
||||
|
||||
class PowerConnectionViewSet(ListModelMixin, GenericViewSet):
|
||||
queryset = PowerPort.objects.prefetch_related(
|
||||
'device', 'connected_endpoint__device'
|
||||
).filter(
|
||||
_connected_poweroutlet__isnull=False
|
||||
queryset = PowerPort.objects.prefetch_related('device', '_path').filter(
|
||||
_path__destination_id__isnull=False
|
||||
)
|
||||
serializer_class = serializers.PowerPortSerializer
|
||||
filterset_class = filters.PowerConnectionFilterSet
|
||||
|
||||
|
||||
class InterfaceConnectionViewSet(ListModelMixin, GenericViewSet):
|
||||
queryset = Interface.objects.prefetch_related(
|
||||
'device', '_connected_interface__device'
|
||||
).filter(
|
||||
queryset = Interface.objects.prefetch_related('device', '_path').filter(
|
||||
# Avoid duplicate connections by only selecting the lower PK in a connected pair
|
||||
_connected_interface__isnull=False,
|
||||
pk__lt=F('_connected_interface')
|
||||
_path__destination_id__isnull=False,
|
||||
pk__lt=F('_path__destination_id')
|
||||
)
|
||||
serializer_class = serializers.InterfaceConnectionSerializer
|
||||
filterset_class = filters.InterfaceConnectionFilterSet
|
||||
@ -664,7 +652,7 @@ class ConnectedDeviceViewSet(ViewSet):
|
||||
device__name=peer_device_name,
|
||||
name=peer_interface_name
|
||||
)
|
||||
local_interface = peer_interface._connected_interface
|
||||
local_interface = peer_interface.connected_endpoint
|
||||
|
||||
if local_interface is None:
|
||||
return Response()
|
||||
|
@ -1171,18 +1171,19 @@ class ConsoleConnectionFilterSet(BaseFilterSet):
|
||||
model = ConsolePort
|
||||
fields = ['name', 'connection_status']
|
||||
|
||||
def filter_site(self, queryset, name, value):
|
||||
if not value.strip():
|
||||
return queryset
|
||||
return queryset.filter(connected_endpoint__device__site__slug=value)
|
||||
|
||||
def filter_device(self, queryset, name, value):
|
||||
if not value:
|
||||
return queryset
|
||||
return queryset.filter(
|
||||
Q(**{'{}__in'.format(name): value}) |
|
||||
Q(**{'connected_endpoint__{}__in'.format(name): value})
|
||||
)
|
||||
# TODO: Fix filters
|
||||
# def filter_site(self, queryset, name, value):
|
||||
# if not value.strip():
|
||||
# return queryset
|
||||
# return queryset.filter(connected_endpoint__device__site__slug=value)
|
||||
#
|
||||
# def filter_device(self, queryset, name, value):
|
||||
# if not value:
|
||||
# return queryset
|
||||
# return queryset.filter(
|
||||
# Q(**{'{}__in'.format(name): value}) |
|
||||
# Q(**{'connected_endpoint__{}__in'.format(name): value})
|
||||
# )
|
||||
|
||||
|
||||
class PowerConnectionFilterSet(BaseFilterSet):
|
||||
@ -1202,18 +1203,19 @@ class PowerConnectionFilterSet(BaseFilterSet):
|
||||
model = PowerPort
|
||||
fields = ['name', 'connection_status']
|
||||
|
||||
def filter_site(self, queryset, name, value):
|
||||
if not value.strip():
|
||||
return queryset
|
||||
return queryset.filter(_connected_poweroutlet__device__site__slug=value)
|
||||
|
||||
def filter_device(self, queryset, name, value):
|
||||
if not value:
|
||||
return queryset
|
||||
return queryset.filter(
|
||||
Q(**{'{}__in'.format(name): value}) |
|
||||
Q(**{'_connected_poweroutlet__{}__in'.format(name): value})
|
||||
)
|
||||
# TODO: Fix filters
|
||||
# def filter_site(self, queryset, name, value):
|
||||
# if not value.strip():
|
||||
# return queryset
|
||||
# return queryset.filter(_connected_poweroutlet__device__site__slug=value)
|
||||
#
|
||||
# def filter_device(self, queryset, name, value):
|
||||
# if not value:
|
||||
# return queryset
|
||||
# return queryset.filter(
|
||||
# Q(**{'{}__in'.format(name): value}) |
|
||||
# Q(**{'_connected_poweroutlet__{}__in'.format(name): value})
|
||||
# )
|
||||
|
||||
|
||||
class InterfaceConnectionFilterSet(BaseFilterSet):
|
||||
@ -1233,21 +1235,22 @@ class InterfaceConnectionFilterSet(BaseFilterSet):
|
||||
model = Interface
|
||||
fields = ['connection_status']
|
||||
|
||||
def filter_site(self, queryset, name, value):
|
||||
if not value.strip():
|
||||
return queryset
|
||||
return queryset.filter(
|
||||
Q(device__site__slug=value) |
|
||||
Q(_connected_interface__device__site__slug=value)
|
||||
)
|
||||
|
||||
def filter_device(self, queryset, name, value):
|
||||
if not value:
|
||||
return queryset
|
||||
return queryset.filter(
|
||||
Q(**{'{}__in'.format(name): value}) |
|
||||
Q(**{'_connected_interface__{}__in'.format(name): value})
|
||||
)
|
||||
# TODO: Fix filters
|
||||
# def filter_site(self, queryset, name, value):
|
||||
# if not value.strip():
|
||||
# return queryset
|
||||
# return queryset.filter(
|
||||
# Q(device__site__slug=value) |
|
||||
# Q(_connected_interface__device__site__slug=value)
|
||||
# )
|
||||
#
|
||||
# def filter_device(self, queryset, name, value):
|
||||
# if not value:
|
||||
# return queryset
|
||||
# return queryset.filter(
|
||||
# Q(**{'{}__in'.format(name): value}) |
|
||||
# Q(**{'_connected_interface__{}__in'.format(name): value})
|
||||
# )
|
||||
|
||||
|
||||
class PowerPanelFilterSet(BaseFilterSet):
|
||||
|
37
netbox/dcim/migrations/0121_drop_connected_endpoint.py
Normal file
37
netbox/dcim/migrations/0121_drop_connected_endpoint.py
Normal file
@ -0,0 +1,37 @@
|
||||
# Generated by Django 3.1 on 2020-10-05 13:56
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dcim', '0120_cablepath'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='consoleport',
|
||||
name='connected_endpoint',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='interface',
|
||||
name='_connected_circuittermination',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='interface',
|
||||
name='_connected_interface',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='powerfeed',
|
||||
name='connected_endpoint',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='powerport',
|
||||
name='_connected_powerfeed',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='powerport',
|
||||
name='_connected_poweroutlet',
|
||||
),
|
||||
]
|
@ -150,6 +150,15 @@ class PathEndpoint(models.Model):
|
||||
# Return the path as a list of three-tuples (A termination, cable, B termination)
|
||||
return list(zip(*[iter(path)] * 3))
|
||||
|
||||
@property
|
||||
def connected_endpoint(self):
|
||||
"""
|
||||
Caching accessor for the attached CablePath's destination (if any)
|
||||
"""
|
||||
if not hasattr(self, '_connected_endpoint'):
|
||||
self._connected_endpoint = self._path.destination if self._path else None
|
||||
return self._connected_endpoint
|
||||
|
||||
|
||||
#
|
||||
# Console ports
|
||||
@ -166,13 +175,6 @@ class ConsolePort(CableTermination, PathEndpoint, ComponentModel):
|
||||
blank=True,
|
||||
help_text='Physical port type'
|
||||
)
|
||||
connected_endpoint = models.OneToOneField(
|
||||
to='dcim.ConsoleServerPort',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='connected_endpoint',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
connection_status = models.BooleanField(
|
||||
choices=CONNECTION_STATUS_CHOICES,
|
||||
blank=True,
|
||||
@ -267,20 +269,6 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Allocated power draw (watts)"
|
||||
)
|
||||
_connected_poweroutlet = models.OneToOneField(
|
||||
to='dcim.PowerOutlet',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='connected_endpoint',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
_connected_powerfeed = models.OneToOneField(
|
||||
to='dcim.PowerFeed',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='+',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
connection_status = models.BooleanField(
|
||||
choices=CONNECTION_STATUS_CHOICES,
|
||||
blank=True,
|
||||
@ -308,43 +296,6 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
|
||||
self.description,
|
||||
)
|
||||
|
||||
@property
|
||||
def connected_endpoint(self):
|
||||
"""
|
||||
Return the connected PowerOutlet, if it exists, or the connected PowerFeed, if it exists. We have to check for
|
||||
ObjectDoesNotExist in case the referenced object has been deleted from the database.
|
||||
"""
|
||||
try:
|
||||
if self._connected_poweroutlet:
|
||||
return self._connected_poweroutlet
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
try:
|
||||
if self._connected_powerfeed:
|
||||
return self._connected_powerfeed
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
return None
|
||||
|
||||
@connected_endpoint.setter
|
||||
def connected_endpoint(self, value):
|
||||
# TODO: Fix circular import
|
||||
from . import PowerFeed
|
||||
|
||||
if value is None:
|
||||
self._connected_poweroutlet = None
|
||||
self._connected_powerfeed = None
|
||||
elif isinstance(value, PowerOutlet):
|
||||
self._connected_poweroutlet = value
|
||||
self._connected_powerfeed = None
|
||||
elif isinstance(value, PowerFeed):
|
||||
self._connected_poweroutlet = None
|
||||
self._connected_powerfeed = value
|
||||
else:
|
||||
raise ValueError(
|
||||
"Connected endpoint must be a PowerOutlet or PowerFeed, not {}.".format(type(value))
|
||||
)
|
||||
|
||||
def get_power_draw(self):
|
||||
"""
|
||||
Return the allocated and maximum power draw (in VA) and child PowerOutlet count for this PowerPort.
|
||||
@ -497,20 +448,6 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
||||
max_length=100,
|
||||
blank=True
|
||||
)
|
||||
_connected_interface = models.OneToOneField(
|
||||
to='self',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='+',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
_connected_circuittermination = models.OneToOneField(
|
||||
to='circuits.CircuitTermination',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='+',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
connection_status = models.BooleanField(
|
||||
choices=CONNECTION_STATUS_CHOICES,
|
||||
blank=True,
|
||||
@ -631,42 +568,6 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
||||
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def connected_endpoint(self):
|
||||
"""
|
||||
Return the connected Interface, if it exists, or the connected CircuitTermination, if it exists. We have to
|
||||
check for ObjectDoesNotExist in case the referenced object has been deleted from the database.
|
||||
"""
|
||||
try:
|
||||
if self._connected_interface:
|
||||
return self._connected_interface
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
try:
|
||||
if self._connected_circuittermination:
|
||||
return self._connected_circuittermination
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
return None
|
||||
|
||||
@connected_endpoint.setter
|
||||
def connected_endpoint(self, value):
|
||||
from circuits.models import CircuitTermination
|
||||
|
||||
if value is None:
|
||||
self._connected_interface = None
|
||||
self._connected_circuittermination = None
|
||||
elif isinstance(value, Interface):
|
||||
self._connected_interface = value
|
||||
self._connected_circuittermination = None
|
||||
elif isinstance(value, CircuitTermination):
|
||||
self._connected_interface = None
|
||||
self._connected_circuittermination = value
|
||||
else:
|
||||
raise ValueError(
|
||||
"Connected endpoint must be an Interface or CircuitTermination, not {}.".format(type(value))
|
||||
)
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
return self.device
|
||||
|
@ -88,13 +88,6 @@ class PowerFeed(ChangeLoggedModel, PathEndpoint, CableTermination, CustomFieldMo
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
connected_endpoint = models.OneToOneField(
|
||||
to='dcim.PowerPort',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='+',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
connection_status = models.BooleanField(
|
||||
choices=CONNECTION_STATUS_CHOICES,
|
||||
blank=True,
|
||||
|
@ -1122,10 +1122,8 @@ class DeviceLLDPNeighborsView(ObjectView):
|
||||
def get(self, request, pk):
|
||||
|
||||
device = get_object_or_404(self.queryset, pk=pk)
|
||||
interfaces = device.vc_interfaces.restrict(request.user, 'view').exclude(
|
||||
interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related('_path').exclude(
|
||||
type__in=NONCONNECTABLE_IFACE_TYPES
|
||||
).prefetch_related(
|
||||
'_connected_interface__device'
|
||||
)
|
||||
|
||||
return render(request, 'dcim/device_lldp_neighbors.html', {
|
||||
@ -1483,8 +1481,6 @@ class InterfaceView(ObjectView):
|
||||
|
||||
return render(request, 'dcim/interface.html', {
|
||||
'instance': interface,
|
||||
'connected_interface': interface._connected_interface,
|
||||
'connected_circuittermination': interface._connected_circuittermination,
|
||||
'ipaddress_table': ipaddress_table,
|
||||
'vlan_table': vlan_table,
|
||||
})
|
||||
@ -2137,7 +2133,7 @@ class InterfaceConnectionsListView(ObjectListView):
|
||||
).filter(
|
||||
# Avoid duplicate connections by only selecting the lower PK in a connected pair
|
||||
_path__isnull=False,
|
||||
pk__lt=F('_connected_interface')
|
||||
pk__lt=F('_path__destination_id')
|
||||
).order_by('device')
|
||||
filterset = filters.InterfaceConnectionFilterSet
|
||||
filterset_form = forms.InterfaceConnectionFilterForm
|
||||
|
@ -190,15 +190,15 @@ class HomeView(View):
|
||||
|
||||
def get(self, request):
|
||||
|
||||
connected_consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(
|
||||
connected_endpoint__isnull=False
|
||||
connected_consoleports = ConsolePort.objects.restrict(request.user, 'view').prefetch_related('_path').filter(
|
||||
_path__destination_id__isnull=False
|
||||
)
|
||||
connected_powerports = PowerPort.objects.restrict(request.user, 'view').filter(
|
||||
_connected_poweroutlet__isnull=False
|
||||
connected_powerports = PowerPort.objects.restrict(request.user, 'view').prefetch_related('_path').filter(
|
||||
_path__destination_id__isnull=False
|
||||
)
|
||||
connected_interfaces = Interface.objects.restrict(request.user, 'view').filter(
|
||||
_connected_interface__isnull=False,
|
||||
pk__lt=F('_connected_interface')
|
||||
connected_interfaces = Interface.objects.restrict(request.user, 'view').prefetch_related('_path').filter(
|
||||
_path__destination_id__isnull=False,
|
||||
pk__lt=F('_path__destination_id')
|
||||
)
|
||||
|
||||
# Report Results
|
||||
|
@ -77,61 +77,63 @@
|
||||
</div>
|
||||
{% if instance.cable %}
|
||||
<table class="table table-hover panel-body attr-table">
|
||||
{% if connected_interface %}
|
||||
<tr>
|
||||
<td>Device</td>
|
||||
<td>
|
||||
<a href="{{ connected_interface.device.get_absolute_url }}">{{ connected_interface.device }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>
|
||||
<a href="{{ connected_interface.get_absolute_url }}">{{ connected_interface.name }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td>{{ connected_interface.get_type_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Enabled</td>
|
||||
<td>
|
||||
{% if connected_interface.enabled %}
|
||||
<span class="text-success"><i class="fa fa-check"></i></span>
|
||||
{% else %}
|
||||
<span class="text-danger"><i class="fa fa-close"></i></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LAG</td>
|
||||
<td>
|
||||
{% if connected_interface.lag%}
|
||||
<a href="{{ connected_interface.lag.get_absolute_url }}">{{ connected_interface.lag }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>{{ connected_interface.description|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MTU</td>
|
||||
<td>{{ connected_interface.mtu|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MAC Address</td>
|
||||
<td>{{ connected_interface.mac_address|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>802.1Q Mode</td>
|
||||
<td>{{ connected_interface.get_mode_display }}</td>
|
||||
</tr>
|
||||
{% elif connected_circuittermination %}
|
||||
{% with ct=connected_circuittermination %}
|
||||
{% if instance.connected_endpoint.device %}
|
||||
{% with iface=instance.connected_endpoint %}
|
||||
<tr>
|
||||
<td>Device</td>
|
||||
<td>
|
||||
<a href="{{ iface.device.get_absolute_url }}">{{ iface.device }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>
|
||||
<a href="{{ iface.get_absolute_url }}">{{ iface.name }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td>{{ iface.get_type_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Enabled</td>
|
||||
<td>
|
||||
{% if iface.enabled %}
|
||||
<span class="text-success"><i class="fa fa-check"></i></span>
|
||||
{% else %}
|
||||
<span class="text-danger"><i class="fa fa-close"></i></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LAG</td>
|
||||
<td>
|
||||
{% if iface.lag%}
|
||||
<a href="{{ iface.lag.get_absolute_url }}">{{ iface.lag }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>{{ iface.description|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MTU</td>
|
||||
<td>{{ iface.mtu|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MAC Address</td>
|
||||
<td>{{ iface.mac_address|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>802.1Q Mode</td>
|
||||
<td>{{ iface.get_mode_display }}</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% elif instance.connected_endpoint.circuit %}
|
||||
{% with ct=instance.connected_endpoint %}
|
||||
<tr>
|
||||
<td>Provider</td>
|
||||
<td><a href="{{ ct.circuit.provider.get_absolute_url }}">{{ ct.circuit.provider }}</a></td>
|
||||
|
Loading…
Reference in New Issue
Block a user