mirror of
https://github.com/netbox-community/netbox.git
synced 2026-04-14 05:00:13 +02:00
@@ -3,7 +3,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from rest_framework import serializers
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import OrganizationalModelSerializer, PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from virtualization.choices import *
|
||||
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
||||
@@ -16,7 +16,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ClusterTypeSerializer(NetBoxModelSerializer):
|
||||
class ClusterTypeSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
cluster_count = RelatedObjectCountField('clusters')
|
||||
@@ -24,13 +24,13 @@ class ClusterTypeSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = ClusterType
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'owner', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'cluster_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'cluster_count')
|
||||
|
||||
|
||||
class ClusterGroupSerializer(NetBoxModelSerializer):
|
||||
class ClusterGroupSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
cluster_count = RelatedObjectCountField('clusters')
|
||||
@@ -38,13 +38,13 @@ class ClusterGroupSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = ClusterGroup
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'owner', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'cluster_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'cluster_count')
|
||||
|
||||
|
||||
class ClusterSerializer(NetBoxModelSerializer):
|
||||
class ClusterSerializer(PrimaryModelSerializer):
|
||||
type = ClusterTypeSerializer(nested=True)
|
||||
group = ClusterGroupSerializer(nested=True, required=False, allow_null=True, default=None)
|
||||
status = ChoiceField(choices=ClusterStatusChoices, required=False)
|
||||
@@ -76,7 +76,7 @@ class ClusterSerializer(NetBoxModelSerializer):
|
||||
model = Cluster
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'type', 'group', 'status', 'tenant', 'scope_type',
|
||||
'scope_id', 'scope', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'scope_id', 'scope', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'device_count', 'virtualmachine_count', 'allocated_vcpus', 'allocated_memory', 'allocated_disk'
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description', 'virtualmachine_count')
|
||||
|
||||
@@ -13,7 +13,7 @@ from ipam.api.serializers_.vlans import VLANSerializer, VLANTranslationPolicySer
|
||||
from ipam.api.serializers_.vrfs import VRFSerializer
|
||||
from ipam.models import VLAN
|
||||
from netbox.api.fields import ChoiceField, SerializedPKRelatedField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import NetBoxModelSerializer, PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from virtualization.choices import *
|
||||
from virtualization.models import VirtualDisk, VirtualMachine, VMInterface
|
||||
@@ -29,7 +29,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class VirtualMachineSerializer(NetBoxModelSerializer):
|
||||
class VirtualMachineSerializer(PrimaryModelSerializer):
|
||||
status = ChoiceField(choices=VirtualMachineStatusChoices, required=False)
|
||||
site = SiteSerializer(nested=True, required=False, allow_null=True, default=None)
|
||||
cluster = ClusterSerializer(nested=True, required=False, allow_null=True, default=None)
|
||||
@@ -51,8 +51,8 @@ class VirtualMachineSerializer(NetBoxModelSerializer):
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'status', 'site', 'cluster', 'device', 'serial', 'role',
|
||||
'tenant', 'platform', 'primary_ip', 'primary_ip4', 'primary_ip6', 'vcpus', 'memory', 'disk', 'description',
|
||||
'comments', 'config_template', 'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'interface_count', 'virtual_disk_count',
|
||||
'owner', 'comments', 'config_template', 'local_context_data', 'tags', 'custom_fields', 'created',
|
||||
'last_updated', 'interface_count', 'virtual_disk_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@ from dcim.models import MACAddress
|
||||
from extras.filtersets import LocalConfigContextFilterSet
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.filtersets import PrimaryIPFilterSet
|
||||
from netbox.filtersets import OrganizationalModelFilterSet, NetBoxModelFilterSet
|
||||
from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet, PrimaryModelFilterSet
|
||||
from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
|
||||
|
||||
from users.filterset_mixins import OwnerFilterMixin
|
||||
from utilities.filters import MultiValueCharFilter, MultiValueMACAddressFilter, TreeNodeMultipleChoiceFilter
|
||||
from .choices import *
|
||||
from .models import *
|
||||
@@ -39,7 +41,7 @@ class ClusterGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet)
|
||||
fields = ('id', 'name', 'slug', 'description')
|
||||
|
||||
|
||||
class ClusterFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ScopedFilterSet, ContactModelFilterSet):
|
||||
class ClusterFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ScopedFilterSet, ContactModelFilterSet):
|
||||
group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
label=_('Parent group (ID)'),
|
||||
@@ -80,7 +82,7 @@ class ClusterFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ScopedFilterSet,
|
||||
|
||||
|
||||
class VirtualMachineFilterSet(
|
||||
NetBoxModelFilterSet,
|
||||
PrimaryModelFilterSet,
|
||||
TenancyFilterSet,
|
||||
ContactModelFilterSet,
|
||||
LocalConfigContextFilterSet,
|
||||
@@ -235,7 +237,7 @@ class VirtualMachineFilterSet(
|
||||
return queryset.exclude(params)
|
||||
|
||||
|
||||
class VMInterfaceFilterSet(NetBoxModelFilterSet, CommonInterfaceFilterSet):
|
||||
class VMInterfaceFilterSet(CommonInterfaceFilterSet, OwnerFilterMixin, NetBoxModelFilterSet):
|
||||
cluster_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine__cluster',
|
||||
queryset=Cluster.objects.all(),
|
||||
@@ -297,7 +299,7 @@ class VMInterfaceFilterSet(NetBoxModelFilterSet, CommonInterfaceFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class VirtualDiskFilterSet(NetBoxModelFilterSet):
|
||||
class VirtualDiskFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
|
||||
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine',
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
|
||||
@@ -7,10 +7,11 @@ from dcim.forms.mixins import ScopedBulkEditForm
|
||||
from dcim.models import Device, DeviceRole, Platform, Site
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.models import VLAN, VLANGroup, VLANTranslationPolicy, VRF
|
||||
from netbox.forms import NetBoxModelBulkEditForm
|
||||
from netbox.forms import NetBoxModelBulkEditForm, OrganizationalModelBulkEditForm, PrimaryModelBulkEditForm
|
||||
from netbox.forms.mixins import OwnerMixin
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms import BulkRenameForm, add_blank_choice
|
||||
from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField
|
||||
from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import BulkEditNullBooleanSelect
|
||||
from virtualization.choices import *
|
||||
@@ -28,13 +29,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ClusterTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
class ClusterTypeBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
model = ClusterType
|
||||
fieldsets = (
|
||||
FieldSet('description'),
|
||||
@@ -42,13 +37,7 @@ class ClusterTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('description',)
|
||||
|
||||
|
||||
class ClusterGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
class ClusterGroupBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
model = ClusterGroup
|
||||
fieldsets = (
|
||||
FieldSet('description'),
|
||||
@@ -56,7 +45,7 @@ class ClusterGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('description',)
|
||||
|
||||
|
||||
class ClusterBulkEditForm(ScopedBulkEditForm, NetBoxModelBulkEditForm):
|
||||
class ClusterBulkEditForm(ScopedBulkEditForm, PrimaryModelBulkEditForm):
|
||||
type = DynamicModelChoiceField(
|
||||
label=_('Type'),
|
||||
queryset=ClusterType.objects.all(),
|
||||
@@ -78,12 +67,6 @@ class ClusterBulkEditForm(ScopedBulkEditForm, NetBoxModelBulkEditForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Cluster
|
||||
fieldsets = (
|
||||
@@ -95,7 +78,7 @@ class ClusterBulkEditForm(ScopedBulkEditForm, NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VirtualMachineBulkEditForm(PrimaryModelBulkEditForm):
|
||||
status = forms.ChoiceField(
|
||||
label=_('Status'),
|
||||
choices=add_blank_choice(VirtualMachineStatusChoices),
|
||||
@@ -155,16 +138,10 @@ class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
label=_('Disk (MB)')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
config_template = DynamicModelChoiceField(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = VirtualMachine
|
||||
fieldsets = (
|
||||
@@ -177,7 +154,7 @@ class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VMInterfaceBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm):
|
||||
virtual_machine = forms.ModelChoiceField(
|
||||
label=_('Virtual machine'),
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
@@ -311,7 +288,7 @@ class VMInterfaceBulkRenameForm(BulkRenameForm):
|
||||
)
|
||||
|
||||
|
||||
class VirtualDiskBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VirtualDiskBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm):
|
||||
virtual_machine = forms.ModelChoiceField(
|
||||
label=_('Virtual machine'),
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
|
||||
@@ -5,9 +5,11 @@ from dcim.forms.mixins import ScopedImportForm
|
||||
from dcim.models import Device, DeviceRole, Platform, Site
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.models import VRF
|
||||
from netbox.forms import NetBoxModelImportForm
|
||||
from netbox.forms import (
|
||||
NetBoxModelImportForm, OrganizationalModelImportForm, OwnerCSVMixin, PrimaryModelImportForm,
|
||||
)
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField, SlugField
|
||||
from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField
|
||||
from virtualization.choices import *
|
||||
from virtualization.models import *
|
||||
|
||||
@@ -21,23 +23,21 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ClusterTypeImportForm(NetBoxModelImportForm):
|
||||
slug = SlugField()
|
||||
class ClusterTypeImportForm(OrganizationalModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ClusterType
|
||||
fields = ('name', 'slug', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class ClusterGroupImportForm(NetBoxModelImportForm):
|
||||
slug = SlugField()
|
||||
class ClusterGroupImportForm(OrganizationalModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ClusterGroup
|
||||
fields = ('name', 'slug', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class ClusterImportForm(ScopedImportForm, NetBoxModelImportForm):
|
||||
class ClusterImportForm(ScopedImportForm, PrimaryModelImportForm):
|
||||
type = CSVModelChoiceField(
|
||||
label=_('Type'),
|
||||
queryset=ClusterType.objects.all(),
|
||||
@@ -74,14 +74,15 @@ class ClusterImportForm(ScopedImportForm, NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = Cluster
|
||||
fields = (
|
||||
'name', 'type', 'group', 'status', 'scope_type', 'scope_id', 'tenant', 'description', 'comments', 'tags',
|
||||
'name', 'type', 'group', 'status', 'scope_type', 'scope_id', 'tenant', 'description', 'owner', 'comments',
|
||||
'tags',
|
||||
)
|
||||
labels = {
|
||||
'scope_id': _('Scope ID'),
|
||||
}
|
||||
|
||||
|
||||
class VirtualMachineImportForm(NetBoxModelImportForm):
|
||||
class VirtualMachineImportForm(PrimaryModelImportForm):
|
||||
status = CSVChoiceField(
|
||||
label=_('Status'),
|
||||
choices=VirtualMachineStatusChoices,
|
||||
@@ -143,11 +144,11 @@ class VirtualMachineImportForm(NetBoxModelImportForm):
|
||||
model = VirtualMachine
|
||||
fields = (
|
||||
'name', 'status', 'role', 'site', 'cluster', 'device', 'tenant', 'platform', 'vcpus', 'memory', 'disk',
|
||||
'description', 'serial', 'config_template', 'comments', 'tags',
|
||||
'description', 'serial', 'config_template', 'comments', 'owner', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class VMInterfaceImportForm(NetBoxModelImportForm):
|
||||
class VMInterfaceImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
virtual_machine = CSVModelChoiceField(
|
||||
label=_('Virtual machine'),
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
@@ -185,7 +186,7 @@ class VMInterfaceImportForm(NetBoxModelImportForm):
|
||||
model = VMInterface
|
||||
fields = (
|
||||
'virtual_machine', 'name', 'parent', 'bridge', 'enabled', 'mtu', 'description', 'mode',
|
||||
'vrf', 'tags'
|
||||
'vrf', 'owner', 'tags'
|
||||
)
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -208,7 +209,7 @@ class VMInterfaceImportForm(NetBoxModelImportForm):
|
||||
return self.cleaned_data['enabled']
|
||||
|
||||
|
||||
class VirtualDiskImportForm(NetBoxModelImportForm):
|
||||
class VirtualDiskImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
virtual_machine = CSVModelChoiceField(
|
||||
label=_('Virtual machine'),
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
@@ -218,5 +219,5 @@ class VirtualDiskImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = VirtualDisk
|
||||
fields = (
|
||||
'virtual_machine', 'name', 'size', 'description', 'tags'
|
||||
'virtual_machine', 'name', 'size', 'description', 'owner', 'tags'
|
||||
)
|
||||
|
||||
@@ -6,10 +6,11 @@ from dcim.models import Device, DeviceRole, Location, Platform, Region, Site, Si
|
||||
from extras.forms import LocalConfigContextFilterForm
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.models import VRF, VLANTranslationPolicy
|
||||
from netbox.forms import NetBoxModelFilterSetForm
|
||||
from netbox.forms import NetBoxModelFilterSetForm, OrganizationalModelFilterSetForm, PrimaryModelFilterSetForm
|
||||
from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
|
||||
from users.models import Owner
|
||||
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES
|
||||
from utilities.forms.fields import DynamicModelMultipleChoiceField, TagFilterField
|
||||
from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, TagFilterField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from virtualization.choices import *
|
||||
from virtualization.models import *
|
||||
@@ -25,24 +26,27 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ClusterTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
class ClusterTypeFilterForm(OrganizationalModelFilterSetForm):
|
||||
model = ClusterType
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class ClusterGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class ClusterGroupFilterForm(ContactModelFilterForm, OrganizationalModelFilterSetForm):
|
||||
model = ClusterGroup
|
||||
tag = TagFilterField(model)
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
)
|
||||
|
||||
|
||||
class ClusterFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class ClusterFilterForm(TenancyFilterForm, ContactModelFilterForm, PrimaryModelFilterSetForm):
|
||||
model = Cluster
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('group_id', 'type_id', 'status', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Scope')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
@@ -97,11 +101,11 @@ class VirtualMachineFilterForm(
|
||||
LocalConfigContextFilterForm,
|
||||
TenancyFilterForm,
|
||||
ContactModelFilterForm,
|
||||
NetBoxModelFilterSetForm
|
||||
PrimaryModelFilterSetForm
|
||||
):
|
||||
model = VirtualMachine
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('cluster_group_id', 'cluster_type_id', 'cluster_id', 'device_id', name=_('Cluster')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -199,7 +203,7 @@ class VirtualMachineFilterForm(
|
||||
class VMInterfaceFilterForm(NetBoxModelFilterSetForm):
|
||||
model = VMInterface
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('cluster_id', 'virtual_machine_id', name=_('Virtual Machine')),
|
||||
FieldSet('enabled', name=_('Attributes')),
|
||||
FieldSet('vrf_id', 'l2vpn_id', 'mac_address', name=_('Addressing')),
|
||||
@@ -250,13 +254,18 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm):
|
||||
required=False,
|
||||
label=_('VLAN Translation Policy')
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class VirtualDiskFilterForm(NetBoxModelFilterSetForm):
|
||||
model = VirtualDisk
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('virtual_machine_id', name=_('Virtual Machine')),
|
||||
FieldSet('size', name=_('Attributes')),
|
||||
)
|
||||
@@ -270,4 +279,9 @@ class VirtualDiskFilterForm(NetBoxModelFilterSetForm):
|
||||
required=False,
|
||||
min_value=1
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
@@ -10,12 +10,11 @@ from dcim.models import Device, DeviceRole, MACAddress, Platform, Rack, Region,
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.choices import VLANQinQRoleChoices
|
||||
from ipam.models import IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF
|
||||
from netbox.forms import NetBoxModelForm
|
||||
from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
|
||||
from netbox.forms.mixins import OwnerMixin
|
||||
from tenancy.forms import TenancyForm
|
||||
from utilities.forms import ConfirmationForm
|
||||
from utilities.forms.fields import (
|
||||
CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, SlugField,
|
||||
)
|
||||
from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import HTMXSelect
|
||||
from virtualization.models import *
|
||||
@@ -32,9 +31,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ClusterTypeForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class ClusterTypeForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Type')),
|
||||
)
|
||||
@@ -42,13 +39,11 @@ class ClusterTypeForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = ClusterType
|
||||
fields = (
|
||||
'name', 'slug', 'description', 'tags',
|
||||
'name', 'slug', 'description', 'owner', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class ClusterGroupForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class ClusterGroupForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Group')),
|
||||
)
|
||||
@@ -56,11 +51,11 @@ class ClusterGroupForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = ClusterGroup
|
||||
fields = (
|
||||
'name', 'slug', 'description', 'tags',
|
||||
'name', 'slug', 'description', 'owner', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class ClusterForm(TenancyForm, ScopedForm, NetBoxModelForm):
|
||||
class ClusterForm(TenancyForm, ScopedForm, PrimaryModelForm):
|
||||
type = DynamicModelChoiceField(
|
||||
label=_('Type'),
|
||||
queryset=ClusterType.objects.all(),
|
||||
@@ -72,7 +67,6 @@ class ClusterForm(TenancyForm, ScopedForm, NetBoxModelForm):
|
||||
required=False,
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'type', 'group', 'status', 'description', 'tags', name=_('Cluster')),
|
||||
@@ -83,7 +77,7 @@ class ClusterForm(TenancyForm, ScopedForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Cluster
|
||||
fields = (
|
||||
'name', 'type', 'group', 'status', 'tenant', 'scope_type', 'description', 'comments', 'tags',
|
||||
'name', 'type', 'group', 'status', 'tenant', 'scope_type', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
@@ -173,7 +167,7 @@ class ClusterRemoveDevicesForm(ConfirmationForm):
|
||||
)
|
||||
|
||||
|
||||
class VirtualMachineForm(TenancyForm, NetBoxModelForm):
|
||||
class VirtualMachineForm(TenancyForm, PrimaryModelForm):
|
||||
site = DynamicModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -221,7 +215,6 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
|
||||
required=False,
|
||||
label=_('Config template')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'role', 'status', 'description', 'serial', 'tags', name=_('Virtual Machine')),
|
||||
@@ -236,7 +229,7 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
|
||||
model = VirtualMachine
|
||||
fields = [
|
||||
'name', 'status', 'site', 'cluster', 'device', 'role', 'tenant_group', 'tenant', 'platform', 'primary_ip4',
|
||||
'primary_ip6', 'vcpus', 'memory', 'disk', 'description', 'serial', 'comments', 'tags',
|
||||
'primary_ip6', 'vcpus', 'memory', 'disk', 'description', 'serial', 'owner', 'comments', 'tags',
|
||||
'local_context_data', 'config_template',
|
||||
]
|
||||
|
||||
@@ -288,7 +281,7 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
|
||||
# Virtual machine components
|
||||
#
|
||||
|
||||
class VMComponentForm(NetBoxModelForm):
|
||||
class VMComponentForm(OwnerMixin, NetBoxModelForm):
|
||||
virtual_machine = DynamicModelChoiceField(
|
||||
label=_('Virtual machine'),
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
@@ -387,7 +380,7 @@ class VMInterfaceForm(InterfaceCommonForm, VMComponentForm):
|
||||
fields = [
|
||||
'virtual_machine', 'name', 'parent', 'bridge', 'enabled', 'mtu', 'description', 'mode', 'vlan_group',
|
||||
'untagged_vlan', 'tagged_vlans', 'qinq_svlan', 'vlan_translation_policy', 'vrf', 'primary_mac_address',
|
||||
'tags',
|
||||
'owner', 'tags',
|
||||
]
|
||||
labels = {
|
||||
'mode': _('802.1Q Mode'),
|
||||
@@ -406,5 +399,5 @@ class VirtualDiskForm(VMComponentForm):
|
||||
class Meta:
|
||||
model = VirtualDisk
|
||||
fields = [
|
||||
'virtual_machine', 'name', 'size', 'description', 'tags',
|
||||
'virtual_machine', 'name', 'size', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
@@ -6,7 +6,8 @@ import strawberry_django
|
||||
from extras.graphql.mixins import ConfigContextMixin, ContactsMixin
|
||||
from ipam.graphql.mixins import IPAddressesMixin, VLANGroupsMixin
|
||||
from netbox.graphql.scalars import BigInt
|
||||
from netbox.graphql.types import OrganizationalObjectType, NetBoxObjectType
|
||||
from netbox.graphql.types import OrganizationalObjectType, PrimaryObjectType, NetBoxObjectType
|
||||
from users.graphql.mixins import OwnerMixin
|
||||
from virtualization import models
|
||||
from .filters import *
|
||||
|
||||
@@ -36,7 +37,7 @@ __all__ = (
|
||||
|
||||
|
||||
@strawberry.type
|
||||
class ComponentType(NetBoxObjectType):
|
||||
class ComponentType(OwnerMixin, NetBoxObjectType):
|
||||
"""
|
||||
Base type for device/VM components
|
||||
"""
|
||||
@@ -49,7 +50,7 @@ class ComponentType(NetBoxObjectType):
|
||||
filters=ClusterFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ClusterType(ContactsMixin, VLANGroupsMixin, NetBoxObjectType):
|
||||
class ClusterType(ContactsMixin, VLANGroupsMixin, PrimaryObjectType):
|
||||
type: Annotated["ClusterTypeType", strawberry.lazy('virtualization.graphql.types')] | None
|
||||
group: Annotated["ClusterGroupType", strawberry.lazy('virtualization.graphql.types')] | None
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -94,7 +95,7 @@ class ClusterTypeType(OrganizationalObjectType):
|
||||
filters=VirtualMachineFilter,
|
||||
pagination=True
|
||||
)
|
||||
class VirtualMachineType(ConfigContextMixin, ContactsMixin, NetBoxObjectType):
|
||||
class VirtualMachineType(ConfigContextMixin, ContactsMixin, PrimaryObjectType):
|
||||
interface_count: BigInt
|
||||
virtual_disk_count: BigInt
|
||||
interface_count: BigInt
|
||||
|
||||
54
netbox/virtualization/migrations/0049_owner.py
Normal file
54
netbox/virtualization/migrations/0049_owner.py
Normal file
@@ -0,0 +1,54 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('users', '0015_owner'),
|
||||
('virtualization', '0048_populate_mac_addresses'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cluster',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='clustergroup',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='clustertype',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='virtualdisk',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='virtualmachine',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vminterface',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -15,6 +15,7 @@ from extras.querysets import ConfigContextModelQuerySet
|
||||
from netbox.config import get_config
|
||||
from netbox.models import NetBoxModel, PrimaryModel
|
||||
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
|
||||
from netbox.models.mixins import OwnerMixin
|
||||
from utilities.fields import CounterCacheField, NaturalOrderingField
|
||||
from utilities.ordering import naturalize_interface
|
||||
from utilities.query_functions import CollateAsChar
|
||||
@@ -263,7 +264,7 @@ class VirtualMachine(ContactsMixin, ImageAttachmentsMixin, RenderConfigMixin, Co
|
||||
#
|
||||
|
||||
|
||||
class ComponentModel(NetBoxModel):
|
||||
class ComponentModel(OwnerMixin, NetBoxModel):
|
||||
"""
|
||||
An abstract model inherited by any model which has a parent VirtualMachine.
|
||||
"""
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from netbox.tables import OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
||||
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
|
||||
__all__ = (
|
||||
'ClusterTable',
|
||||
'ClusterGroupTable',
|
||||
@@ -12,7 +12,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ClusterTypeTable(NetBoxTable):
|
||||
class ClusterTypeTable(OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -26,7 +26,7 @@ class ClusterTypeTable(NetBoxTable):
|
||||
url_name='virtualization:clustertype_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = ClusterType
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'slug', 'cluster_count', 'description', 'created', 'last_updated', 'tags', 'actions',
|
||||
@@ -34,7 +34,7 @@ class ClusterTypeTable(NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'cluster_count', 'description')
|
||||
|
||||
|
||||
class ClusterGroupTable(ContactsColumnMixin, NetBoxTable):
|
||||
class ClusterGroupTable(ContactsColumnMixin, OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -48,7 +48,7 @@ class ClusterGroupTable(ContactsColumnMixin, NetBoxTable):
|
||||
url_name='virtualization:clustergroup_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = ClusterGroup
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'slug', 'cluster_count', 'description', 'contacts', 'tags', 'created', 'last_updated',
|
||||
@@ -57,7 +57,7 @@ class ClusterGroupTable(ContactsColumnMixin, NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'cluster_count', 'description')
|
||||
|
||||
|
||||
class ClusterTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
class ClusterTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -91,14 +91,11 @@ class ClusterTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
url_params={'cluster_id': 'pk'},
|
||||
verbose_name=_('VMs')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='virtualization:cluster_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Cluster
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'type', 'group', 'status', 'tenant', 'tenant_group', 'scope', 'scope_type',
|
||||
|
||||
@@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from dcim.tables.devices import BaseInterfaceTable
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import NetBoxTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
from utilities.templatetags.helpers import humanize_disk_megabytes
|
||||
from virtualization.models import VirtualDisk, VirtualMachine, VMInterface
|
||||
@@ -21,7 +21,7 @@ __all__ = (
|
||||
# Virtual machines
|
||||
#
|
||||
|
||||
class VirtualMachineTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
class VirtualMachineTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -48,9 +48,6 @@ class VirtualMachineTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable)
|
||||
linkify=True,
|
||||
verbose_name=_('Platform')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
primary_ip4 = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('IPv4 Address')
|
||||
@@ -81,7 +78,7 @@ class VirtualMachineTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable)
|
||||
verbose_name=_('Disk'),
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = VirtualMachine
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'status', 'site', 'cluster', 'device', 'role', 'tenant', 'tenant_group', 'vcpus',
|
||||
|
||||
Reference in New Issue
Block a user