From f048cf36ce2aa2b50dd1193eb18aa3635eb9c3ed Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 11 Jul 2018 15:30:54 -0400 Subject: [PATCH] Implemented a view for interfaces --- netbox/dcim/models.py | 6 +- netbox/dcim/urls.py | 1 + netbox/dcim/views.py | 42 +++ netbox/ipam/tables.py | 35 +++ netbox/templates/dcim/device.html | 3 +- netbox/templates/dcim/inc/interface.html | 13 +- netbox/templates/dcim/interface.html | 275 ++++++++++++++++++ .../virtualization/virtualmachine.html | 5 +- 8 files changed, 366 insertions(+), 14 deletions(-) create mode 100644 netbox/templates/dcim/interface.html diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index a7e5c9ee7..0eea17c32 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -1871,7 +1871,7 @@ class Interface(ComponentModel): return self.name def get_absolute_url(self): - return self.parent.get_absolute_url() + return reverse('dcim:interface', kwargs={'pk': self.pk}) def get_component_parent(self): return self.device or self.virtual_machine @@ -1967,6 +1967,10 @@ class Interface(ComponentModel): def parent(self): return self.device or self.virtual_machine + @property + def is_connectable(self): + return self.form_factor not in NONCONNECTABLE_IFACE_TYPES + @property def is_virtual(self): return self.form_factor in VIRTUAL_IFACE_TYPES diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 6824f620a..9910c60da 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -199,6 +199,7 @@ urlpatterns = [ url(r'^devices/(?P\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'), url(r'^devices/(?P\d+)/interface-connections/add/$', views.InterfaceConnectionAddView.as_view(), name='interfaceconnection_add'), url(r'^interface-connections/(?P\d+)/delete/$', views.InterfaceConnectionDeleteView.as_view(), name='interfaceconnection_delete'), + url(r'^interfaces/(?P\d+)/$', views.InterfaceView.as_view(), name='interface'), url(r'^interfaces/(?P\d+)/edit/$', views.InterfaceEditView.as_view(), name='interface_edit'), url(r'^interfaces/(?P\d+)/assign-vlans/$', views.InterfaceAssignVLANsView.as_view(), name='interface_assign_vlans'), url(r'^interfaces/(?P\d+)/delete/$', views.InterfaceDeleteView.as_view(), name='interface_delete'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 9520297f1..737a33977 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -21,6 +21,7 @@ from circuits.models import Circuit from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE from extras.views import ObjectConfigContextView from ipam.models import Prefix, Service, VLAN +from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable from utilities.forms import ConfirmationForm from utilities.paginator import EnhancedPaginator from utilities.views import ( @@ -1616,6 +1617,47 @@ class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): # Interfaces # +class InterfaceView(View): + + def get(self, request, pk): + + interface = get_object_or_404(Interface, pk=pk) + + # Get connected interface + connected_interface = interface.connected_interface + if connected_interface is None and hasattr(interface, 'circuit_termination'): + peer_termination = interface.circuit_termination.get_peer_termination() + if peer_termination is not None: + connected_interface = peer_termination.interface + + # Get assigned IP addresses + ipaddress_table = InterfaceIPAddressTable( + data=interface.ip_addresses.select_related('vrf', 'tenant'), + orderable=False + ) + + # Get assigned VLANs and annotate whether each is tagged or untagged + vlans = [] + if interface.untagged_vlan is not None: + vlans.append(interface.untagged_vlan) + vlans[0].tagged = False + for vlan in interface.tagged_vlans.select_related('site', 'group', 'tenant', 'role'): + vlan.tagged = True + vlans.append(vlan) + vlan_table = InterfaceVLANTable( + interface=interface, + data=vlans, + orderable=False + ) + + return render(request, 'dcim/interface.html', { + 'interface': interface, + 'connected_interface': connected_interface, + 'ipaddress_table': ipaddress_table, + 'vlan_table': vlan_table, + }) + + class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView): permission_required = 'dcim.add_interface' parent_model = Device diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index e444cfe28..2d6ec11a4 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -342,6 +342,20 @@ class IPAddressAssignTable(BaseTable): orderable = False +class InterfaceIPAddressTable(BaseTable): + """ + List IP addresses assigned to a specific Interface. + """ + address = tables.TemplateColumn(IPADDRESS_ASSIGN_LINK, verbose_name='IP Address') + vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF') + status = tables.TemplateColumn(STATUS_LABEL) + tenant = tables.TemplateColumn(template_code=TENANT_LINK) + + class Meta(BaseTable.Meta): + model = IPAddress + fields = ('address', 'vrf', 'status', 'role', 'tenant', 'description') + + # # VLAN groups # @@ -403,6 +417,27 @@ class VLANMemberTable(BaseTable): fields = ('parent', 'name', 'untagged', 'actions') +class InterfaceVLANTable(BaseTable): + """ + List VLANs assigned to a specific Interface. + """ + vid = tables.LinkColumn('ipam:vlan', args=[Accessor('pk')], verbose_name='ID') + tagged = BooleanColumn() + site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')]) + group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group') + tenant = tables.TemplateColumn(template_code=COL_TENANT) + status = tables.TemplateColumn(STATUS_LABEL) + role = tables.TemplateColumn(VLAN_ROLE_LINK) + + class Meta(BaseTable.Meta): + model = VLAN + fields = ('vid', 'tagged', 'site', 'group', 'name', 'tenant', 'status', 'role', 'description') + + def __init__(self, interface, *args, **kwargs): + self.interface = interface + super(InterfaceVLANTable, self).__init__(*args, **kwargs) + + # # Services # diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 623efa9c4..d0751f363 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -522,8 +522,7 @@ Name LAG Description - MTU - MAC Address + Mode Connection diff --git a/netbox/templates/dcim/inc/interface.html b/netbox/templates/dcim/inc/interface.html index b254794df..6fd0bd52e 100644 --- a/netbox/templates/dcim/inc/interface.html +++ b/netbox/templates/dcim/inc/interface.html @@ -11,7 +11,7 @@ - {{ iface }} + {{ iface }} @@ -23,13 +23,10 @@ {# Description #} - {{ iface.description }} + {{ iface.description|default:"—" }} - {# MTU #} - {{ iface.mtu|default:"" }} - - {# MAC address #} - {{ iface.mac_address|default:"" }} + {# 802.1Q mode #} + {{ iface.get_mode_display }} {# Connection or type #} {% if iface.is_lag %} @@ -141,7 +138,7 @@ {% endif %} {# IP addresses table #} - + diff --git a/netbox/templates/dcim/interface.html b/netbox/templates/dcim/interface.html new file mode 100644 index 000000000..d0f9b82c0 --- /dev/null +++ b/netbox/templates/dcim/interface.html @@ -0,0 +1,275 @@ +{% extends '_base.html' %} +{% load helpers %} + +{% block header %} +
+
+ +
+
+
+ {% if perms.dcim.change_interface %} + + Edit this interface + + {% endif %} + {% if perms.dcim.delete_interface %} + + Delete this interface + + {% endif %} +
+

{% block title %}{{ interface.parent }} / {{ interface.name }}{% endblock %}

+{% endblock %} + +{% block content %} +
+
+
+
+ Interface +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{% if interface.device %}Device{% else %}Virtual Machine{% endif %} + {{ interface.parent }} +
Name{{ interface.name }}
Type{{ interface.get_form_factor_display }}
Enabled + {% if interface.enabled %} + + {% else %} + + {% endif %} +
LAG + {% if interface.lag%} + {{ interface.lag }} + {% else %} + None + {% endif %} +
Description + {% if interface.description %} + {{ interface.description }} + {% else %} + N/A + {% endif %} +
MTU + {% if interface.mtu %} + {{ interface.mtu }} + {% else %} + N/A + {% endif %} +
MAC Address + {% if interface.mac_address %} + {{ interface.mac_address }} + {% else %} + N/A + {% endif %} +
802.1Q Mode{{ interface.get_mode_display }}
+ + {% include 'extras/inc/tags_panel.html' with tags=interface.tags.all %} + +
+ {% if interface.is_connectable %} +
+
+ Connected Interface +
+ {% if connected_interface %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% if interface.connection %} + + + + + {% endif %} +
{% if connected_interface.device %}Device{% else %}Virtual Machine{% endif %} + {{ connected_interface.parent }} +
Name{{ connected_interface.name }}
Type{{ connected_interface.get_form_factor_display }}
Enabled + {% if connected_interface.enabled %} + + {% else %} + + {% endif %} +
LAG + {% if connected_interface.lag%} + {{ connected_interface.lag }} + {% else %} + None + {% endif %} +
Description + {% if connected_interface.description %} + {{ connected_interface.description }} + {% else %} + N/A + {% endif %} +
MTU + {% if connected_interface.mtu %} + {{ connected_interface.mtu }} + {% else %} + N/A + {% endif %} +
MAC Address + {% if connected_interface.mac_address %} + {{ connected_interface.mac_address }} + {% else %} + N/A + {% endif %} +
802.1Q Mode{{ connected_interface.get_mode_display }}
Connection Status + {% if interface.connection.connection_status %} + {{ interface.connection.get_connection_status_display }} + {% else %} + {{ interface.connection.get_connection_status_display }} + {% endif %} +
+ {% else %} +
+ No connected interface +
+ {% endif %} +
+
+
+ Circuit Termination +
+ + {% if interface.circuit_termination %} + + + + + + + + + {% else %} + + + + {% endif %} +
Circuit{{ interface.circuit_termination.circuit }}
Side{{ interface.circuit_termination.term_side }}
None
+
+ {% endif %} + {% if interface.is_lag %} +
+
LAG Members
+ + + + + + + + + + {% for member in interface.member_interfaces.all %} + + + + + + {% empty %} + + + + {% endfor %} + +
ParentInterfaceType
+ {{ member.parent }} + + {{ member }} + + {{ member.get_form_factor_display }} +
No member interfaces
+
+ {% endif %} +
+ +
+
+ {% include 'panel_table.html' with table=ipaddress_table heading="IP Addresses" %} +
+
+
+
+ {% include 'panel_table.html' with table=vlan_table heading="VLANs" %} +
+
+{% endblock %} diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 6323f31cc..9c6c8b0e3 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -261,8 +261,7 @@ Name LAG Description - MTU - MAC Address + Mode Connection @@ -272,7 +271,7 @@ {% include 'dcim/inc/interface.html' with device=virtualmachine %} {% empty %} - — No interfaces defined — + — No interfaces defined — {% endfor %}