Added virtual chassis member remove view

This commit is contained in:
Jeremy Stretch 2018-02-01 12:49:23 -05:00
parent f1da517c84
commit b61bccbb67
5 changed files with 95 additions and 7 deletions

View File

@ -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."
})

View File

@ -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'),
]

View File

@ -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),
})

View File

@ -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>

View 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 %}