mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Fixes #2573: Fix bulk console/power/interface disconnections
This commit is contained in:
parent
30f8fb4c11
commit
788847edaa
@ -45,6 +45,7 @@ NetBox now supports modeling physical cables for console, power, and interface c
|
|||||||
* [#2569](https://github.com/digitalocean/netbox/issues/2569) - Added LSH fiber type; removed SC duplex/simplex designations
|
* [#2569](https://github.com/digitalocean/netbox/issues/2569) - Added LSH fiber type; removed SC duplex/simplex designations
|
||||||
* [#2571](https://github.com/digitalocean/netbox/issues/2571) - Enforce deletion of attached cable when deleting a termination point
|
* [#2571](https://github.com/digitalocean/netbox/issues/2571) - Enforce deletion of attached cable when deleting a termination point
|
||||||
* [#2572](https://github.com/digitalocean/netbox/issues/2572) - Add button to disconnect cable from circuit termination
|
* [#2572](https://github.com/digitalocean/netbox/issues/2572) - Add button to disconnect cable from circuit termination
|
||||||
|
* [#2573](https://github.com/digitalocean/netbox/issues/2573) - Fix bulk console/power/interface disconnections
|
||||||
|
|
||||||
## API Changes
|
## API Changes
|
||||||
|
|
||||||
|
@ -169,13 +169,13 @@ urlpatterns = [
|
|||||||
# Console server ports
|
# Console server ports
|
||||||
url(r'^devices/console-server-ports/add/$', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
|
url(r'^devices/console-server-ports/add/$', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
|
||||||
url(r'^devices/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortCreateView.as_view(), name='consoleserverport_add'),
|
url(r'^devices/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortCreateView.as_view(), name='consoleserverport_add'),
|
||||||
url(r'^devices/(?P<pk>\d+)/console-server-ports/disconnect/$', views.ConsoleServerPortBulkDisconnectView.as_view(), name='consoleserverport_bulk_disconnect'),
|
|
||||||
url(r'^devices/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'),
|
||||||
url(r'^console-server-ports/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='consoleserverport_connect', kwargs={'termination_a_type': ConsoleServerPort}),
|
url(r'^console-server-ports/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='consoleserverport_connect', kwargs={'termination_a_type': ConsoleServerPort}),
|
||||||
url(r'^console-server-ports/(?P<pk>\d+)/edit/$', views.ConsoleServerPortEditView.as_view(), name='consoleserverport_edit'),
|
url(r'^console-server-ports/(?P<pk>\d+)/edit/$', views.ConsoleServerPortEditView.as_view(), name='consoleserverport_edit'),
|
||||||
url(r'^console-server-ports/(?P<pk>\d+)/delete/$', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'),
|
url(r'^console-server-ports/(?P<pk>\d+)/delete/$', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'),
|
||||||
url(r'^console-server-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}),
|
url(r'^console-server-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}),
|
||||||
url(r'^console-server-ports/rename/$', views.ConsoleServerPortBulkRenameView.as_view(), name='consoleserverport_bulk_rename'),
|
url(r'^console-server-ports/rename/$', views.ConsoleServerPortBulkRenameView.as_view(), name='consoleserverport_bulk_rename'),
|
||||||
|
url(r'^console-server-ports/disconnect/$', views.ConsoleServerPortBulkDisconnectView.as_view(), name='consoleserverport_bulk_disconnect'),
|
||||||
|
|
||||||
# Power ports
|
# Power ports
|
||||||
url(r'^devices/power-ports/add/$', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
|
url(r'^devices/power-ports/add/$', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
|
||||||
@ -189,19 +189,18 @@ urlpatterns = [
|
|||||||
# Power outlets
|
# Power outlets
|
||||||
url(r'^devices/power-outlets/add/$', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
|
url(r'^devices/power-outlets/add/$', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
|
||||||
url(r'^devices/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletCreateView.as_view(), name='poweroutlet_add'),
|
url(r'^devices/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletCreateView.as_view(), name='poweroutlet_add'),
|
||||||
url(r'^devices/(?P<pk>\d+)/power-outlets/disconnect/$', views.PowerOutletBulkDisconnectView.as_view(), name='poweroutlet_bulk_disconnect'),
|
|
||||||
url(r'^devices/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'),
|
||||||
url(r'^power-outlets/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='poweroutlet_connect', kwargs={'termination_a_type': PowerOutlet}),
|
url(r'^power-outlets/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='poweroutlet_connect', kwargs={'termination_a_type': PowerOutlet}),
|
||||||
url(r'^power-outlets/(?P<pk>\d+)/edit/$', views.PowerOutletEditView.as_view(), name='poweroutlet_edit'),
|
url(r'^power-outlets/(?P<pk>\d+)/edit/$', views.PowerOutletEditView.as_view(), name='poweroutlet_edit'),
|
||||||
url(r'^power-outlets/(?P<pk>\d+)/delete/$', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'),
|
url(r'^power-outlets/(?P<pk>\d+)/delete/$', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'),
|
||||||
url(r'^power-outlets/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}),
|
url(r'^power-outlets/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}),
|
||||||
url(r'^power-outlets/rename/$', views.PowerOutletBulkRenameView.as_view(), name='poweroutlet_bulk_rename'),
|
url(r'^power-outlets/rename/$', views.PowerOutletBulkRenameView.as_view(), name='poweroutlet_bulk_rename'),
|
||||||
|
url(r'^power-outlets/disconnect/$', views.PowerOutletBulkDisconnectView.as_view(), name='poweroutlet_bulk_disconnect'),
|
||||||
|
|
||||||
# Interfaces
|
# Interfaces
|
||||||
url(r'^devices/interfaces/add/$', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'),
|
url(r'^devices/interfaces/add/$', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'),
|
||||||
url(r'^devices/(?P<pk>\d+)/interfaces/add/$', views.InterfaceCreateView.as_view(), name='interface_add'),
|
url(r'^devices/(?P<pk>\d+)/interfaces/add/$', views.InterfaceCreateView.as_view(), name='interface_add'),
|
||||||
url(r'^devices/(?P<pk>\d+)/interfaces/edit/$', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'),
|
url(r'^devices/(?P<pk>\d+)/interfaces/edit/$', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'),
|
||||||
url(r'^devices/(?P<pk>\d+)/interfaces/disconnect/$', views.InterfaceBulkDisconnectView.as_view(), name='interface_bulk_disconnect'),
|
|
||||||
url(r'^devices/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
|
||||||
url(r'^interfaces/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='interface_connect', kwargs={'termination_a_type': Interface}),
|
url(r'^interfaces/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='interface_connect', kwargs={'termination_a_type': Interface}),
|
||||||
url(r'^interfaces/(?P<pk>\d+)/$', views.InterfaceView.as_view(), name='interface'),
|
url(r'^interfaces/(?P<pk>\d+)/$', views.InterfaceView.as_view(), name='interface'),
|
||||||
@ -211,6 +210,7 @@ urlpatterns = [
|
|||||||
url(r'^interfaces/(?P<pk>\d+)/changelog/$', ObjectChangeLogView.as_view(), name='interface_changelog', kwargs={'model': Interface}),
|
url(r'^interfaces/(?P<pk>\d+)/changelog/$', ObjectChangeLogView.as_view(), name='interface_changelog', kwargs={'model': Interface}),
|
||||||
url(r'^interfaces/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='interface_trace', kwargs={'model': Interface}),
|
url(r'^interfaces/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='interface_trace', kwargs={'model': Interface}),
|
||||||
url(r'^interfaces/rename/$', views.InterfaceBulkRenameView.as_view(), name='interface_bulk_rename'),
|
url(r'^interfaces/rename/$', views.InterfaceBulkRenameView.as_view(), name='interface_bulk_rename'),
|
||||||
|
url(r'^interfaces/disconnect/$', views.InterfaceBulkDisconnectView.as_view(), name='interface_bulk_disconnect'),
|
||||||
|
|
||||||
# Front ports
|
# Front ports
|
||||||
# url(r'^devices/front-ports/add/$', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'),
|
# url(r'^devices/front-ports/add/$', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'),
|
||||||
|
@ -74,7 +74,7 @@ class BulkRenameView(GetReturnURLMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class BulkDisconnectView(View):
|
class BulkDisconnectView(GetReturnURLMixin, View):
|
||||||
"""
|
"""
|
||||||
An extendable view for disconnection console/power/interface components in bulk.
|
An extendable view for disconnection console/power/interface components in bulk.
|
||||||
"""
|
"""
|
||||||
@ -82,22 +82,30 @@ class BulkDisconnectView(View):
|
|||||||
form = None
|
form = None
|
||||||
template_name = 'dcim/bulk_disconnect.html'
|
template_name = 'dcim/bulk_disconnect.html'
|
||||||
|
|
||||||
def disconnect_objects(self, objects):
|
def post(self, request):
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def post(self, request, pk):
|
|
||||||
|
|
||||||
device = get_object_or_404(Device, pk=pk)
|
|
||||||
selected_objects = []
|
selected_objects = []
|
||||||
|
return_url = self.get_return_url(request)
|
||||||
|
|
||||||
if '_confirm' in request.POST:
|
if '_confirm' in request.POST:
|
||||||
form = self.form(request.POST)
|
form = self.form(request.POST)
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
count = self.disconnect_objects(form.cleaned_data['pk'])
|
|
||||||
messages.success(request, "Disconnected {} {} on {}".format(
|
with transaction.atomic():
|
||||||
count, self.model._meta.verbose_name_plural, device
|
|
||||||
|
count = 0
|
||||||
|
for obj in self.model.objects.filter(pk__in=form.cleaned_data['pk']):
|
||||||
|
if obj.cable is None:
|
||||||
|
continue
|
||||||
|
obj.cable.delete()
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
messages.success(request, "Disconnected {} {}".format(
|
||||||
|
count, self.model._meta.verbose_name_plural
|
||||||
))
|
))
|
||||||
return redirect(device.get_absolute_url())
|
|
||||||
|
return redirect(return_url)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
form = self.form(initial={'pk': request.POST.getlist('pk')})
|
form = self.form(initial={'pk': request.POST.getlist('pk')})
|
||||||
@ -105,10 +113,9 @@ class BulkDisconnectView(View):
|
|||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
'form': form,
|
'form': form,
|
||||||
'device': device,
|
|
||||||
'obj_type_plural': self.model._meta.verbose_name_plural,
|
'obj_type_plural': self.model._meta.verbose_name_plural,
|
||||||
'selected_objects': selected_objects,
|
'selected_objects': selected_objects,
|
||||||
'return_url': device.get_absolute_url(),
|
'return_url': return_url,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -1139,14 +1146,6 @@ class ConsoleServerPortBulkDisconnectView(PermissionRequiredMixin, BulkDisconnec
|
|||||||
model = ConsoleServerPort
|
model = ConsoleServerPort
|
||||||
form = forms.ConsoleServerPortBulkDisconnectForm
|
form = forms.ConsoleServerPortBulkDisconnectForm
|
||||||
|
|
||||||
def disconnect_objects(self, consoleserverports):
|
|
||||||
return ConsolePort.objects.filter(
|
|
||||||
connected_endpoint__in=consoleserverports
|
|
||||||
).update(
|
|
||||||
connected_endpoint=None,
|
|
||||||
connection_status=None
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ConsoleServerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class ConsoleServerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_consoleserverport'
|
permission_required = 'dcim.delete_consoleserverport'
|
||||||
@ -1223,11 +1222,6 @@ class PowerOutletBulkDisconnectView(PermissionRequiredMixin, BulkDisconnectView)
|
|||||||
model = PowerOutlet
|
model = PowerOutlet
|
||||||
form = forms.PowerOutletBulkDisconnectForm
|
form = forms.PowerOutletBulkDisconnectForm
|
||||||
|
|
||||||
def disconnect_objects(self, poweroutlets):
|
|
||||||
return PowerPort.objects.filter(connected_endpoint__in=poweroutlets).update(
|
|
||||||
connected_endpoint=None, connection_status=None
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_poweroutlet'
|
permission_required = 'dcim.delete_poweroutlet'
|
||||||
@ -1308,11 +1302,6 @@ class InterfaceBulkDisconnectView(PermissionRequiredMixin, BulkDisconnectView):
|
|||||||
model = Interface
|
model = Interface
|
||||||
form = forms.InterfaceBulkDisconnectForm
|
form = forms.InterfaceBulkDisconnectForm
|
||||||
|
|
||||||
def disconnect_objects(self, interfaces):
|
|
||||||
return Interface.objects.filter(_connected_interface__in=interfaces).update(
|
|
||||||
_connected_interface=None, connection_status=None
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView):
|
class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView):
|
||||||
permission_required = 'dcim.change_interface'
|
permission_required = 'dcim.change_interface'
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{% block title %}Disconnect {{ obj_type_plural|bettertitle }}{% endblock %}
|
{% block title %}Disconnect {{ obj_type_plural|bettertitle }}{% endblock %}
|
||||||
|
|
||||||
{% block message %}
|
{% block message %}
|
||||||
<p>Are you sure you want to disconnect all {{ selected_objects|length }} of these {{ obj_type_plural }} on <strong>{{ device }}</strong>?</p>
|
<p>Are you sure you want to disconnect these {{ selected_objects|length }} {{ obj_type_plural }}?</p>
|
||||||
<ul>
|
<ul>
|
||||||
{% for obj in selected_objects %}
|
{% for obj in selected_objects %}
|
||||||
<li>{{ obj }}</li>
|
<li>{{ obj }}</li>
|
||||||
|
@ -530,7 +530,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if interfaces and perms.dcim.change_interface %}
|
{% if interfaces and perms.dcim.change_interface %}
|
||||||
<button type="submit" name="_disconnect" formaction="{% url 'dcim:interface_bulk_disconnect' pk=device.pk %}" class="btn btn-danger btn-xs">
|
<button type="submit" name="_disconnect" formaction="{% url 'dcim:interface_bulk_disconnect' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
|
||||||
<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 %}
|
||||||
@ -585,7 +585,7 @@
|
|||||||
<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>
|
||||||
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleserverport_bulk_disconnect' pk=device.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
|
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleserverport_bulk_disconnect' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
|
||||||
<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 %}
|
||||||
@ -640,7 +640,7 @@
|
|||||||
<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>
|
||||||
<button type="submit" name="_disconnect" formaction="{% url 'dcim:poweroutlet_bulk_disconnect' pk=device.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
|
<button type="submit" name="_disconnect" formaction="{% url 'dcim:poweroutlet_bulk_disconnect' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
|
||||||
<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 %}
|
||||||
|
Loading…
Reference in New Issue
Block a user