Enabled bulk deletion of device bays, interfaces, console server ports, and power outlets from devices

This commit is contained in:
Jeremy Stretch 2016-07-26 10:14:51 -04:00
parent 88b022d742
commit 4be5c33905
11 changed files with 178 additions and 32 deletions

View File

@ -103,6 +103,7 @@ urlpatterns = [
# Console ports # Console ports
url(r'^devices/(?P<pk>\d+)/console-ports/add/$', views.consoleport_add, name='consoleport_add'), url(r'^devices/(?P<pk>\d+)/console-ports/add/$', views.consoleport_add, name='consoleport_add'),
url(r'^devices/(?P<pk>\d+)/console-ports/delete/$', views.ConsolePortBulkDeleteView.as_view(), name='consoleport_bulk_delete'),
url(r'^console-ports/(?P<pk>\d+)/connect/$', views.consoleport_connect, name='consoleport_connect'), url(r'^console-ports/(?P<pk>\d+)/connect/$', views.consoleport_connect, name='consoleport_connect'),
url(r'^console-ports/(?P<pk>\d+)/disconnect/$', views.consoleport_disconnect, name='consoleport_disconnect'), url(r'^console-ports/(?P<pk>\d+)/disconnect/$', views.consoleport_disconnect, name='consoleport_disconnect'),
url(r'^console-ports/(?P<pk>\d+)/edit/$', views.consoleport_edit, name='consoleport_edit'), url(r'^console-ports/(?P<pk>\d+)/edit/$', views.consoleport_edit, name='consoleport_edit'),
@ -110,6 +111,7 @@ urlpatterns = [
# Console server ports # Console server ports
url(r'^devices/(?P<pk>\d+)/console-server-ports/add/$', views.consoleserverport_add, name='consoleserverport_add'), url(r'^devices/(?P<pk>\d+)/console-server-ports/add/$', views.consoleserverport_add, name='consoleserverport_add'),
url(r'^devices/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'),
url(r'^console-server-ports/(?P<pk>\d+)/connect/$', views.consoleserverport_connect, name='consoleserverport_connect'), url(r'^console-server-ports/(?P<pk>\d+)/connect/$', views.consoleserverport_connect, name='consoleserverport_connect'),
url(r'^console-server-ports/(?P<pk>\d+)/disconnect/$', views.consoleserverport_disconnect, name='consoleserverport_disconnect'), url(r'^console-server-ports/(?P<pk>\d+)/disconnect/$', views.consoleserverport_disconnect, name='consoleserverport_disconnect'),
url(r'^console-server-ports/(?P<pk>\d+)/edit/$', views.consoleserverport_edit, name='consoleserverport_edit'), url(r'^console-server-ports/(?P<pk>\d+)/edit/$', views.consoleserverport_edit, name='consoleserverport_edit'),
@ -117,6 +119,7 @@ urlpatterns = [
# Power ports # Power ports
url(r'^devices/(?P<pk>\d+)/power-ports/add/$', views.powerport_add, name='powerport_add'), url(r'^devices/(?P<pk>\d+)/power-ports/add/$', views.powerport_add, name='powerport_add'),
url(r'^devices/(?P<pk>\d+)/power-ports/delete/$', views.PowerPortBulkDeleteView.as_view(), name='powerport_bulk_delete'),
url(r'^power-ports/(?P<pk>\d+)/connect/$', views.powerport_connect, name='powerport_connect'), url(r'^power-ports/(?P<pk>\d+)/connect/$', views.powerport_connect, name='powerport_connect'),
url(r'^power-ports/(?P<pk>\d+)/disconnect/$', views.powerport_disconnect, name='powerport_disconnect'), url(r'^power-ports/(?P<pk>\d+)/disconnect/$', views.powerport_disconnect, name='powerport_disconnect'),
url(r'^power-ports/(?P<pk>\d+)/edit/$', views.powerport_edit, name='powerport_edit'), url(r'^power-ports/(?P<pk>\d+)/edit/$', views.powerport_edit, name='powerport_edit'),
@ -124,6 +127,7 @@ urlpatterns = [
# Power outlets # Power outlets
url(r'^devices/(?P<pk>\d+)/power-outlets/add/$', views.poweroutlet_add, name='poweroutlet_add'), url(r'^devices/(?P<pk>\d+)/power-outlets/add/$', views.poweroutlet_add, name='poweroutlet_add'),
url(r'^devices/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'),
url(r'^power-outlets/(?P<pk>\d+)/connect/$', views.poweroutlet_connect, name='poweroutlet_connect'), url(r'^power-outlets/(?P<pk>\d+)/connect/$', views.poweroutlet_connect, name='poweroutlet_connect'),
url(r'^power-outlets/(?P<pk>\d+)/disconnect/$', views.poweroutlet_disconnect, name='poweroutlet_disconnect'), url(r'^power-outlets/(?P<pk>\d+)/disconnect/$', views.poweroutlet_disconnect, name='poweroutlet_disconnect'),
url(r'^power-outlets/(?P<pk>\d+)/edit/$', views.poweroutlet_edit, name='poweroutlet_edit'), url(r'^power-outlets/(?P<pk>\d+)/edit/$', views.poweroutlet_edit, name='poweroutlet_edit'),
@ -131,6 +135,7 @@ urlpatterns = [
# Device bays # Device bays
url(r'^devices/(?P<pk>\d+)/bays/add/$', views.devicebay_add, name='devicebay_add'), url(r'^devices/(?P<pk>\d+)/bays/add/$', views.devicebay_add, name='devicebay_add'),
url(r'^devices/(?P<pk>\d+)/bays/delete/$', views.DeviceBayBulkDeleteView.as_view(), name='devicebay_bulk_delete'),
url(r'^device-bays/(?P<pk>\d+)/edit/$', views.devicebay_edit, name='devicebay_edit'), url(r'^device-bays/(?P<pk>\d+)/edit/$', views.devicebay_edit, name='devicebay_edit'),
url(r'^device-bays/(?P<pk>\d+)/delete/$', views.devicebay_delete, name='devicebay_delete'), url(r'^device-bays/(?P<pk>\d+)/delete/$', views.devicebay_delete, name='devicebay_delete'),
url(r'^device-bays/(?P<pk>\d+)/populate/$', views.devicebay_populate, name='devicebay_populate'), url(r'^device-bays/(?P<pk>\d+)/populate/$', views.devicebay_populate, name='devicebay_populate'),
@ -145,8 +150,9 @@ urlpatterns = [
url(r'^interface-connections/import/$', views.InterfaceConnectionsBulkImportView.as_view(), name='interface_connections_import'), url(r'^interface-connections/import/$', views.InterfaceConnectionsBulkImportView.as_view(), name='interface_connections_import'),
# Interfaces # Interfaces
url(r'^devices/interfaces/add/$', views.InterfaceBulkAddView.as_view(), name='interface_bulk_add'), url(r'^devices/interfaces/add/$', views.InterfaceBulkAddView.as_view(), name='interface_add_multi'),
url(r'^devices/(?P<pk>\d+)/interfaces/add/$', views.interface_add, name='interface_add'), url(r'^devices/(?P<pk>\d+)/interfaces/add/$', views.interface_add, name='interface_add'),
url(r'^devices/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
url(r'^devices/(?P<pk>\d+)/interface-connections/add/$', views.interfaceconnection_add, name='interfaceconnection_add'), url(r'^devices/(?P<pk>\d+)/interface-connections/add/$', views.interfaceconnection_add, name='interfaceconnection_add'),
url(r'^interface-connections/(?P<pk>\d+)/delete/$', views.interfaceconnection_delete, name='interfaceconnection_delete'), url(r'^interface-connections/(?P<pk>\d+)/delete/$', views.interfaceconnection_delete, name='interfaceconnection_delete'),
url(r'^interfaces/(?P<pk>\d+)/edit/$', views.interface_edit, name='interface_edit'), url(r'^interfaces/(?P<pk>\d+)/edit/$', views.interface_edit, name='interface_edit'),

View File

@ -813,6 +813,12 @@ def consoleport_delete(request, pk):
}) })
class ConsolePortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_consoleport'
cls = ConsolePort
parent_cls = Device
class ConsoleConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView): class ConsoleConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.change_consoleport' permission_required = 'dcim.change_consoleport'
form = forms.ConsoleConnectionImportForm form = forms.ConsoleConnectionImportForm
@ -968,6 +974,12 @@ def consoleserverport_delete(request, pk):
}) })
class ConsoleServerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_consoleserverport'
cls = ConsoleServerPort
parent_cls = Device
# #
# Power ports # Power ports
# #
@ -1113,6 +1125,12 @@ def powerport_delete(request, pk):
}) })
class PowerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_powerport'
cls = PowerPort
parent_cls = Device
class PowerConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView): class PowerConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.change_powerport' permission_required = 'dcim.change_powerport'
form = forms.PowerConnectionImportForm form = forms.PowerConnectionImportForm
@ -1266,6 +1284,12 @@ def poweroutlet_delete(request, pk):
}) })
class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_poweroutlet'
cls = PowerOutlet
parent_cls = Device
# #
# Interfaces # Interfaces
# #
@ -1360,7 +1384,7 @@ class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView):
permission_required = 'dcim.add_interface' permission_required = 'dcim.add_interface'
cls = Device cls = Device
form = forms.InterfaceBulkCreateForm form = forms.InterfaceBulkCreateForm
template_name = 'dcim/interface_bulk_add.html' template_name = 'dcim/interface_add_multi.html'
default_redirect_url = 'dcim:device_list' default_redirect_url = 'dcim:device_list'
def update_objects(self, pk_list, form): def update_objects(self, pk_list, form):
@ -1389,6 +1413,12 @@ class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView):
len(selected_devices))) len(selected_devices)))
class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_interface'
cls = Interface
parent_cls = Device
# #
# Device bays # Device bays
# #
@ -1526,6 +1556,12 @@ def devicebay_depopulate(request, pk):
}) })
class DeviceBayBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_devicebay'
cls = DeviceBay
parent_cls = Device
# #
# Interface connections # Interface connections
# #

View File

@ -289,97 +289,171 @@
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
{% if device_bays or device.device_type.is_parent_device %} {% if device_bays or device.device_type.is_parent_device %}
{% if perms.dcim.delete_devicebay %}
<form method="post" action="{% url 'dcim:devicebay_bulk_delete' pk=device.pk %}">
{% csrf_token %}
{% endif %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<strong>Device Bays</strong> <strong>Device Bays</strong>
</div> </div>
<table class="table table-hover panel-body"> <table class="table table-hover panel-body">
{% for devicebay in device_bays %} {% for devicebay in device_bays %}
{% include 'dcim/inc/_devicebay.html' %} {% include 'dcim/inc/_devicebay.html' with selectable=True %}
{% empty %} {% empty %}
<tr> <tr>
<td colspan="4">No device bays defined</td> <td colspan="4">No device bays defined</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% if perms.dcim.add_devicebay %} {% if perms.dcim.add_devicebay or perms.dcim.delete_devicebay %}
<div class="panel-footer text-right"> <div class="panel-footer">
<a href="{% url 'dcim:devicebay_add' pk=device.pk %}" class="btn btn-primary btn-xs"> <div class="row">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <div class="col-md-6">
Add device bays {% if device_bays and perms.dcim.delete_devicebay %}
</a> <button type="submit" class="btn btn-xs btn-danger">
</div> <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete Selected
</button>
{% endif %}
</div>
<div class="col-md-6 text-right">
{% if perms.dcim.add_devicebay %}
<a href="{% url 'dcim:devicebay_add' pk=device.pk %}" class="btn btn-primary btn-xs">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
Add device bay
</a>
{% endif %}
</div>
</div>
</div>
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
{% if interfaces or device.device_type.is_network_device %} {% if interfaces or device.device_type.is_network_device %}
{% if perms.dcim.delete_interface %}
<form method="post" action="{% url 'dcim:interface_bulk_delete' pk=device.pk %}">
{% csrf_token %}
{% endif %}
<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> </div>
<table class="table table-hover panel-body"> <table class="table table-hover panel-body">
{% for iface in interfaces %} {% for iface in interfaces %}
{% include 'dcim/inc/_interface.html' %} {% include 'dcim/inc/_interface.html' with selectable=True %}
{% empty %} {% empty %}
<tr> <tr>
<td colspan="4">No interfaces defined</td> <td colspan="4">No interfaces defined</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% if perms.dcim.add_interface %} {% if perms.dcim.add_interface or perms.dcim.delete_interface %}
<div class="panel-footer text-right"> <div class="panel-footer">
<a href="{% url 'dcim:interface_add' pk=device.pk %}" class="btn btn-primary btn-xs"> <div class="row">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <div class="col-md-6">
Add interface {% if interfaces and perms.dcim.delete_interface %}
</a> <button type="submit" class="btn btn-xs btn-danger">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete Selected
</button>
{% endif %}
</div>
<div class="col-md-6 text-right">
{% if perms.dcim.add_interface %}
<a href="{% url 'dcim:interface_add' pk=device.pk %}" class="btn btn-primary btn-xs">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
Add interface
</a>
{% endif %}
</div>
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
{% if perms.dcim.delete_interface %}
</form>
{% endif %}
{% endif %} {% endif %}
{% if cs_ports or device.device_type.is_console_server %} {% if cs_ports or device.device_type.is_console_server %}
{% if perms.dcim.delete_consoleserverport %}
<form method="post" action="{% url 'dcim:consoleserverport_bulk_delete' pk=device.pk %}">
{% csrf_token %}
{% endif %}
<div class="panel panel-default"> <div class="panel panel-default">
<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 panel-body"> <table class="table table-hover panel-body">
{% for csp in cs_ports %} {% for csp in cs_ports %}
{% include 'dcim/inc/_consoleserverport.html' %} {% include 'dcim/inc/_consoleserverport.html' with selectable=True %}
{% empty %} {% empty %}
<tr> <tr>
<td colspan="4">No console server ports defined</td> <td colspan="4">No console server ports defined</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% if perms.dcim.add_consoleserverport %} {% if perms.dcim.add_consoleserverport or perms.dcim.delete_consoleserverport %}
<div class="panel-footer text-right"> <div class="panel-footer">
<a href="{% url 'dcim:consoleserverport_add' pk=device.pk %}" class="btn btn-primary btn-xs"> <div class="row">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <div class="col-md-6">
Add console server ports {% if cs_ports and perms.dcim.delete_consoleserverport %}
</a> <button type="submit" class="btn btn-xs btn-danger">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete Selected
</button>
{% endif %}
</div>
<div class="col-md-6 text-right">
{% if perms.dcim.add_consoleserverport %}
<a href="{% url 'dcim:consoleserverport_add' pk=device.pk %}" class="btn btn-primary btn-xs">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
Add console server ports
</a>
{% endif %}
</div>
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
{% if perms.dcim.delete_consoleserverport %}
</form>
{% endif %}
{% endif %} {% endif %}
{% if power_outlets or device.device_type.is_pdu %} {% if power_outlets or device.device_type.is_pdu %}
{% if perms.dcim.delete_poweroutlet %}
<form method="post" action="{% url 'dcim:poweroutlet_bulk_delete' pk=device.pk %}">
{% csrf_token %}
{% endif %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<strong>Power Outlets</strong> <strong>Power Outlets</strong>
</div> </div>
<table class="table table-hover panel-body"> <table class="table table-hover panel-body">
{% for po in power_outlets %} {% for po in power_outlets %}
{% include 'dcim/inc/_poweroutlet.html' %} {% include 'dcim/inc/_poweroutlet.html' with selectable=True %}
{% empty %} {% empty %}
<tr> <tr>
<td colspan="4">No power outlets defined</td> <td colspan="4">No power outlets defined</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% if perms.dcim.add_poweroutlet %} {% if perms.dcim.add_poweroutlet or perms.dcim.delete_poweroutlet %}
<div class="panel-footer text-right"> <div class="panel-footer">
<a href="{% url 'dcim:poweroutlet_add' pk=device.pk %}" class="btn btn-primary btn-xs"> <div class="row">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <div class="col-md-6">
Add power outlets {% if power_outlets and perms.dcim.delete_poweroutlet %}
</a> <button type="submit" class="btn btn-xs btn-danger">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete Selected
</button>
{% endif %}
</div>
<div class="col-md-6 text-right">
{% if perms.dcim.add_poweroutlet %}
<a href="{% url 'dcim:poweroutlet_add' pk=device.pk %}" class="btn btn-primary btn-xs">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
Add power outlets
</a>
{% endif %}
</div>
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@ -1,4 +1,9 @@
<tr{% if cp.cs_port and not cp.connection_status %} class="info"{% endif %}> <tr{% if cp.cs_port and not cp.connection_status %} class="info"{% endif %}>
{% if selectable and perms.dcim.delete_consoleport %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ cp.pk }}" />
</td>
{% endif %}
<td> <td>
<i class="fa fa-fw fa-keyboard-o"></i> {{ cp.name }} <i class="fa fa-fw fa-keyboard-o"></i> {{ cp.name }}
</td> </td>

View File

@ -1,4 +1,9 @@
<tr{% if csp.connected_console and not csp.connected_console.connection_status %} class="info"{% endif %}> <tr{% if csp.connected_console and not csp.connected_console.connection_status %} class="info"{% endif %}>
{% if selectable and perms.dcim.delete_consoleserverport %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ csp.pk }}" />
</td>
{% endif %}
<td> <td>
<i class="fa fa-fw fa-keyboard-o"></i> {{ csp.name }} <i class="fa fa-fw fa-keyboard-o"></i> {{ csp.name }}
</td> </td>

View File

@ -1,4 +1,9 @@
<tr> <tr>
{% if selectable and perms.dcim.delete_devicebay %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ devicebay.pk }}" />
</td>
{% endif %}
<td> <td>
<i class="fa fa-fw fa-{% if devicebay.installed_device %}dot-circle-o{% else %}circle-o{% endif %}"></i> {{ devicebay.name }} <i class="fa fa-fw fa-{% if devicebay.installed_device %}dot-circle-o{% else %}circle-o{% endif %}"></i> {{ devicebay.name }}
</td> </td>

View File

@ -1,4 +1,9 @@
<tr{% if iface.connection and not iface.connection.connection_status %} class="info"{% endif %}> <tr{% if iface.connection and not iface.connection.connection_status %} class="info"{% endif %}>
{% if selectable and perms.dcim.delete_interface %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ iface.pk }}" />
</td>
{% endif %}
<td> <td>
<i class="fa fa-fw fa-{{ icon|default:"exchange" }}"></i> <span title="{{ iface.get_form_factor_display }}">{{ iface.name }}</span> <i class="fa fa-fw fa-{{ icon|default:"exchange" }}"></i> <span title="{{ iface.get_form_factor_display }}">{{ iface.name }}</span>
{% if iface.description %} {% if iface.description %}

View File

@ -1,4 +1,9 @@
<tr{% if po.connected_port and not po.connected_port.connection_status %} class="info"{% endif %}> <tr{% if po.connected_port and not po.connected_port.connection_status %} class="info"{% endif %}>
{% if selectable and perms.dcim.delete_poweroutlet %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ po.pk }}" />
</td>
{% endif %}
<td> <td>
<i class="fa fa-fw fa-bolt"></i> {{ po.name }} <i class="fa fa-fw fa-bolt"></i> {{ po.name }}
</td> </td>

View File

@ -1,4 +1,9 @@
<tr{% if pp.power_outlet and not pp.connection_status %} class="info"{% endif %}> <tr{% if pp.power_outlet and not pp.connection_status %} class="info"{% endif %}>
{% if selectable and perms.dcim.delete_powerport %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ pp.pk }}" />
</td>
{% endif %}
<td> <td>
<i class="fa fa-fw fa-bolt"></i> {{ pp.name }} <i class="fa fa-fw fa-bolt"></i> {{ pp.name }}
</td> </td>

View File

@ -7,7 +7,7 @@
<input type="hidden" name="pk_all" value="{% for row in table.rows %}{{ row.record.pk|default:'' }}{% if not forloop.last %},{% endif %}{% endfor %}" /> <input type="hidden" name="pk_all" value="{% for row in table.rows %}{{ row.record.pk|default:'' }}{% if not forloop.last %},{% endif %}{% endfor %}" />
{% render_table table table_template|default:'table.html' %} {% render_table table table_template|default:'table.html' %}
{% if perms.dcim.add_interface %} {% if perms.dcim.add_interface %}
<button type="submit" name="_edit" formaction="{% url 'dcim:interface_bulk_add' %}" class="btn btn-primary btn-sm"> <button type="submit" name="_edit" formaction="{% url 'dcim:interface_add_multi' %}" class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
Add Interfaces Add Interfaces
</button> </button>