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

Merge pull request #5251 from netbox-community/4786-device-component-tables

#4786: Convert device component templates to tables
This commit is contained in:
Jeremy Stretch
2020-10-19 15:01:40 -04:00
committed by GitHub
20 changed files with 575 additions and 1230 deletions

View File

@ -10,15 +10,28 @@ from utilities.tables import (
BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn, BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn,
TagColumn, ToggleColumn, TagColumn, ToggleColumn,
) )
from .template_code import DEVICE_LINK, INTERFACE_IPADDRESSES, INTERFACE_TAGGED_VLANS from .template_code import (
CABLETERMINATION, CONSOLEPORT_BUTTONS, CONSOLESERVERPORT_BUTTONS, DEVICE_LINK, DEVICEBAY_BUTTONS, DEVICEBAY_STATUS,
FRONTPORT_BUTTONS, INTERFACE_BUTTONS, INTERFACE_IPADDRESSES, INTERFACE_TAGGED_VLANS, POWEROUTLET_BUTTONS,
POWERPORT_BUTTONS, REARPORT_BUTTONS,
)
__all__ = ( __all__ = (
'ConsolePortTable', 'ConsolePortTable',
'ConsoleServerPortTable', 'ConsoleServerPortTable',
'DeviceImportTable',
'DeviceTable',
'DeviceBayTable', 'DeviceBayTable',
'DeviceConsolePortTable',
'DeviceConsoleServerPortTable',
'DeviceDeviceBayTable',
'DeviceFrontPortTable',
'DeviceImportTable',
'DeviceInterfaceTable',
'DeviceInventoryItemTable',
'DevicePowerPortTable',
'DevicePowerOutletTable',
'DeviceRearPortTable',
'DeviceRoleTable', 'DeviceRoleTable',
'DeviceTable',
'FrontPortTable', 'FrontPortTable',
'InterfaceTable', 'InterfaceTable',
'InventoryItemTable', 'InventoryItemTable',
@ -204,29 +217,93 @@ class DeviceComponentTable(BaseTable):
order_by = ('device', 'name') order_by = ('device', 'name')
class ConsolePortTable(DeviceComponentTable): class CableTerminationTable(BaseTable):
cable = tables.Column(
linkify=True
)
cable_peer = tables.TemplateColumn(
accessor='get_cable_peer',
template_code=CABLETERMINATION,
orderable=False
)
class PathEndpointTable(CableTerminationTable):
connection = tables.TemplateColumn(
accessor='_path.destination',
template_code=CABLETERMINATION,
verbose_name='Connection',
orderable=False
)
class ConsolePortTable(DeviceComponentTable, PathEndpointTable):
tags = TagColumn( tags = TagColumn(
url_name='dcim:consoleport_list' url_name='dcim:consoleport_list'
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
model = ConsolePort model = ConsolePort
fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags') fields = (
'pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags',
)
default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
class ConsoleServerPortTable(DeviceComponentTable): class DeviceConsolePortTable(ConsolePortTable):
name = tables.TemplateColumn(
template_code='<i class="fa fa-keyboard-o"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
)
actions = ButtonsColumn(
model=ConsolePort,
buttons=('edit', 'delete'),
prepend_template=CONSOLEPORT_BUTTONS
)
class Meta(DeviceComponentTable.Meta):
model = ConsolePort
fields = (
'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions'
)
default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'connection', 'actions')
row_attrs = {
'class': lambda record: record.cable.get_status_class() if record.cable else ''
}
class ConsoleServerPortTable(DeviceComponentTable, PathEndpointTable):
tags = TagColumn( tags = TagColumn(
url_name='dcim:consoleserverport_list' url_name='dcim:consoleserverport_list'
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
model = ConsoleServerPort model = ConsoleServerPort
fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags') fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags')
default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
class PowerPortTable(DeviceComponentTable): class DeviceConsoleServerPortTable(ConsoleServerPortTable):
name = tables.TemplateColumn(
template_code='<i class="fa fa-keyboard-o"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
)
actions = ButtonsColumn(
model=ConsoleServerPort,
buttons=('edit', 'delete'),
prepend_template=CONSOLESERVERPORT_BUTTONS
)
class Meta(DeviceComponentTable.Meta):
model = ConsoleServerPort
fields = (
'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions'
)
default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'connection', 'actions')
row_attrs = {
'class': lambda record: record.cable.get_status_class() if record.cable else ''
}
class PowerPortTable(DeviceComponentTable, PathEndpointTable):
tags = TagColumn( tags = TagColumn(
url_name='dcim:powerport_list' url_name='dcim:powerport_list'
) )
@ -234,22 +311,78 @@ class PowerPortTable(DeviceComponentTable):
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
model = PowerPort model = PowerPort
fields = ( fields = (
'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable', 'tags', 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable',
'cable_peer', 'connection', 'tags',
) )
default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description') default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
class PowerOutletTable(DeviceComponentTable): class DevicePowerPortTable(PowerPortTable):
name = tables.TemplateColumn(
template_code='<i class="fa fa-bolt"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
)
actions = ButtonsColumn(
model=PowerPort,
buttons=('edit', 'delete'),
prepend_template=POWERPORT_BUTTONS
)
class Meta(DeviceComponentTable.Meta):
model = PowerPort
fields = (
'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'cable_peer',
'connection', 'tags', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'connection',
'actions',
)
row_attrs = {
'class': lambda record: record.cable.get_status_class() if record.cable else ''
}
class PowerOutletTable(DeviceComponentTable, PathEndpointTable):
power_port = tables.Column(
linkify=True
)
tags = TagColumn( tags = TagColumn(
url_name='dcim:poweroutlet_list' url_name='dcim:poweroutlet_list'
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
model = PowerOutlet model = PowerOutlet
fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'tags') fields = (
'pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'cable_peer',
'connection', 'tags',
)
default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description') default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description')
class DevicePowerOutletTable(PowerOutletTable):
name = tables.TemplateColumn(
template_code='<i class="fa fa-bolt"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
)
actions = ButtonsColumn(
model=PowerOutlet,
buttons=('edit', 'delete'),
prepend_template=POWEROUTLET_BUTTONS
)
class Meta(DeviceComponentTable.Meta):
model = PowerOutlet
fields = (
'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'cable_peer', 'connection',
'tags', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'connection', 'actions',
)
row_attrs = {
'class': lambda record: record.cable.get_status_class() if record.cable else ''
}
class BaseInterfaceTable(BaseTable): class BaseInterfaceTable(BaseTable):
enabled = BooleanColumn() enabled = BooleanColumn()
ip_addresses = tables.TemplateColumn( ip_addresses = tables.TemplateColumn(
@ -265,7 +398,7 @@ class BaseInterfaceTable(BaseTable):
) )
class InterfaceTable(DeviceComponentTable, BaseInterfaceTable): class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable):
tags = TagColumn( tags = TagColumn(
url_name='dcim:interface_list' url_name='dcim:interface_list'
) )
@ -274,15 +407,49 @@ class InterfaceTable(DeviceComponentTable, BaseInterfaceTable):
model = Interface model = Interface
fields = ( fields = (
'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address', 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address',
'description', 'cable', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans',
) )
default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description') default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description')
class FrontPortTable(DeviceComponentTable): class DeviceInterfaceTable(InterfaceTable):
name = tables.TemplateColumn(
template_code='<i class="fa fa-{% if iface.mgmt_only %}wrench{% elif iface.is_lag %}align-justify'
'{% elif iface.is_virtual %}circle{% elif iface.is_wireless %}wifi{% else %}exchange'
'{% endif %}"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
)
lag = tables.Column(
linkify=True,
verbose_name='LAG'
)
actions = ButtonsColumn(
model=Interface,
buttons=('edit', 'delete'),
prepend_template=INTERFACE_BUTTONS
)
class Meta(DeviceComponentTable.Meta):
model = Interface
fields = (
'pk', 'name', 'label', 'enabled', 'type', 'lag', 'mgmt_only', 'mtu', 'mode', 'mac_address', 'description',
'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'enabled', 'type', 'lag', 'mtu', 'mode', 'description', 'ip_addresses', 'cable',
'connection', 'actions',
)
row_attrs = {
'class': lambda record: record.cable.get_status_class() if record.cable else ''
}
class FrontPortTable(DeviceComponentTable, CableTerminationTable):
rear_port_position = tables.Column( rear_port_position = tables.Column(
verbose_name='Position' verbose_name='Position'
) )
rear_port = tables.Column(
linkify=True
)
tags = TagColumn( tags = TagColumn(
url_name='dcim:frontport_list' url_name='dcim:frontport_list'
) )
@ -290,23 +457,77 @@ class FrontPortTable(DeviceComponentTable):
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
model = FrontPort model = FrontPort
fields = ( fields = (
'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'tags', 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable',
'cable_peer', 'tags',
) )
default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description') default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description')
class RearPortTable(DeviceComponentTable): class DeviceFrontPortTable(FrontPortTable):
name = tables.TemplateColumn(
template_code='<i class="fa fa-square{% if not record.cable %}-o{% endif %}"></i> '
'<a href="{{ record.get_absolute_url }}">{{ value }}</a>'
)
actions = ButtonsColumn(
model=FrontPort,
buttons=('edit', 'delete'),
prepend_template=FRONTPORT_BUTTONS
)
class Meta(DeviceComponentTable.Meta):
model = FrontPort
fields = (
'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer',
'tags', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer',
'actions',
)
row_attrs = {
'class': lambda record: record.cable.get_status_class() if record.cable else ''
}
class RearPortTable(DeviceComponentTable, CableTerminationTable):
tags = TagColumn( tags = TagColumn(
url_name='dcim:rearport_list' url_name='dcim:rearport_list'
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
model = RearPort model = RearPort
fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'tags') fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags')
default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
class DeviceRearPortTable(RearPortTable):
name = tables.TemplateColumn(
template_code='<i class="fa fa-square{% if not record.cable %}-o{% endif %}"></i> '
'<a href="{{ record.get_absolute_url }}">{{ value }}</a>'
)
actions = ButtonsColumn(
model=RearPort,
buttons=('edit', 'delete'),
prepend_template=REARPORT_BUTTONS
)
class Meta(DeviceComponentTable.Meta):
model = RearPort
fields = (
'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'actions',
)
row_attrs = {
'class': lambda record: record.cable.get_status_class() if record.cable else ''
}
class DeviceBayTable(DeviceComponentTable): class DeviceBayTable(DeviceComponentTable):
status = tables.TemplateColumn(
template_code=DEVICEBAY_STATUS
)
installed_device = tables.Column( installed_device = tables.Column(
linkify=True linkify=True
) )
@ -316,8 +537,29 @@ class DeviceBayTable(DeviceComponentTable):
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
model = DeviceBay model = DeviceBay
fields = ('pk', 'device', 'name', 'label', 'installed_device', 'description', 'tags') fields = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description', 'tags')
default_columns = ('pk', 'device', 'name', 'label', 'installed_device', 'description') default_columns = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description')
class DeviceDeviceBayTable(DeviceBayTable):
name = tables.TemplateColumn(
template_code='<i class="fa fa-square{% if record.installed_device %}dot-circle-o{% else %}circle-o{% endif %}'
'"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
)
actions = ButtonsColumn(
model=DeviceBay,
buttons=('edit', 'delete'),
prepend_template=DEVICEBAY_BUTTONS
)
class Meta(DeviceComponentTable.Meta):
model = DeviceBay
fields = (
'pk', 'name', 'label', 'status', 'installed_device', 'description', 'tags', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'status', 'installed_device', 'description', 'actions',
)
class InventoryItemTable(DeviceComponentTable): class InventoryItemTable(DeviceComponentTable):
@ -339,6 +581,28 @@ class InventoryItemTable(DeviceComponentTable):
default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag') default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag')
class DeviceInventoryItemTable(InventoryItemTable):
name = tables.TemplateColumn(
template_code='<a href="{{ record.get_absolute_url }}" style="padding-left: {{ record.level }}0px">'
'{{ value }}</a>'
)
actions = ButtonsColumn(
model=InventoryItem,
buttons=('edit', 'delete')
)
class Meta(DeviceComponentTable.Meta):
model = InventoryItem
fields = (
'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered',
'tags', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered',
'actions',
)
# #
# Virtual chassis # Virtual chassis
# #

View File

@ -3,6 +3,7 @@ from django_tables2.utils import Accessor
from dcim.models import PowerFeed, PowerPanel from dcim.models import PowerFeed, PowerPanel
from utilities.tables import BaseTable, ChoiceFieldColumn, LinkedCountColumn, TagColumn, ToggleColumn from utilities.tables import BaseTable, ChoiceFieldColumn, LinkedCountColumn, TagColumn, ToggleColumn
from .devices import CableTerminationTable
from .template_code import POWERFEED_CABLE, POWERFEED_CABLETERMINATION from .template_code import POWERFEED_CABLE, POWERFEED_CABLETERMINATION
__all__ = ( __all__ = (
@ -41,7 +42,9 @@ class PowerPanelTable(BaseTable):
# Power feeds # Power feeds
# #
class PowerFeedTable(BaseTable): # We're not using PathEndpointTable for PowerFeed because power connections
# cannot traverse pass-through ports.
class PowerFeedTable(CableTerminationTable):
pk = ToggleColumn() pk = ToggleColumn()
name = tables.LinkColumn() name = tables.LinkColumn()
power_panel = tables.Column( power_panel = tables.Column(
@ -55,15 +58,6 @@ class PowerFeedTable(BaseTable):
max_utilization = tables.TemplateColumn( max_utilization = tables.TemplateColumn(
template_code="{{ value }}%" template_code="{{ value }}%"
) )
cable = tables.TemplateColumn(
template_code=POWERFEED_CABLE,
orderable=False
)
connection = tables.TemplateColumn(
accessor='get_cable_peer',
template_code=POWERFEED_CABLETERMINATION,
orderable=False
)
available_power = tables.Column( available_power = tables.Column(
verbose_name='Available power (VA)' verbose_name='Available power (VA)'
) )
@ -75,9 +69,9 @@ class PowerFeedTable(BaseTable):
model = PowerFeed model = PowerFeed
fields = ( fields = (
'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
'max_utilization', 'cable', 'connection', 'available_power', 'tags', 'max_utilization', 'cable', 'cable_peer', 'connection', 'available_power', 'tags',
) )
default_columns = ( default_columns = (
'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', 'cable', 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', 'cable',
'connection', 'cable_peer',
) )

View File

@ -1,3 +1,13 @@
CABLETERMINATION = """
{% if value %}
<a href="{{ value.parent.get_absolute_url }}">{{ value.parent }}</a>
<i class="fa fa-caret-right"></i>
<a href="{{ value.get_absolute_url }}">{{ value }}</a>
{% else %}
&mdash;
{% endif %}
"""
CABLE_LENGTH = """ CABLE_LENGTH = """
{% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}&mdash;{% endif %} {% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}&mdash;{% endif %}
""" """
@ -18,8 +28,18 @@ DEVICE_LINK = """
</a> </a>
""" """
DEVICEBAY_STATUS = """
{% if record.installed_device_id %}
<span class="label label-{{ record.installed_device.get_status_class }}">
{{ record.installed_device.get_status_display }}
</span>
{% else %}
<span class="label label-default">Vacant</span>
{% endif %}
"""
INTERFACE_IPADDRESSES = """ INTERFACE_IPADDRESSES = """
{% for ip in record.ip_addresses.unrestricted %} {% for ip in record.ip_addresses.all %}
<a href="{{ ip.get_absolute_url }}">{{ ip }}</a><br /> <a href="{{ ip.get_absolute_url }}">{{ ip }}</a><br />
{% endfor %} {% endfor %}
""" """
@ -63,3 +83,149 @@ UTILIZATION_GRAPH = """
{% load helpers %} {% load helpers %}
{% utilization_graph value %} {% utilization_graph value %}
""" """
#
# Device component buttons
#
CONSOLEPORT_BUTTONS = """
{% if record.cable %}
<a href="{% url 'dcim:consoleport_trace' pk=record.pk %}" class="btn btn-primary btn-xs" title="Trace"><i class="fa fa-share-alt"></i></a>
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=record.pk termination_b_type='console-server-port' %}?return_url={{ device.get_absolute_url }}">Console Server Port</a></li>
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=record.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=record.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
</ul>
</span>
{% endif %}
"""
CONSOLESERVERPORT_BUTTONS = """
{% if record.cable %}
<a href="{% url 'dcim:consoleserverport_trace' pk=record.pk %}" class="btn btn-primary btn-xs" title="Trace"><i class="fa fa-share-alt"></i></a>
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=record.pk termination_b_type='console-port' %}?return_url={{ device.get_absolute_url }}">Console Port</a></li>
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=record.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=record.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
</ul>
</span>
{% endif %}
"""
POWERPORT_BUTTONS = """
{% if record.cable %}
<a href="{% url 'dcim:powerport_trace' pk=record.pk %}" class="btn btn-primary btn-xs" title="Trace"><i class="fa fa-share-alt"></i></a>
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:powerport_connect' termination_a_id=record.pk termination_b_type='power-outlet' %}?return_url={{ device.get_absolute_url }}">Power Outlet</a></li>
<li><a href="{% url 'dcim:powerport_connect' termination_a_id=record.pk termination_b_type='power-feed' %}?return_url={{ device.get_absolute_url }}">Power Feed</a></li>
</ul>
</span>
{% endif %}
"""
POWEROUTLET_BUTTONS = """
{% if record.cable %}
<a href="{% url 'dcim:poweroutlet_trace' pk=record.pk %}" class="btn btn-primary btn-xs" title="Trace"><i class="fa fa-share-alt"></i></a>
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %}
{% elif perms.dcim.add_cable %}
<a href="{% url 'dcim:poweroutlet_connect' termination_a_id=record.pk termination_b_type='power-port' %}?return_url={{ device.get_absolute_url }}" title="Connect" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
</a>
{% endif %}
"""
INTERFACE_BUTTONS = """
{% if perms.ipam.add_ipaddress %}
<a href="{% url 'ipam:ipaddress_add' %}?interface={{ record.pk }}&return_url={{ device.get_absolute_url }}" class="btn btn-xs btn-success" title="Add IP address">
<i class="glyphicon glyphicon-plus" aria-hidden="true"></i>
</a>
{% endif %}
{% if record.cable %}
<a href="{% url 'dcim:interface_trace' pk=record.pk %}" class="btn btn-primary btn-xs" title="Trace"><i class="fa fa-share-alt"></i></a>
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %}
{% elif record.is_connectable and perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:interface_connect' termination_a_id=record.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=record.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=record.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=record.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %}
"""
FRONTPORT_BUTTONS = """
{% if record.cable %}
<a href="{% url 'dcim:frontport_trace' pk=record.pk %}" class="btn btn-primary btn-xs" title="Trace"><i class="fa fa-share-alt"></i></a>
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=record.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=record.pk termination_b_type='console-server-port' %}?return_url={{ device.get_absolute_url }}">Console Server Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=record.pk termination_b_type='console-port' %}?return_url={{ device.get_absolute_url }}">Console Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=record.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=record.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=record.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %}
"""
REARPORT_BUTTONS = """
{% if record.cable %}
<a href="{% url 'dcim:rearport_trace' pk=record.pk %}" class="btn btn-primary btn-xs" title="Trace"><i class="fa fa-share-alt"></i></a>
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=record.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=record.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=record.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=record.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %}
"""
DEVICEBAY_BUTTONS = """
{% if perms.dcim.change_devicebay %}
{% if record.installed_device %}
<a href="{% url 'dcim:devicebay_depopulate' pk=record.pk %}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-remove" aria-hidden="true" title="Remove device"></i>
</a>
{% else %}
<a href="{% url 'dcim:devicebay_populate' pk=record.pk %}" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-plus" aria-hidden="true" title="Install device"></i>
</a>
{% endif %}
{% endif %}
"""

View File

@ -1019,6 +1019,9 @@ class DeviceView(ObjectView):
consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'cable', '_path__destination', 'cable', '_path__destination',
) )
consoleport_table = tables.DeviceConsolePortTable(consoleports, orderable=False)
if request.user.has_perm('dcim.change_consoleport') or request.user.has_perm('dcim.delete_consoleport'):
consoleport_table.columns.show('pk')
# Console server ports # Console server ports
consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter( consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter(
@ -1026,16 +1029,26 @@ class DeviceView(ObjectView):
).prefetch_related( ).prefetch_related(
'cable', '_path__destination', 'cable', '_path__destination',
) )
consoleserverport_table = tables.DeviceConsoleServerPortTable(consoleserverports, orderable=False)
if request.user.has_perm('dcim.change_consoleserverport') or \
request.user.has_perm('dcim.delete_consoleserverport'):
consoleserverport_table.columns.show('pk')
# Power ports # Power ports
powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'cable', '_path__destination', 'cable', '_path__destination',
) )
powerport_table = tables.DevicePowerPortTable(powerports, orderable=False)
if request.user.has_perm('dcim.change_powerport') or request.user.has_perm('dcim.delete_powerport'):
powerport_table.columns.show('pk')
# Power outlets # Power outlets
poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'cable', 'power_port', '_path__destination', 'cable', 'power_port', '_path__destination',
) )
poweroutlet_table = tables.DevicePowerOutletTable(poweroutlets, orderable=False)
if request.user.has_perm('dcim.change_poweroutlet') or request.user.has_perm('dcim.delete_poweroutlet'):
poweroutlet_table.columns.show('pk')
# Interfaces # Interfaces
interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related( interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related(
@ -1043,24 +1056,39 @@ class DeviceView(ObjectView):
Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)),
'lag', 'cable', '_path__destination', 'tags', 'lag', 'cable', '_path__destination', 'tags',
) )
interface_table = tables.DeviceInterfaceTable(interfaces, orderable=False)
if request.user.has_perm('dcim.change_interface') or request.user.has_perm('dcim.delete_interface'):
interface_table.columns.show('pk')
# Front ports # Front ports
frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'rear_port', 'cable', 'rear_port', 'cable',
) )
frontport_table = tables.DeviceFrontPortTable(frontports, orderable=False)
if request.user.has_perm('dcim.change_frontport') or request.user.has_perm('dcim.delete_frontport'):
frontport_table.columns.show('pk')
# Rear ports # Rear ports
rearports = RearPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related('cable') rearports = RearPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related('cable')
rearport_table = tables.DeviceRearPortTable(rearports, orderable=False)
if request.user.has_perm('dcim.change_rearport') or request.user.has_perm('dcim.delete_rearport'):
rearport_table.columns.show('pk')
# Device bays # Device bays
devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'installed_device__device_type__manufacturer', 'installed_device__device_type__manufacturer',
) )
devicebay_table = tables.DeviceDeviceBayTable(devicebays, orderable=False)
if request.user.has_perm('dcim.change_devicebay') or request.user.has_perm('dcim.delete_devicebay'):
devicebay_table.columns.show('pk')
# Inventory items # Inventory items
inventoryitems = InventoryItem.objects.restrict(request.user, 'view').filter( inventoryitems = InventoryItem.objects.restrict(request.user, 'view').filter(
device=device device=device
).prefetch_related('manufacturer') ).prefetch_related('manufacturer')
inventoryitem_table = tables.DeviceInventoryItemTable(inventoryitems, orderable=False)
if request.user.has_perm('dcim.change_inventoryitem') or request.user.has_perm('dcim.delete_inventoryitem'):
devicebay_table.columns.show('pk')
# Services # Services
services = Service.objects.restrict(request.user, 'view').filter(device=device) services = Service.objects.restrict(request.user, 'view').filter(device=device)
@ -1079,15 +1107,15 @@ class DeviceView(ObjectView):
return render(request, 'dcim/device.html', { return render(request, 'dcim/device.html', {
'device': device, 'device': device,
'consoleports': consoleports, 'consoleport_table': consoleport_table,
'consoleserverports': consoleserverports, 'consoleserverport_table': consoleserverport_table,
'powerports': powerports, 'powerport_table': powerport_table,
'poweroutlets': poweroutlets, 'poweroutlet_table': poweroutlet_table,
'interfaces': interfaces, 'interface_table': interface_table,
'frontports': frontports, 'frontport_table': frontport_table,
'rearports': rearports, 'rearport_table': rearport_table,
'devicebays': devicebays, 'devicebay_table': devicebay_table,
'inventoryitems': inventoryitems, 'inventoryitem_table': inventoryitem_table,
'services': services, 'services': services,
'secrets': secrets, 'secrets': secrets,
'vc_members': vc_members, 'vc_members': vc_members,

View File

@ -1,16 +1,3 @@
// Toggle the display of IP addresses under interfaces
$('button.toggle-ips').click(function() {
var selected = $(this).attr('selected');
if (selected) {
$('#interfaces_table tr.interface:visible + tr.ipaddresses').hide();
} else {
$('#interfaces_table tr.interface:visible + tr.ipaddresses').show();
}
$(this).attr('selected', !selected);
$(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked');
return false;
});
// Inteface filtering // Inteface filtering
$('input.interface-filter').on('input', function() { $('input.interface-filter').on('input', function() {
var filter = new RegExp(this.value); var filter = new RegExp(this.value);

View File

@ -122,31 +122,31 @@
<a href="#details" role="tab" data-toggle="tab">Details</a> <a href="#details" role="tab" data-toggle="tab">Details</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#interfaces" role="tab" data-toggle="tab">Interfaces {% badge interfaces|length %}</a> <a href="#interfaces" role="tab" data-toggle="tab">Interfaces {% badge interface_table.rows|length %}</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#frontports" role="tab" data-toggle="tab">Front Ports {% badge frontports|length %}</a> <a href="#frontports" role="tab" data-toggle="tab">Front Ports {% badge frontport_table.rows|length %}</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#rearports" role="tab" data-toggle="tab">Rear Ports {% badge rearports|length %}</a> <a href="#rearports" role="tab" data-toggle="tab">Rear Ports {% badge rearport_table.rows|length %}</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#consoleports" role="tab" data-toggle="tab">Console Ports {% badge consoleports|length %}</a> <a href="#consoleports" role="tab" data-toggle="tab">Console Ports {% badge consoleport_table.rows|length %}</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#consoleserverports" role="tab" data-toggle="tab">Console Server Ports {% badge consoleserverports|length %}</a> <a href="#consoleserverports" role="tab" data-toggle="tab">Console Server Ports {% badge consoleserverport_table.rows|length %}</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#powerports" role="tab" data-toggle="tab">Power Ports {% badge powerports|length %}</a> <a href="#powerports" role="tab" data-toggle="tab">Power Ports {% badge powerport_table.rows|length %}</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#poweroutlets" role="tab" data-toggle="tab">Power Outlets {% badge poweroutlets|length %}</a> <a href="#poweroutlets" role="tab" data-toggle="tab">Power Outlets {% badge poweroutlet_table.rows|length %}</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#devicebays" role="tab" data-toggle="tab">Device Bays {% badge devicebays|length %}</a> <a href="#devicebays" role="tab" data-toggle="tab">Device Bays {% badge devicebay_table.rows|length %}</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="#inventoryitems" role="tab" data-toggle="tab">Inventory {% badge inventoryitems|length %}</a> <a href="#inventoryitems" role="tab" data-toggle="tab">Inventory {% badge inventoryitem_table.rows|length %}</a>
</li> </li>
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
@ -485,38 +485,11 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<strong>Interfaces</strong> <strong>Interfaces</strong>
<div class="pull-right noprint">
<button class="btn btn-default btn-xs toggle-ips" selected="selected">
<span class="glyphicon glyphicon-check" aria-hidden="true"></span> Show IPs
</button>
</div>
<div class="col-md-2 pull-right noprint"> <div class="col-md-2 pull-right noprint">
<input class="form-control interface-filter" type="text" placeholder="Filter" title="Filter text (regular expressions supported)" style="height: 23px" /> <input class="form-control interface-filter" type="text" placeholder="Filter" title="Filter text (regular expressions supported)" style="height: 23px" />
</div> </div>
</div> </div>
<table id="interfaces_table" class="table table-hover table-headings panel-body component-list"> {% include 'responsive_table.html' with table=interface_table %}
<thead>
<tr>
{% if perms.dcim.change_interface or perms.dcim.delete_interface %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>LAG</th>
<th>Description</th>
<th>MTU</th>
<th>Mode</th>
<th>Cable</th>
<th colspan="2">Cable Termination</th>
<th colspan="2">Connection</th>
<th></th>
</tr>
</thead>
<tbody>
{% for iface in interfaces %}
{% include 'dcim/inc/interface.html' %}
{% endfor %}
</tbody>
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if interfaces and perms.dcim.change_interface %} {% if interfaces and perms.dcim.change_interface %}
<button type="submit" name="_rename" formaction="{% url 'dcim:interface_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:interface_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
@ -542,8 +515,8 @@
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add interfaces <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add interfaces
</a> </a>
</div> </div>
<div class="clearfix"></div>
{% endif %} {% endif %}
<div class="clearfix"></div>
</div> </div>
</div> </div>
</form> </form>
@ -555,30 +528,9 @@
<div class="panel-heading"> <div class="panel-heading">
<strong>Front Ports</strong> <strong>Front Ports</strong>
</div> </div>
<table class="table table-hover table-headings panel-body component-list"> {% include 'responsive_table.html' with table=frontport_table %}
<thead>
<tr>
{% if perms.dcim.change_frontport or perms.dcim.delete_frontport %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Type</th>
<th>Rear Port</th>
<th>Position</th>
<th>Description</th>
<th>Cable</th>
<th colspan="2">Cable Termination</th>
<th></th>
</tr>
</thead>
<tbody>
{% for frontport in frontports %}
{% include 'dcim/inc/frontport.html' %}
{% endfor %}
</tbody>
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if frontports and perms.dcim.change_frontport %} {% if perms.dcim.change_frontport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:frontport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:frontport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
</button> </button>
@ -589,7 +541,7 @@
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
</button> </button>
{% endif %} {% endif %}
{% if frontports and perms.dcim.delete_frontport %} {% if perms.dcim.delete_frontport %}
<button type="submit" formaction="{% url 'dcim:frontport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs"> <button type="submit" formaction="{% url 'dcim:frontport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button> </button>
@ -600,8 +552,8 @@
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add front ports <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add front ports
</a> </a>
</div> </div>
<div class="clearfix"></div>
{% endif %} {% endif %}
<div class="clearfix"></div>
</div> </div>
</div> </div>
</form> </form>
@ -613,29 +565,9 @@
<div class="panel-heading"> <div class="panel-heading">
<strong>Rear Ports</strong> <strong>Rear Ports</strong>
</div> </div>
<table class="table table-hover table-headings panel-body component-list"> {% include 'responsive_table.html' with table=rearport_table %}
<thead>
<tr>
{% if perms.dcim.change_rearport or perms.dcim.delete_rearport %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Type</th>
<th>Positions</th>
<th>Description</th>
<th>Cable</th>
<th colspan="2">Cable Termination</th>
<th></th>
</tr>
</thead>
<tbody>
{% for rearport in rearports %}
{% include 'dcim/inc/rearport.html' %}
{% endfor %}
</tbody>
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if rearports and perms.dcim.change_rearport %} {% if perms.dcim.change_rearport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:rearport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:rearport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
</button> </button>
@ -646,7 +578,7 @@
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
</button> </button>
{% endif %} {% endif %}
{% if rearports and perms.dcim.delete_rearport %} {% if perms.dcim.delete_rearport %}
<button type="submit" formaction="{% url 'dcim:rearport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs"> <button type="submit" formaction="{% url 'dcim:rearport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button> </button>
@ -657,8 +589,8 @@
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add rear ports <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add rear ports
</a> </a>
</div> </div>
<div class="clearfix"></div>
{% endif %} {% endif %}
<div class="clearfix"></div>
</div> </div>
</div> </div>
</form> </form>
@ -670,27 +602,9 @@
<div class="panel-heading"> <div class="panel-heading">
<strong>Console Ports</strong> <strong>Console Ports</strong>
</div> </div>
<table class="table table-hover panel-body component-list"> {% include 'responsive_table.html' with table=consoleport_table %}
<thead>
<tr>
{% if perms.dcim.change_consoleport or perms.dcim.delete_consoleport %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Cable</th>
<th colspan="2">Cable Termination</th>
<th colspan="2">Connection</th>
<th></th>
</tr>
</thead>
{% for cp in consoleports %}
{% include 'dcim/inc/consoleport.html' %}
{% endfor %}
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if consoleports and perms.dcim.change_consoleport %} {% if perms.dcim.change_consoleport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:consoleport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
</button> </button>
@ -701,7 +615,7 @@
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
</button> </button>
{% endif %} {% endif %}
{% if consoleports and perms.dcim.delete_consoleport %} {% if perms.dcim.delete_consoleport %}
<button type="submit" name="_delete" formaction="{% url 'dcim:consoleport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs"> <button type="submit" name="_delete" formaction="{% url 'dcim:consoleport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button> </button>
@ -713,6 +627,7 @@
</a> </a>
</div> </div>
{% endif %} {% endif %}
<div class="clearfix"></div>
</div> </div>
</div> </div>
</form> </form>
@ -724,29 +639,9 @@
<div class="panel-heading"> <div class="panel-heading">
<strong>Console Server Ports</strong> <strong>Console Server Ports</strong>
</div> </div>
<table class="table table-hover table-headings panel-body component-list"> {% include 'responsive_table.html' with table=consoleserverport_table %}
<thead>
<tr>
{% if perms.dcim.change_consoleserverport or perms.dcim.delete_consoleserverport %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Cable</th>
<th colspan="2">Cable Termination</th>
<th colspan="2">Connection</th>
<th></th>
</tr>
</thead>
<tbody>
{% for csp in consoleserverports %}
{% include 'dcim/inc/consoleserverport.html' %}
{% endfor %}
</tbody>
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if consoleserverports and perms.dcim.change_consoleport %} {% if perms.dcim.change_consoleport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleserverport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:consoleserverport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
</button> </button>
@ -757,7 +652,7 @@
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
</button> </button>
{% endif %} {% endif %}
{% if consoleserverports and perms.dcim.delete_consoleserverport %} {% if perms.dcim.delete_consoleserverport %}
<button type="submit" formaction="{% url 'dcim:consoleserverport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs"> <button type="submit" formaction="{% url 'dcim:consoleserverport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button> </button>
@ -768,8 +663,8 @@
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add console server ports <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add console server ports
</a> </a>
</div> </div>
<div class="clearfix"></div>
{% endif %} {% endif %}
<div class="clearfix"></div>
</div> </div>
</div> </div>
</form> </form>
@ -781,27 +676,9 @@
<div class="panel-heading"> <div class="panel-heading">
<strong>Power Ports</strong> <strong>Power Ports</strong>
</div> </div>
<table class="table table-hover panel-body component-list"> {% include 'responsive_table.html' with table=powerport_table %}
<thead>
<tr>
{% if perms.dcim.change_consoleport or perms.dcim.delete_consoleport %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Type</th>
<th>Draw</th>
<th>Description</th>
<th>Cable</th>
<th colspan="2">Connection</th>
<th></th>
</tr>
</thead>
{% for pp in powerports %}
{% include 'dcim/inc/powerport.html' %}
{% endfor %}
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if powerports and perms.dcim.change_powerport %} {% if perms.dcim.change_powerport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:powerport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:powerport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
</button> </button>
@ -812,7 +689,7 @@
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
</button> </button>
{% endif %} {% endif %}
{% if powerports and perms.dcim.delete_powerport %} {% if perms.dcim.delete_powerport %}
<button type="submit" name="_delete" formaction="{% url 'dcim:powerport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs"> <button type="submit" name="_delete" formaction="{% url 'dcim:powerport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button> </button>
@ -835,29 +712,9 @@
<div class="panel-heading"> <div class="panel-heading">
<strong>Power Outlets</strong> <strong>Power Outlets</strong>
</div> </div>
<table class="table table-hover table-headings panel-body component-list"> {% include 'responsive_table.html' with table=poweroutlet_table %}
<thead>
<tr>
{% if perms.dcim.change_poweroutlet or perms.dcim.delete_poweroutlet %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Type</th>
<th>Input/Leg</th>
<th>Description</th>
<th>Cable</th>
<th colspan="3">Connection</th>
<th></th>
</tr>
</thead>
<tbody>
{% for po in poweroutlets %}
{% include 'dcim/inc/poweroutlet.html' %}
{% endfor %}
</tbody>
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if poweroutlets and perms.dcim.change_powerport %} {% if perms.dcim.change_powerport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:poweroutlet_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:poweroutlet_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
</button> </button>
@ -868,7 +725,7 @@
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
</button> </button>
{% endif %} {% endif %}
{% if poweroutlets and perms.dcim.delete_poweroutlet %} {% if perms.dcim.delete_poweroutlet %}
<button type="submit" formaction="{% url 'dcim:poweroutlet_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs"> <button type="submit" formaction="{% url 'dcim:poweroutlet_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button> </button>
@ -879,8 +736,8 @@
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add power outlets <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add power outlets
</a> </a>
</div> </div>
<div class="clearfix"></div>
{% endif %} {% endif %}
<div class="clearfix"></div>
</div> </div>
</div> </div>
</form> </form>
@ -892,36 +749,14 @@
<div class="panel-heading"> <div class="panel-heading">
<strong>Device Bays</strong> <strong>Device Bays</strong>
</div> </div>
<table class="table table-hover table-headings panel-body component-list"> {% include 'responsive_table.html' with table=devicebay_table %}
<thead>
<tr>
{% if perms.dcim.change_devicebay or perms.dcim.delete_devicebay %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Status</th>
<th>Description</th>
<th colspan="2">Installed Device</th>
<th></th>
</tr>
</thead>
<tbody>
{% for devicebay in devicebays %}
{% include 'dcim/inc/devicebay.html' %}
{% empty %}
<tr>
<td colspan="5" class="text-center text-muted">&mdash; No device bays defined &mdash;</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if devicebays and perms.dcim.change_devicebay %} {% if perms.dcim.change_devicebay %}
<button type="submit" name="_rename" formaction="{% url 'dcim:devicebay_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:devicebay_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
</button> </button>
{% endif %} {% endif %}
{% if devicebays and perms.dcim.delete_devicebay %} {% if perms.dcim.delete_devicebay %}
<button type="submit" formaction="{% url 'dcim:devicebay_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs"> <button type="submit" formaction="{% url 'dcim:devicebay_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete selected <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete selected
</button> </button>
@ -932,8 +767,8 @@
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add device bays <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add device bays
</a> </a>
</div> </div>
<div class="clearfix"></div>
{% endif %} {% endif %}
<div class="clearfix"></div>
</div> </div>
</div> </div>
</form> </form>
@ -945,28 +780,7 @@
<div class="panel-heading"> <div class="panel-heading">
<strong>Inventory Items</strong> <strong>Inventory Items</strong>
</div> </div>
<table class="table table-hover table-condensed panel-body" id="hardware"> {% include 'responsive_table.html' with table=inventoryitem_table %}
<thead>
<tr>
{% if perms.dcim.change_inventoryitem or perms.dcim.delete_inventoryitem %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Manufacturer</th>
<th>Part ID</th>
<th>Serial Number</th>
<th>Asset Tag</th>
<th>Discovered</th>
<th>Description</th>
<th></th>
</tr>
</thead>
<tbody>
{% for item in inventoryitems %}
{% include 'dcim/inc/inventoryitem.html' %}
{% endfor %}
</tbody>
</table>
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if inventoryitems and perms.dcim.change_inventoryitem %} {% if inventoryitems and perms.dcim.change_inventoryitem %}
<button type="submit" name="_rename" formaction="{% url 'dcim:inventoryitem_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs"> <button type="submit" name="_rename" formaction="{% url 'dcim:inventoryitem_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
@ -988,6 +802,7 @@
</a> </a>
</div> </div>
{% endif %} {% endif %}
<div class="clearfix"></div>
</div> </div>
</div> </div>
</form> </form>

View File

@ -1,77 +0,0 @@
<tr class="consoleport{% if cp.cable %} {{ cp.cable.get_status_class }}{% endif %}">
{# Checkbox #}
{% if perms.dcim.change_consoleport or perms.dcim.delete_consoleport %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ cp.pk }}" />
</td>
{% endif %}
{# Name #}
<td>
<i class="fa fa-fw fa-keyboard-o"></i>
<a href="{{ cp.get_absolute_url }}">{{ cp }}</a>
</td>
{# Type #}
<td>
{% if cp.type %}{{ cp.get_type_display }}{% else %}&mdash;{% endif %}
</td>
{# Description #}
<td>
{{ cp.description }}
</td>
{# Cable #}
{% if cp.cable %}
<td>
<a href="{{ cp.cable.get_absolute_url }}">{{ cp.cable }}</a>
<a href="{% url 'dcim:consoleport_trace' pk=cp.pk %}" class="btn btn-primary btn-xs" title="Trace">
<i class="fa fa-share-alt" aria-hidden="true"></i>
</a>
</td>
{% include 'dcim/inc/cabletermination.html' with termination=cp.get_cable_peer %}
{% else %}
<td colspan="3">
<span class="text-muted">Not connected</span>
</td>
{% endif %}
{# Connection #}
{% include 'dcim/inc/endpoint_connection.html' with path=cp.path %}
{# Actions #}
<td class="text-right noprint">
{% if cp.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=cp.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=cp.pk termination_b_type='console-server-port' %}?return_url={{ device.get_absolute_url }}">Console Server Port</a></li>
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=cp.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=cp.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
</ul>
</span>
{% endif %}
{% if perms.dcim.change_consoleport %}
<a href="{% url 'dcim:consoleport_edit' pk=cp.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_consoleport %}
{% if cp.connected_endpoint %}
<button class="btn btn-danger btn-xs" disabled="disabled">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:consoleport_delete' pk=cp.pk %}?return_url={{ device.get_absolute_url }}" title="Delete port" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
{% endif %}
</td>
</tr>

View File

@ -1,79 +0,0 @@
{% load helpers %}
<tr class="consoleserverport{% if csp.cable %} {{ csp.cable.get_status_class }}{% endif %}">
{# Checkbox #}
{% if perms.dcim.change_consoleserverport or perms.dcim.delete_consoleserverport %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ csp.pk }}" />
</td>
{% endif %}
{# Name #}
<td>
<i class="fa fa-fw fa-keyboard-o"></i>
<a href="{{ csp.get_absolute_url }}">{{ csp }}</a>
</td>
{# Type #}
<td>
{% if csp.type %}{{ csp.get_type_display }}{% else %}&mdash;{% endif %}
</td>
{# Description #}
<td>
{{ csp.description|placeholder }}
</td>
{# Cable #}
{% if csp.cable %}
<td>
<a href="{{ csp.cable.get_absolute_url }}">{{ csp.cable }}</a>
<a href="{% url 'dcim:consoleserverport_trace' pk=csp.pk %}" class="btn btn-primary btn-xs" title="Trace">
<i class="fa fa-share-alt" aria-hidden="true"></i>
</a>
</td>
{% include 'dcim/inc/cabletermination.html' with termination=csp.get_cable_peer %}
{% else %}
<td colspan="3">
<span class="text-muted">Not connected</span>
</td>
{% endif %}
{# Connection #}
{% include 'dcim/inc/endpoint_connection.html' with path=csp.path %}
{# Actions #}
<td class="text-right noprint">
{% if csp.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=csp.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=csp.pk termination_b_type='console-port' %}?return_url={{ device.get_absolute_url }}">Console Port</a></li>
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=csp.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=csp.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
</ul>
</span>
{% endif %}
{% if perms.dcim.change_consoleserverport %}
<a href="{% url 'dcim:consoleserverport_edit' pk=csp.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_consoleserverport %}
{% if csp.connected_endpoint %}
<button class="btn btn-danger btn-xs" disabled="disabled">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:consoleserverport_delete' pk=csp.pk %}?return_url={{ device.get_absolute_url }}" title="Delete port" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
{% endif %}
</td>
</tr>

View File

@ -1,71 +0,0 @@
{% load helpers %}
<tr class="devicebay">
{% if perms.dcim.change_devicebay or perms.dcim.delete_devicebay %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ devicebay.pk }}" />
</td>
{% endif %}
{# Name #}
<td>
<i class="fa fa-fw fa-{% if devicebay.installed_device %}dot-circle-o{% else %}circle-o{% endif %}"></i>
<a href="{{ devicebay.get_absolute_url }}">{{ devicebay.name }}</a>
</td>
{# Status #}
<td>
{% if devicebay.installed_device %}
<span class="label label-{{ devicebay.installed_device.get_status_class }}">
{{ devicebay.installed_device.get_status_display }}
</span>
{% else %}
<span class="label label-default">Vacant</span>
{% endif %}
</td>
{# Description #}
<td>
{{ devicebay.description|placeholder }}
</td>
{# Installed device #}
{% if devicebay.installed_device %}
<td>
<a href="{% url 'dcim:device' pk=devicebay.installed_device.pk %}">{{ devicebay.installed_device }}</a>
</td>
<td>
<span>{{ devicebay.installed_device.device_type.display_name }}</span>
</td>
{% else %}
<td colspan="2"></td>
{% endif %}
<td class="text-right noprint">
{% if perms.dcim.change_devicebay %}
{% if devicebay.installed_device %}
<a href="{% url 'dcim:devicebay_depopulate' pk=devicebay.pk %}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-remove" aria-hidden="true" title="Remove device"></i>
</a>
{% else %}
<a href="{% url 'dcim:devicebay_populate' pk=devicebay.pk %}" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-plus" aria-hidden="true" title="Install device"></i>
</a>
{% endif %}
<a href="{% url 'dcim:devicebay_edit' pk=devicebay.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit device bay"></i>
</a>
{% endif %}
{% if perms.dcim.delete_devicebay %}
{% if devicebay.installed_device %}
<button class="btn btn-danger btn-xs" disabled="disabled">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:devicebay_delete' pk=devicebay.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete device bay"></i>
</a>
{% endif %}
{% endif %}
</td>
</tr>

View File

@ -1,72 +0,0 @@
{% load helpers %}
<tr class="frontport{% if frontport.cable %} {{ frontport.cable.get_status_class }}{% endif %}">
{# Checkbox #}
{% if perms.dcim.change_frontport or perms.dcim.delete_frontport %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ frontport.pk }}" />
</td>
{% endif %}
{# Name #}
<td>
<i class="fa fa-fw fa-square{% if not frontport.cable %}-o{% endif %}"></i>
<a href="{{ frontport.get_absolute_url }}">{{ frontport }}</a>
</td>
{# Type #}
<td>{{ frontport.get_type_display }}</td>
{# Rear port #}
<td>{{ frontport.rear_port }}</td>
<td>{{ frontport.rear_port_position }}</td>
{# Description #}
<td>{{ frontport.description|placeholder }}</td>
{# Cable #}
{% if frontport.cable %}
<td>
<a href="{{ frontport.cable.get_absolute_url }}">{{ frontport.cable }}</a>
<a href="{% url 'dcim:frontport_trace' pk=frontport.pk %}" class="btn btn-primary btn-xs" title="Trace">
<i class="fa fa-share-alt" aria-hidden="true"></i>
</a>
</td>
{% include 'dcim/inc/cabletermination.html' with termination=frontport.get_cable_peer %}
{% else %}
<td colspan="3">
<span class="text-muted">Not connected</span>
</td>
{% endif %}
{# Actions #}
<td class="text-right noprint">
{% if frontport.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=frontport.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='console-server-port' %}?return_url={{ device.get_absolute_url }}">Console Server Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='console-port' %}?return_url={{ device.get_absolute_url }}">Console Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %}
{% if perms.dcim.change_frontport %}
<a href="{% url 'dcim:frontport_edit' pk=frontport.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_frontport %}
<a href="{% url 'dcim:frontport_delete' pk=frontport.pk %}?return_url={{ device.get_absolute_url }}" title="Delete port" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
</td>
</tr>

View File

@ -1,200 +0,0 @@
{% load helpers %}
<tr class="interface{% if not iface.enabled %} danger{% elif iface.cable %} {{ iface.cable.get_status_class }}{% elif iface.is_virtual %} warning{% endif %}" id="interface_{{ iface.name }}">
{# Checkbox #}
{% if perms.dcim.change_interface or perms.dcim.delete_interface %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ iface.pk }}" />
</td>
{% endif %}
{# Icon and name #}
<td class="text-nowrap">
<span title="{{ iface.get_type_display }}">
<i class="fa fa-fw fa-{% if iface.mgmt_only %}wrench{% elif iface.is_lag %}align-justify{% elif iface.is_virtual %}circle{% elif iface.is_wireless %}wifi{% else %}exchange{% endif %}"></i>
<a href="{{ iface.get_absolute_url }}">{{ iface }}</a>
</span>
{% if iface.mac_address %}
<br/><small class="text-muted">{{ iface.mac_address }}</small>
{% endif %}
</td>
{# LAG #}
<td>
{% if iface.lag %}
<a href="{{ iface.lag.device.get_absolute_url }}#interface_{{ iface.lag }}" class="label label-primary" title="{{ iface.lag.description }}">{{ iface.lag }}</a>
{% endif %}
</td>
{# Description/tags #}
<td>
{% if iface.description %}
{{ iface.description }}<br/>
{% endif %}
{% for tag in iface.tags.all %}
{% tag tag %}
{% empty %}
{% if not iface.description %}&mdash;{% endif %}
{% endfor %}
</td>
{# MTU #}
<td>{{ iface.mtu|default:"&mdash;" }}</td>
{# 802.1Q mode #}
<td>{{ iface.get_mode_display|default:"&mdash;" }}</td>
{# Cable #}
{% if iface.cable %}
<td>
<a href="{{ iface.cable.get_absolute_url }}">{{ iface.cable }}</a>
<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>
</a>
</td>
{% include 'dcim/inc/cabletermination.html' with termination=iface.get_cable_peer %}
{% else %}
<td colspan="3">
<span class="text-muted">Not connected</span>
</td>
{% endif %}
{# Connection or type #}
{% if iface.is_lag %}
<td colspan="2" class="text-muted">
LAG interface<br />
<small class="text-muted">
{% for member in iface.member_interfaces.all %}
<a href="{{ member.get_absolute_url }}">{{ member }}</a>{% if not forloop.last %}, {% endif %}
{% empty %}
No members
{% endfor %}
</small>
</td>
{% elif iface.is_virtual %}
<td colspan="2" class="text-muted">Virtual interface</td>
{% elif iface.is_wireless %}
<td colspan="2" class="text-muted">Wireless interface</td>
{% else %}
{% include 'dcim/inc/endpoint_connection.html' with path=iface.path %}
{% endif %}
{# Buttons #}
<td class="text-right text-nowrap noprint">
{% if perms.ipam.add_ipaddress %}
<a href="{% url 'ipam:ipaddress_add' %}?interface={{ iface.pk }}&return_url={{ device.get_absolute_url }}" class="btn btn-xs btn-success" title="Add IP address">
<i class="glyphicon glyphicon-plus" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.change_interface %}
{% if iface.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=iface.cable %}
{% elif iface.is_connectable and perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %}
<a href="{% url 'dcim:interface_edit' pk=iface.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-info btn-xs" title="Edit interface">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_interface %}
{% if iface.connection or iface.circuit_termination %}
<button class="btn btn-danger btn-xs" disabled="disabled">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:interface_delete' pk=iface.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs" title="Delete interface">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
{% endif %}
</td>
</tr>
{% with ipaddresses=iface.ip_addresses.all %}
{% if ipaddresses %}
<tr class="ipaddresses">
{# Placeholder #}
{% if perms.dcim.change_interface or perms.dcim.delete_interface %}
<td></td>
{% endif %}
{# IP addresses table #}
<td colspan="9" style="padding: 0">
<table class="table table-condensed interface-ips">
<thead>
<tr class="text-muted">
<th class="col-md-3">IP Address</th>
<th class="col-md-2">Status/Role</th>
<th class="col-md-3">VRF</th>
<th class="col-md-3">Description</th>
<th class="col-md-1"></th>
</tr>
</thead>
{% for ip in iface.ip_addresses.all %}
<tr>
{# IP address #}
<td>
<a href="{% url 'ipam:ipaddress' pk=ip.pk %}">{{ ip }}</a>
</td>
{# Primary/status/role #}
<td>
{% if device.primary_ip4 == ip or device.primary_ip6 == ip %}
<span class="label label-success">Primary</span>
{% endif %}
<span class="label label-{{ ip.get_status_class }}">{{ ip.get_status_display }}</span>
{% if ip.role %}
<span class="label label-{{ ip.get_role_class }}">{{ ip.get_role_display }}</span>
{% endif %}
</td>
{# VRF #}
<td>
{% if ip.vrf %}
<a href="{% url 'ipam:vrf' pk=ip.vrf.pk %}" title="{{ ip.vrf.rd }}">{{ ip.vrf.name }}</a>
{% else %}
<span class="text-muted">Global</span>
{% endif %}
</td>
{# Description #}
<td>
{% if ip.description %}
{{ ip.description }}
{% else %}
<span class="text-muted">&mdash;</span>
{% endif %}
</td>
{# Buttons #}
<td class="text-right text-nowrap noprint">
{% if perms.ipam.change_ipaddress %}
<a href="{% url 'ipam:ipaddress_edit' pk=ip.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit IP address"></i>
</a>
{% endif %}
{% if perms.ipam.delete_ipaddress %}
<a href="{% url 'ipam:ipaddress_delete' pk=ip.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete IP address"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
{% endif %}
{% endwith %}

View File

@ -1,40 +0,0 @@
{% load helpers %}
<tr>
{# Checkbox #}
{% if perms.dcim.change_inventoryitem or perms.dcim.delete_inventoryitem %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ item.pk }}" />
</td>
{% endif %}
<td style="padding-left: {{ item.level }}0px">
<a href="{{ item.get_absolute_url }}">{{ item }}</a>
</td>
<td>
{% if item.manufacturer %}
<a href="{{ item.manufacturer.get_absolute_url }}">{{ item.manufacturer }}</a>
{% else %}
<span class="text-muted">&mdash;</span>
{% endif %}
</td>
<td>{{ item.part_id|placeholder }}</td>
<td>{{ item.serial|placeholder }}</td>
<td>{{ item.asset_tag|placeholder }}</td>
<td>
{% if item.discovered %}
<span class="text-success"><i class="fa fa-check"></i></span>
{% else %}
<span class="text-muted">&mdash;</span>
{% endif %}
</td>
<td>{{ item.description|placeholder }}</td>
<td class="text-right noprint">
{% if perms.dcim.change_inventoryitem %}
<a href="{% url 'dcim:inventoryitem_edit' pk=item.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-xs btn-warning"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a>
{% endif %}
{% if perms.dcim.delete_inventoryitem %}
<a href="{% url 'dcim:inventoryitem_delete' pk=item.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></a>
{% endif %}
</td>
</tr>

View File

@ -1,93 +0,0 @@
{% load helpers %}
<tr class="poweroutlet{% if po.cable %} {{ po.cable.get_status_class }}{% endif %}">
{# Checkbox #}
{% if perms.dcim.change_poweroutlet or perms.dcim.delete_poweroutlet %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ po.pk }}" />
</td>
{% endif %}
{# Name #}
<td>
<i class="fa fa-fw fa-bolt"></i>
<a href="{{ po.get_absolute_url }}">{{ po }}</a>
</td>
{# Type #}
<td>
{{ po.get_type_display }}
</td>
{# Input/leg #}
<td>
{% if po.power_port %}
{{ po.power_port }}{% if po.feed_leg %} / {{ po.get_feed_leg_display }}{% endif %}
{% elif po.feed_leg %}
{{ po.get_feed_leg_display }}
{% else %}
<span class="text-warning">None</span>
{% endif %}
</td>
{# Description #}
<td>
{{ po.description|placeholder }}
</td>
{# Cable #}
{% if po.cable %}
<td>
<a href="{{ po.cable.get_absolute_url }}">{{ po.cable }}</a>
<a href="{% url 'dcim:poweroutlet_trace' pk=po.pk %}" class="btn btn-primary btn-xs" title="Trace">
<i class="fa fa-share-alt" aria-hidden="true"></i>
</a>
</td>
{% else %}
<td><span class="text-muted">Not connected</span></td>
{% endif %}
{# Connection #}
{% with path=po.path %}
{% include 'dcim/inc/endpoint_connection.html' %}
<td>
{% if paths|length == 1 %}
{% with pp=paths.0.destination %}
{% if pp.allocated_draw %}
{{ pp.allocated_draw }}W{% if pp.maximum_draw %} ({{ pp.maximum_draw }}W max){% endif %}
{% elif pp.maximum_draw %}
{{ pp.maximum_draw }}W
{% endif %}
{% endwith %}
{% endif %}
</td>
{% endwith %}
{# Actions #}
<td class="text-right noprint">
{% if po.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=po.cable %}
{% elif perms.dcim.add_cable %}
<a href="{% url 'dcim:poweroutlet_connect' termination_a_id=po.pk termination_b_type='power-port' %}?return_url={{ device.get_absolute_url }}" title="Connect" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.change_poweroutlet %}
<a href="{% url 'dcim:poweroutlet_edit' pk=po.pk %}?return_url={{ device.get_absolute_url }}" title="Edit outlet" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_poweroutlet %}
{% if po.connected_endpoint %}
<button class="btn btn-danger btn-xs" disabled="disabled">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:poweroutlet_delete' pk=po.pk %}?return_url={{ device.get_absolute_url }}" title="Delete outlet" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
{% endif %}
</td>
</tr>

View File

@ -1,82 +0,0 @@
<tr class="powerport{% if pp.cable %} {{ pp.cable.get_status_class }}{% endif %}">
{# Checkbox #}
{% if perms.dcim.change_powerport or perms.dcim.delete_powerport %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ pp.pk }}" />
</td>
{% endif %}
{# Name #}
<td>
<i class="fa fa-fw fa-bolt"></i>
<a href="{{ pp.get_absolute_url }}">{{ pp }}</a>
</td>
{# Type #}
<td>
{{ pp.get_type_display }}
</td>
{# Current draw #}
<td>
{% if pp.allocated_draw %}
{{ pp.allocated_draw }}W{% if pp.maximum_draw %} ({{ pp.maximum_draw }}W max){% endif %}
{% elif pp.maximum_draw %}
{{ pp.maximum_draw }}W
{% endif %}
</td>
{# Description #}
<td>
{{ pp.description }}
</td>
{# Cable #}
{% if pp.cable %}
<td>
<a href="{{ pp.cable.get_absolute_url }}">{{ pp.cable }}</a>
<a href="{% url 'dcim:powerport_trace' pk=pp.pk %}" class="btn btn-primary btn-xs" title="Trace">
<i class="fa fa-share-alt" aria-hidden="true"></i>
</a>
</td>
{% else %}
<td><span class="text-muted">Not connected</span></td>
{% endif %}
{# Connection #}
{% include 'dcim/inc/endpoint_connection.html' with path=pp.path %}
{# Actions #}
<td class="text-right noprint">
{% if pp.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=pp.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:powerport_connect' termination_a_id=pp.pk termination_b_type='power-outlet' %}?return_url={{ device.get_absolute_url }}">Power Outlet</a></li>
<li><a href="{% url 'dcim:powerport_connect' termination_a_id=pp.pk termination_b_type='power-feed' %}?return_url={{ device.get_absolute_url }}">Power Feed</a></li>
</ul>
</span>
{% endif %}
{% if perms.dcim.change_powerport %}
<a href="{% url 'dcim:powerport_edit' pk=pp.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_powerport %}
{% if pp.connected_endpoint %}
<button class="btn btn-danger btn-xs" disabled="disabled">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:powerport_delete' pk=pp.pk %}?return_url={{ device.get_absolute_url }}" title="Delete port" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
{% endif %}
</td>
</tr>

View File

@ -1,69 +0,0 @@
{% load helpers %}
<tr class="rearport{% if rearport.cable %} {{ rearport.cable.get_status_class }}{% endif %}">
{# Checkbox #}
{% if perms.dcim.change_rearport or perms.dcim.delete_rearport %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ rearport.pk }}" />
</td>
{% endif %}
{# Name #}
<td>
<i class="fa fa-fw fa-square{% if not rearport.cable %}-o{% endif %}"></i>
<a href="{{ rearport.get_absolute_url }}">{{ rearport }}</a>
</td>
{# Type #}
<td>{{ rearport.get_type_display }}</td>
{# Positions #}
<td>{{ rearport.positions }}</td>
{# Description #}
<td>{{ rearport.description|placeholder }}</td>
{# Cable #}
{% if rearport.cable %}
<td>
<a href="{{ rearport.cable.get_absolute_url }}">{{ rearport.cable }}</a>
<a href="{% url 'dcim:rearport_trace' pk=rearport.pk %}" class="btn btn-primary btn-xs" title="Trace">
<i class="fa fa-share-alt" aria-hidden="true"></i>
</a>
</td>
{% include 'dcim/inc/cabletermination.html' with termination=rearport.get_cable_peer %}
{% else %}
<td colspan="3">
<span class="text-muted">Not connected</span>
</td>
{% endif %}
{# Actions #}
<td class="text-right noprint">
{% if rearport.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=rearport.cable %}
{% elif perms.dcim.add_cable %}
<span class="dropdown">
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %}
{% if perms.dcim.change_rearport %}
<a href="{% url 'dcim:rearport_edit' pk=rearport.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_rearport %}
<a href="{% url 'dcim:rearport_delete' pk=rearport.pk %}?return_url={{ device.get_absolute_url }}" title="Delete port" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
</td>
</tr>

View File

@ -1,136 +0,0 @@
{% load helpers %}
<tr class="interface{% if not iface.enabled %} danger{% endif %}" id="interface_{{ iface.name }}">
{# Checkbox #}
{% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ iface.pk }}" />
</td>
{% endif %}
{# Name #}
<td>
<a href="{{ iface.get_absolute_url }}">{{ iface }}</a>
</td>
{# MAC address #}
<td class="text-monospace">
{{ iface.mac_address|default:"&mdash;" }}
</td>
{# MTU #}
<td>{{ iface.mtu|default:"&mdash;" }}</td>
{# 802.1Q mode #}
<td>{{ iface.get_mode_display|default:"&mdash;" }}</td>
{# Description/tags #}
<td>
{% if iface.description %}
{{ iface.description }}<br/>
{% endif %}
{% for tag in iface.tags.all %}
{% tag tag %}
{% empty %}
{% if not iface.description %}&mdash;{% endif %}
{% endfor %}
</td>
{# Buttons #}
<td class="text-right text-nowrap noprint">
{% if perms.ipam.add_ipaddress %}
<a href="{% url 'ipam:ipaddress_add' %}?vminterface={{ iface.pk }}&return_url={{ virtualmachine.get_absolute_url }}" class="btn btn-xs btn-success" title="Add IP address">
<i class="glyphicon glyphicon-plus" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.virtualization.change_vminterface %}
<a href="{% url 'virtualization:vminterface_edit' pk=iface.pk %}?return_url={{ virtualmachine.get_absolute_url }}" class="btn btn-info btn-xs" title="Edit interface">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.virtualization.delete_vminterface %}
<a href="{% url 'virtualization:vminterface_delete' pk=iface.pk %}?return_url={{ virtualmachine.get_absolute_url }}" class="btn btn-danger btn-xs" title="Delete interface">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
</td>
</tr>
{% with ipaddresses=iface.ip_addresses.all %}
{% if ipaddresses %}
<tr class="ipaddresses">
{# Placeholder #}
{% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %}
<td></td>
{% endif %}
{# IP addresses table #}
<td colspan="9" style="padding: 0">
<table class="table table-condensed interface-ips">
<thead>
<tr class="text-muted">
<th class="col-md-3">IP Address</th>
<th class="col-md-2">Status/Role</th>
<th class="col-md-3">VRF</th>
<th class="col-md-3">Description</th>
<th class="col-md-1"></th>
</tr>
</thead>
{% for ip in iface.ip_addresses.all %}
<tr>
{# IP address #}
<td>
<a href="{% url 'ipam:ipaddress' pk=ip.pk %}">{{ ip }}</a>
</td>
{# Primary/status/role #}
<td>
{% if virtualmachine.primary_ip4 == ip or virtualmachine.primary_ip6 == ip %}
<span class="label label-success">Primary</span>
{% endif %}
<span class="label label-{{ ip.get_status_class }}">{{ ip.get_status_display }}</span>
{% if ip.role %}
<span class="label label-{{ ip.get_role_class }}">{{ ip.get_role_display }}</span>
{% endif %}
</td>
{# VRF #}
<td>
{% if ip.vrf %}
<a href="{% url 'ipam:vrf' pk=ip.vrf.pk %}" title="{{ ip.vrf.rd }}">{{ ip.vrf.name }}</a>
{% else %}
<span class="text-muted">Global</span>
{% endif %}
</td>
{# Description #}
<td>
{% if ip.description %}
{{ ip.description }}
{% else %}
<span class="text-muted">&mdash;</span>
{% endif %}
</td>
{# Buttons #}
<td class="text-right text-nowrap noprint">
{% if perms.ipam.change_ipaddress %}
<a href="{% url 'ipam:ipaddress_edit' pk=ip.pk %}?return_url={{ virtualmachine.get_absolute_url }}" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit IP address"></i>
</a>
{% endif %}
{% if perms.ipam.delete_ipaddress %}
<a href="{% url 'ipam:ipaddress_delete' pk=ip.pk %}?return_url={{ virtualmachine.get_absolute_url }}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete IP address"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
{% endif %}
{% endwith %}

View File

@ -276,39 +276,11 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<strong>Interfaces</strong> <strong>Interfaces</strong>
<div class="pull-right">
<button class="btn btn-default btn-xs toggle-ips" selected="selected">
<span class="glyphicon glyphicon-check" aria-hidden="true"></span> Show IPs
</button>
</div>
<div class="col-md-2 pull-right noprint"> <div class="col-md-2 pull-right noprint">
<input class="form-control interface-filter" type="text" placeholder="Filter" title="RegEx-enabled" style="height: 23px" /> <input class="form-control interface-filter" type="text" placeholder="Filter" title="RegEx-enabled" style="height: 23px" />
</div> </div>
</div> </div>
<table id="interfaces_table" class="table table-hover table-headings panel-body component-list"> {% include 'responsive_table.html' with table=vminterface_table %}
<thead>
<tr>
{% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %}
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>MAC Address</th>
<th>MTU</th>
<th>Mode</th>
<th>Description</th>
<th></th>
</tr>
</thead>
<tbody>
{% for iface in interfaces %}
{% include 'virtualization/inc/vminterface.html' %}
{% empty %}
<tr>
<td colspan="8" class="text-center text-muted">&mdash; No interfaces defined &mdash;</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if perms.virtualization.add_vminterface or perms.virtualization.delete_vminterface %} {% if perms.virtualization.add_vminterface or perms.virtualization.delete_vminterface %}
<div class="panel-footer noprint"> <div class="panel-footer noprint">
{% if interfaces and perms.virtualization.change_vminterface %} {% if interfaces and perms.virtualization.change_vminterface %}

View File

@ -142,7 +142,7 @@ class ButtonsColumn(tables.TemplateColumn):
</a> </a>
{{% endif %}} {{% endif %}}
{{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}} {{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}}
<a href="{{% url '{app_label}:{model_name}_edit' {pk_field}=record.{pk_field} %}}?return_url={{{{ request.path }}}}" class="btn btn-xs btn-warning" title="Edit"> <a href="{{% url '{app_label}:{model_name}_edit' {pk_field}=record.{pk_field} %}}?return_url={{{{ request.path }}}}" class="btn btn-xs btn-info" title="Edit">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</a> </a>
{{% endif %}} {{% endif %}}

View File

@ -7,6 +7,24 @@ from utilities.tables import (
) )
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
__all__ = (
'ClusterTable',
'ClusterGroupTable',
'ClusterTypeTable',
'VirtualMachineDetailTable',
'VirtualMachineTable',
'VirtualMachineVMInterfaceTable',
'VMInterfaceTable',
)
VMINTERFACE_BUTTONS = """
{% if perms.ipam.add_ipaddress %}
<a href="{% url 'ipam:ipaddress_add' %}?vminterface={{ record.pk }}&return_url={{ virtualmachine.get_absolute_url }}" class="btn btn-xs btn-success" title="Add IP address">
<i class="glyphicon glyphicon-plus" aria-hidden="true"></i>
</a>
{% endif %}
"""
# #
# Cluster types # Cluster types
@ -147,3 +165,19 @@ class VMInterfaceTable(BaseInterfaceTable):
'untagged_vlan', 'tagged_vlans', 'untagged_vlan', 'tagged_vlans',
) )
default_columns = ('pk', 'virtual_machine', 'name', 'enabled', 'description') default_columns = ('pk', 'virtual_machine', 'name', 'enabled', 'description')
class VirtualMachineVMInterfaceTable(VMInterfaceTable):
actions = ButtonsColumn(
model=VMInterface,
buttons=('edit', 'delete'),
prepend_template=VMINTERFACE_BUTTONS
)
class Meta(BaseTable.Meta):
model = VMInterface
fields = (
'pk', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'tags', 'ip_addresses',
'untagged_vlan', 'tagged_vlans', 'actions',
)
default_columns = ('pk', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'actions')

View File

@ -244,11 +244,15 @@ class VirtualMachineView(ObjectView):
virtualmachine = get_object_or_404(self.queryset, pk=pk) virtualmachine = get_object_or_404(self.queryset, pk=pk)
# Interfaces # Interfaces
interfaces = VMInterface.objects.restrict(request.user, 'view').filter( vminterfaces = VMInterface.objects.restrict(request.user, 'view').filter(
virtual_machine=virtualmachine virtual_machine=virtualmachine
).prefetch_related( ).prefetch_related(
Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)) Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user))
) )
vminterface_table = tables.VirtualMachineVMInterfaceTable(vminterfaces, orderable=False)
if request.user.has_perm('virtualization.change_vminterface') or \
request.user.has_perm('virtualization.delete_vminterface'):
vminterface_table.columns.show('pk')
# Services # Services
services = Service.objects.restrict(request.user, 'view').filter( services = Service.objects.restrict(request.user, 'view').filter(
@ -262,7 +266,7 @@ class VirtualMachineView(ObjectView):
return render(request, 'virtualization/virtualmachine.html', { return render(request, 'virtualization/virtualmachine.html', {
'virtualmachine': virtualmachine, 'virtualmachine': virtualmachine,
'interfaces': interfaces, 'vminterface_table': vminterface_table,
'services': services, 'services': services,
'secrets': secrets, 'secrets': secrets,
}) })