1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Added dedicated cable trace view; removed modal

This commit is contained in:
Jeremy Stretch
2018-10-30 16:30:03 -04:00
parent 669fe1f192
commit 470aabe1d7
9 changed files with 111 additions and 10 deletions

View File

@ -1,6 +1,6 @@
from django.conf.urls import url
from dcim.views import CableCreateView
from dcim.views import CableCreateView, CableTraceView
from extras.views import ObjectChangeLogView
from . import views
from .models import Circuit, CircuitTermination, CircuitType, Provider
@ -44,5 +44,6 @@ urlpatterns = [
url(r'^circuit-terminations/(?P<pk>\d+)/edit/$', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
url(r'^circuit-terminations/(?P<pk>\d+)/delete/$', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
url(r'^circuit-terminations/(?P<termination_a_id>\d+)/connect/$', CableCreateView.as_view(), name='circuittermination_connect', kwargs={'termination_a_type': CircuitTermination}),
url(r'^circuit-terminations/(?P<pk>\d+)/trace/$', CableTraceView.as_view(), name='circuittermination_trace', kwargs={'model': CircuitTermination}),
]

View File

@ -85,6 +85,7 @@ class CableTermination(models.Model):
]
"""
def get_peer_port(termination, position=1):
from circuits.models import CircuitTermination
# Map a front port to its corresponding rear port
if isinstance(termination, FrontPort):
@ -102,6 +103,13 @@ class CableTermination(models.Model):
)
return peer_port, 1
# Follow a circuit to its other termination
elif isinstance(termination, CircuitTermination):
peer_termination = termination.get_peer_termination()
if peer_termination is None:
return None, None
return peer_termination, position
# Termination is not a pass-through port
else:
return None, None

View File

@ -5,8 +5,8 @@ from ipam.views import ServiceCreateView
from secrets.views import secret_add
from . import views
from .models import (
ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, Interface, Manufacturer, Platform, PowerPort,
PowerOutlet, Rack, RackGroup, RackReservation, RackRole, Region, Site, VirtualChassis,
ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, FrontPort, Interface, Manufacturer, Platform,
PowerPort, PowerOutlet, Rack, RackGroup, RackReservation, RackRole, RearPort, Region, Site, VirtualChassis,
)
app_name = 'dcim'
@ -166,6 +166,7 @@ urlpatterns = [
url(r'^console-ports/(?P<pk>\d+)/disconnect/$', views.ConsolePortDisconnectView.as_view(), name='consoleport_disconnect'),
url(r'^console-ports/(?P<pk>\d+)/edit/$', views.ConsolePortEditView.as_view(), name='consoleport_edit'),
url(r'^console-ports/(?P<pk>\d+)/delete/$', views.ConsolePortDeleteView.as_view(), name='consoleport_delete'),
url(r'^console-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='consoleport_trace', kwargs={'model': ConsolePort}),
# Console server ports
url(r'^devices/console-server-ports/add/$', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
@ -177,6 +178,7 @@ urlpatterns = [
url(r'^console-server-ports/(?P<pk>\d+)/disconnect/$', views.ConsoleServerPortDisconnectView.as_view(), name='consoleserverport_disconnect'),
url(r'^console-server-ports/(?P<pk>\d+)/edit/$', views.ConsoleServerPortEditView.as_view(), name='consoleserverport_edit'),
url(r'^console-server-ports/(?P<pk>\d+)/delete/$', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'),
url(r'^console-server-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}),
url(r'^console-server-ports/rename/$', views.ConsoleServerPortBulkRenameView.as_view(), name='consoleserverport_bulk_rename'),
# Power ports
@ -188,6 +190,7 @@ urlpatterns = [
url(r'^power-ports/(?P<pk>\d+)/disconnect/$', views.PowerPortDisconnectView.as_view(), name='powerport_disconnect'),
url(r'^power-ports/(?P<pk>\d+)/edit/$', views.PowerPortEditView.as_view(), name='powerport_edit'),
url(r'^power-ports/(?P<pk>\d+)/delete/$', views.PowerPortDeleteView.as_view(), name='powerport_delete'),
url(r'^power-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='powerport_trace', kwargs={'model': PowerPort}),
# Power outlets
url(r'^devices/power-outlets/add/$', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
@ -199,6 +202,7 @@ urlpatterns = [
url(r'^power-outlets/(?P<pk>\d+)/disconnect/$', views.PowerOutletDisconnectView.as_view(), name='poweroutlet_disconnect'),
url(r'^power-outlets/(?P<pk>\d+)/edit/$', views.PowerOutletEditView.as_view(), name='poweroutlet_edit'),
url(r'^power-outlets/(?P<pk>\d+)/delete/$', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'),
url(r'^power-outlets/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}),
url(r'^power-outlets/rename/$', views.PowerOutletBulkRenameView.as_view(), name='poweroutlet_bulk_rename'),
# Interfaces
@ -213,6 +217,7 @@ urlpatterns = [
url(r'^interfaces/(?P<pk>\d+)/assign-vlans/$', views.InterfaceAssignVLANsView.as_view(), name='interface_assign_vlans'),
url(r'^interfaces/(?P<pk>\d+)/delete/$', views.InterfaceDeleteView.as_view(), name='interface_delete'),
url(r'^interfaces/(?P<pk>\d+)/changelog/$', ObjectChangeLogView.as_view(), name='interface_changelog', kwargs={'model': Interface}),
url(r'^interfaces/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='interface_trace', kwargs={'model': Interface}),
url(r'^interfaces/rename/$', views.InterfaceBulkRenameView.as_view(), name='interface_bulk_rename'),
# Front ports
@ -221,6 +226,7 @@ urlpatterns = [
url(r'^devices/(?P<pk>\d+)/front-ports/delete/$', views.FrontPortBulkDeleteView.as_view(), name='frontport_bulk_delete'),
url(r'^front-ports/(?P<pk>\d+)/edit/$', views.FrontPortEditView.as_view(), name='frontport_edit'),
url(r'^front-ports/(?P<pk>\d+)/delete/$', views.FrontPortDeleteView.as_view(), name='frontport_delete'),
url(r'^front-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='frontport_trace', kwargs={'model': FrontPort}),
url(r'^front-ports/rename/$', views.FrontPortBulkRenameView.as_view(), name='frontport_bulk_rename'),
# Rear ports
@ -229,6 +235,7 @@ urlpatterns = [
url(r'^devices/(?P<pk>\d+)/rear-ports/delete/$', views.RearPortBulkDeleteView.as_view(), name='rearport_bulk_delete'),
url(r'^rear-ports/(?P<pk>\d+)/edit/$', views.RearPortEditView.as_view(), name='rearport_edit'),
url(r'^rear-ports/(?P<pk>\d+)/delete/$', views.RearPortDeleteView.as_view(), name='rearport_delete'),
url(r'^rear-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='rearport_trace', kwargs={'model': RearPort}),
url(r'^rear-ports/rename/$', views.RearPortBulkRenameView.as_view(), name='rearport_bulk_rename'),
# Device bays

View File

@ -2063,6 +2063,21 @@ class CableDeleteView(PermissionRequiredMixin, ObjectDeleteView):
default_return_url = 'dcim:cable_list'
class CableTraceView(View):
"""
Trace a cable path beginning from the given termination.
"""
def get(self, request, model, pk):
obj = get_object_or_404(model, pk=pk)
return render(request, 'dcim/cable_trace.html', {
'obj': obj,
'trace': obj.trace(),
})
#
# Connections
#

View File

@ -39,9 +39,12 @@
<tr>
<td>Termination</td>
<td>
{% if termination.cable %}
<a href="{{ termination.cable.get_absolute_url }}">{{ termination.cable }}</a>
{% if termination.connected_endpoint %}
<a href="{% url 'dcim:device' pk=termination.connected_endpoint.device.pk %}">{{ termination.connected_endpoint.device }}</a>
to <a href="{% url 'dcim:device' pk=termination.connected_endpoint.device.pk %}">{{ termination.connected_endpoint.device }}</a>
<i class="fa fa-angle-right"></i> {{ termination.connected_endpoint }}
{% endif %}
{% else %}
{% if perms.circuits.change_circuittermination %}
<div class="pull-right">

View File

@ -0,0 +1,42 @@
{% extends '_base.html' %}
{% load helpers %}
{% block header %}
<h1>{% block title %}Cable Trace for {{ obj }}{% endblock %}</h1>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-4 col-md-offset-1 text-center">
<h4>Near End</h4>
</div>
<div class="col-md-4 col-md-offset-3 text-center">
<h4>Far End</h4>
</div>
</div>
{% for near_end, cable, far_end in trace %}
<div class="row">
<div class="col-md-1 text-right">
<h3>{{ forloop.counter }}</h3>
</div>
<div class="col-md-4">
{% include 'dcim/inc/cable_trace_end.html' with end=near_end %}
</div>
<div class="col-md-3 text-center">
<h4>
<a href="{% url 'dcim:cable' pk=cable.pk %}">
{% if cable.label %}<code>{{ cable.label }}</code>{% else %}Cable #{{ cable.pk }}{% endif %}
</a>
</h4>
{{ cable.get_status_display }}<br />
{{ cable.get_type_display|default:"" }}
{% if cable.length %}- {{ cable.length }}{{ cable.length_unit }}{% endif %}
<span class="label color-block center-block" style="background-color: #{{ cable.color }}">&nbsp;</span>
</div>
<div class="col-md-4">
{% include 'dcim/inc/cable_trace_end.html' with end=far_end %}
</div>
</div>
{% if not forloop.last %}<hr />{% endif %}
{% endfor %}
{% endblock %}

View File

@ -777,7 +777,6 @@
</div>
</div>
{% include 'inc/modal.html' with modal_name='graphs' %}
{% include 'inc/modal.html' with modal_name='cabletrace' %}
{% include 'secrets/inc/private_key_modal.html' %}
{% endblock %}
@ -848,7 +847,6 @@ $('button.toggle-ips').click(function() {
return false;
});
</script>
<script src="{% static 'js/cabletrace.js' %}?v{{ settings.VERSION }}"></script>
<script src="{% static 'js/graphs.js' %}?v{{ settings.VERSION }}"></script>
<script src="{% static 'js/secrets.js' %}?v{{ settings.VERSION }}"></script>
{% endblock %}

View File

@ -0,0 +1,27 @@
{% load helpers %}
<div class="panel panel-default">
<div class="panel-heading text-center">
{% if end.device %}
<strong><a href="{{ end.device.get_absolute_url }}">{{ end.device }}</a></strong>
{% else %}
<strong><a href="{{ end.circuit.get_absolute_url }}">{{ end.circuit }}</a></strong>
{% endif %}
</div>
<div class="panel-body text-center">
{% if end.device %}
{# Device component #}
{% with model=end|model_name %}
<strong>{{ model|bettertitle }} {{ end }}</strong><br />
{% if model == 'interface' %}
{{ end.get_form_factor_display }}
{% elif model == 'front port' or model == 'rear port' %}
{{ end.get_type_display }}
{% endif %}
{% endwith %}
{% else %}
{# Circuit termination #}
<strong>Side {{ end.term_side }}</strong>
{% endif %}
</div>
</div>

View File

@ -32,9 +32,9 @@
<td>
{% if iface.cable %}
<a href="{{ iface.cable.get_absolute_url }}">{{ iface.cable }}</a>
<button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#cabletrace_modal" data-obj="{{ device.name }} - {{ iface.name }}" data-url="{% url 'dcim-api:interface-trace' pk=iface.pk %}" title="Trace cable">
<a href="{% url 'dcim:interface_trace' pk=iface.pk %}" class="btn btn-primary btn-xs" title="Trace">
<i class="fa fa-share-alt" aria-hidden="true"></i>
</button>
</a>
{% else %}
&mdash;
{% endif %}