8356 add supplemental forms

This commit is contained in:
Arthur 2023-10-18 16:21:29 -07:00
parent 5bcf351bdc
commit 12861a19a8
10 changed files with 219 additions and 4 deletions

View File

@ -10,7 +10,7 @@ from netbox.filtersets import OrganizationalModelFilterSet, NetBoxModelFilterSet
from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
from utilities.filters import MultiValueCharFilter, MultiValueMACAddressFilter, TreeNodeMultipleChoiceFilter
from .choices import *
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
from .models import Cluster, ClusterGroup, ClusterType, VirtualDisk, VirtualMachine, VMInterface
__all__ = (
'ClusterFilterSet',
@ -303,3 +303,28 @@ class VMInterfaceFilterSet(NetBoxModelFilterSet, CommonInterfaceFilterSet):
Q(name__icontains=value) |
Q(description__icontains=value)
)
class VirtualDiskFilterSet(NetBoxModelFilterSet):
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine',
queryset=VirtualMachine.objects.all(),
label=_('Virtual machine (ID)'),
)
virtual_machine = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine__name',
queryset=VirtualMachine.objects.all(),
to_field_name='name',
label=_('Virtual machine'),
)
class Meta:
model = VirtualDisk
fields = ['id', 'name', 'size',]
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value)
)

View File

@ -3,7 +3,7 @@ from django.utils.translation import gettext_lazy as _
from utilities.forms import BootstrapMixin, form_from_model
from utilities.forms.fields import ExpandableNameField
from virtualization.models import VMInterface, VirtualMachine
from virtualization.models import VirtualDisk, VMInterface, VirtualMachine
__all__ = (
'VMInterfaceBulkCreateForm',
@ -30,3 +30,10 @@ class VMInterfaceBulkCreateForm(
VirtualMachineBulkAddComponentForm
):
replication_fields = ('name',)
class VirtualDiskBulkCreateForm(
form_from_model(VirtualDisk, ['tags']),
VirtualMachineBulkAddComponentForm
):
replication_fields = ('name', 'size')

View File

@ -18,6 +18,7 @@ __all__ = (
'ClusterBulkEditForm',
'ClusterGroupBulkEditForm',
'ClusterTypeBulkEditForm',
'VirtualDiskBulkEditForm',
'VirtualMachineBulkEditForm',
'VMInterfaceBulkEditForm',
'VMInterfaceBulkRenameForm',
@ -315,3 +316,19 @@ class VMInterfaceBulkRenameForm(BulkRenameForm):
queryset=VMInterface.objects.all(),
widget=forms.MultipleHiddenInput()
)
class VirtualDiskBulkEditForm(NetBoxModelBulkEditForm):
virtual_machine = forms.ModelChoiceField(
label=_('Virtual machine'),
queryset=VirtualMachine.objects.all(),
required=False,
disabled=True,
widget=forms.HiddenInput()
)
model = VirtualDisk
fieldsets = (
(None, ('mtu', 'enabled', 'vrf', 'size')),
)
nullable_fields = ()

View File

@ -14,6 +14,7 @@ __all__ = (
'ClusterImportForm',
'ClusterGroupImportForm',
'ClusterTypeImportForm',
'VirtualDiskImportForm',
'VirtualMachineImportForm',
'VMInterfaceImportForm',
)
@ -199,3 +200,17 @@ class VMInterfaceImportForm(NetBoxModelImportForm):
return True
else:
return self.cleaned_data['enabled']
class VirtualDiskImportForm(NetBoxModelImportForm):
virtual_machine = CSVModelChoiceField(
label=_('Virtual machine'),
queryset=VirtualMachine.objects.all(),
to_field_name='name'
)
class Meta:
model = VirtualDisk
fields = (
'virtual_machine', 'name', 'size', 'tags'
)

View File

@ -16,6 +16,7 @@ __all__ = (
'ClusterFilterForm',
'ClusterGroupFilterForm',
'ClusterTypeFilterForm',
'VirtualDiskFilterForm',
'VirtualMachineFilterForm',
'VMInterfaceFilterForm',
)
@ -221,3 +222,20 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm):
label=_('L2VPN')
)
tag = TagFilterField(model)
class VirtualDiskFilterForm(NetBoxModelFilterSetForm):
model = VirtualDisk
fieldsets = (
(None, ('q', 'filter_id', 'tag')),
(_('Virtual Machine'), ('virtual_machine_id')),
)
virtual_machine_id = DynamicModelMultipleChoiceField(
queryset=VirtualMachine.objects.all(),
required=False,
query_params={
'cluster_id': '$cluster_id'
},
label=_('Virtual machine')
)
tag = TagFilterField(model)

View File

@ -22,6 +22,7 @@ __all__ = (
'ClusterGroupForm',
'ClusterRemoveDevicesForm',
'ClusterTypeForm',
'VirtualDiskForm',
'VirtualMachineForm',
'VMInterfaceForm',
)
@ -349,3 +350,28 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
# Disable reassignment of VirtualMachine when editing an existing instance
if self.instance.pk:
self.fields['virtual_machine'].disabled = True
class VirtualDiskForm(NetBoxModelForm):
virtual_machine = DynamicModelChoiceField(
label=_('Virtual machine'),
queryset=VirtualMachine.objects.all(),
selector=True
)
fieldsets = (
(_(''), ('virtual_machine', 'name', 'size', 'tags')),
)
class Meta:
model = VirtualDisk
fields = [
'virtual_machine', 'name', 'size', 'tags',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Disable reassignment of VirtualMachine when editing an existing instance
if self.instance.pk:
self.fields['virtual_machine'].disabled = True

View File

@ -21,6 +21,7 @@ from utilities.tracking import TrackingModelMixin
from virtualization.choices import *
__all__ = (
'VirtualDisk',
'VirtualMachine',
'VMInterface',
)

View File

@ -4,9 +4,10 @@ from django.utils.translation import gettext_lazy as _
from dcim.tables.devices import BaseInterfaceTable
from netbox.tables import NetBoxTable, columns
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
from virtualization.models import VirtualMachine, VMInterface
from virtualization.models import VirtualDisk, VirtualMachine, VMInterface
__all__ = (
'VirtualDiskTable',
'VirtualMachineTable',
'VirtualMachineVMInterfaceTable',
'VMInterfaceTable',
@ -155,3 +156,19 @@ class VirtualMachineVMInterfaceTable(VMInterfaceTable):
row_attrs = {
'data-name': lambda record: record.name,
}
class VirtualDiskTable(VMInterfaceTable):
actions = columns.ActionsColumn(
actions=('edit', 'delete'),
)
class Meta(NetBoxTable.Meta):
model = VirtualDisk
fields = (
'pk', 'id', 'name', 'size', 'tags', 'actions',
)
default_columns = ('pk', 'name', 'size')
row_attrs = {
'data-name': lambda record: record.name,
}

View File

@ -48,4 +48,13 @@ urlpatterns = [
path('interfaces/<int:pk>/', include(get_model_urls('virtualization', 'vminterface'))),
path('virtual-machines/interfaces/add/', views.VirtualMachineBulkAddInterfaceView.as_view(), name='virtualmachine_bulk_add_vminterface'),
# Virtual disks
# path('disks/', views.VirtualDiskListView.as_view(), name='virtualdisk_list'),
# path('disks/add/', views.VirtualDiskCreateView.as_view(), name='virtualdisk_add'),
# path('disks/import/', views.VirtualDiskBulkImportView.as_view(), name='virtualdisk_import'),
# path('disks/edit/', views.VirtualDiskBulkEditView.as_view(), name='virtualdisk_bulk_edit'),
# path('disks/rename/', views.VirtualDiskBulkRenameView.as_view(), name='virtualdisk_bulk_rename'),
# path('disks/delete/', views.VirtualDiskBulkDeleteView.as_view(), name='virtualdisk_bulk_delete'),
# path('disks/<int:pk>/', include(get_model_urls('virtualization', 'virtualdisk'))),
# path('virtual-machines/disks/add/', views.VirtualMachineBulkAddDiskView.as_view(), name='virtualmachine_bulk_add_disk'),
]

View File

@ -21,7 +21,7 @@ from tenancy.views import ObjectContactsView
from utilities.utils import count_related
from utilities.views import ViewTab, register_model_view
from . import filtersets, forms, tables
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
from .models import Cluster, ClusterGroup, ClusterType, VirtualDisk, VirtualMachine, VMInterface
#
@ -574,3 +574,83 @@ class VirtualMachineBulkAddInterfaceView(generic.BulkComponentCreateView):
def get_required_permission(self):
return f'virtualization.add_vminterface'
#
# Virtual Disk
#
class VirtualDiskListView(generic.ObjectListView):
queryset = VirtualDisk.objects.all()
filterset = filtersets.VirtualDiskFilterSet
filterset_form = forms.VirtualDiskFilterForm
table = tables.VirtualDiskTable
@register_model_view(VirtualDisk)
class VirtualDiskView(generic.ObjectView):
queryset = VirtualDisk.objects.all()
def get_extra_context(self, request, instance):
# Get child interfaces
child_interfaces = VirtualDisk.objects.restrict(request.user, 'view').filter(parent=instance)
child_interfaces_tables = tables.VirtualDiskTable(
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 {
'child_interfaces_table': child_interfaces_tables,
'vlan_table': vlan_table,
}
# class VirtualDiskCreateView(generic.ComponentCreateView):
# queryset = VirtualDisk.objects.all()
# form = forms.VirtualDiskCreateForm
# model_form = forms.VirtualDiskForm
@register_model_view(VirtualDisk, 'edit')
class VirtualDiskEditView(generic.ObjectEditView):
queryset = VirtualDisk.objects.all()
form = forms.VirtualDiskForm
@register_model_view(VirtualDisk, 'delete')
class VirtualDiskDeleteView(generic.ObjectDeleteView):
queryset = VirtualDisk.objects.all()
class VirtualDiskBulkImportView(generic.BulkImportView):
queryset = VirtualDisk.objects.all()
model_form = forms.VirtualDiskImportForm
class VirtualDiskBulkEditView(generic.BulkEditView):
queryset = VirtualDisk.objects.all()
filterset = filtersets.VirtualDiskFilterSet
table = tables.VirtualDiskTable
form = forms.VirtualDiskBulkEditForm
class VirtualDiskBulkDeleteView(generic.BulkDeleteView):
queryset = VirtualDisk.objects.all()
filterset = filtersets.VirtualDiskFilterSet
table = tables.VirtualDiskTable