Added views to add/remove hosts to/from clusters

This commit is contained in:
Jeremy Stretch
2017-08-21 16:53:36 -04:00
parent e0c0bbba56
commit 6813721997
8 changed files with 275 additions and 12 deletions

View File

@@ -1,15 +1,19 @@
from __future__ import unicode_literals
from mptt.forms import TreeNodeChoiceField
from django import forms
from django.db.models import Count
from dcim.formfields import MACAddressFormField
from dcim.models import Device, Rack, Region, Site
from extras.forms import CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
from tenancy.forms import TenancyForm
from tenancy.models import Tenant
from utilities.forms import (
APISelect, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ChainedModelChoiceField, ComponentForm,
ExpandableNameField, FilterChoiceField, SlugField,
APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ChainedFieldsMixin,
ChainedModelChoiceField, ChainedModelMultipleChoiceField, ComponentForm, ConfirmationForm, ExpandableNameField,
FilterChoiceField, SlugField,
)
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
@@ -88,6 +92,65 @@ class ClusterFilterForm(BootstrapMixin, CustomFieldFilterForm):
)
class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
region = TreeNodeChoiceField(
queryset=Region.objects.all(),
required=False,
widget=forms.Select(
attrs={'filter-for': 'site'}
)
)
site = ChainedModelChoiceField(
queryset=Site.objects.all(),
chains=(
('region', 'region'),
),
required=False,
widget=APISelect(
api_url='/api/dcim/sites/?region_id={{region}}',
attrs={'filter-for': 'rack'}
)
)
rack = ChainedModelChoiceField(
queryset=Rack.objects.all(),
chains=(
('site', 'site'),
),
required=False,
widget=APISelect(
api_url='/api/dcim/racks/?site_id={{site}}',
attrs={'filter-for': 'devices', 'nullable': 'true'}
)
)
devices = ChainedModelMultipleChoiceField(
queryset=Device.objects.filter(cluster__isnull=True),
chains=(
('site', 'site'),
('rack', 'rack'),
),
label='Device',
required=False,
widget=APISelectMultiple(
api_url='/api/dcim/devices/?site_id={{site}}&rack_id={{rack}}',
display_field='display_name',
disabled_indicator='cluster'
)
)
class Meta:
fields = ['region', 'site', 'rack', 'devices']
def __init__(self, *args, **kwargs):
super(ClusterAddDevicesForm, self).__init__(*args, **kwargs)
self.fields['devices'].choices = []
class ClusterRemoveDevicesForm(ConfirmationForm):
pk = forms.ModelMultipleChoiceField(queryset=Device.objects.all(), widget=forms.MultipleHiddenInput)
#
# Virtual Machines
#

View File

@@ -28,6 +28,8 @@ urlpatterns = [
url(r'^clusters/(?P<pk>\d+)/$', views.ClusterView.as_view(), name='cluster'),
url(r'^clusters/(?P<pk>\d+)/edit/$', views.ClusterEditView.as_view(), name='cluster_edit'),
url(r'^clusters/(?P<pk>\d+)/delete/$', views.ClusterDeleteView.as_view(), name='cluster_delete'),
url(r'^clusters/(?P<pk>\d+)/devices/add/$', views.ClusterAddDevicesView.as_view(), name='cluster_add_devices'),
url(r'^clusters/(?P<pk>\d+)/devices/remove/$', views.ClusterRemoveDevicesView.as_view(), name='cluster_remove_devices'),
# Virtual machines
url(r'^virtual-machines/$', views.VirtualMachineListView.as_view(), name='virtualmachine_list'),

View File

@@ -1,12 +1,14 @@
from __future__ import unicode_literals
from django.contrib import messages
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db.models import Count
from django.shortcuts import get_object_or_404, render
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.views.generic import View
from dcim.models import Device
from dcim.tables import DeviceTable
from utilities.views import (
BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ComponentDeleteView, ComponentEditView,
ObjectDeleteView, ObjectEditView, ObjectListView,
@@ -96,11 +98,16 @@ class ClusterView(View):
def get(self, request, pk):
cluster = get_object_or_404(Cluster, pk=pk)
devices = Device.objects.filter(cluster=cluster)
devices = Device.objects.filter(cluster=cluster).select_related(
'site', 'rack', 'tenant', 'device_type__manufacturer'
)
device_table = DeviceTable(list(devices), orderable=False)
if request.user.has_perm('virtualization:change_cluster'):
device_table.columns.show('pk')
return render(request, 'virtualization/cluster.html', {
'cluster': cluster,
'devices': devices,
'device_table': device_table,
})
@@ -109,9 +116,6 @@ class ClusterCreateView(PermissionRequiredMixin, ObjectEditView):
model = Cluster
form_class = forms.ClusterForm
def get_return_url(self, request, obj):
return reverse('virtualization:cluster_list')
class ClusterEditView(ClusterCreateView):
permission_required = 'virtualization.change_cluster'
@@ -138,6 +142,82 @@ class ClusterBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
default_return_url = 'virtualization:cluster_list'
class ClusterAddDevicesView(PermissionRequiredMixin, View):
permission_required = 'virtualization.change_cluster'
form = forms.ClusterAddDevicesForm
template_name = 'virtualization/cluster_add_devices.html'
def get(self, request, pk):
cluster = get_object_or_404(Cluster, pk=pk)
form = self.form()
return render(request, self.template_name, {
'cluster': cluster,
'form': form,
'return_url': reverse('virtualization:cluster', kwargs={'pk': pk}),
})
def post(self, request, pk):
cluster = get_object_or_404(Cluster, pk=pk)
form = self.form(request.POST)
if form.is_valid():
# Assign the selected Devices to the Cluster
devices = form.cleaned_data['devices']
Device.objects.filter(pk__in=devices).update(cluster=cluster)
messages.success(request, "Added {} devices to cluster {}".format(
len(devices), cluster
))
return redirect(cluster.get_absolute_url())
return render(request, self.template_name, {
'cluser': cluster,
'form': form,
'return_url': cluster.get_absolute_url(),
})
class ClusterRemoveDevicesView(PermissionRequiredMixin, View):
permission_required = 'virtualization.change_cluster'
form = forms.ClusterRemoveDevicesForm
template_name = 'utilities/obj_bulk_remove.html'
def post(self, request, pk):
cluster = get_object_or_404(Cluster, pk=pk)
if '_confirm' in request.POST:
form = self.form(request.POST)
if form.is_valid():
# Remove the selected Devices from the Cluster
devices = form.cleaned_data['pk']
Device.objects.filter(pk__in=devices).update(cluster=None)
messages.success(request, "Removed {} devices from cluster {}".format(
len(devices), cluster
))
return redirect(cluster.get_absolute_url())
else:
form = self.form(initial={'pk': request.POST.getlist('pk')})
selected_objects = Device.objects.filter(pk__in=form.initial['pk'])
device_table = DeviceTable(list(selected_objects), orderable=False)
return render(request, self.template_name, {
'form': form,
'parent_obj': cluster,
'table': device_table,
'obj_type_plural': 'devices',
'return_url': cluster.get_absolute_url(),
})
#
# Virtual machines
#