1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

504 lines
16 KiB
Python

from django.contrib import messages
from django.db import transaction
from django.db.models import Prefetch
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from dcim.filtersets import DeviceFilterSet
from dcim.models import Device
from dcim.tables import DeviceTable
from extras.views import ObjectConfigContextView
from ipam.models import IPAddress, Service
from ipam.tables import AssignedIPAddressesTable, InterfaceVLANTable
from netbox.views import generic
from utilities.utils import count_related
from . import filtersets, forms, tables
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
#
# Cluster types
#
class ClusterTypeListView(generic.ObjectListView):
queryset = ClusterType.objects.annotate(
cluster_count=count_related(Cluster, 'type')
)
filterset = filtersets.ClusterTypeFilterSet
filterset_form = forms.ClusterTypeFilterForm
table = tables.ClusterTypeTable
class ClusterTypeView(generic.ObjectView):
queryset = ClusterType.objects.all()
def get_extra_context(self, request, instance):
clusters = Cluster.objects.restrict(request.user, 'view').filter(
type=instance
).annotate(
device_count=count_related(Device, 'cluster'),
vm_count=count_related(VirtualMachine, 'cluster')
)
clusters_table = tables.ClusterTable(clusters, user=request.user, exclude=('type',))
clusters_table.configure(request)
return {
'clusters_table': clusters_table,
}
class ClusterTypeEditView(generic.ObjectEditView):
queryset = ClusterType.objects.all()
form = forms.ClusterTypeForm
class ClusterTypeDeleteView(generic.ObjectDeleteView):
queryset = ClusterType.objects.all()
class ClusterTypeBulkImportView(generic.BulkImportView):
queryset = ClusterType.objects.all()
model_form = forms.ClusterTypeCSVForm
table = tables.ClusterTypeTable
class ClusterTypeBulkEditView(generic.BulkEditView):
queryset = ClusterType.objects.annotate(
cluster_count=count_related(Cluster, 'type')
)
filterset = filtersets.ClusterTypeFilterSet
table = tables.ClusterTypeTable
form = forms.ClusterTypeBulkEditForm
class ClusterTypeBulkDeleteView(generic.BulkDeleteView):
queryset = ClusterType.objects.annotate(
cluster_count=count_related(Cluster, 'type')
)
table = tables.ClusterTypeTable
#
# Cluster groups
#
class ClusterGroupListView(generic.ObjectListView):
queryset = ClusterGroup.objects.annotate(
cluster_count=count_related(Cluster, 'group')
)
filterset = filtersets.ClusterGroupFilterSet
filterset_form = forms.ClusterGroupFilterForm
table = tables.ClusterGroupTable
class ClusterGroupView(generic.ObjectView):
queryset = ClusterGroup.objects.all()
def get_extra_context(self, request, instance):
clusters = Cluster.objects.restrict(request.user, 'view').filter(
group=instance
).annotate(
device_count=count_related(Device, 'cluster'),
vm_count=count_related(VirtualMachine, 'cluster')
)
clusters_table = tables.ClusterTable(clusters, user=request.user, exclude=('group',))
clusters_table.configure(request)
return {
'clusters_table': clusters_table,
}
class ClusterGroupEditView(generic.ObjectEditView):
queryset = ClusterGroup.objects.all()
form = forms.ClusterGroupForm
class ClusterGroupDeleteView(generic.ObjectDeleteView):
queryset = ClusterGroup.objects.all()
class ClusterGroupBulkImportView(generic.BulkImportView):
queryset = ClusterGroup.objects.annotate(
cluster_count=count_related(Cluster, 'group')
)
model_form = forms.ClusterGroupCSVForm
table = tables.ClusterGroupTable
class ClusterGroupBulkEditView(generic.BulkEditView):
queryset = ClusterGroup.objects.annotate(
cluster_count=count_related(Cluster, 'group')
)
filterset = filtersets.ClusterGroupFilterSet
table = tables.ClusterGroupTable
form = forms.ClusterGroupBulkEditForm
class ClusterGroupBulkDeleteView(generic.BulkDeleteView):
queryset = ClusterGroup.objects.annotate(
cluster_count=count_related(Cluster, 'group')
)
table = tables.ClusterGroupTable
#
# Clusters
#
class ClusterListView(generic.ObjectListView):
permission_required = 'virtualization.view_cluster'
queryset = Cluster.objects.annotate(
device_count=count_related(Device, 'cluster'),
vm_count=count_related(VirtualMachine, 'cluster')
)
table = tables.ClusterTable
filterset = filtersets.ClusterFilterSet
filterset_form = forms.ClusterFilterForm
class ClusterView(generic.ObjectView):
queryset = Cluster.objects.all()
class ClusterVirtualMachinesView(generic.ObjectChildrenView):
queryset = Cluster.objects.all()
child_model = VirtualMachine
table = tables.VirtualMachineTable
filterset = filtersets.VirtualMachineFilterSet
template_name = 'virtualization/cluster/virtual_machines.html'
def get_children(self, request, parent):
return VirtualMachine.objects.restrict(request.user, 'view').filter(cluster=parent)
def get_extra_context(self, request, instance):
return {
'active_tab': 'virtual-machines',
}
class ClusterDevicesView(generic.ObjectChildrenView):
queryset = Cluster.objects.all()
child_model = Device
table = DeviceTable
filterset = DeviceFilterSet
template_name = 'virtualization/cluster/devices.html'
def get_children(self, request, parent):
return Device.objects.restrict(request.user, 'view').filter(cluster=parent)
def get_extra_context(self, request, instance):
return {
'active_tab': 'devices',
}
class ClusterEditView(generic.ObjectEditView):
queryset = Cluster.objects.all()
form = forms.ClusterForm
class ClusterDeleteView(generic.ObjectDeleteView):
queryset = Cluster.objects.all()
class ClusterBulkImportView(generic.BulkImportView):
queryset = Cluster.objects.all()
model_form = forms.ClusterCSVForm
table = tables.ClusterTable
class ClusterBulkEditView(generic.BulkEditView):
queryset = Cluster.objects.prefetch_related('type', 'group', 'site')
filterset = filtersets.ClusterFilterSet
table = tables.ClusterTable
form = forms.ClusterBulkEditForm
class ClusterBulkDeleteView(generic.BulkDeleteView):
queryset = Cluster.objects.prefetch_related('type', 'group', 'site')
filterset = filtersets.ClusterFilterSet
table = tables.ClusterTable
class ClusterAddDevicesView(generic.ObjectEditView):
queryset = Cluster.objects.all()
form = forms.ClusterAddDevicesForm
template_name = 'virtualization/cluster_add_devices.html'
def get(self, request, pk):
cluster = get_object_or_404(self.queryset, pk=pk)
form = self.form(cluster, initial=request.GET)
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(self.queryset, pk=pk)
form = self.form(cluster, request.POST)
if form.is_valid():
device_pks = form.cleaned_data['devices']
with transaction.atomic():
# Assign the selected Devices to the Cluster
for device in Device.objects.filter(pk__in=device_pks):
device.cluster = cluster
device.save()
messages.success(request, "Added {} devices to cluster {}".format(
len(device_pks), cluster
))
return redirect(cluster.get_absolute_url())
return render(request, self.template_name, {
'cluster': cluster,
'form': form,
'return_url': cluster.get_absolute_url(),
})
class ClusterRemoveDevicesView(generic.ObjectEditView):
queryset = Cluster.objects.all()
form = forms.ClusterRemoveDevicesForm
template_name = 'generic/bulk_remove.html'
def post(self, request, pk):
cluster = get_object_or_404(self.queryset, pk=pk)
if '_confirm' in request.POST:
form = self.form(request.POST)
if form.is_valid():
device_pks = form.cleaned_data['pk']
with transaction.atomic():
# Remove the selected Devices from the Cluster
for device in Device.objects.filter(pk__in=device_pks):
device.cluster = None
device.save()
messages.success(request, "Removed {} devices from cluster {}".format(
len(device_pks), 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
#
class VirtualMachineListView(generic.ObjectListView):
queryset = VirtualMachine.objects.all()
filterset = filtersets.VirtualMachineFilterSet
filterset_form = forms.VirtualMachineFilterForm
table = tables.VirtualMachineTable
template_name = 'virtualization/virtualmachine_list.html'
class VirtualMachineView(generic.ObjectView):
queryset = VirtualMachine.objects.prefetch_related('tenant__group')
def get_extra_context(self, request, instance):
# Interfaces
vminterfaces = VMInterface.objects.restrict(request.user, 'view').filter(
virtual_machine=instance
).prefetch_related(
Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user))
)
vminterface_table = tables.VirtualMachineVMInterfaceTable(vminterfaces, user=request.user, orderable=False)
if request.user.has_perm('virtualization.change_vminterface') or \
request.user.has_perm('virtualization.delete_vminterface'):
vminterface_table.columns.show('pk')
# Services
services = Service.objects.restrict(request.user, 'view').filter(
virtual_machine=instance
).prefetch_related(
Prefetch('ipaddresses', queryset=IPAddress.objects.restrict(request.user))
)
return {
'vminterface_table': vminterface_table,
'services': services,
}
class VirtualMachineInterfacesView(generic.ObjectChildrenView):
queryset = VirtualMachine.objects.all()
child_model = VMInterface
table = tables.VirtualMachineVMInterfaceTable
filterset = filtersets.VMInterfaceFilterSet
template_name = 'virtualization/virtualmachine/interfaces.html'
def get_children(self, request, parent):
return parent.interfaces.restrict(request.user, 'view').prefetch_related(
Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)),
'tags',
)
def get_extra_context(self, request, instance):
return {
'active_tab': 'interfaces',
}
class VirtualMachineConfigContextView(ObjectConfigContextView):
queryset = VirtualMachine.objects.annotate_config_context_data()
base_template = 'virtualization/virtualmachine.html'
class VirtualMachineEditView(generic.ObjectEditView):
queryset = VirtualMachine.objects.all()
form = forms.VirtualMachineForm
class VirtualMachineDeleteView(generic.ObjectDeleteView):
queryset = VirtualMachine.objects.all()
class VirtualMachineBulkImportView(generic.BulkImportView):
queryset = VirtualMachine.objects.all()
model_form = forms.VirtualMachineCSVForm
table = tables.VirtualMachineTable
class VirtualMachineBulkEditView(generic.BulkEditView):
queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role')
filterset = filtersets.VirtualMachineFilterSet
table = tables.VirtualMachineTable
form = forms.VirtualMachineBulkEditForm
class VirtualMachineBulkDeleteView(generic.BulkDeleteView):
queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role')
filterset = filtersets.VirtualMachineFilterSet
table = tables.VirtualMachineTable
#
# VM interfaces
#
class VMInterfaceListView(generic.ObjectListView):
queryset = VMInterface.objects.all()
filterset = filtersets.VMInterfaceFilterSet
filterset_form = forms.VMInterfaceFilterForm
table = tables.VMInterfaceTable
actions = ('import', 'export', 'bulk_edit', 'bulk_delete')
class VMInterfaceView(generic.ObjectView):
queryset = VMInterface.objects.all()
def get_extra_context(self, request, instance):
# Get assigned IP addresses
ipaddress_table = AssignedIPAddressesTable(
data=instance.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'),
orderable=False
)
# Get child interfaces
child_interfaces = VMInterface.objects.restrict(request.user, 'view').filter(parent=instance)
child_interfaces_tables = tables.VMInterfaceTable(
child_interfaces,
exclude=('virtual_machine',),
orderable=False
)
# Get assigned VLANs and annotate whether each is tagged or untagged
vlans = []
if instance.untagged_vlan is not None:
vlans.append(instance.untagged_vlan)
vlans[0].tagged = False
for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'):
vlan.tagged = True
vlans.append(vlan)
vlan_table = InterfaceVLANTable(
interface=instance,
data=vlans,
orderable=False
)
return {
'ipaddress_table': ipaddress_table,
'child_interfaces_table': child_interfaces_tables,
'vlan_table': vlan_table,
}
class VMInterfaceCreateView(generic.ComponentCreateView):
queryset = VMInterface.objects.all()
form = forms.VMInterfaceCreateForm
model_form = forms.VMInterfaceForm
patterned_fields = ('name',)
class VMInterfaceEditView(generic.ObjectEditView):
queryset = VMInterface.objects.all()
form = forms.VMInterfaceForm
template_name = 'virtualization/vminterface_edit.html'
class VMInterfaceDeleteView(generic.ObjectDeleteView):
queryset = VMInterface.objects.all()
class VMInterfaceBulkImportView(generic.BulkImportView):
queryset = VMInterface.objects.all()
model_form = forms.VMInterfaceCSVForm
table = tables.VMInterfaceTable
class VMInterfaceBulkEditView(generic.BulkEditView):
queryset = VMInterface.objects.all()
table = tables.VMInterfaceTable
form = forms.VMInterfaceBulkEditForm
class VMInterfaceBulkRenameView(generic.BulkRenameView):
queryset = VMInterface.objects.all()
form = forms.VMInterfaceBulkRenameForm
class VMInterfaceBulkDeleteView(generic.BulkDeleteView):
queryset = VMInterface.objects.all()
table = tables.VMInterfaceTable
#
# Bulk Device component creation
#
class VirtualMachineBulkAddInterfaceView(generic.BulkComponentCreateView):
parent_model = VirtualMachine
parent_field = 'virtual_machine'
form = forms.VMInterfaceBulkCreateForm
queryset = VMInterface.objects.all()
model_form = forms.VMInterfaceForm
filterset = filtersets.VirtualMachineFilterSet
table = tables.VirtualMachineTable
default_return_url = 'virtualization:virtualmachine_list'
def get_required_permission(self):
return f'virtualization.add_vminterface'