mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-21 03:27:21 -06:00
Added virtual chassis member remove view
This commit is contained in:
parent
f1da517c84
commit
b61bccbb67
@ -1011,6 +1011,14 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
|
||||
raise ValidationError({
|
||||
'vc_position': "A device assigned to a virtual chassis must have its position defined."
|
||||
})
|
||||
try:
|
||||
virtual_chassis = VirtualChassis.objects.filter(master=self.pk)
|
||||
if self.virtual_chassis != virtual_chassis:
|
||||
raise ValidationError(
|
||||
"This device has been designated the master of a virtual chassis but is not assigned to it."
|
||||
)
|
||||
except VirtualChassis.DoesNotExist:
|
||||
pass
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
||||
@ -1627,3 +1635,11 @@ class VirtualChassis(models.Model):
|
||||
|
||||
def get_absolute_url(self):
|
||||
return self.master.get_absolute_url()
|
||||
|
||||
def clean(self):
|
||||
|
||||
# Validate master assignment
|
||||
if self.master not in self.members.all():
|
||||
raise ValidationError({
|
||||
'master': "The selected master is not assigned to this virtual chassis."
|
||||
})
|
||||
|
@ -221,5 +221,6 @@ urlpatterns = [
|
||||
url(r'^virtual-chassis/(?P<pk>\d+)/edit/$', views.VirtualChassisEditView.as_view(), name='virtualchassis_edit'),
|
||||
url(r'^virtual-chassis/(?P<pk>\d+)/delete/$', views.VirtualChassisDeleteView.as_view(), name='virtualchassis_delete'),
|
||||
url(r'^virtual-chassis/(?P<pk>\d+)/add-member/$', views.VirtualChassisAddMemberView.as_view(), name='virtualchassis_add_member'),
|
||||
url(r'^virtual-chassis-members/(?P<pk>\d+)/delete/$', views.VirtualChassisRemoveMemberView.as_view(), name='virtualchassis_remove_member'),
|
||||
|
||||
]
|
||||
|
@ -2172,7 +2172,7 @@ class VirtualChassisDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||
|
||||
|
||||
class VirtualChassisAddMemberView(PermissionRequiredMixin, GetReturnURLMixin, View):
|
||||
permission_required = 'dcim.change_device'
|
||||
permission_required = 'dcim.change_virtualchassis'
|
||||
|
||||
def get(self, request, pk):
|
||||
|
||||
@ -2224,3 +2224,50 @@ class VirtualChassisAddMemberView(PermissionRequiredMixin, GetReturnURLMixin, Vi
|
||||
'membership_form': membership_form,
|
||||
'return_url': self.get_return_url(request, virtual_chassis),
|
||||
})
|
||||
|
||||
|
||||
class VirtualChassisRemoveMemberView(PermissionRequiredMixin, GetReturnURLMixin, View):
|
||||
permission_required = 'dcim.change_virtualchassis'
|
||||
|
||||
def get(self, request, pk):
|
||||
|
||||
device = get_object_or_404(Device, pk=pk, virtual_chassis__isnull=False)
|
||||
form = ConfirmationForm(initial=request.GET)
|
||||
|
||||
return render(request, 'dcim/virtualchassis_remove_member.html', {
|
||||
'device': device,
|
||||
'form': form,
|
||||
'return_url': self.get_return_url(request, device),
|
||||
})
|
||||
|
||||
def post(self, request, pk):
|
||||
|
||||
device = get_object_or_404(Device, pk=pk, virtual_chassis__isnull=False)
|
||||
form = ConfirmationForm(request.POST)
|
||||
|
||||
# Protect master device from being removed
|
||||
virtual_chassis = VirtualChassis.objects.filter(master=device).first()
|
||||
if virtual_chassis is not None:
|
||||
msg = 'Unable to remove master device {} from the virtual chassis.'.format(escape(device))
|
||||
messages.error(request, mark_safe(msg))
|
||||
return redirect(device.get_absolute_url())
|
||||
|
||||
if form.is_valid():
|
||||
|
||||
Device.objects.filter(pk=device.pk).update(
|
||||
virtual_chassis=None,
|
||||
vc_position=None,
|
||||
vc_priority=None
|
||||
)
|
||||
|
||||
msg = 'Removed {} from virtual chassis {}'.format(device, device.virtual_chassis)
|
||||
messages.success(request, msg)
|
||||
UserAction.objects.log_edit(request.user, device, msg)
|
||||
|
||||
return redirect(self.get_return_url(request, device))
|
||||
|
||||
return render(request, 'dcim/virtualchassis_remove_member.html', {
|
||||
'device': device,
|
||||
'form': form,
|
||||
'return_url': self.get_return_url(request, device),
|
||||
})
|
||||
|
@ -31,6 +31,7 @@
|
||||
<th>Device</th>
|
||||
<th>Position</th>
|
||||
<th>Priority</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -38,11 +39,22 @@
|
||||
{% for field in form.hidden_fields %}
|
||||
{{ field }}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td>{{ form.instance.name }}</td>
|
||||
<td>{{ form.vc_position }}</td>
|
||||
<td>{{ form.vc_priority }}</td>
|
||||
</tr>
|
||||
{% with device=form.instance virtual_chassis=vc_form.instance %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ device.get_absolute_url }}">{{ device }}</a>
|
||||
</td>
|
||||
<td>{{ form.vc_position }}</td>
|
||||
<td>{{ form.vc_priority }}</td>
|
||||
<td>
|
||||
{% if virtual_chassis.pk %}
|
||||
<a href="{% url 'dcim:virtualchassis_remove_member' pk=device.pk %}?return_url={% url 'dcim:virtualchassis_edit' pk=virtual_chassis.pk %}" class="btn btn-danger btn-xs{% if virtual_chassis.master == device %} disabled{% endif %}">
|
||||
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
@ -51,7 +63,11 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3 text-right">
|
||||
<button type="submit" name="_create" class="btn btn-primary">Create</button>
|
||||
{% if vc_form.instance.pk %}
|
||||
<button type="submit" name="_update" class="btn btn-primary">Update</button>
|
||||
{% else %}
|
||||
<button type="submit" name="_create" class="btn btn-primary">Create</button>
|
||||
{% endif %}
|
||||
<a href="{{ return_url }}" class="btn btn-default">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
|
8
netbox/templates/dcim/virtualchassis_remove_member.html
Normal file
8
netbox/templates/dcim/virtualchassis_remove_member.html
Normal file
@ -0,0 +1,8 @@
|
||||
{% extends 'utilities/confirmation_form.html' %}
|
||||
{% load form_helpers %}
|
||||
|
||||
{% block title %}Remove Virtual Chassis Member?{% endblock %}
|
||||
|
||||
{% block message %}
|
||||
<p>Are you sure you want to remove <strong>{{ device }}</strong> from virtual chassis {{ device.virtual_chassis }}?</p>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user