mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-23 07:56:44 -06:00
8356 add supplemental forms
This commit is contained in:
parent
5bcf351bdc
commit
12861a19a8
@ -10,7 +10,7 @@ from netbox.filtersets import OrganizationalModelFilterSet, NetBoxModelFilterSet
|
|||||||
from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
|
from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
|
||||||
from utilities.filters import MultiValueCharFilter, MultiValueMACAddressFilter, TreeNodeMultipleChoiceFilter
|
from utilities.filters import MultiValueCharFilter, MultiValueMACAddressFilter, TreeNodeMultipleChoiceFilter
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
from .models import Cluster, ClusterGroup, ClusterType, VirtualDisk, VirtualMachine, VMInterface
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ClusterFilterSet',
|
'ClusterFilterSet',
|
||||||
@ -303,3 +303,28 @@ class VMInterfaceFilterSet(NetBoxModelFilterSet, CommonInterfaceFilterSet):
|
|||||||
Q(name__icontains=value) |
|
Q(name__icontains=value) |
|
||||||
Q(description__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)
|
||||||
|
)
|
||||||
|
@ -3,7 +3,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
|
|
||||||
from utilities.forms import BootstrapMixin, form_from_model
|
from utilities.forms import BootstrapMixin, form_from_model
|
||||||
from utilities.forms.fields import ExpandableNameField
|
from utilities.forms.fields import ExpandableNameField
|
||||||
from virtualization.models import VMInterface, VirtualMachine
|
from virtualization.models import VirtualDisk, VMInterface, VirtualMachine
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'VMInterfaceBulkCreateForm',
|
'VMInterfaceBulkCreateForm',
|
||||||
@ -30,3 +30,10 @@ class VMInterfaceBulkCreateForm(
|
|||||||
VirtualMachineBulkAddComponentForm
|
VirtualMachineBulkAddComponentForm
|
||||||
):
|
):
|
||||||
replication_fields = ('name',)
|
replication_fields = ('name',)
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualDiskBulkCreateForm(
|
||||||
|
form_from_model(VirtualDisk, ['tags']),
|
||||||
|
VirtualMachineBulkAddComponentForm
|
||||||
|
):
|
||||||
|
replication_fields = ('name', 'size')
|
||||||
|
@ -18,6 +18,7 @@ __all__ = (
|
|||||||
'ClusterBulkEditForm',
|
'ClusterBulkEditForm',
|
||||||
'ClusterGroupBulkEditForm',
|
'ClusterGroupBulkEditForm',
|
||||||
'ClusterTypeBulkEditForm',
|
'ClusterTypeBulkEditForm',
|
||||||
|
'VirtualDiskBulkEditForm',
|
||||||
'VirtualMachineBulkEditForm',
|
'VirtualMachineBulkEditForm',
|
||||||
'VMInterfaceBulkEditForm',
|
'VMInterfaceBulkEditForm',
|
||||||
'VMInterfaceBulkRenameForm',
|
'VMInterfaceBulkRenameForm',
|
||||||
@ -315,3 +316,19 @@ class VMInterfaceBulkRenameForm(BulkRenameForm):
|
|||||||
queryset=VMInterface.objects.all(),
|
queryset=VMInterface.objects.all(),
|
||||||
widget=forms.MultipleHiddenInput()
|
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 = ()
|
||||||
|
@ -14,6 +14,7 @@ __all__ = (
|
|||||||
'ClusterImportForm',
|
'ClusterImportForm',
|
||||||
'ClusterGroupImportForm',
|
'ClusterGroupImportForm',
|
||||||
'ClusterTypeImportForm',
|
'ClusterTypeImportForm',
|
||||||
|
'VirtualDiskImportForm',
|
||||||
'VirtualMachineImportForm',
|
'VirtualMachineImportForm',
|
||||||
'VMInterfaceImportForm',
|
'VMInterfaceImportForm',
|
||||||
)
|
)
|
||||||
@ -199,3 +200,17 @@ class VMInterfaceImportForm(NetBoxModelImportForm):
|
|||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return self.cleaned_data['enabled']
|
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'
|
||||||
|
)
|
||||||
|
@ -16,6 +16,7 @@ __all__ = (
|
|||||||
'ClusterFilterForm',
|
'ClusterFilterForm',
|
||||||
'ClusterGroupFilterForm',
|
'ClusterGroupFilterForm',
|
||||||
'ClusterTypeFilterForm',
|
'ClusterTypeFilterForm',
|
||||||
|
'VirtualDiskFilterForm',
|
||||||
'VirtualMachineFilterForm',
|
'VirtualMachineFilterForm',
|
||||||
'VMInterfaceFilterForm',
|
'VMInterfaceFilterForm',
|
||||||
)
|
)
|
||||||
@ -221,3 +222,20 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm):
|
|||||||
label=_('L2VPN')
|
label=_('L2VPN')
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
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)
|
||||||
|
@ -22,6 +22,7 @@ __all__ = (
|
|||||||
'ClusterGroupForm',
|
'ClusterGroupForm',
|
||||||
'ClusterRemoveDevicesForm',
|
'ClusterRemoveDevicesForm',
|
||||||
'ClusterTypeForm',
|
'ClusterTypeForm',
|
||||||
|
'VirtualDiskForm',
|
||||||
'VirtualMachineForm',
|
'VirtualMachineForm',
|
||||||
'VMInterfaceForm',
|
'VMInterfaceForm',
|
||||||
)
|
)
|
||||||
@ -349,3 +350,28 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
|||||||
# Disable reassignment of VirtualMachine when editing an existing instance
|
# Disable reassignment of VirtualMachine when editing an existing instance
|
||||||
if self.instance.pk:
|
if self.instance.pk:
|
||||||
self.fields['virtual_machine'].disabled = True
|
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
|
||||||
|
@ -21,6 +21,7 @@ from utilities.tracking import TrackingModelMixin
|
|||||||
from virtualization.choices import *
|
from virtualization.choices import *
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
|
'VirtualDisk',
|
||||||
'VirtualMachine',
|
'VirtualMachine',
|
||||||
'VMInterface',
|
'VMInterface',
|
||||||
)
|
)
|
||||||
|
@ -4,9 +4,10 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from dcim.tables.devices import BaseInterfaceTable
|
from dcim.tables.devices import BaseInterfaceTable
|
||||||
from netbox.tables import NetBoxTable, columns
|
from netbox.tables import NetBoxTable, columns
|
||||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||||
from virtualization.models import VirtualMachine, VMInterface
|
from virtualization.models import VirtualDisk, VirtualMachine, VMInterface
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
|
'VirtualDiskTable',
|
||||||
'VirtualMachineTable',
|
'VirtualMachineTable',
|
||||||
'VirtualMachineVMInterfaceTable',
|
'VirtualMachineVMInterfaceTable',
|
||||||
'VMInterfaceTable',
|
'VMInterfaceTable',
|
||||||
@ -155,3 +156,19 @@ class VirtualMachineVMInterfaceTable(VMInterfaceTable):
|
|||||||
row_attrs = {
|
row_attrs = {
|
||||||
'data-name': lambda record: record.name,
|
'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,
|
||||||
|
}
|
||||||
|
@ -48,4 +48,13 @@ urlpatterns = [
|
|||||||
path('interfaces/<int:pk>/', include(get_model_urls('virtualization', 'vminterface'))),
|
path('interfaces/<int:pk>/', include(get_model_urls('virtualization', 'vminterface'))),
|
||||||
path('virtual-machines/interfaces/add/', views.VirtualMachineBulkAddInterfaceView.as_view(), name='virtualmachine_bulk_add_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'),
|
||||||
]
|
]
|
||||||
|
@ -21,7 +21,7 @@ from tenancy.views import ObjectContactsView
|
|||||||
from utilities.utils import count_related
|
from utilities.utils import count_related
|
||||||
from utilities.views import ViewTab, register_model_view
|
from utilities.views import ViewTab, register_model_view
|
||||||
from . import filtersets, forms, tables
|
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):
|
def get_required_permission(self):
|
||||||
return f'virtualization.add_vminterface'
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user