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:
@ -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}),
|
||||
|
||||
]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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">
|
||||
|
42
netbox/templates/dcim/cable_trace.html
Normal file
42
netbox/templates/dcim/cable_trace.html
Normal 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 }}"> </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 %}
|
@ -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 %}
|
||||
|
27
netbox/templates/dcim/inc/cable_trace_end.html
Normal file
27
netbox/templates/dcim/inc/cable_trace_end.html
Normal 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>
|
@ -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 %}
|
||||
—
|
||||
{% endif %}
|
||||
|
Reference in New Issue
Block a user