Browse Source

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

Jeremy Stretch 9 years ago
parent
commit
4be5c33905

+ 7 - 1
netbox/dcim/urls.py

@@ -103,6 +103,7 @@ urlpatterns = [
 
     # 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/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+)/disconnect/$', views.consoleport_disconnect, name='consoleport_disconnect'),
     url(r'^console-ports/(?P<pk>\d+)/edit/$', views.consoleport_edit, name='consoleport_edit'),
@@ -110,6 +111,7 @@ urlpatterns = [
 
     # 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/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+)/disconnect/$', views.consoleserverport_disconnect, name='consoleserverport_disconnect'),
     url(r'^console-server-ports/(?P<pk>\d+)/edit/$', views.consoleserverport_edit, name='consoleserverport_edit'),
@@ -117,6 +119,7 @@ urlpatterns = [
 
     # 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/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+)/disconnect/$', views.powerport_disconnect, name='powerport_disconnect'),
     url(r'^power-ports/(?P<pk>\d+)/edit/$', views.powerport_edit, name='powerport_edit'),
@@ -124,6 +127,7 @@ urlpatterns = [
 
     # 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/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+)/disconnect/$', views.poweroutlet_disconnect, name='poweroutlet_disconnect'),
     url(r'^power-outlets/(?P<pk>\d+)/edit/$', views.poweroutlet_edit, name='poweroutlet_edit'),
@@ -131,6 +135,7 @@ urlpatterns = [
 
     # Device bays
     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+)/delete/$', views.devicebay_delete, name='devicebay_delete'),
     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'),
 
     # 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/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'^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'),

+ 37 - 1
netbox/dcim/views.py

@@ -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):
     permission_required = 'dcim.change_consoleport'
     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
 #
@@ -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):
     permission_required = 'dcim.change_powerport'
     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
 #
@@ -1360,7 +1384,7 @@ class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'dcim.add_interface'
     cls = Device
     form = forms.InterfaceBulkCreateForm
-    template_name = 'dcim/interface_bulk_add.html'
+    template_name = 'dcim/interface_add_multi.html'
     default_redirect_url = 'dcim:device_list'
 
     def update_objects(self, pk_list, form):
@@ -1389,6 +1413,12 @@ class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView):
                                                                                       len(selected_devices)))
 
 
+class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
+    permission_required = 'dcim.delete_interface'
+    cls = Interface
+    parent_cls = Device
+
+
 #
 # 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
 #

+ 103 - 29
netbox/templates/dcim/device.html

@@ -289,97 +289,171 @@
 	</div>
 	<div class="col-md-6">
         {% 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-heading">
                     <strong>Device Bays</strong>
                 </div>
                 <table class="table table-hover panel-body">
                     {% for devicebay in device_bays %}
-                        {% include 'dcim/inc/_devicebay.html' %}
+                        {% include 'dcim/inc/_devicebay.html' with selectable=True %}
                     {% empty %}
                         <tr>
                             <td colspan="4">No device bays defined</td>
                         </tr>
                     {% endfor %}
                 </table>
-                {% if perms.dcim.add_devicebay %}
-                    <div class="panel-footer text-right">
-                        <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 bays
-                        </a>
-                    </div>
+                {% if perms.dcim.add_devicebay or perms.dcim.delete_devicebay %}
+                    <div class="panel-footer">
+                        <div class="row">
+                            <div class="col-md-6">
+                                {% if device_bays and perms.dcim.delete_devicebay %}
+                                    <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_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 %}
             </div>
         {% endif %}
         {% 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-heading">
                     <strong>Interfaces</strong>
                 </div>
                 <table class="table table-hover panel-body">
                     {% for iface in interfaces %}
-                        {% include 'dcim/inc/_interface.html' %}
+                        {% include 'dcim/inc/_interface.html' with selectable=True %}
                     {% empty %}
                         <tr>
                             <td colspan="4">No interfaces defined</td>
                         </tr>
                     {% endfor %}
                 </table>
-                {% if perms.dcim.add_interface %}
-                    <div class="panel-footer text-right">
-                        <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>
+                {% if perms.dcim.add_interface or perms.dcim.delete_interface %}
+                    <div class="panel-footer">
+                        <div class="row">
+                            <div class="col-md-6">
+                                {% if interfaces and perms.dcim.delete_interface %}
+                                    <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>
                 {% endif %}
             </div>
+            {% if perms.dcim.delete_interface %}
+                </form>
+            {% endif %}
         {% endif %}
         {% 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-heading">
                     <strong>Console Server Ports</strong>
                 </div>
                 <table class="table table-hover panel-body">
                     {% for csp in cs_ports %}
-                        {% include 'dcim/inc/_consoleserverport.html' %}
+                        {% include 'dcim/inc/_consoleserverport.html' with selectable=True %}
                     {% empty %}
                         <tr>
                             <td colspan="4">No console server ports defined</td>
                         </tr>
                     {% endfor %}
                 </table>
-                {% if perms.dcim.add_consoleserverport %}
-                    <div class="panel-footer text-right">
-                        <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>
+                {% if perms.dcim.add_consoleserverport or perms.dcim.delete_consoleserverport %}
+                    <div class="panel-footer">
+                        <div class="row">
+                            <div class="col-md-6">
+                                {% if cs_ports and perms.dcim.delete_consoleserverport %}
+                                    <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>
                 {% endif %}
             </div>
+            {% if perms.dcim.delete_consoleserverport %}
+                </form>
+            {% endif %}
         {% endif %}
         {% 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-heading">
                     <strong>Power Outlets</strong>
                 </div>
                 <table class="table table-hover panel-body">
                     {% for po in power_outlets %}
-                        {% include 'dcim/inc/_poweroutlet.html' %}
+                        {% include 'dcim/inc/_poweroutlet.html' with selectable=True %}
                     {% empty %}
                         <tr>
                             <td colspan="4">No power outlets defined</td>
                         </tr>
                     {% endfor %}
                 </table>
-                {% if perms.dcim.add_poweroutlet %}
-                    <div class="panel-footer text-right">
-                        <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>
+                {% if perms.dcim.add_poweroutlet or perms.dcim.delete_poweroutlet %}
+                    <div class="panel-footer">
+                        <div class="row">
+                            <div class="col-md-6">
+                                {% if power_outlets and perms.dcim.delete_poweroutlet %}
+                                    <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>
                 {% endif %}
             </div>

+ 5 - 0
netbox/templates/dcim/inc/_consoleport.html

@@ -1,4 +1,9 @@
 <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>
         <i class="fa fa-fw fa-keyboard-o"></i> {{ cp.name }}
     </td>

+ 5 - 0
netbox/templates/dcim/inc/_consoleserverport.html

@@ -1,4 +1,9 @@
 <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>
         <i class="fa fa-fw fa-keyboard-o"></i> {{ csp.name }}
     </td>

+ 5 - 0
netbox/templates/dcim/inc/_devicebay.html

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

+ 5 - 0
netbox/templates/dcim/inc/_interface.html

@@ -1,4 +1,9 @@
 <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>
         <i class="fa fa-fw fa-{{ icon|default:"exchange" }}"></i> <span title="{{ iface.get_form_factor_display }}">{{ iface.name }}</span>
         {% if iface.description %}

+ 5 - 0
netbox/templates/dcim/inc/_poweroutlet.html

@@ -1,4 +1,9 @@
 <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>
         <i class="fa fa-fw fa-bolt"></i> {{ po.name }}
     </td>

+ 5 - 0
netbox/templates/dcim/inc/_powerport.html

@@ -1,4 +1,9 @@
 <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>
         <i class="fa fa-fw fa-bolt"></i> {{ pp.name }}
     </td>

+ 1 - 1
netbox/templates/dcim/inc/device_table.html

@@ -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 %}" />
         {% render_table table table_template|default:'table.html' %}
         {% 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>
                 Add Interfaces
             </button>

netbox/templates/dcim/interface_bulk_add.html → netbox/templates/dcim/interface_add_multi.html