mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-18 19:32:24 -06:00
Closes #20304: Object owners (#20634)
Some checks failed
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Has been cancelled
Some checks failed
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Has been cancelled
This commit is contained in:
11723
contrib/openapi.json
11723
contrib/openapi.json
File diff suppressed because it is too large
Load Diff
10
docs/features/resource-ownership.md
Normal file
10
docs/features/resource-ownership.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Resource Ownership
|
||||
|
||||
!!! info "This feature was introduced in NetBox v4.5."
|
||||
|
||||
Most objects in NetBox can be assigned an owner. An owner is a set of users and/or groups who are responsible for the administration of associated objects. For example, you might designate the operations team at a site as the owner for all prefixes and VLANs deployed at that site. The users and groups assigned to an owner are referred to as its members.
|
||||
|
||||
!!! note
|
||||
Ownership of an object should not be confused with the concept of [tenancy](./tenancy.md), which indicates the dedication of an object to a specific tenant. For instance, a tenant might represent a customer served by the object, whereas an owner typically represents a set of internal users responsible for the management of the object.
|
||||
|
||||
Owners can be organized into groups for easier management.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Tenancy
|
||||
|
||||
Most core objects within NetBox's data model support _tenancy_. This is the association of an object with a particular tenant to convey ownership or dependency. For example, an enterprise might represent its internal business units as tenants, whereas a managed services provider might create a tenant in NetBox to represent each of its customers.
|
||||
Most core objects within NetBox's data model support _tenancy_. This is the association of an object with a particular tenant to convey assignment or dependency. For example, an enterprise might represent its internal business units as tenants, whereas a managed services provider might create a tenant in NetBox to represent each of its customers.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
@@ -19,20 +19,36 @@ Tenants can be grouped by any logic that your use case demands, and groups can b
|
||||
|
||||
Typically, the tenant model is used to represent a customer or internal organization, however it can be used for whatever purpose meets your needs.
|
||||
|
||||
Most core objects within NetBox can be assigned to particular tenant, so this model provides a very convenient way to correlate ownership across object types. For example, each of your customers might have its own racks, devices, IP addresses, circuits and so on: These can all be easily tracked via tenant assignment.
|
||||
Most core objects within NetBox can be assigned to a particular tenant, so this model provides a very convenient way to correlate resource allocation across object types. For example, each of your customers might have its own racks, devices, IP addresses, circuits and so on: These can all be easily tracked via tenant assignment.
|
||||
|
||||
The following objects can be assigned to tenants:
|
||||
|
||||
* Sites
|
||||
* Circuits
|
||||
* Circuit groups
|
||||
* Virtual circuits
|
||||
* Cables
|
||||
* Devices
|
||||
* Virtual device contexts
|
||||
* Power feeds
|
||||
* Racks
|
||||
* Rack reservations
|
||||
* Devices
|
||||
* VRFs
|
||||
* Sites
|
||||
* Locations
|
||||
* ASNs
|
||||
* ASN ranges
|
||||
* Aggregates
|
||||
* Prefixes
|
||||
* IP ranges
|
||||
* IP addresses
|
||||
* VLANs
|
||||
* Circuits
|
||||
* VLAN groups
|
||||
* VRFs
|
||||
* Route targets
|
||||
* Clusters
|
||||
* Virtual machines
|
||||
* L2VPNs
|
||||
* Tunnels
|
||||
* Wireless LANs
|
||||
* Wireless links
|
||||
|
||||
Tenant assignment is used to signify the ownership of an object in NetBox. As such, each object may only be owned by a single tenant. For example, if you have a firewall dedicated to a particular customer, you would assign it to the tenant which represents that customer. However, if the firewall serves multiple customers, it doesn't *belong* to any particular customer, so tenant assignment would not be appropriate.
|
||||
Tenancy represents the dedication of an object to a specific tenant. As such, each object may only be assigned to a single tenant. For example, if you have a firewall dedicated to a particular customer, you would assign it to the tenant which represents that customer. However, if the firewall serves multiple customers, it doesn't *belong* to any particular customer, so the assignment of a tenant would not be appropriate.
|
||||
|
||||
23
docs/models/users/owner.md
Normal file
23
docs/models/users/owner.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Owner
|
||||
|
||||
An owner is a set of users and/or groups who are responsible for the administration of certain resources within NetBox. The users and groups assigned to an owner are referred to as its members. Owner assignments are useful for indicating which parties are responsible for the administration of a particular object.
|
||||
|
||||
Most objects within NetBox can be assigned an owner, although this is not required.
|
||||
|
||||
## Fields
|
||||
|
||||
### Name
|
||||
|
||||
The owner's name.
|
||||
|
||||
### Group
|
||||
|
||||
The [group](./ownergroup.md) to which the owner is assigned. The assignment of an owner to a group is optional.
|
||||
|
||||
### User Groups
|
||||
|
||||
Groups of users that are members of the owner.
|
||||
|
||||
### Users
|
||||
|
||||
Individual users that are members of the owner.
|
||||
9
docs/models/users/ownergroup.md
Normal file
9
docs/models/users/ownergroup.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Owner Groups
|
||||
|
||||
Groups are used to correlate and organize [owners](./owner.md). The assignment of an owner to a group has no bearing on the relationship of owned objects to their owners.
|
||||
|
||||
## Fields
|
||||
|
||||
### Name
|
||||
|
||||
The name of the group.
|
||||
@@ -77,6 +77,7 @@ nav:
|
||||
- Wireless: 'features/wireless.md'
|
||||
- Virtualization: 'features/virtualization.md'
|
||||
- VPN Tunnels: 'features/vpn-tunnels.md'
|
||||
- Resource Ownership: 'features/resource-ownership.md'
|
||||
- Tenancy: 'features/tenancy.md'
|
||||
- Contacts: 'features/contacts.md'
|
||||
- Search: 'features/search.md'
|
||||
@@ -273,6 +274,9 @@ nav:
|
||||
- ContactRole: 'models/tenancy/contactrole.md'
|
||||
- Tenant: 'models/tenancy/tenant.md'
|
||||
- TenantGroup: 'models/tenancy/tenantgroup.md'
|
||||
- Users:
|
||||
- Owner: 'models/users/owner.md'
|
||||
- OwnerGroup: 'models/users/ownergroup.md'
|
||||
- Virtualization:
|
||||
- Cluster: 'models/virtualization/cluster.md'
|
||||
- ClusterGroup: 'models/virtualization/clustergroup.md'
|
||||
|
||||
@@ -11,7 +11,9 @@ from circuits.models import (
|
||||
from dcim.api.serializers_.device_components import InterfaceSerializer
|
||||
from dcim.api.serializers_.cables import CabledObjectSerializer
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer
|
||||
from netbox.api.serializers import (
|
||||
NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer, WritableNestedSerializer,
|
||||
)
|
||||
from netbox.choices import DistanceUnitChoices
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from utilities.api import get_serializer_for_model
|
||||
@@ -29,7 +31,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class CircuitTypeSerializer(NetBoxModelSerializer):
|
||||
class CircuitTypeSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
circuit_count = RelatedObjectCountField('circuits')
|
||||
@@ -37,8 +39,8 @@ class CircuitTypeSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = CircuitType
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'circuit_count',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'owner', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'circuit_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'circuit_count')
|
||||
|
||||
@@ -71,15 +73,15 @@ class CircuitCircuitTerminationSerializer(WritableNestedSerializer):
|
||||
return serializer(obj.termination, nested=True, context=context).data
|
||||
|
||||
|
||||
class CircuitGroupSerializer(NetBoxModelSerializer):
|
||||
class CircuitGroupSerializer(OrganizationalModelSerializer):
|
||||
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
||||
circuit_count = RelatedObjectCountField('assignments')
|
||||
|
||||
class Meta:
|
||||
model = CircuitGroup
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'tenant',
|
||||
'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count'
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'tenant', 'owner', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'circuit_count'
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name')
|
||||
|
||||
@@ -99,7 +101,7 @@ class CircuitGroupAssignmentSerializer_(NetBoxModelSerializer):
|
||||
brief_fields = ('id', 'url', 'display', 'group', 'priority')
|
||||
|
||||
|
||||
class CircuitSerializer(NetBoxModelSerializer):
|
||||
class CircuitSerializer(PrimaryModelSerializer):
|
||||
provider = ProviderSerializer(nested=True)
|
||||
provider_account = ProviderAccountSerializer(nested=True, required=False, allow_null=True, default=None)
|
||||
status = ChoiceField(choices=CircuitStatusChoices, required=False)
|
||||
@@ -115,7 +117,7 @@ class CircuitSerializer(NetBoxModelSerializer):
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'cid', 'provider', 'provider_account', 'type', 'status', 'tenant',
|
||||
'install_date', 'termination_date', 'commit_rate', 'description', 'distance', 'distance_unit',
|
||||
'termination_a', 'termination_z', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'termination_a', 'termination_z', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'assignments',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'provider', 'cid', 'description')
|
||||
@@ -176,7 +178,7 @@ class CircuitGroupAssignmentSerializer(CircuitGroupAssignmentSerializer_):
|
||||
return serializer(obj.member, nested=True, context=context).data
|
||||
|
||||
|
||||
class VirtualCircuitTypeSerializer(NetBoxModelSerializer):
|
||||
class VirtualCircuitTypeSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
virtual_circuit_count = RelatedObjectCountField('virtual_circuits')
|
||||
@@ -184,13 +186,13 @@ class VirtualCircuitTypeSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = VirtualCircuitType
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'virtual_circuit_count',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'owner', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'virtual_circuit_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'virtual_circuit_count')
|
||||
|
||||
|
||||
class VirtualCircuitSerializer(NetBoxModelSerializer):
|
||||
class VirtualCircuitSerializer(PrimaryModelSerializer):
|
||||
provider_network = ProviderNetworkSerializer(nested=True)
|
||||
provider_account = ProviderAccountSerializer(nested=True, required=False, allow_null=True, default=None)
|
||||
type = VirtualCircuitTypeSerializer(nested=True)
|
||||
@@ -201,7 +203,7 @@ class VirtualCircuitSerializer(NetBoxModelSerializer):
|
||||
model = VirtualCircuit
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'cid', 'provider_network', 'provider_account', 'type', 'status',
|
||||
'tenant', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'tenant', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'provider_network', 'cid', 'description')
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from circuits.models import Provider, ProviderAccount, ProviderNetwork
|
||||
from ipam.api.serializers_.asns import ASNSerializer
|
||||
from ipam.models import ASN
|
||||
from netbox.api.fields import RelatedObjectCountField, SerializedPKRelatedField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from .nested import NestedProviderAccountSerializer
|
||||
|
||||
__all__ = (
|
||||
@@ -14,7 +14,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ProviderSerializer(NetBoxModelSerializer):
|
||||
class ProviderSerializer(PrimaryModelSerializer):
|
||||
accounts = SerializedPKRelatedField(
|
||||
queryset=ProviderAccount.objects.all(),
|
||||
serializer=NestedProviderAccountSerializer,
|
||||
@@ -35,32 +35,32 @@ class ProviderSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = Provider
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'accounts', 'description', 'comments',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'accounts', 'description', 'owner', 'comments',
|
||||
'asns', 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'circuit_count')
|
||||
|
||||
|
||||
class ProviderAccountSerializer(NetBoxModelSerializer):
|
||||
class ProviderAccountSerializer(PrimaryModelSerializer):
|
||||
provider = ProviderSerializer(nested=True)
|
||||
name = serializers.CharField(allow_blank=True, max_length=100, required=False, default='')
|
||||
|
||||
class Meta:
|
||||
model = ProviderAccount
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'provider', 'name', 'account', 'description', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated',
|
||||
'id', 'url', 'display_url', 'display', 'provider', 'name', 'account', 'description', 'owner', 'comments',
|
||||
'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'account', 'description')
|
||||
|
||||
|
||||
class ProviderNetworkSerializer(NetBoxModelSerializer):
|
||||
class ProviderNetworkSerializer(PrimaryModelSerializer):
|
||||
provider = ProviderSerializer(nested=True)
|
||||
|
||||
class Meta:
|
||||
model = ProviderNetwork
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'provider', 'name', 'service_id', 'description', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated',
|
||||
'id', 'url', 'display_url', 'display', 'provider', 'name', 'service_id', 'description', 'owner', 'comments',
|
||||
'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
@@ -6,7 +6,7 @@ from django.utils.translation import gettext as _
|
||||
from dcim.filtersets import CabledObjectFilterSet
|
||||
from dcim.models import Interface, Location, Region, Site, SiteGroup
|
||||
from ipam.models import ASN
|
||||
from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet
|
||||
from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet, PrimaryModelFilterSet
|
||||
from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet
|
||||
from utilities.filters import (
|
||||
ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter, TreeNodeMultipleChoiceFilter,
|
||||
@@ -29,7 +29,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
class ProviderFilterSet(PrimaryModelFilterSet, ContactModelFilterSet):
|
||||
region_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='circuits__terminations___region',
|
||||
@@ -95,7 +95,7 @@ class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class ProviderAccountFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
class ProviderAccountFilterSet(PrimaryModelFilterSet, ContactModelFilterSet):
|
||||
provider_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Provider.objects.all(),
|
||||
label=_('Provider (ID)'),
|
||||
@@ -122,7 +122,7 @@ class ProviderAccountFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
).distinct()
|
||||
|
||||
|
||||
class ProviderNetworkFilterSet(NetBoxModelFilterSet):
|
||||
class ProviderNetworkFilterSet(PrimaryModelFilterSet):
|
||||
provider_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Provider.objects.all(),
|
||||
label=_('Provider (ID)'),
|
||||
@@ -156,7 +156,7 @@ class CircuitTypeFilterSet(OrganizationalModelFilterSet):
|
||||
fields = ('id', 'name', 'slug', 'color', 'description')
|
||||
|
||||
|
||||
class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
class CircuitFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
provider_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Provider.objects.all(),
|
||||
label=_('Provider (ID)'),
|
||||
@@ -475,7 +475,7 @@ class VirtualCircuitTypeFilterSet(OrganizationalModelFilterSet):
|
||||
fields = ('id', 'name', 'slug', 'color', 'description')
|
||||
|
||||
|
||||
class VirtualCircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
class VirtualCircuitFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
|
||||
provider_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='provider_network__provider',
|
||||
queryset=Provider.objects.all(),
|
||||
|
||||
@@ -11,11 +11,11 @@ from circuits.models import *
|
||||
from dcim.models import Site
|
||||
from ipam.models import ASN
|
||||
from netbox.choices import DistanceUnitChoices
|
||||
from netbox.forms import NetBoxModelBulkEditForm
|
||||
from netbox.forms import NetBoxModelBulkEditForm, OrganizationalModelBulkEditForm, PrimaryModelBulkEditForm
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms import add_blank_choice, get_field_value
|
||||
from utilities.forms.fields import (
|
||||
ColorField, CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
|
||||
ColorField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import BulkEditNullBooleanSelect, DatePicker, HTMXSelect, NumberWithOptions
|
||||
@@ -36,18 +36,12 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ProviderBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ProviderBulkEditForm(PrimaryModelBulkEditForm):
|
||||
asns = DynamicModelMultipleChoiceField(
|
||||
queryset=ASN.objects.all(),
|
||||
label=_('ASNs'),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Provider
|
||||
fieldsets = (
|
||||
@@ -58,18 +52,12 @@ class ProviderBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class ProviderAccountBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ProviderAccountBulkEditForm(PrimaryModelBulkEditForm):
|
||||
provider = DynamicModelChoiceField(
|
||||
label=_('Provider'),
|
||||
queryset=Provider.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = ProviderAccount
|
||||
fieldsets = (
|
||||
@@ -80,7 +68,7 @@ class ProviderAccountBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ProviderNetworkBulkEditForm(PrimaryModelBulkEditForm):
|
||||
provider = DynamicModelChoiceField(
|
||||
label=_('Provider'),
|
||||
queryset=Provider.objects.all(),
|
||||
@@ -91,12 +79,6 @@ class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
label=_('Service ID')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = ProviderNetwork
|
||||
fieldsets = (
|
||||
@@ -107,16 +89,11 @@ class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class CircuitTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class CircuitTypeBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
color = ColorField(
|
||||
label=_('Color'),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
model = CircuitType
|
||||
fieldsets = (
|
||||
@@ -125,7 +102,7 @@ class CircuitTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('color', 'description')
|
||||
|
||||
|
||||
class CircuitBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class CircuitBulkEditForm(PrimaryModelBulkEditForm):
|
||||
type = DynamicModelChoiceField(
|
||||
label=_('Type'),
|
||||
queryset=CircuitType.objects.all(),
|
||||
@@ -183,12 +160,6 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
initial=''
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=100,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Circuit
|
||||
fieldsets = (
|
||||
@@ -261,12 +232,7 @@ class CircuitTerminationBulkEditForm(NetBoxModelBulkEditForm):
|
||||
pass
|
||||
|
||||
|
||||
class CircuitGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
class CircuitGroupBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
tenant = DynamicModelChoiceField(
|
||||
label=_('Tenant'),
|
||||
queryset=Tenant.objects.all(),
|
||||
@@ -298,16 +264,11 @@ class CircuitGroupAssignmentBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('priority',)
|
||||
|
||||
|
||||
class VirtualCircuitTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VirtualCircuitTypeBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
color = ColorField(
|
||||
label=_('Color'),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
model = VirtualCircuitType
|
||||
fieldsets = (
|
||||
@@ -316,7 +277,7 @@ class VirtualCircuitTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('color', 'description')
|
||||
|
||||
|
||||
class VirtualCircuitBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VirtualCircuitBulkEditForm(PrimaryModelBulkEditForm):
|
||||
provider_network = DynamicModelChoiceField(
|
||||
label=_('Provider network'),
|
||||
queryset=ProviderNetwork.objects.all(),
|
||||
@@ -343,12 +304,6 @@ class VirtualCircuitBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=100,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = VirtualCircuit
|
||||
fieldsets = (
|
||||
|
||||
@@ -7,7 +7,7 @@ from circuits.constants import *
|
||||
from circuits.models import *
|
||||
from dcim.models import Interface
|
||||
from netbox.choices import DistanceUnitChoices
|
||||
from netbox.forms import NetBoxModelImportForm
|
||||
from netbox.forms import NetBoxModelImportForm, OrganizationalModelImportForm, PrimaryModelImportForm
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms.fields import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, SlugField
|
||||
|
||||
@@ -28,17 +28,17 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ProviderImportForm(NetBoxModelImportForm):
|
||||
class ProviderImportForm(PrimaryModelImportForm):
|
||||
slug = SlugField()
|
||||
|
||||
class Meta:
|
||||
model = Provider
|
||||
fields = (
|
||||
'name', 'slug', 'description', 'comments', 'tags',
|
||||
'name', 'slug', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class ProviderAccountImportForm(NetBoxModelImportForm):
|
||||
class ProviderAccountImportForm(PrimaryModelImportForm):
|
||||
provider = CSVModelChoiceField(
|
||||
label=_('Provider'),
|
||||
queryset=Provider.objects.all(),
|
||||
@@ -49,11 +49,11 @@ class ProviderAccountImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = ProviderAccount
|
||||
fields = (
|
||||
'provider', 'name', 'account', 'description', 'comments', 'tags',
|
||||
'provider', 'name', 'account', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class ProviderNetworkImportForm(NetBoxModelImportForm):
|
||||
class ProviderNetworkImportForm(PrimaryModelImportForm):
|
||||
provider = CSVModelChoiceField(
|
||||
label=_('Provider'),
|
||||
queryset=Provider.objects.all(),
|
||||
@@ -64,19 +64,19 @@ class ProviderNetworkImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = ProviderNetwork
|
||||
fields = [
|
||||
'provider', 'name', 'service_id', 'description', 'comments', 'tags'
|
||||
'provider', 'name', 'service_id', 'description', 'owner', 'comments', 'tags'
|
||||
]
|
||||
|
||||
|
||||
class CircuitTypeImportForm(NetBoxModelImportForm):
|
||||
class CircuitTypeImportForm(OrganizationalModelImportForm):
|
||||
slug = SlugField()
|
||||
|
||||
class Meta:
|
||||
model = CircuitType
|
||||
fields = ('name', 'slug', 'color', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'color', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class CircuitImportForm(NetBoxModelImportForm):
|
||||
class CircuitImportForm(PrimaryModelImportForm):
|
||||
provider = CSVModelChoiceField(
|
||||
label=_('Provider'),
|
||||
queryset=Provider.objects.all(),
|
||||
@@ -119,7 +119,7 @@ class CircuitImportForm(NetBoxModelImportForm):
|
||||
model = Circuit
|
||||
fields = [
|
||||
'cid', 'provider', 'provider_account', 'type', 'status', 'tenant', 'install_date', 'termination_date',
|
||||
'commit_rate', 'distance', 'distance_unit', 'description', 'comments', 'tags'
|
||||
'commit_rate', 'distance', 'distance_unit', 'description', 'owner', 'comments', 'tags'
|
||||
]
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ class CircuitTerminationImportForm(NetBoxModelImportForm, BaseCircuitTermination
|
||||
}
|
||||
|
||||
|
||||
class CircuitGroupImportForm(NetBoxModelImportForm):
|
||||
class CircuitGroupImportForm(OrganizationalModelImportForm):
|
||||
tenant = CSVModelChoiceField(
|
||||
label=_('Tenant'),
|
||||
queryset=Tenant.objects.all(),
|
||||
@@ -176,7 +176,7 @@ class CircuitGroupImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = CircuitGroup
|
||||
fields = ('name', 'slug', 'description', 'tenant', 'tags')
|
||||
fields = ('name', 'slug', 'description', 'tenant', 'owner', 'tags')
|
||||
|
||||
|
||||
class CircuitGroupAssignmentImportForm(NetBoxModelImportForm):
|
||||
@@ -195,15 +195,14 @@ class CircuitGroupAssignmentImportForm(NetBoxModelImportForm):
|
||||
fields = ('member_type', 'member_id', 'group', 'priority')
|
||||
|
||||
|
||||
class VirtualCircuitTypeImportForm(NetBoxModelImportForm):
|
||||
slug = SlugField()
|
||||
class VirtualCircuitTypeImportForm(OrganizationalModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = VirtualCircuitType
|
||||
fields = ('name', 'slug', 'color', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'color', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class VirtualCircuitImportForm(NetBoxModelImportForm):
|
||||
class VirtualCircuitImportForm(PrimaryModelImportForm):
|
||||
provider_network = CSVModelChoiceField(
|
||||
label=_('Provider network'),
|
||||
queryset=ProviderNetwork.objects.all(),
|
||||
@@ -239,8 +238,8 @@ class VirtualCircuitImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = VirtualCircuit
|
||||
fields = [
|
||||
'cid', 'provider_network', 'provider_account', 'type', 'status', 'tenant', 'description', 'comments',
|
||||
'tags',
|
||||
'cid', 'provider_network', 'provider_account', 'type', 'status', 'tenant', 'description', 'owner',
|
||||
'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from circuits.models import *
|
||||
from dcim.models import Location, Region, Site, SiteGroup
|
||||
from ipam.models import ASN
|
||||
from netbox.choices import DistanceUnitChoices
|
||||
from netbox.forms import NetBoxModelFilterSetForm
|
||||
from netbox.forms import NetBoxModelFilterSetForm, OrganizationalModelFilterSetForm, PrimaryModelFilterSetForm
|
||||
from tenancy.forms import TenancyFilterForm, ContactModelFilterForm
|
||||
from utilities.forms import add_blank_choice
|
||||
from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField
|
||||
@@ -31,10 +31,10 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ProviderFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class ProviderFilterForm(ContactModelFilterForm, PrimaryModelFilterSetForm):
|
||||
model = Provider
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')),
|
||||
FieldSet('asn_id', name=_('ASN')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
@@ -66,10 +66,10 @@ class ProviderFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class ProviderAccountFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class ProviderAccountFilterForm(ContactModelFilterForm, PrimaryModelFilterSetForm):
|
||||
model = ProviderAccount
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('provider_id', 'account', name=_('Attributes')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
)
|
||||
@@ -85,10 +85,10 @@ class ProviderAccountFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class ProviderNetworkFilterForm(NetBoxModelFilterSetForm):
|
||||
class ProviderNetworkFilterForm(PrimaryModelFilterSetForm):
|
||||
model = ProviderNetwork
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('provider_id', 'service_id', name=_('Attributes')),
|
||||
)
|
||||
provider_id = DynamicModelMultipleChoiceField(
|
||||
@@ -104,10 +104,10 @@ class ProviderNetworkFilterForm(NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class CircuitTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
class CircuitTypeFilterForm(OrganizationalModelFilterSetForm):
|
||||
model = CircuitType
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('color', name=_('Attributes')),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
@@ -118,10 +118,10 @@ class CircuitTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
)
|
||||
|
||||
|
||||
class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, PrimaryModelFilterSetForm):
|
||||
model = Circuit
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('provider_id', 'provider_account_id', 'provider_network_id', name=_('Provider')),
|
||||
FieldSet(
|
||||
'type_id', 'status', 'install_date', 'termination_date', 'commit_rate', 'distance', 'distance_unit',
|
||||
@@ -271,10 +271,10 @@ class CircuitTerminationFilterForm(NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class CircuitGroupFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class CircuitGroupFilterForm(TenancyFilterForm, OrganizationalModelFilterSetForm):
|
||||
model = CircuitGroup
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
@@ -309,10 +309,10 @@ class CircuitGroupAssignmentFilterForm(NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class VirtualCircuitTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
class VirtualCircuitTypeFilterForm(OrganizationalModelFilterSetForm):
|
||||
model = VirtualCircuitType
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('color', name=_('Attributes')),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
@@ -323,10 +323,10 @@ class VirtualCircuitTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
)
|
||||
|
||||
|
||||
class VirtualCircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class VirtualCircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, PrimaryModelFilterSetForm):
|
||||
model = VirtualCircuit
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('provider_id', 'provider_account_id', 'provider_network_id', name=_('Provider')),
|
||||
FieldSet('type_id', 'status', name=_('Attributes')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
|
||||
@@ -10,11 +10,11 @@ from circuits.constants import *
|
||||
from circuits.models import *
|
||||
from dcim.models import Interface, Site
|
||||
from ipam.models import ASN
|
||||
from netbox.forms import NetBoxModelForm
|
||||
from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
|
||||
from tenancy.forms import TenancyForm
|
||||
from utilities.forms import get_field_value
|
||||
from utilities.forms.fields import (
|
||||
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField,
|
||||
ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField,
|
||||
)
|
||||
from utilities.forms.mixins import DistanceValidationMixin
|
||||
from utilities.forms.rendering import FieldSet, InlineFields
|
||||
@@ -36,14 +36,13 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ProviderForm(NetBoxModelForm):
|
||||
class ProviderForm(PrimaryModelForm):
|
||||
slug = SlugField()
|
||||
asns = DynamicModelMultipleChoiceField(
|
||||
queryset=ASN.objects.all(),
|
||||
label=_('ASNs'),
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'asns', 'description', 'tags'),
|
||||
@@ -52,34 +51,32 @@ class ProviderForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Provider
|
||||
fields = [
|
||||
'name', 'slug', 'asns', 'description', 'comments', 'tags',
|
||||
'name', 'slug', 'asns', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class ProviderAccountForm(NetBoxModelForm):
|
||||
class ProviderAccountForm(PrimaryModelForm):
|
||||
provider = DynamicModelChoiceField(
|
||||
label=_('Provider'),
|
||||
queryset=Provider.objects.all(),
|
||||
selector=True,
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
class Meta:
|
||||
model = ProviderAccount
|
||||
fields = [
|
||||
'provider', 'name', 'account', 'description', 'comments', 'tags',
|
||||
'provider', 'name', 'account', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class ProviderNetworkForm(NetBoxModelForm):
|
||||
class ProviderNetworkForm(PrimaryModelForm):
|
||||
provider = DynamicModelChoiceField(
|
||||
label=_('Provider'),
|
||||
queryset=Provider.objects.all(),
|
||||
selector=True,
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('provider', 'name', 'service_id', 'description', 'tags'),
|
||||
@@ -88,15 +85,13 @@ class ProviderNetworkForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = ProviderNetwork
|
||||
fields = [
|
||||
'provider', 'name', 'service_id', 'description', 'comments', 'tags',
|
||||
'provider', 'name', 'service_id', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class CircuitTypeForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class CircuitTypeForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'color', 'description', 'tags'),
|
||||
FieldSet('name', 'slug', 'color', 'description', 'owner', 'tags'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@@ -106,7 +101,7 @@ class CircuitTypeForm(NetBoxModelForm):
|
||||
]
|
||||
|
||||
|
||||
class CircuitForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm):
|
||||
class CircuitForm(DistanceValidationMixin, TenancyForm, PrimaryModelForm):
|
||||
provider = DynamicModelChoiceField(
|
||||
label=_('Provider'),
|
||||
queryset=Provider.objects.all(),
|
||||
@@ -125,7 +120,6 @@ class CircuitForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm):
|
||||
queryset=CircuitType.objects.all(),
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -147,7 +141,7 @@ class CircuitForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm):
|
||||
model = Circuit
|
||||
fields = [
|
||||
'cid', 'type', 'provider', 'provider_account', 'status', 'install_date', 'termination_date', 'commit_rate',
|
||||
'distance', 'distance_unit', 'description', 'tenant_group', 'tenant', 'comments', 'tags',
|
||||
'distance', 'distance_unit', 'description', 'tenant_group', 'tenant', 'owner', 'comments', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'install_date': DatePicker(),
|
||||
@@ -233,9 +227,7 @@ class CircuitTerminationForm(NetBoxModelForm):
|
||||
self.instance.termination = self.cleaned_data.get('termination')
|
||||
|
||||
|
||||
class CircuitGroupForm(TenancyForm, NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class CircuitGroupForm(TenancyForm, OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'description', 'tags', name=_('Circuit Group')),
|
||||
FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
|
||||
@@ -244,7 +236,7 @@ class CircuitGroupForm(TenancyForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = CircuitGroup
|
||||
fields = [
|
||||
'name', 'slug', 'description', 'tenant_group', 'tenant', 'tags',
|
||||
'name', 'slug', 'description', 'tenant_group', 'tenant', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -307,9 +299,7 @@ class CircuitGroupAssignmentForm(NetBoxModelForm):
|
||||
self.instance.member = self.cleaned_data.get('member')
|
||||
|
||||
|
||||
class VirtualCircuitTypeForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class VirtualCircuitTypeForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'color', 'description', 'tags'),
|
||||
)
|
||||
@@ -317,11 +307,11 @@ class VirtualCircuitTypeForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = VirtualCircuitType
|
||||
fields = [
|
||||
'name', 'slug', 'color', 'description', 'tags',
|
||||
'name', 'slug', 'color', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class VirtualCircuitForm(TenancyForm, NetBoxModelForm):
|
||||
class VirtualCircuitForm(TenancyForm, PrimaryModelForm):
|
||||
provider_network = DynamicModelChoiceField(
|
||||
label=_('Provider network'),
|
||||
queryset=ProviderNetwork.objects.all(),
|
||||
@@ -336,7 +326,6 @@ class VirtualCircuitForm(TenancyForm, NetBoxModelForm):
|
||||
queryset=VirtualCircuitType.objects.all(),
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -350,7 +339,7 @@ class VirtualCircuitForm(TenancyForm, NetBoxModelForm):
|
||||
model = VirtualCircuit
|
||||
fields = [
|
||||
'cid', 'provider_network', 'provider_account', 'type', 'status', 'description', 'tenant_group', 'tenant',
|
||||
'comments', 'tags',
|
||||
'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import strawberry_django
|
||||
from circuits import models
|
||||
from dcim.graphql.mixins import CabledObjectMixin
|
||||
from extras.graphql.mixins import ContactsMixin, CustomFieldsMixin, TagsMixin
|
||||
from netbox.graphql.types import BaseObjectType, NetBoxObjectType, ObjectType, OrganizationalObjectType
|
||||
from netbox.graphql.types import BaseObjectType, ObjectType, OrganizationalObjectType, PrimaryObjectType
|
||||
from tenancy.graphql.types import TenantType
|
||||
from .filters import *
|
||||
|
||||
@@ -35,8 +35,7 @@ __all__ = (
|
||||
filters=ProviderFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ProviderType(NetBoxObjectType, ContactsMixin):
|
||||
|
||||
class ProviderType(ContactsMixin, PrimaryObjectType):
|
||||
networks: List[Annotated["ProviderNetworkType", strawberry.lazy('circuits.graphql.types')]]
|
||||
circuits: List[Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]]
|
||||
asns: List[Annotated["ASNType", strawberry.lazy('ipam.graphql.types')]]
|
||||
@@ -49,9 +48,8 @@ class ProviderType(NetBoxObjectType, ContactsMixin):
|
||||
filters=ProviderAccountFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ProviderAccountType(ContactsMixin, NetBoxObjectType):
|
||||
class ProviderAccountType(ContactsMixin, PrimaryObjectType):
|
||||
provider: Annotated["ProviderType", strawberry.lazy('circuits.graphql.types')]
|
||||
|
||||
circuits: List[Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]]
|
||||
|
||||
|
||||
@@ -61,9 +59,8 @@ class ProviderAccountType(ContactsMixin, NetBoxObjectType):
|
||||
filters=ProviderNetworkFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ProviderNetworkType(NetBoxObjectType):
|
||||
class ProviderNetworkType(PrimaryObjectType):
|
||||
provider: Annotated["ProviderType", strawberry.lazy('circuits.graphql.types')]
|
||||
|
||||
circuit_terminations: List[Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')]]
|
||||
|
||||
|
||||
@@ -105,14 +102,13 @@ class CircuitTypeType(OrganizationalObjectType):
|
||||
filters=CircuitFilter,
|
||||
pagination=True
|
||||
)
|
||||
class CircuitType(NetBoxObjectType, ContactsMixin):
|
||||
class CircuitType(PrimaryObjectType, ContactsMixin):
|
||||
provider: ProviderType
|
||||
provider_account: ProviderAccountType | None
|
||||
termination_a: CircuitTerminationType | None
|
||||
termination_z: CircuitTerminationType | None
|
||||
type: CircuitTypeType
|
||||
tenant: TenantType | None
|
||||
|
||||
terminations: List[CircuitTerminationType]
|
||||
|
||||
|
||||
@@ -178,12 +174,11 @@ class VirtualCircuitTerminationType(CustomFieldsMixin, TagsMixin, ObjectType):
|
||||
filters=VirtualCircuitFilter,
|
||||
pagination=True
|
||||
)
|
||||
class VirtualCircuitType(NetBoxObjectType):
|
||||
class VirtualCircuitType(PrimaryObjectType):
|
||||
provider_network: ProviderNetworkType = strawberry_django.field(select_related=["provider_network"])
|
||||
provider_account: ProviderAccountType | None
|
||||
type: Annotated["VirtualCircuitTypeType", strawberry.lazy('circuits.graphql.types')] = strawberry_django.field(
|
||||
select_related=["type"]
|
||||
)
|
||||
tenant: TenantType | None
|
||||
|
||||
terminations: List[VirtualCircuitTerminationType]
|
||||
|
||||
68
netbox/circuits/migrations/0053_owner.py
Normal file
68
netbox/circuits/migrations/0053_owner.py
Normal file
@@ -0,0 +1,68 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('circuits', '0052_extend_circuit_abs_distance_upper_limit'),
|
||||
('users', '0015_owner'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='circuit',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='circuitgroup',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='circuittype',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='provider',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='provideraccount',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='providernetwork',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='virtualcircuit',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='virtualcircuittype',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -1,11 +1,9 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from circuits.models import *
|
||||
from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
|
||||
from .columns import CommitRateColumn
|
||||
|
||||
__all__ = (
|
||||
@@ -24,7 +22,7 @@ CIRCUITTERMINATION_LINK = """
|
||||
"""
|
||||
|
||||
|
||||
class CircuitTypeTable(NetBoxTable):
|
||||
class CircuitTypeTable(OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Name'),
|
||||
@@ -39,7 +37,7 @@ class CircuitTypeTable(NetBoxTable):
|
||||
verbose_name=_('Circuits')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = CircuitType
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'circuit_count', 'color', 'description', 'slug', 'tags', 'created', 'last_updated',
|
||||
@@ -48,7 +46,7 @@ class CircuitTypeTable(NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'circuit_count', 'color', 'description')
|
||||
|
||||
|
||||
class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable):
|
||||
cid = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Circuit ID')
|
||||
@@ -79,9 +77,6 @@ class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
verbose_name=_('Commit Rate')
|
||||
)
|
||||
distance = columns.DistanceColumn()
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments')
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='circuits:circuit_list'
|
||||
)
|
||||
@@ -90,7 +85,7 @@ class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
linkify_item=True
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Circuit
|
||||
fields = (
|
||||
'pk', 'id', 'cid', 'provider', 'provider_account', 'type', 'status', 'tenant', 'tenant_group',
|
||||
@@ -163,7 +158,7 @@ class CircuitTerminationTable(NetBoxTable):
|
||||
)
|
||||
|
||||
|
||||
class CircuitGroupTable(NetBoxTable):
|
||||
class CircuitGroupTable(OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -177,7 +172,7 @@ class CircuitGroupTable(NetBoxTable):
|
||||
url_name='circuits:circuitgroup_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = CircuitGroup
|
||||
fields = (
|
||||
'pk', 'name', 'description', 'circuit_group_assignment_count', 'tags',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from circuits.models import *
|
||||
from django_tables2.utils import Accessor
|
||||
from tenancy.tables import ContactsColumnMixin
|
||||
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from circuits.models import *
|
||||
from netbox.tables import PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin
|
||||
|
||||
__all__ = (
|
||||
'ProviderTable',
|
||||
@@ -13,7 +13,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ProviderTable(ContactsColumnMixin, NetBoxTable):
|
||||
class ProviderTable(ContactsColumnMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -42,14 +42,11 @@ class ProviderTable(ContactsColumnMixin, NetBoxTable):
|
||||
url_params={'provider_id': 'pk'},
|
||||
verbose_name=_('Circuits')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='circuits:provider_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Provider
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'accounts', 'account_count', 'asns', 'asn_count', 'circuit_count', 'description',
|
||||
@@ -58,7 +55,7 @@ class ProviderTable(ContactsColumnMixin, NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'account_count', 'circuit_count')
|
||||
|
||||
|
||||
class ProviderAccountTable(ContactsColumnMixin, NetBoxTable):
|
||||
class ProviderAccountTable(ContactsColumnMixin, PrimaryModelTable):
|
||||
account = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Account'),
|
||||
@@ -76,14 +73,11 @@ class ProviderAccountTable(ContactsColumnMixin, NetBoxTable):
|
||||
url_params={'provider_account_id': 'pk'},
|
||||
verbose_name=_('Circuits')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='circuits:provideraccount_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = ProviderAccount
|
||||
fields = (
|
||||
'pk', 'id', 'account', 'name', 'provider', 'circuit_count', 'comments', 'contacts', 'tags', 'created',
|
||||
@@ -92,7 +86,7 @@ class ProviderAccountTable(ContactsColumnMixin, NetBoxTable):
|
||||
default_columns = ('pk', 'account', 'name', 'provider', 'circuit_count')
|
||||
|
||||
|
||||
class ProviderNetworkTable(NetBoxTable):
|
||||
class ProviderNetworkTable(PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -101,14 +95,11 @@ class ProviderNetworkTable(NetBoxTable):
|
||||
verbose_name=_('Provider'),
|
||||
linkify=True
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='circuits:providernetwork_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = ProviderNetwork
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'provider', 'service_id', 'description', 'comments', 'created', 'last_updated', 'tags',
|
||||
|
||||
@@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from circuits.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
|
||||
__all__ = (
|
||||
@@ -12,7 +12,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class VirtualCircuitTypeTable(NetBoxTable):
|
||||
class VirtualCircuitTypeTable(OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Name'),
|
||||
@@ -27,7 +27,7 @@ class VirtualCircuitTypeTable(NetBoxTable):
|
||||
verbose_name=_('Circuits')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = VirtualCircuitType
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'virtual_circuit_count', 'color', 'description', 'slug', 'tags', 'created',
|
||||
@@ -36,7 +36,7 @@ class VirtualCircuitTypeTable(NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'virtual_circuit_count', 'color', 'description')
|
||||
|
||||
|
||||
class VirtualCircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
class VirtualCircuitTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable):
|
||||
cid = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Circuit ID')
|
||||
@@ -63,14 +63,11 @@ class VirtualCircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable)
|
||||
url_params={'virtual_circuit_id': 'pk'},
|
||||
verbose_name=_('Terminations')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments')
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='circuits:virtualcircuit_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = VirtualCircuit
|
||||
fields = (
|
||||
'pk', 'id', 'cid', 'provider', 'provider_account', 'provider_network', 'type', 'status', 'tenant',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from core.choices import *
|
||||
from core.models import DataFile, DataSource
|
||||
from netbox.api.fields import ChoiceField, RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import NetBoxModelSerializer, PrimaryModelSerializer
|
||||
from netbox.utils import get_data_backend_choices
|
||||
|
||||
__all__ = (
|
||||
@@ -10,7 +10,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class DataSourceSerializer(NetBoxModelSerializer):
|
||||
class DataSourceSerializer(PrimaryModelSerializer):
|
||||
type = ChoiceField(
|
||||
choices=get_data_backend_choices()
|
||||
)
|
||||
@@ -26,8 +26,8 @@ class DataSourceSerializer(NetBoxModelSerializer):
|
||||
model = DataSource
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'type', 'source_url', 'enabled', 'status', 'description',
|
||||
'sync_interval', 'parameters', 'ignore_rules', 'comments', 'custom_fields', 'created', 'last_updated',
|
||||
'last_synced', 'file_count',
|
||||
'sync_interval', 'parameters', 'ignore_rules', 'owner', 'comments', 'custom_fields', 'created',
|
||||
'last_updated', 'last_synced', 'file_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet
|
||||
from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, PrimaryModelFilterSet
|
||||
from netbox.utils import get_data_backend_choices
|
||||
from users.models import User
|
||||
from utilities.filters import ContentTypeFilter
|
||||
@@ -20,7 +20,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class DataSourceFilterSet(NetBoxModelFilterSet):
|
||||
class DataSourceFilterSet(PrimaryModelFilterSet):
|
||||
type = django_filters.MultipleChoiceFilter(
|
||||
choices=get_data_backend_choices,
|
||||
null_value=None
|
||||
|
||||
@@ -3,9 +3,8 @@ from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from core.choices import JobIntervalChoices
|
||||
from core.models import *
|
||||
from netbox.forms import NetBoxModelBulkEditForm
|
||||
from netbox.forms import PrimaryModelBulkEditForm
|
||||
from netbox.utils import get_data_backend_choices
|
||||
from utilities.forms.fields import CommentField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import BulkEditNullBooleanSelect
|
||||
|
||||
@@ -14,7 +13,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class DataSourceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class DataSourceBulkEditForm(PrimaryModelBulkEditForm):
|
||||
type = forms.ChoiceField(
|
||||
label=_('Type'),
|
||||
choices=get_data_backend_choices,
|
||||
@@ -25,17 +24,11 @@ class DataSourceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label=_('Enabled')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
sync_interval = forms.ChoiceField(
|
||||
choices=JobIntervalChoices,
|
||||
required=False,
|
||||
label=_('Sync interval')
|
||||
)
|
||||
comments = CommentField()
|
||||
parameters = forms.JSONField(
|
||||
label=_('Parameters'),
|
||||
required=False
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
from core.models import *
|
||||
from netbox.forms import NetBoxModelImportForm
|
||||
from netbox.forms import PrimaryModelImportForm
|
||||
|
||||
__all__ = (
|
||||
'DataSourceImportForm',
|
||||
)
|
||||
|
||||
|
||||
class DataSourceImportForm(NetBoxModelImportForm):
|
||||
class DataSourceImportForm(PrimaryModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = DataSource
|
||||
fields = (
|
||||
'name', 'type', 'source_url', 'enabled', 'description', 'sync_interval', 'parameters', 'ignore_rules',
|
||||
'comments',
|
||||
'owner', 'comments',
|
||||
)
|
||||
|
||||
@@ -3,13 +3,13 @@ from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from core.choices import *
|
||||
from core.models import *
|
||||
from netbox.forms import NetBoxModelFilterSetForm
|
||||
from netbox.forms import NetBoxModelFilterSetForm, PrimaryModelFilterSetForm
|
||||
from netbox.forms.mixins import SavedFiltersMixin
|
||||
from netbox.utils import get_data_backend_choices
|
||||
from users.models import User
|
||||
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
|
||||
from utilities.forms.fields import (
|
||||
ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField,
|
||||
ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField,
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import DateTimePicker
|
||||
@@ -23,10 +23,10 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class DataSourceFilterForm(NetBoxModelFilterSetForm):
|
||||
class DataSourceFilterForm(PrimaryModelFilterSetForm):
|
||||
model = DataSource
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('type', 'status', 'enabled', 'sync_interval', name=_('Data Source')),
|
||||
)
|
||||
type = forms.MultipleChoiceField(
|
||||
@@ -51,6 +51,7 @@ class DataSourceFilterForm(NetBoxModelFilterSetForm):
|
||||
choices=JobIntervalChoices,
|
||||
required=False
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class DataFileFilterForm(NetBoxModelFilterSetForm):
|
||||
|
||||
@@ -9,11 +9,11 @@ from django.utils.translation import gettext_lazy as _
|
||||
from core.forms.mixins import SyncedDataMixin
|
||||
from core.models import *
|
||||
from netbox.config import get_config, PARAMS
|
||||
from netbox.forms import NetBoxModelForm
|
||||
from netbox.forms import NetBoxModelForm, PrimaryModelForm
|
||||
from netbox.registry import registry
|
||||
from netbox.utils import get_data_backend_choices
|
||||
from utilities.forms import get_field_value
|
||||
from utilities.forms.fields import CommentField, JSONField
|
||||
from utilities.forms.fields import JSONField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import HTMXSelect
|
||||
|
||||
@@ -26,17 +26,17 @@ __all__ = (
|
||||
EMPTY_VALUES = ('', None, [], ())
|
||||
|
||||
|
||||
class DataSourceForm(NetBoxModelForm):
|
||||
class DataSourceForm(PrimaryModelForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=get_data_backend_choices,
|
||||
widget=HTMXSelect()
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
class Meta:
|
||||
model = DataSource
|
||||
fields = [
|
||||
'name', 'type', 'source_url', 'enabled', 'description', 'sync_interval', 'ignore_rules', 'comments', 'tags',
|
||||
'name', 'type', 'source_url', 'enabled', 'description', 'sync_interval', 'ignore_rules', 'owner',
|
||||
'comments', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'ignore_rules': forms.Textarea(
|
||||
|
||||
@@ -5,7 +5,7 @@ import strawberry_django
|
||||
from django.contrib.contenttypes.models import ContentType as DjangoContentType
|
||||
|
||||
from core import models
|
||||
from netbox.graphql.types import BaseObjectType, NetBoxObjectType
|
||||
from netbox.graphql.types import BaseObjectType, PrimaryObjectType
|
||||
from .filters import *
|
||||
|
||||
__all__ = (
|
||||
@@ -32,8 +32,7 @@ class DataFileType(BaseObjectType):
|
||||
filters=DataSourceFilter,
|
||||
pagination=True
|
||||
)
|
||||
class DataSourceType(NetBoxObjectType):
|
||||
|
||||
class DataSourceType(PrimaryObjectType):
|
||||
datafiles: List[Annotated["DataFileType", strawberry.lazy('core.graphql.types')]]
|
||||
|
||||
|
||||
|
||||
19
netbox/core/migrations/0020_owner.py
Normal file
19
netbox/core/migrations/0020_owner.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('core', '0019_configrevision_active'),
|
||||
('users', '0015_owner'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='datasource',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -2,7 +2,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
|
||||
from core.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import NetBoxTable, PrimaryModelTable, columns
|
||||
from .columns import BackendTypeColumn
|
||||
from .template_code import DATA_SOURCE_SYNC_BUTTON
|
||||
|
||||
@@ -12,7 +12,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class DataSourceTable(NetBoxTable):
|
||||
class DataSourceTable(PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True,
|
||||
@@ -42,7 +42,7 @@ class DataSourceTable(NetBoxTable):
|
||||
extra_buttons=DATA_SOURCE_SYNC_BUTTON,
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = DataSource
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'type', 'status', 'enabled', 'source_url', 'description', 'sync_interval', 'comments',
|
||||
|
||||
@@ -5,7 +5,9 @@ from rest_framework import serializers
|
||||
from dcim.choices import *
|
||||
from dcim.models import Cable, CablePath, CableTermination
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField
|
||||
from netbox.api.serializers import BaseModelSerializer, GenericObjectSerializer, NetBoxModelSerializer
|
||||
from netbox.api.serializers import (
|
||||
BaseModelSerializer, GenericObjectSerializer, NetBoxModelSerializer, PrimaryModelSerializer,
|
||||
)
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from utilities.api import get_serializer_for_model
|
||||
|
||||
@@ -18,7 +20,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class CableSerializer(NetBoxModelSerializer):
|
||||
class CableSerializer(PrimaryModelSerializer):
|
||||
a_terminations = GenericObjectSerializer(many=True, required=False)
|
||||
b_terminations = GenericObjectSerializer(many=True, required=False)
|
||||
status = ChoiceField(choices=LinkStatusChoices, required=False)
|
||||
@@ -29,8 +31,8 @@ class CableSerializer(NetBoxModelSerializer):
|
||||
model = Cable
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'type', 'a_terminations', 'b_terminations', 'status', 'tenant',
|
||||
'label', 'color', 'length', 'length_unit', 'description', 'comments', 'tags', 'custom_fields', 'created',
|
||||
'last_updated',
|
||||
'label', 'color', 'length', 'length_unit', 'description', 'owner', 'comments', 'tags', 'custom_fields',
|
||||
'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'label', 'description')
|
||||
|
||||
|
||||
@@ -11,15 +11,15 @@ from dcim.models import Device, DeviceBay, MACAddress, Module, VirtualDeviceCont
|
||||
from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
|
||||
from ipam.api.serializers_.ip import IPAddressSerializer
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from utilities.api import get_serializer_for_model
|
||||
from virtualization.api.serializers_.clusters import ClusterSerializer
|
||||
from .devicetypes import *
|
||||
from .nested import NestedDeviceBaySerializer, NestedDeviceSerializer, NestedModuleBaySerializer
|
||||
from .platforms import PlatformSerializer
|
||||
from .racks import RackSerializer
|
||||
from .roles import DeviceRoleSerializer
|
||||
from .nested import NestedDeviceBaySerializer, NestedDeviceSerializer, NestedModuleBaySerializer
|
||||
from .sites import LocationSerializer, SiteSerializer
|
||||
from .virtualchassis import VirtualChassisSerializer
|
||||
|
||||
@@ -32,7 +32,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class DeviceSerializer(NetBoxModelSerializer):
|
||||
class DeviceSerializer(PrimaryModelSerializer):
|
||||
device_type = DeviceTypeSerializer(nested=True)
|
||||
role = DeviceRoleSerializer(nested=True)
|
||||
tenant = TenantSerializer(
|
||||
@@ -84,8 +84,8 @@ class DeviceSerializer(NetBoxModelSerializer):
|
||||
'id', 'url', 'display_url', 'display', 'name', 'device_type', 'role', 'tenant', 'platform', 'serial',
|
||||
'asset_tag', 'site', 'location', 'rack', 'position', 'face', 'latitude', 'longitude', 'parent_device',
|
||||
'status', 'airflow', 'primary_ip', 'primary_ip4', 'primary_ip6', 'oob_ip', 'cluster', 'virtual_chassis',
|
||||
'vc_position', 'vc_priority', 'description', 'comments', 'config_template', 'local_context_data', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'console_port_count', 'console_server_port_count',
|
||||
'vc_position', 'vc_priority', 'description', 'owner', 'comments', 'config_template', 'local_context_data',
|
||||
'tags', 'custom_fields', 'created', 'last_updated', 'console_port_count', 'console_server_port_count',
|
||||
'power_port_count', 'power_outlet_count', 'interface_count', 'front_port_count', 'rear_port_count',
|
||||
'device_bay_count', 'module_bay_count', 'inventory_item_count',
|
||||
]
|
||||
@@ -122,7 +122,7 @@ class DeviceWithConfigContextSerializer(DeviceSerializer):
|
||||
return obj.get_config_context()
|
||||
|
||||
|
||||
class VirtualDeviceContextSerializer(NetBoxModelSerializer):
|
||||
class VirtualDeviceContextSerializer(PrimaryModelSerializer):
|
||||
device = DeviceSerializer(nested=True)
|
||||
identifier = serializers.IntegerField(allow_null=True, max_value=32767, min_value=0, required=False, default=None)
|
||||
tenant = TenantSerializer(nested=True, required=False, allow_null=True, default=None)
|
||||
@@ -138,13 +138,13 @@ class VirtualDeviceContextSerializer(NetBoxModelSerializer):
|
||||
model = VirtualDeviceContext
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'device', 'identifier', 'tenant', 'primary_ip',
|
||||
'primary_ip4', 'primary_ip6', 'status', 'description', 'comments', 'tags', 'custom_fields',
|
||||
'primary_ip4', 'primary_ip6', 'status', 'description', 'owner', 'comments', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'interface_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'identifier', 'device', 'description')
|
||||
|
||||
|
||||
class ModuleSerializer(NetBoxModelSerializer):
|
||||
class ModuleSerializer(PrimaryModelSerializer):
|
||||
device = DeviceSerializer(nested=True)
|
||||
module_bay = NestedModuleBaySerializer()
|
||||
module_type = ModuleTypeSerializer(nested=True)
|
||||
@@ -154,12 +154,12 @@ class ModuleSerializer(NetBoxModelSerializer):
|
||||
model = Module
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'device', 'module_bay', 'module_type', 'status', 'serial',
|
||||
'asset_tag', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'asset_tag', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'device', 'module_bay', 'module_type', 'description')
|
||||
|
||||
|
||||
class MACAddressSerializer(NetBoxModelSerializer):
|
||||
class MACAddressSerializer(PrimaryModelSerializer):
|
||||
assigned_object_type = ContentTypeField(
|
||||
queryset=ContentType.objects.filter(MACADDRESS_ASSIGNMENT_MODELS),
|
||||
required=False,
|
||||
@@ -171,7 +171,7 @@ class MACAddressSerializer(NetBoxModelSerializer):
|
||||
model = MACAddress
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'mac_address', 'assigned_object_type', 'assigned_object_id',
|
||||
'assigned_object', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'assigned_object', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'mac_address', 'description')
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from rest_framework import serializers
|
||||
from dcim.choices import *
|
||||
from dcim.models import DeviceType, ModuleType, ModuleTypeProfile
|
||||
from netbox.api.fields import AttributesField, ChoiceField, RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from netbox.choices import *
|
||||
from .manufacturers import ManufacturerSerializer
|
||||
from .platforms import PlatformSerializer
|
||||
@@ -18,7 +18,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class DeviceTypeSerializer(NetBoxModelSerializer):
|
||||
class DeviceTypeSerializer(PrimaryModelSerializer):
|
||||
manufacturer = ManufacturerSerializer(nested=True)
|
||||
default_platform = PlatformSerializer(nested=True, required=False, allow_null=True)
|
||||
u_height = serializers.DecimalField(
|
||||
@@ -54,7 +54,7 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'manufacturer', 'default_platform', 'model', 'slug', 'part_number',
|
||||
'u_height', 'exclude_from_utilization', 'is_full_depth', 'subdevice_role', 'airflow', 'weight',
|
||||
'weight_unit', 'front_image', 'rear_image', 'description', 'comments', 'tags', 'custom_fields',
|
||||
'weight_unit', 'front_image', 'rear_image', 'description', 'owner', 'comments', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'device_count', 'console_port_template_count',
|
||||
'console_server_port_template_count', 'power_port_template_count', 'power_outlet_template_count',
|
||||
'interface_template_count', 'front_port_template_count', 'rear_port_template_count',
|
||||
@@ -63,18 +63,18 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
|
||||
brief_fields = ('id', 'url', 'display', 'manufacturer', 'model', 'slug', 'description', 'device_count')
|
||||
|
||||
|
||||
class ModuleTypeProfileSerializer(NetBoxModelSerializer):
|
||||
class ModuleTypeProfileSerializer(PrimaryModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ModuleTypeProfile
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'description', 'schema', 'comments', 'tags', 'custom_fields',
|
||||
'created', 'last_updated',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'description', 'schema', 'owner', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
|
||||
class ModuleTypeSerializer(NetBoxModelSerializer):
|
||||
class ModuleTypeSerializer(PrimaryModelSerializer):
|
||||
profile = ModuleTypeProfileSerializer(
|
||||
nested=True,
|
||||
required=False,
|
||||
@@ -105,7 +105,7 @@ class ModuleTypeSerializer(NetBoxModelSerializer):
|
||||
model = ModuleType
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'profile', 'manufacturer', 'model', 'part_number', 'airflow',
|
||||
'weight', 'weight_unit', 'description', 'attributes', 'comments', 'tags', 'custom_fields', 'created',
|
||||
'last_updated',
|
||||
'weight', 'weight_unit', 'description', 'attributes', 'owner', 'comments', 'tags', 'custom_fields',
|
||||
'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'profile', 'manufacturer', 'model', 'description')
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
from dcim.models import Manufacturer
|
||||
from netbox.api.fields import RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import OrganizationalModelSerializer
|
||||
|
||||
__all__ = (
|
||||
'ManufacturerSerializer',
|
||||
)
|
||||
|
||||
|
||||
class ManufacturerSerializer(NetBoxModelSerializer):
|
||||
class ManufacturerSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
devicetype_count = RelatedObjectCountField('device_types')
|
||||
@@ -17,7 +17,7 @@ class ManufacturerSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = Manufacturer
|
||||
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', 'devicetype_count', 'inventoryitem_count', 'platform_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'devicetype_count')
|
||||
|
||||
@@ -24,7 +24,7 @@ class PlatformSerializer(NestedGroupModelSerializer):
|
||||
model = Platform
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'parent', 'name', 'slug', 'manufacturer', 'config_template',
|
||||
'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count',
|
||||
'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count',
|
||||
'virtualmachine_count', '_depth',
|
||||
]
|
||||
brief_fields = (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from dcim.choices import *
|
||||
from dcim.models import PowerFeed, PowerPanel
|
||||
from netbox.api.fields import ChoiceField, RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from .base import ConnectedEndpointsSerializer
|
||||
from .cables import CabledObjectSerializer
|
||||
@@ -14,7 +14,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class PowerPanelSerializer(NetBoxModelSerializer):
|
||||
class PowerPanelSerializer(PrimaryModelSerializer):
|
||||
site = SiteSerializer(nested=True)
|
||||
location = LocationSerializer(
|
||||
nested=True,
|
||||
@@ -29,13 +29,13 @@ class PowerPanelSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = PowerPanel
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'site', 'location', 'name', 'description', 'comments', 'tags',
|
||||
'custom_fields', 'powerfeed_count', 'created', 'last_updated',
|
||||
'id', 'url', 'display_url', 'display', 'site', 'location', 'name', 'description', 'owner', 'comments',
|
||||
'tags', 'custom_fields', 'powerfeed_count', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description', 'powerfeed_count')
|
||||
|
||||
|
||||
class PowerFeedSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
|
||||
class PowerFeedSerializer(PrimaryModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
|
||||
power_panel = PowerPanelSerializer(nested=True)
|
||||
rack = RackSerializer(
|
||||
nested=True,
|
||||
@@ -71,6 +71,7 @@ class PowerFeedSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
|
||||
'id', 'url', 'display_url', 'display', 'power_panel', 'rack', 'name', 'status', 'type', 'supply',
|
||||
'phase', 'voltage', 'amperage', 'max_utilization', 'mark_connected', 'cable', 'cable_end', 'link_peers',
|
||||
'link_peers_type', 'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable',
|
||||
'description', 'tenant', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied',
|
||||
'description', 'tenant', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'_occupied',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description', 'cable', '_occupied')
|
||||
|
||||
@@ -5,7 +5,7 @@ from dcim.choices import *
|
||||
from dcim.constants import *
|
||||
from dcim.models import Rack, RackReservation, RackRole, RackType
|
||||
from netbox.api.fields import ChoiceField, RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import OrganizationalModelSerializer, PrimaryModelSerializer
|
||||
from netbox.choices import *
|
||||
from netbox.config import ConfigItem
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
@@ -22,7 +22,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class RackRoleSerializer(NetBoxModelSerializer):
|
||||
class RackRoleSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
rack_count = RelatedObjectCountField('racks')
|
||||
@@ -30,13 +30,13 @@ class RackRoleSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = RackRole
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'rack_count',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'owner', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'rack_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'rack_count')
|
||||
|
||||
|
||||
class RackBaseSerializer(NetBoxModelSerializer):
|
||||
class RackBaseSerializer(PrimaryModelSerializer):
|
||||
form_factor = ChoiceField(
|
||||
choices=RackFormFactorChoices,
|
||||
allow_blank=True,
|
||||
@@ -71,8 +71,8 @@ class RackTypeSerializer(RackBaseSerializer):
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'manufacturer', 'model', 'slug', 'description', 'form_factor',
|
||||
'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_height', 'outer_depth',
|
||||
'outer_unit', 'weight', 'max_weight', 'weight_unit', 'mounting_depth', 'description', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated',
|
||||
'outer_unit', 'weight', 'max_weight', 'weight_unit', 'mounting_depth', 'description', 'owner', 'comments',
|
||||
'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'manufacturer', 'model', 'slug', 'description')
|
||||
|
||||
@@ -130,13 +130,13 @@ class RackSerializer(RackBaseSerializer):
|
||||
'id', 'url', 'display_url', 'display', 'name', 'facility_id', 'site', 'location', 'tenant', 'status',
|
||||
'role', 'serial', 'asset_tag', 'rack_type', 'form_factor', 'width', 'u_height', 'starting_unit', 'weight',
|
||||
'max_weight', 'weight_unit', 'desc_units', 'outer_width', 'outer_height', 'outer_depth', 'outer_unit',
|
||||
'mounting_depth', 'airflow', 'description', 'comments', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'device_count', 'powerfeed_count',
|
||||
'mounting_depth', 'airflow', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created',
|
||||
'last_updated', 'device_count', 'powerfeed_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description', 'device_count')
|
||||
|
||||
|
||||
class RackReservationSerializer(NetBoxModelSerializer):
|
||||
class RackReservationSerializer(PrimaryModelSerializer):
|
||||
rack = RackSerializer(
|
||||
nested=True,
|
||||
)
|
||||
@@ -157,7 +157,7 @@ class RackReservationSerializer(NetBoxModelSerializer):
|
||||
model = RackReservation
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'rack', 'units', 'status', 'created', 'last_updated', 'user',
|
||||
'tenant', 'description', 'comments', 'tags', 'custom_fields',
|
||||
'tenant', 'description', 'owner', 'comments', 'tags', 'custom_fields',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'status', 'user', 'description', 'units')
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from rest_framework import serializers
|
||||
from dcim.models import DeviceRole, InventoryItemRole
|
||||
from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
|
||||
from netbox.api.fields import RelatedObjectCountField
|
||||
from netbox.api.serializers import NestedGroupModelSerializer, NetBoxModelSerializer
|
||||
from netbox.api.serializers import NestedGroupModelSerializer, OrganizationalModelSerializer
|
||||
from .nested import NestedDeviceRoleSerializer
|
||||
|
||||
__all__ = (
|
||||
@@ -23,14 +23,14 @@ class DeviceRoleSerializer(NestedGroupModelSerializer):
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'vm_role', 'config_template', 'parent',
|
||||
'description', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'virtualmachine_count',
|
||||
'comments', '_depth',
|
||||
'owner', 'comments', '_depth',
|
||||
]
|
||||
brief_fields = (
|
||||
'id', 'url', 'display', 'name', 'slug', 'description', 'device_count', 'virtualmachine_count', '_depth'
|
||||
)
|
||||
|
||||
|
||||
class InventoryItemRoleSerializer(NetBoxModelSerializer):
|
||||
class InventoryItemRoleSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
inventoryitem_count = RelatedObjectCountField('inventory_items')
|
||||
@@ -38,7 +38,7 @@ class InventoryItemRoleSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = InventoryItemRole
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'inventoryitem_count',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'owner', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'inventoryitem_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'inventoryitem_count')
|
||||
|
||||
@@ -6,7 +6,7 @@ from dcim.models import Location, Region, Site, SiteGroup
|
||||
from ipam.api.serializers_.asns import ASNSerializer
|
||||
from ipam.models import ASN
|
||||
from netbox.api.fields import ChoiceField, RelatedObjectCountField, SerializedPKRelatedField
|
||||
from netbox.api.serializers import NestedGroupModelSerializer, NetBoxModelSerializer
|
||||
from netbox.api.serializers import NestedGroupModelSerializer, PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from .nested import NestedLocationSerializer, NestedRegionSerializer, NestedSiteGroupSerializer
|
||||
|
||||
@@ -27,7 +27,7 @@ class RegionSerializer(NestedGroupModelSerializer):
|
||||
model = Region
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'site_count', 'prefix_count', 'comments', '_depth',
|
||||
'created', 'last_updated', 'site_count', 'prefix_count', 'owner', 'comments', '_depth',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'site_count', '_depth')
|
||||
|
||||
@@ -41,12 +41,12 @@ class SiteGroupSerializer(NestedGroupModelSerializer):
|
||||
model = SiteGroup
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'site_count', 'prefix_count', 'comments', '_depth',
|
||||
'created', 'last_updated', 'site_count', 'prefix_count', 'owner', 'comments', '_depth',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'site_count', '_depth')
|
||||
|
||||
|
||||
class SiteSerializer(NetBoxModelSerializer):
|
||||
class SiteSerializer(PrimaryModelSerializer):
|
||||
status = ChoiceField(choices=SiteStatusChoices, required=False)
|
||||
region = RegionSerializer(nested=True, required=False, allow_null=True)
|
||||
group = SiteGroupSerializer(nested=True, required=False, allow_null=True)
|
||||
@@ -72,7 +72,7 @@ class SiteSerializer(NetBoxModelSerializer):
|
||||
model = Site
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility',
|
||||
'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude',
|
||||
'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'owner',
|
||||
'comments', 'asns', 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count', 'device_count',
|
||||
'prefix_count', 'rack_count', 'virtualmachine_count', 'vlan_count',
|
||||
]
|
||||
@@ -93,6 +93,6 @@ class LocationSerializer(NestedGroupModelSerializer):
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'site', 'parent', 'status', 'tenant', 'facility',
|
||||
'description', 'tags', 'custom_fields', 'created', 'last_updated', 'rack_count', 'device_count',
|
||||
'prefix_count', 'comments', '_depth',
|
||||
'prefix_count', 'owner', 'comments', '_depth',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'rack_count', '_depth')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from dcim.models import VirtualChassis
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from .nested import NestedDeviceSerializer
|
||||
|
||||
__all__ = (
|
||||
@@ -9,7 +9,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class VirtualChassisSerializer(NetBoxModelSerializer):
|
||||
class VirtualChassisSerializer(PrimaryModelSerializer):
|
||||
master = NestedDeviceSerializer(required=False, allow_null=True, default=None)
|
||||
members = NestedDeviceSerializer(many=True, read_only=True)
|
||||
|
||||
@@ -19,7 +19,7 @@ class VirtualChassisSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = VirtualChassis
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'domain', 'master', 'description', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'member_count', 'members',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'domain', 'master', 'description', 'owner', 'comments',
|
||||
'tags', 'custom_fields', 'created', 'last_updated', 'member_count', 'members',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'master', 'description', 'member_count')
|
||||
|
||||
@@ -11,11 +11,12 @@ from ipam.filtersets import PrimaryIPFilterSet
|
||||
from ipam.models import ASN, IPAddress, VLANTranslationPolicy, VRF
|
||||
from netbox.choices import ColorChoices
|
||||
from netbox.filtersets import (
|
||||
AttributeFiltersMixin, BaseFilterSet, ChangeLoggedModelFilterSet, NestedGroupModelFilterSet, NetBoxModelFilterSet,
|
||||
OrganizationalModelFilterSet,
|
||||
AttributeFiltersMixin, BaseFilterSet, ChangeLoggedModelFilterSet, NestedGroupModelFilterSet,
|
||||
OrganizationalModelFilterSet, PrimaryModelFilterSet, NetBoxModelFilterSet,
|
||||
)
|
||||
from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
|
||||
from tenancy.models import *
|
||||
from users.filterset_mixins import OwnerFilterMixin
|
||||
from users.models import User
|
||||
from utilities.filters import (
|
||||
ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
|
||||
@@ -143,7 +144,7 @@ class SiteGroupFilterSet(NestedGroupModelFilterSet, ContactModelFilterSet):
|
||||
fields = ('id', 'name', 'slug', 'description')
|
||||
|
||||
|
||||
class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
class SiteFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=SiteStatusChoices,
|
||||
null_value=None
|
||||
@@ -293,7 +294,7 @@ class RackRoleFilterSet(OrganizationalModelFilterSet):
|
||||
fields = ('id', 'name', 'slug', 'color', 'description')
|
||||
|
||||
|
||||
class RackTypeFilterSet(NetBoxModelFilterSet):
|
||||
class RackTypeFilterSet(PrimaryModelFilterSet):
|
||||
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Manufacturer.objects.all(),
|
||||
label=_('Manufacturer (ID)'),
|
||||
@@ -328,7 +329,7 @@ class RackTypeFilterSet(NetBoxModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
class RackFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
region_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
@@ -444,7 +445,7 @@ class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
|
||||
)
|
||||
|
||||
|
||||
class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
class RackReservationFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
|
||||
rack_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Rack.objects.all(),
|
||||
label=_('Rack (ID)'),
|
||||
@@ -540,7 +541,7 @@ class ManufacturerFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet)
|
||||
fields = ('id', 'name', 'slug', 'description')
|
||||
|
||||
|
||||
class DeviceTypeFilterSet(NetBoxModelFilterSet):
|
||||
class DeviceTypeFilterSet(PrimaryModelFilterSet):
|
||||
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Manufacturer.objects.all(),
|
||||
label=_('Manufacturer (ID)'),
|
||||
@@ -682,7 +683,7 @@ class DeviceTypeFilterSet(NetBoxModelFilterSet):
|
||||
return queryset.exclude(inventoryitemtemplates__isnull=value)
|
||||
|
||||
|
||||
class ModuleTypeProfileFilterSet(NetBoxModelFilterSet):
|
||||
class ModuleTypeProfileFilterSet(PrimaryModelFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = ModuleTypeProfile
|
||||
@@ -698,7 +699,7 @@ class ModuleTypeProfileFilterSet(NetBoxModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class ModuleTypeFilterSet(AttributeFiltersMixin, NetBoxModelFilterSet):
|
||||
class ModuleTypeFilterSet(AttributeFiltersMixin, PrimaryModelFilterSet):
|
||||
profile_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ModuleTypeProfile.objects.all(),
|
||||
label=_('Profile (ID)'),
|
||||
@@ -951,7 +952,7 @@ class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeCompo
|
||||
return queryset.filter(qs_filter)
|
||||
|
||||
|
||||
class DeviceRoleFilterSet(OrganizationalModelFilterSet):
|
||||
class DeviceRoleFilterSet(NestedGroupModelFilterSet):
|
||||
config_template_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
label=_('Config template (ID)'),
|
||||
@@ -985,7 +986,7 @@ class DeviceRoleFilterSet(OrganizationalModelFilterSet):
|
||||
fields = ('id', 'name', 'slug', 'color', 'vm_role', 'description')
|
||||
|
||||
|
||||
class PlatformFilterSet(OrganizationalModelFilterSet):
|
||||
class PlatformFilterSet(NestedGroupModelFilterSet):
|
||||
parent_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Platform.objects.all(),
|
||||
label=_('Immediate parent platform (ID)'),
|
||||
@@ -1043,7 +1044,7 @@ class PlatformFilterSet(OrganizationalModelFilterSet):
|
||||
|
||||
|
||||
class DeviceFilterSet(
|
||||
NetBoxModelFilterSet,
|
||||
PrimaryModelFilterSet,
|
||||
TenancyFilterSet,
|
||||
ContactModelFilterSet,
|
||||
LocalConfigContextFilterSet,
|
||||
@@ -1345,7 +1346,7 @@ class DeviceFilterSet(
|
||||
return queryset.exclude(params)
|
||||
|
||||
|
||||
class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet, PrimaryIPFilterSet):
|
||||
class VirtualDeviceContextFilterSet(PrimaryModelFilterSet, TenancyFilterSet, PrimaryIPFilterSet):
|
||||
device_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='device',
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1394,7 +1395,7 @@ class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet, Prim
|
||||
return queryset.exclude(params)
|
||||
|
||||
|
||||
class ModuleFilterSet(NetBoxModelFilterSet):
|
||||
class ModuleFilterSet(PrimaryModelFilterSet):
|
||||
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='module_type__manufacturer',
|
||||
queryset=Manufacturer.objects.all(),
|
||||
@@ -1516,7 +1517,7 @@ class ModuleFilterSet(NetBoxModelFilterSet):
|
||||
).distinct()
|
||||
|
||||
|
||||
class DeviceComponentFilterSet(django_filters.FilterSet):
|
||||
class DeviceComponentFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -1682,12 +1683,7 @@ class PathEndpointFilterSet(django_filters.FilterSet):
|
||||
return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False))
|
||||
|
||||
|
||||
class ConsolePortFilterSet(
|
||||
ModularDeviceComponentFilterSet,
|
||||
NetBoxModelFilterSet,
|
||||
CabledObjectFilterSet,
|
||||
PathEndpointFilterSet
|
||||
):
|
||||
class ConsolePortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
|
||||
type = django_filters.MultipleChoiceFilter(
|
||||
choices=ConsolePortTypeChoices,
|
||||
null_value=None
|
||||
@@ -1698,12 +1694,7 @@ class ConsolePortFilterSet(
|
||||
fields = ('id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end')
|
||||
|
||||
|
||||
class ConsoleServerPortFilterSet(
|
||||
ModularDeviceComponentFilterSet,
|
||||
NetBoxModelFilterSet,
|
||||
CabledObjectFilterSet,
|
||||
PathEndpointFilterSet
|
||||
):
|
||||
class ConsoleServerPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
|
||||
type = django_filters.MultipleChoiceFilter(
|
||||
choices=ConsolePortTypeChoices,
|
||||
null_value=None
|
||||
@@ -1714,12 +1705,7 @@ class ConsoleServerPortFilterSet(
|
||||
fields = ('id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end')
|
||||
|
||||
|
||||
class PowerPortFilterSet(
|
||||
ModularDeviceComponentFilterSet,
|
||||
NetBoxModelFilterSet,
|
||||
CabledObjectFilterSet,
|
||||
PathEndpointFilterSet
|
||||
):
|
||||
class PowerPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
|
||||
type = django_filters.MultipleChoiceFilter(
|
||||
choices=PowerPortTypeChoices,
|
||||
null_value=None
|
||||
@@ -1732,12 +1718,7 @@ class PowerPortFilterSet(
|
||||
)
|
||||
|
||||
|
||||
class PowerOutletFilterSet(
|
||||
ModularDeviceComponentFilterSet,
|
||||
NetBoxModelFilterSet,
|
||||
CabledObjectFilterSet,
|
||||
PathEndpointFilterSet
|
||||
):
|
||||
class PowerOutletFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
|
||||
type = django_filters.MultipleChoiceFilter(
|
||||
choices=PowerOutletTypeChoices,
|
||||
null_value=None
|
||||
@@ -1762,7 +1743,7 @@ class PowerOutletFilterSet(
|
||||
)
|
||||
|
||||
|
||||
class MACAddressFilterSet(NetBoxModelFilterSet):
|
||||
class MACAddressFilterSet(PrimaryModelFilterSet):
|
||||
mac_address = MultiValueMACAddressFilter()
|
||||
assigned_object_type = ContentTypeFilter()
|
||||
device = MultiValueCharFilter(
|
||||
@@ -1914,7 +1895,6 @@ class CommonInterfaceFilterSet(django_filters.FilterSet):
|
||||
|
||||
class InterfaceFilterSet(
|
||||
ModularDeviceComponentFilterSet,
|
||||
NetBoxModelFilterSet,
|
||||
CabledObjectFilterSet,
|
||||
PathEndpointFilterSet,
|
||||
CommonInterfaceFilterSet
|
||||
@@ -2075,11 +2055,7 @@ class InterfaceFilterSet(
|
||||
)
|
||||
|
||||
|
||||
class FrontPortFilterSet(
|
||||
ModularDeviceComponentFilterSet,
|
||||
NetBoxModelFilterSet,
|
||||
CabledObjectFilterSet
|
||||
):
|
||||
class FrontPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet):
|
||||
type = django_filters.MultipleChoiceFilter(
|
||||
choices=PortTypeChoices,
|
||||
null_value=None
|
||||
@@ -2095,11 +2071,7 @@ class FrontPortFilterSet(
|
||||
)
|
||||
|
||||
|
||||
class RearPortFilterSet(
|
||||
ModularDeviceComponentFilterSet,
|
||||
NetBoxModelFilterSet,
|
||||
CabledObjectFilterSet
|
||||
):
|
||||
class RearPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet):
|
||||
type = django_filters.MultipleChoiceFilter(
|
||||
choices=PortTypeChoices,
|
||||
null_value=None
|
||||
@@ -2112,7 +2084,7 @@ class RearPortFilterSet(
|
||||
)
|
||||
|
||||
|
||||
class ModuleBayFilterSet(ModularDeviceComponentFilterSet, NetBoxModelFilterSet):
|
||||
class ModuleBayFilterSet(ModularDeviceComponentFilterSet):
|
||||
parent_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ModuleBay.objects.all(),
|
||||
label=_('Parent module bay (ID)'),
|
||||
@@ -2128,7 +2100,7 @@ class ModuleBayFilterSet(ModularDeviceComponentFilterSet, NetBoxModelFilterSet):
|
||||
fields = ('id', 'name', 'label', 'position', 'description')
|
||||
|
||||
|
||||
class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
|
||||
class DeviceBayFilterSet(DeviceComponentFilterSet):
|
||||
installed_device_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Device.objects.all(),
|
||||
label=_('Installed device (ID)'),
|
||||
@@ -2145,7 +2117,7 @@ class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
|
||||
fields = ('id', 'name', 'label', 'description')
|
||||
|
||||
|
||||
class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
|
||||
class InventoryItemFilterSet(DeviceComponentFilterSet):
|
||||
parent_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=InventoryItem.objects.all(),
|
||||
label=_('Parent inventory item (ID)'),
|
||||
@@ -2204,7 +2176,7 @@ class InventoryItemRoleFilterSet(OrganizationalModelFilterSet):
|
||||
fields = ('id', 'name', 'slug', 'color', 'description')
|
||||
|
||||
|
||||
class VirtualChassisFilterSet(NetBoxModelFilterSet):
|
||||
class VirtualChassisFilterSet(PrimaryModelFilterSet):
|
||||
master_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Device.objects.all(),
|
||||
label=_('Master (ID)'),
|
||||
@@ -2280,7 +2252,7 @@ class VirtualChassisFilterSet(NetBoxModelFilterSet):
|
||||
return queryset.filter(qs_filter).distinct()
|
||||
|
||||
|
||||
class CableFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
||||
class CableFilterSet(TenancyFilterSet, PrimaryModelFilterSet):
|
||||
termination_a_type = ContentTypeFilter(
|
||||
field_name='terminations__termination_type'
|
||||
)
|
||||
@@ -2457,7 +2429,7 @@ class CableTerminationFilterSet(ChangeLoggedModelFilterSet):
|
||||
fields = ('id', 'cable', 'cable_end', 'termination_type', 'termination_id')
|
||||
|
||||
|
||||
class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
class PowerPanelFilterSet(PrimaryModelFilterSet, ContactModelFilterSet):
|
||||
region_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
@@ -2515,7 +2487,7 @@ class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
return queryset.filter(qs_filter)
|
||||
|
||||
|
||||
class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, TenancyFilterSet):
|
||||
class PowerFeedFilterSet(PrimaryModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, TenancyFilterSet):
|
||||
region_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='power_panel__site__region',
|
||||
|
||||
@@ -10,14 +10,14 @@ from extras.models import ConfigTemplate
|
||||
from ipam.choices import VLANQinQRoleChoices
|
||||
from ipam.models import ASN, VLAN, VLANGroup, VRF
|
||||
from netbox.choices import *
|
||||
from netbox.forms import NetBoxModelBulkEditForm
|
||||
from netbox.forms.mixins import ChangelogMessageMixin
|
||||
from netbox.forms import (
|
||||
NestedGroupModelBulkEditForm, NetBoxModelBulkEditForm, OrganizationalModelBulkEditForm, PrimaryModelBulkEditForm,
|
||||
)
|
||||
from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin
|
||||
from tenancy.models import Tenant
|
||||
from users.models import User
|
||||
from utilities.forms import BulkEditForm, add_blank_choice, form_from_model
|
||||
from utilities.forms.fields import (
|
||||
ColorField, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField,
|
||||
)
|
||||
from utilities.forms.fields import ColorField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField
|
||||
from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups
|
||||
from utilities.forms.widgets import BulkEditNullBooleanSelect, NumberWithOptions
|
||||
from virtualization.models import Cluster
|
||||
@@ -71,18 +71,12 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class RegionBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class RegionBulkEditForm(NestedGroupModelBulkEditForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=Region.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Region
|
||||
fieldsets = (
|
||||
@@ -91,18 +85,12 @@ class RegionBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('parent', 'description', 'comments')
|
||||
|
||||
|
||||
class SiteGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class SiteGroupBulkEditForm(NestedGroupModelBulkEditForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=SiteGroup.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = SiteGroup
|
||||
fieldsets = (
|
||||
@@ -111,7 +99,7 @@ class SiteGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('parent', 'description', 'comments')
|
||||
|
||||
|
||||
class SiteBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class SiteBulkEditForm(PrimaryModelBulkEditForm):
|
||||
status = forms.ChoiceField(
|
||||
label=_('Status'),
|
||||
choices=add_blank_choice(SiteStatusChoices),
|
||||
@@ -162,12 +150,6 @@ class SiteBulkEditForm(NetBoxModelBulkEditForm):
|
||||
choices=add_blank_choice(TimeZoneFormField().choices),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Site
|
||||
fieldsets = (
|
||||
@@ -178,7 +160,7 @@ class SiteBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class LocationBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class LocationBulkEditForm(NestedGroupModelBulkEditForm):
|
||||
site = DynamicModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -208,12 +190,6 @@ class LocationBulkEditForm(NetBoxModelBulkEditForm):
|
||||
max_length=50,
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Location
|
||||
fieldsets = (
|
||||
@@ -222,16 +198,11 @@ class LocationBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('parent', 'tenant', 'facility', 'description', 'comments')
|
||||
|
||||
|
||||
class RackRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class RackRoleBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
color = ColorField(
|
||||
label=_('Color'),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
model = RackRole
|
||||
fieldsets = (
|
||||
@@ -240,7 +211,7 @@ class RackRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('color', 'description')
|
||||
|
||||
|
||||
class RackTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class RackTypeBulkEditForm(PrimaryModelBulkEditForm):
|
||||
manufacturer = DynamicModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all(),
|
||||
@@ -310,12 +281,6 @@ class RackTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
initial=''
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = RackType
|
||||
fieldsets = (
|
||||
@@ -334,7 +299,7 @@ class RackTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class RackBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class RackBulkEditForm(PrimaryModelBulkEditForm):
|
||||
region = DynamicModelChoiceField(
|
||||
label=_('Region'),
|
||||
queryset=Region.objects.all(),
|
||||
@@ -464,12 +429,6 @@ class RackBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
initial=''
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Rack
|
||||
fieldsets = (
|
||||
@@ -485,7 +444,7 @@ class RackBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class RackReservationBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class RackReservationBulkEditForm(PrimaryModelBulkEditForm):
|
||||
status = forms.ChoiceField(
|
||||
label=_('Status'),
|
||||
choices=add_blank_choice(RackReservationStatusChoices),
|
||||
@@ -502,12 +461,6 @@ class RackReservationBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = RackReservation
|
||||
fieldsets = (
|
||||
@@ -516,13 +469,7 @@ class RackReservationBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('comments',)
|
||||
|
||||
|
||||
class ManufacturerBulkEditForm(NetBoxModelBulkEditForm):
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
class ManufacturerBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
model = Manufacturer
|
||||
fieldsets = (
|
||||
FieldSet('description'),
|
||||
@@ -530,7 +477,7 @@ class ManufacturerBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('description',)
|
||||
|
||||
|
||||
class DeviceTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class DeviceTypeBulkEditForm(PrimaryModelBulkEditForm):
|
||||
manufacturer = DynamicModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all(),
|
||||
@@ -576,12 +523,6 @@ class DeviceTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
initial=''
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = DeviceType
|
||||
fieldsets = (
|
||||
@@ -594,17 +535,11 @@ class DeviceTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('part_number', 'airflow', 'weight', 'weight_unit', 'description', 'comments')
|
||||
|
||||
|
||||
class ModuleTypeProfileBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ModuleTypeProfileBulkEditForm(PrimaryModelBulkEditForm):
|
||||
schema = JSONField(
|
||||
label=_('Schema'),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = ModuleTypeProfile
|
||||
fieldsets = (
|
||||
@@ -613,7 +548,7 @@ class ModuleTypeProfileBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('description', 'comments')
|
||||
|
||||
|
||||
class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ModuleTypeBulkEditForm(PrimaryModelBulkEditForm):
|
||||
profile = DynamicModelChoiceField(
|
||||
label=_('Profile'),
|
||||
queryset=ModuleTypeProfile.objects.all(),
|
||||
@@ -644,12 +579,6 @@ class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
initial=''
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = ModuleType
|
||||
fieldsets = (
|
||||
@@ -663,7 +592,7 @@ class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('part_number', 'weight', 'weight_unit', 'profile', 'description', 'comments')
|
||||
|
||||
|
||||
class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class DeviceRoleBulkEditForm(NestedGroupModelBulkEditForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=DeviceRole.objects.all(),
|
||||
@@ -683,12 +612,6 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = DeviceRole
|
||||
fieldsets = (
|
||||
@@ -697,7 +620,7 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('parent', 'color', 'config_template', 'description', 'comments')
|
||||
|
||||
|
||||
class PlatformBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class PlatformBulkEditForm(NestedGroupModelBulkEditForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=Platform.objects.all(),
|
||||
@@ -713,12 +636,6 @@ class PlatformBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Platform
|
||||
fieldsets = (
|
||||
@@ -727,7 +644,7 @@ class PlatformBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('parent', 'manufacturer', 'config_template', 'description', 'comments')
|
||||
|
||||
|
||||
class DeviceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class DeviceBulkEditForm(PrimaryModelBulkEditForm):
|
||||
manufacturer = DynamicModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all(),
|
||||
@@ -787,11 +704,6 @@ class DeviceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
label=_('Serial Number')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
config_template = DynamicModelChoiceField(
|
||||
label=_('Config template'),
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
@@ -805,7 +717,6 @@ class DeviceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
'site_id': ['$site', 'null']
|
||||
},
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Device
|
||||
fieldsets = (
|
||||
@@ -820,7 +731,7 @@ class DeviceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class ModuleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ModuleBulkEditForm(PrimaryModelBulkEditForm):
|
||||
manufacturer = DynamicModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all(),
|
||||
@@ -848,12 +759,6 @@ class ModuleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
label=_('Serial Number')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Module
|
||||
fieldsets = (
|
||||
@@ -862,7 +767,7 @@ class ModuleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('serial', 'description', 'comments')
|
||||
|
||||
|
||||
class CableBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class CableBulkEditForm(PrimaryModelBulkEditForm):
|
||||
type = forms.ChoiceField(
|
||||
label=_('Type'),
|
||||
choices=add_blank_choice(CableTypeChoices),
|
||||
@@ -900,12 +805,6 @@ class CableBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
initial=''
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Cable
|
||||
fieldsets = (
|
||||
@@ -917,18 +816,12 @@ class CableBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class VirtualChassisBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VirtualChassisBulkEditForm(PrimaryModelBulkEditForm):
|
||||
domain = forms.CharField(
|
||||
label=_('Domain'),
|
||||
max_length=30,
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = VirtualChassis
|
||||
fieldsets = (
|
||||
@@ -937,7 +830,7 @@ class VirtualChassisBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('domain', 'description', 'comments')
|
||||
|
||||
|
||||
class PowerPanelBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class PowerPanelBulkEditForm(PrimaryModelBulkEditForm):
|
||||
region = DynamicModelChoiceField(
|
||||
label=_('Region'),
|
||||
queryset=Region.objects.all(),
|
||||
@@ -971,12 +864,6 @@ class PowerPanelBulkEditForm(NetBoxModelBulkEditForm):
|
||||
'site_id': '$site'
|
||||
}
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = PowerPanel
|
||||
fieldsets = (
|
||||
@@ -985,7 +872,7 @@ class PowerPanelBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('location', 'description', 'comments')
|
||||
|
||||
|
||||
class PowerFeedBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class PowerFeedBulkEditForm(PrimaryModelBulkEditForm):
|
||||
power_panel = DynamicModelChoiceField(
|
||||
label=_('Power panel'),
|
||||
queryset=PowerPanel.objects.all(),
|
||||
@@ -1041,12 +928,6 @@ class PowerFeedBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = PowerFeed
|
||||
fieldsets = (
|
||||
@@ -1369,7 +1250,7 @@ class InventoryItemTemplateBulkEditForm(ComponentTemplateBulkEditForm):
|
||||
# Device components
|
||||
#
|
||||
|
||||
class ComponentBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ComponentBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm):
|
||||
device = forms.ModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1822,16 +1703,11 @@ class InventoryItemBulkEditForm(
|
||||
# Device component roles
|
||||
#
|
||||
|
||||
class InventoryItemRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class InventoryItemRoleBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
color = ColorField(
|
||||
label=_('Color'),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
model = InventoryItemRole
|
||||
fieldsets = (
|
||||
@@ -1840,7 +1716,7 @@ class InventoryItemRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('color', 'description')
|
||||
|
||||
|
||||
class VirtualDeviceContextBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VirtualDeviceContextBulkEditForm(PrimaryModelBulkEditForm):
|
||||
device = DynamicModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1856,6 +1732,7 @@ class VirtualDeviceContextBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
model = VirtualDeviceContext
|
||||
fieldsets = (
|
||||
FieldSet('device', 'status', 'tenant'),
|
||||
@@ -1867,14 +1744,7 @@ class VirtualDeviceContextBulkEditForm(NetBoxModelBulkEditForm):
|
||||
# Addressing
|
||||
#
|
||||
|
||||
class MACAddressBulkEditForm(NetBoxModelBulkEditForm):
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
class MACAddressBulkEditForm(PrimaryModelBulkEditForm):
|
||||
model = MACAddress
|
||||
fieldsets = (
|
||||
FieldSet('description'),
|
||||
|
||||
@@ -11,7 +11,10 @@ from dcim.models import *
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.models import VRF, IPAddress
|
||||
from netbox.choices import *
|
||||
from netbox.forms import NetBoxModelImportForm
|
||||
from netbox.forms import (
|
||||
NestedGroupModelImportForm, NetBoxModelImportForm, OrganizationalModelImportForm, OwnerCSVMixin,
|
||||
PrimaryModelImportForm,
|
||||
)
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms.fields import (
|
||||
CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVModelMultipleChoiceField, CSVTypedChoiceField,
|
||||
@@ -58,7 +61,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class RegionImportForm(NetBoxModelImportForm):
|
||||
class RegionImportForm(NestedGroupModelImportForm):
|
||||
parent = CSVModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=Region.objects.all(),
|
||||
@@ -69,10 +72,10 @@ class RegionImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = Region
|
||||
fields = ('name', 'slug', 'parent', 'description', 'tags', 'comments')
|
||||
fields = ('name', 'slug', 'parent', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class SiteGroupImportForm(NetBoxModelImportForm):
|
||||
class SiteGroupImportForm(NestedGroupModelImportForm):
|
||||
parent = CSVModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=SiteGroup.objects.all(),
|
||||
@@ -83,10 +86,10 @@ class SiteGroupImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = SiteGroup
|
||||
fields = ('name', 'slug', 'parent', 'description', 'comments', 'tags')
|
||||
fields = ('name', 'slug', 'parent', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class SiteImportForm(NetBoxModelImportForm):
|
||||
class SiteImportForm(PrimaryModelImportForm):
|
||||
status = CSVChoiceField(
|
||||
label=_('Status'),
|
||||
choices=SiteStatusChoices,
|
||||
@@ -118,7 +121,7 @@ class SiteImportForm(NetBoxModelImportForm):
|
||||
model = Site
|
||||
fields = (
|
||||
'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'time_zone', 'description',
|
||||
'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments', 'tags'
|
||||
'physical_address', 'shipping_address', 'latitude', 'longitude', 'owner', 'comments', 'tags'
|
||||
)
|
||||
help_texts = {
|
||||
'time_zone': mark_safe(
|
||||
@@ -129,7 +132,7 @@ class SiteImportForm(NetBoxModelImportForm):
|
||||
}
|
||||
|
||||
|
||||
class LocationImportForm(NetBoxModelImportForm):
|
||||
class LocationImportForm(NestedGroupModelImportForm):
|
||||
site = CSVModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -162,8 +165,8 @@ class LocationImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = Location
|
||||
fields = (
|
||||
'site', 'parent', 'name', 'slug', 'status', 'tenant', 'facility', 'description',
|
||||
'tags', 'comments',
|
||||
'site', 'parent', 'name', 'slug', 'status', 'tenant', 'facility', 'description', 'owner', 'comments',
|
||||
'tags',
|
||||
)
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -175,15 +178,14 @@ class LocationImportForm(NetBoxModelImportForm):
|
||||
self.fields['parent'].queryset = self.fields['parent'].queryset.filter(**params)
|
||||
|
||||
|
||||
class RackRoleImportForm(NetBoxModelImportForm):
|
||||
slug = SlugField()
|
||||
class RackRoleImportForm(OrganizationalModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = RackRole
|
||||
fields = ('name', 'slug', 'color', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'color', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class RackTypeImportForm(NetBoxModelImportForm):
|
||||
class RackTypeImportForm(PrimaryModelImportForm):
|
||||
manufacturer = forms.ModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all(),
|
||||
@@ -224,14 +226,14 @@ class RackTypeImportForm(NetBoxModelImportForm):
|
||||
fields = (
|
||||
'manufacturer', 'model', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units',
|
||||
'outer_width', 'outer_height', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight',
|
||||
'weight_unit', 'description', 'comments', 'tags',
|
||||
'weight_unit', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
super().__init__(data, *args, **kwargs)
|
||||
|
||||
|
||||
class RackImportForm(NetBoxModelImportForm):
|
||||
class RackImportForm(PrimaryModelImportForm):
|
||||
site = CSVModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -309,7 +311,8 @@ class RackImportForm(NetBoxModelImportForm):
|
||||
fields = (
|
||||
'site', 'location', 'name', 'facility_id', 'tenant', 'status', 'role', 'rack_type', 'form_factor', 'serial',
|
||||
'asset_tag', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_height', 'outer_depth', 'outer_unit',
|
||||
'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', 'description', 'comments', 'tags',
|
||||
'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', 'description', 'owner', 'comments',
|
||||
'tags',
|
||||
)
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -332,7 +335,7 @@ class RackImportForm(NetBoxModelImportForm):
|
||||
raise forms.ValidationError(_("U height must be set if not specifying a rack type."))
|
||||
|
||||
|
||||
class RackReservationImportForm(NetBoxModelImportForm):
|
||||
class RackReservationImportForm(PrimaryModelImportForm):
|
||||
site = CSVModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -373,7 +376,7 @@ class RackReservationImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = RackReservation
|
||||
fields = ('site', 'location', 'rack', 'units', 'status', 'tenant', 'description', 'comments', 'tags')
|
||||
fields = ('site', 'location', 'rack', 'units', 'status', 'tenant', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
super().__init__(data, *args, **kwargs)
|
||||
@@ -392,14 +395,14 @@ class RackReservationImportForm(NetBoxModelImportForm):
|
||||
self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params)
|
||||
|
||||
|
||||
class ManufacturerImportForm(NetBoxModelImportForm):
|
||||
class ManufacturerImportForm(OrganizationalModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = Manufacturer
|
||||
fields = ('name', 'slug', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class DeviceTypeImportForm(NetBoxModelImportForm):
|
||||
class DeviceTypeImportForm(PrimaryModelImportForm):
|
||||
manufacturer = CSVModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all(),
|
||||
@@ -429,20 +432,21 @@ class DeviceTypeImportForm(NetBoxModelImportForm):
|
||||
model = DeviceType
|
||||
fields = [
|
||||
'manufacturer', 'default_platform', 'model', 'slug', 'part_number', 'u_height', 'exclude_from_utilization',
|
||||
'is_full_depth', 'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'comments', 'tags',
|
||||
'is_full_depth', 'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'owner', 'comments',
|
||||
'tags',
|
||||
]
|
||||
|
||||
|
||||
class ModuleTypeProfileImportForm(NetBoxModelImportForm):
|
||||
class ModuleTypeProfileImportForm(PrimaryModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ModuleTypeProfile
|
||||
fields = [
|
||||
'name', 'description', 'schema', 'comments', 'tags',
|
||||
'name', 'description', 'schema', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class ModuleTypeImportForm(NetBoxModelImportForm):
|
||||
class ModuleTypeImportForm(PrimaryModelImportForm):
|
||||
profile = forms.ModelChoiceField(
|
||||
label=_('Profile'),
|
||||
queryset=ModuleTypeProfile.objects.all(),
|
||||
@@ -476,11 +480,11 @@ class ModuleTypeImportForm(NetBoxModelImportForm):
|
||||
model = ModuleType
|
||||
fields = [
|
||||
'manufacturer', 'model', 'part_number', 'description', 'airflow', 'weight', 'weight_unit', 'profile',
|
||||
'comments', 'tags'
|
||||
'owner', 'comments', 'tags'
|
||||
]
|
||||
|
||||
|
||||
class DeviceRoleImportForm(NetBoxModelImportForm):
|
||||
class DeviceRoleImportForm(NestedGroupModelImportForm):
|
||||
parent = CSVModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=DeviceRole.objects.all(),
|
||||
@@ -498,17 +502,15 @@ class DeviceRoleImportForm(NetBoxModelImportForm):
|
||||
required=False,
|
||||
help_text=_('Config template')
|
||||
)
|
||||
slug = SlugField()
|
||||
|
||||
class Meta:
|
||||
model = DeviceRole
|
||||
fields = (
|
||||
'name', 'slug', 'parent', 'color', 'vm_role', 'config_template', 'description', 'comments', 'tags'
|
||||
'name', 'slug', 'parent', 'color', 'vm_role', 'config_template', 'description', 'owner', 'comments', 'tags'
|
||||
)
|
||||
|
||||
|
||||
class PlatformImportForm(NetBoxModelImportForm):
|
||||
slug = SlugField()
|
||||
class PlatformImportForm(NestedGroupModelImportForm):
|
||||
parent = CSVModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=Platform.objects.all(),
|
||||
@@ -537,11 +539,11 @@ class PlatformImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = Platform
|
||||
fields = (
|
||||
'name', 'slug', 'parent', 'manufacturer', 'config_template', 'description', 'tags',
|
||||
'name', 'slug', 'parent', 'manufacturer', 'config_template', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class BaseDeviceImportForm(NetBoxModelImportForm):
|
||||
class BaseDeviceImportForm(PrimaryModelImportForm):
|
||||
role = CSVModelChoiceField(
|
||||
label=_('Device role'),
|
||||
queryset=DeviceRole.objects.all(),
|
||||
@@ -667,8 +669,8 @@ class DeviceImportForm(BaseDeviceImportForm):
|
||||
fields = [
|
||||
'name', 'role', 'tenant', 'manufacturer', 'device_type', 'platform', 'serial', 'asset_tag', 'status',
|
||||
'site', 'location', 'rack', 'position', 'face', 'latitude', 'longitude', 'parent', 'device_bay', 'airflow',
|
||||
'virtual_chassis', 'vc_position', 'vc_priority', 'cluster', 'description', 'config_template', 'comments',
|
||||
'tags',
|
||||
'virtual_chassis', 'vc_position', 'vc_priority', 'cluster', 'description', 'config_template', 'owner',
|
||||
'comments', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -715,7 +717,7 @@ class DeviceImportForm(BaseDeviceImportForm):
|
||||
self.instance.parent_bay = device_bay
|
||||
|
||||
|
||||
class ModuleImportForm(ModuleCommonForm, NetBoxModelImportForm):
|
||||
class ModuleImportForm(ModuleCommonForm, PrimaryModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -753,7 +755,7 @@ class ModuleImportForm(ModuleCommonForm, NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = Module
|
||||
fields = (
|
||||
'device', 'module_bay', 'module_type', 'serial', 'asset_tag', 'status', 'description', 'comments',
|
||||
'device', 'module_bay', 'module_type', 'serial', 'asset_tag', 'status', 'description', 'owner', 'comments',
|
||||
'replicate_components', 'adopt_components', 'tags',
|
||||
)
|
||||
|
||||
@@ -777,7 +779,7 @@ class ModuleImportForm(ModuleCommonForm, NetBoxModelImportForm):
|
||||
# Device components
|
||||
#
|
||||
|
||||
class ConsolePortImportForm(NetBoxModelImportForm):
|
||||
class ConsolePortImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -800,10 +802,10 @@ class ConsolePortImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ConsolePort
|
||||
fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags')
|
||||
fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class ConsoleServerPortImportForm(NetBoxModelImportForm):
|
||||
class ConsoleServerPortImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -826,10 +828,10 @@ class ConsoleServerPortImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ConsoleServerPort
|
||||
fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags')
|
||||
fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class PowerPortImportForm(NetBoxModelImportForm):
|
||||
class PowerPortImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -845,11 +847,12 @@ class PowerPortImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = PowerPort
|
||||
fields = (
|
||||
'device', 'name', 'label', 'type', 'mark_connected', 'maximum_draw', 'allocated_draw', 'description', 'tags'
|
||||
'device', 'name', 'label', 'type', 'mark_connected', 'maximum_draw', 'allocated_draw', 'description',
|
||||
'owner', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class PowerOutletImportForm(NetBoxModelImportForm):
|
||||
class PowerOutletImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -879,7 +882,7 @@ class PowerOutletImportForm(NetBoxModelImportForm):
|
||||
model = PowerOutlet
|
||||
fields = (
|
||||
'device', 'name', 'label', 'type', 'color', 'mark_connected', 'power_port', 'feed_leg', 'description',
|
||||
'tags',
|
||||
'owner', 'tags',
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -905,7 +908,7 @@ class PowerOutletImportForm(NetBoxModelImportForm):
|
||||
self.fields['power_port'].queryset = PowerPort.objects.none()
|
||||
|
||||
|
||||
class InterfaceImportForm(NetBoxModelImportForm):
|
||||
class InterfaceImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -988,7 +991,7 @@ class InterfaceImportForm(NetBoxModelImportForm):
|
||||
fields = (
|
||||
'device', 'name', 'label', 'parent', 'bridge', 'lag', 'type', 'speed', 'duplex', 'enabled',
|
||||
'mark_connected', 'wwn', 'vdcs', 'mtu', 'mgmt_only', 'description', 'poe_mode', 'poe_type', 'mode',
|
||||
'vrf', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'tags'
|
||||
'vrf', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'owner', 'tags'
|
||||
)
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -1023,7 +1026,7 @@ class InterfaceImportForm(NetBoxModelImportForm):
|
||||
return self.cleaned_data['vdcs']
|
||||
|
||||
|
||||
class FrontPortImportForm(NetBoxModelImportForm):
|
||||
class FrontPortImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1045,7 +1048,7 @@ class FrontPortImportForm(NetBoxModelImportForm):
|
||||
model = FrontPort
|
||||
fields = (
|
||||
'device', 'name', 'label', 'type', 'color', 'mark_connected', 'rear_port', 'rear_port_position',
|
||||
'description', 'tags'
|
||||
'description', 'owner', 'tags'
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -1071,7 +1074,7 @@ class FrontPortImportForm(NetBoxModelImportForm):
|
||||
self.fields['rear_port'].queryset = RearPort.objects.none()
|
||||
|
||||
|
||||
class RearPortImportForm(NetBoxModelImportForm):
|
||||
class RearPortImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1085,10 +1088,12 @@ class RearPortImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = RearPort
|
||||
fields = ('device', 'name', 'label', 'type', 'color', 'mark_connected', 'positions', 'description', 'tags')
|
||||
fields = (
|
||||
'device', 'name', 'label', 'type', 'color', 'mark_connected', 'positions', 'description', 'owner', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class ModuleBayImportForm(NetBoxModelImportForm):
|
||||
class ModuleBayImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1097,10 +1102,10 @@ class ModuleBayImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ModuleBay
|
||||
fields = ('device', 'name', 'label', 'position', 'description', 'tags')
|
||||
fields = ('device', 'name', 'label', 'position', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class DeviceBayImportForm(NetBoxModelImportForm):
|
||||
class DeviceBayImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1119,7 +1124,7 @@ class DeviceBayImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = DeviceBay
|
||||
fields = ('device', 'name', 'label', 'installed_device', 'description', 'tags')
|
||||
fields = ('device', 'name', 'label', 'installed_device', 'description', 'owner', 'tags')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -1148,7 +1153,7 @@ class DeviceBayImportForm(NetBoxModelImportForm):
|
||||
self.fields['installed_device'].queryset = Device.objects.none()
|
||||
|
||||
|
||||
class InventoryItemImportForm(NetBoxModelImportForm):
|
||||
class InventoryItemImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1195,7 +1200,7 @@ class InventoryItemImportForm(NetBoxModelImportForm):
|
||||
model = InventoryItem
|
||||
fields = (
|
||||
'device', 'name', 'label', 'status', 'role', 'manufacturer', 'parent', 'part_id', 'serial', 'asset_tag',
|
||||
'discovered', 'description', 'tags', 'component_type', 'component_name',
|
||||
'discovered', 'description', 'owner', 'tags', 'component_type', 'component_name',
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -1258,7 +1263,7 @@ class InventoryItemImportForm(NetBoxModelImportForm):
|
||||
# Device component roles
|
||||
#
|
||||
|
||||
class InventoryItemRoleImportForm(NetBoxModelImportForm):
|
||||
class InventoryItemRoleImportForm(OrganizationalModelImportForm):
|
||||
slug = SlugField()
|
||||
|
||||
class Meta:
|
||||
@@ -1270,7 +1275,7 @@ class InventoryItemRoleImportForm(NetBoxModelImportForm):
|
||||
# Addressing
|
||||
#
|
||||
|
||||
class MACAddressImportForm(NetBoxModelImportForm):
|
||||
class MACAddressImportForm(PrimaryModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1301,7 +1306,8 @@ class MACAddressImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = MACAddress
|
||||
fields = [
|
||||
'mac_address', 'device', 'virtual_machine', 'interface', 'is_primary', 'description', 'comments', 'tags',
|
||||
'mac_address', 'device', 'virtual_machine', 'interface', 'is_primary', 'description', 'owner', 'comments',
|
||||
'tags',
|
||||
]
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -1354,7 +1360,7 @@ class MACAddressImportForm(NetBoxModelImportForm):
|
||||
# Cables
|
||||
#
|
||||
|
||||
class CableImportForm(NetBoxModelImportForm):
|
||||
class CableImportForm(PrimaryModelImportForm):
|
||||
# Termination A
|
||||
side_a_site = CSVModelChoiceField(
|
||||
label=_('Side A site'),
|
||||
@@ -1443,7 +1449,7 @@ class CableImportForm(NetBoxModelImportForm):
|
||||
fields = [
|
||||
'side_a_site', 'side_a_device', 'side_a_type', 'side_a_name', 'side_b_site', 'side_b_device', 'side_b_type',
|
||||
'side_b_name', 'type', 'status', 'tenant', 'label', 'color', 'length', 'length_unit', 'description',
|
||||
'comments', 'tags',
|
||||
'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -1537,7 +1543,7 @@ class CableImportForm(NetBoxModelImportForm):
|
||||
#
|
||||
|
||||
|
||||
class VirtualChassisImportForm(NetBoxModelImportForm):
|
||||
class VirtualChassisImportForm(PrimaryModelImportForm):
|
||||
master = CSVModelChoiceField(
|
||||
label=_('Master'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1548,14 +1554,14 @@ class VirtualChassisImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = VirtualChassis
|
||||
fields = ('name', 'domain', 'master', 'description', 'comments', 'tags')
|
||||
fields = ('name', 'domain', 'master', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
#
|
||||
# Power
|
||||
#
|
||||
|
||||
class PowerPanelImportForm(NetBoxModelImportForm):
|
||||
class PowerPanelImportForm(PrimaryModelImportForm):
|
||||
site = CSVModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -1571,7 +1577,7 @@ class PowerPanelImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = PowerPanel
|
||||
fields = ('site', 'location', 'name', 'description', 'comments', 'tags')
|
||||
fields = ('site', 'location', 'name', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
super().__init__(data, *args, **kwargs)
|
||||
@@ -1583,7 +1589,7 @@ class PowerPanelImportForm(NetBoxModelImportForm):
|
||||
self.fields['location'].queryset = self.fields['location'].queryset.filter(**params)
|
||||
|
||||
|
||||
class PowerFeedImportForm(NetBoxModelImportForm):
|
||||
class PowerFeedImportForm(PrimaryModelImportForm):
|
||||
site = CSVModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -1641,7 +1647,7 @@ class PowerFeedImportForm(NetBoxModelImportForm):
|
||||
model = PowerFeed
|
||||
fields = (
|
||||
'site', 'power_panel', 'location', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', 'phase',
|
||||
'voltage', 'amperage', 'max_utilization', 'tenant', 'description', 'comments', 'tags',
|
||||
'voltage', 'amperage', 'max_utilization', 'tenant', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -1665,8 +1671,7 @@ class PowerFeedImportForm(NetBoxModelImportForm):
|
||||
self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params)
|
||||
|
||||
|
||||
class VirtualDeviceContextImportForm(NetBoxModelImportForm):
|
||||
|
||||
class VirtualDeviceContextImportForm(PrimaryModelImportForm):
|
||||
device = CSVModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1701,7 +1706,7 @@ class VirtualDeviceContextImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
fields = [
|
||||
'name', 'device', 'status', 'tenant', 'identifier', 'comments', 'primary_ip4', 'primary_ip6',
|
||||
'name', 'device', 'status', 'tenant', 'identifier', 'owner', 'comments', 'primary_ip4', 'primary_ip6',
|
||||
]
|
||||
model = VirtualDeviceContext
|
||||
|
||||
|
||||
@@ -8,11 +8,14 @@ from extras.forms import LocalConfigContextFilterForm
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.models import ASN, VRF, VLANTranslationPolicy
|
||||
from netbox.choices import *
|
||||
from netbox.forms import NetBoxModelFilterSetForm
|
||||
from netbox.forms import (
|
||||
NestedGroupModelFilterSetForm, NetBoxModelFilterSetForm, OrganizationalModelFilterSetForm,
|
||||
PrimaryModelFilterSetForm,
|
||||
)
|
||||
from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
|
||||
from users.models import User
|
||||
from users.models import Owner, User
|
||||
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
|
||||
from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField
|
||||
from utilities.forms.fields import ColorField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, TagFilterField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import NumberWithOptions
|
||||
from virtualization.models import Cluster, ClusterGroup, VirtualMachine
|
||||
@@ -137,12 +140,18 @@ class DeviceComponentFilterForm(NetBoxModelFilterSetForm):
|
||||
required=False,
|
||||
label=_('Device Status'),
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class RegionFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class RegionFilterForm(ContactModelFilterForm, NestedGroupModelFilterSetForm):
|
||||
model = Region
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'parent_id'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('parent_id', name=_('Region')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts'))
|
||||
)
|
||||
parent_id = DynamicModelMultipleChoiceField(
|
||||
@@ -153,10 +162,11 @@ class RegionFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class SiteGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class SiteGroupFilterForm(ContactModelFilterForm, NestedGroupModelFilterSetForm):
|
||||
model = SiteGroup
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'parent_id'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('parent_id', name=_('Site Group')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts'))
|
||||
)
|
||||
parent_id = DynamicModelMultipleChoiceField(
|
||||
@@ -167,10 +177,10 @@ class SiteGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, PrimaryModelFilterSetForm):
|
||||
model = Site
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('status', 'region_id', 'group_id', 'asn_id', name=_('Attributes')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
@@ -199,10 +209,10 @@ class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class LocationFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class LocationFilterForm(TenancyFilterForm, ContactModelFilterForm, NestedGroupModelFilterSetForm):
|
||||
model = Location
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'parent_id', 'status', 'facility', name=_('Attributes')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
@@ -247,12 +257,15 @@ class LocationFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelF
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class RackRoleFilterForm(NetBoxModelFilterSetForm):
|
||||
class RackRoleFilterForm(OrganizationalModelFilterSetForm):
|
||||
model = RackRole
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class RackBaseFilterForm(NetBoxModelFilterSetForm):
|
||||
class RackBaseFilterForm(PrimaryModelFilterSetForm):
|
||||
form_factor = forms.MultipleChoiceField(
|
||||
label=_('Form factor'),
|
||||
choices=RackFormFactorChoices,
|
||||
@@ -303,7 +316,7 @@ class RackBaseFilterForm(NetBoxModelFilterSetForm):
|
||||
class RackTypeFilterForm(RackBaseFilterForm):
|
||||
model = RackType
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('manufacturer_id', 'form_factor', 'width', 'u_height', name=_('Rack Type')),
|
||||
FieldSet('starting_unit', 'desc_units', name=_('Numbering')),
|
||||
FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')),
|
||||
@@ -320,7 +333,7 @@ class RackTypeFilterForm(RackBaseFilterForm):
|
||||
class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, RackBaseFilterForm):
|
||||
model = Rack
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Location')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
FieldSet('status', 'role_id', 'manufacturer_id', 'rack_type_id', 'serial', 'asset_tag', name=_('Rack')),
|
||||
@@ -413,10 +426,10 @@ class RackElevationFilterForm(RackFilterForm):
|
||||
)
|
||||
|
||||
|
||||
class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class RackReservationFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = RackReservation
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('status', 'user_id', name=_('Reservation')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Rack')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
@@ -471,19 +484,19 @@ class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class ManufacturerFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class ManufacturerFilterForm(ContactModelFilterForm, OrganizationalModelFilterSetForm):
|
||||
model = Manufacturer
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts'))
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class DeviceTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
class DeviceTypeFilterForm(PrimaryModelFilterSetForm):
|
||||
model = DeviceType
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet(
|
||||
'manufacturer_id', 'default_platform_id', 'part_number', 'subdevice_role', 'airflow', name=_('Hardware')
|
||||
),
|
||||
@@ -608,18 +621,18 @@ class DeviceTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
)
|
||||
|
||||
|
||||
class ModuleTypeProfileFilterForm(NetBoxModelFilterSetForm):
|
||||
class ModuleTypeProfileFilterForm(PrimaryModelFilterSetForm):
|
||||
model = ModuleTypeProfile
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
)
|
||||
selector_fields = ('filter_id', 'q')
|
||||
|
||||
|
||||
class ModuleTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
class ModuleTypeFilterForm(PrimaryModelFilterSetForm):
|
||||
model = ModuleType
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('profile_id', 'manufacturer_id', 'part_number', 'airflow', name=_('Hardware')),
|
||||
FieldSet(
|
||||
'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces',
|
||||
@@ -701,8 +714,12 @@ class ModuleTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
)
|
||||
|
||||
|
||||
class DeviceRoleFilterForm(NetBoxModelFilterSetForm):
|
||||
class DeviceRoleFilterForm(NestedGroupModelFilterSetForm):
|
||||
model = DeviceRole
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('parent_id', 'config_template_id', name=_('Device Role'))
|
||||
)
|
||||
config_template_id = DynamicModelMultipleChoiceField(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
required=False,
|
||||
@@ -716,8 +733,12 @@ class DeviceRoleFilterForm(NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class PlatformFilterForm(NetBoxModelFilterSetForm):
|
||||
class PlatformFilterForm(NestedGroupModelFilterSetForm):
|
||||
model = Platform
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('manufacturer_id', 'parent_id', 'config_template_id', name=_('Platform'))
|
||||
)
|
||||
selector_fields = ('filter_id', 'q', 'manufacturer_id')
|
||||
parent_id = DynamicModelMultipleChoiceField(
|
||||
queryset=Platform.objects.all(),
|
||||
@@ -741,11 +762,11 @@ class DeviceFilterForm(
|
||||
LocalConfigContextFilterForm,
|
||||
TenancyFilterForm,
|
||||
ContactModelFilterForm,
|
||||
NetBoxModelFilterSetForm
|
||||
PrimaryModelFilterSetForm
|
||||
):
|
||||
model = Device
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet('status', 'role_id', 'airflow', 'serial', 'asset_tag', 'mac_address', name=_('Operation')),
|
||||
FieldSet('manufacturer_id', 'device_type_id', 'platform_id', name=_('Hardware')),
|
||||
@@ -935,13 +956,10 @@ class DeviceFilterForm(
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class VirtualDeviceContextFilterForm(
|
||||
TenancyFilterForm,
|
||||
NetBoxModelFilterSetForm
|
||||
):
|
||||
class VirtualDeviceContextFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = VirtualDeviceContext
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('device', 'status', 'has_primary_ip', name=_('Attributes')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
@@ -965,10 +983,10 @@ class VirtualDeviceContextFilterForm(
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = Module
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'device_id', name=_('Location')),
|
||||
FieldSet('manufacturer_id', 'module_type_id', 'status', 'serial', 'asset_tag', name=_('Hardware')),
|
||||
)
|
||||
@@ -1048,10 +1066,10 @@ class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxMo
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class VirtualChassisFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class VirtualChassisFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = VirtualChassis
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
@@ -1077,10 +1095,10 @@ class VirtualChassisFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class CableFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class CableFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = Cable
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('site_id', 'location_id', 'rack_id', 'device_id', name=_('Location')),
|
||||
FieldSet('type', 'status', 'color', 'length', 'length_unit', 'unterminated', name=_('Attributes')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
@@ -1161,10 +1179,10 @@ class CableFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class PowerPanelFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
class PowerPanelFilterForm(ContactModelFilterForm, PrimaryModelFilterSetForm):
|
||||
model = PowerPanel
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Location')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
)
|
||||
@@ -1200,10 +1218,10 @@ class PowerPanelFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class PowerFeedFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class PowerFeedFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = PowerFeed
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'power_panel_id', 'rack_id', name=_('Location')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
FieldSet('status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization', name=_('Attributes')),
|
||||
@@ -1313,7 +1331,7 @@ class PathEndpointFilterForm(CabledFilterForm):
|
||||
class ConsolePortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
model = ConsolePort
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', 'type', 'speed', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -1337,7 +1355,7 @@ class ConsolePortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
class ConsoleServerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
model = ConsoleServerPort
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', 'type', 'speed', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -1362,7 +1380,7 @@ class ConsoleServerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterF
|
||||
class PowerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
model = PowerPort
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', 'type', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -1381,7 +1399,7 @@ class PowerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
model = PowerOutlet
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', 'type', 'color', 'status', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -1410,7 +1428,7 @@ class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
model = Interface
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', 'kind', 'type', 'speed', 'duplex', 'enabled', 'mgmt_only', name=_('Attributes')),
|
||||
FieldSet('vrf_id', 'l2vpn_id', 'mac_address', 'wwn', name=_('Addressing')),
|
||||
FieldSet('poe_mode', 'poe_type', name=_('PoE')),
|
||||
@@ -1535,7 +1553,7 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
|
||||
class FrontPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', 'type', 'color', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -1559,7 +1577,7 @@ class FrontPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
|
||||
class RearPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
|
||||
model = RearPort
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', 'type', 'color', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -1583,7 +1601,7 @@ class RearPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
|
||||
class ModuleBayFilterForm(DeviceComponentFilterForm):
|
||||
model = ModuleBay
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', 'position', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -1601,7 +1619,7 @@ class ModuleBayFilterForm(DeviceComponentFilterForm):
|
||||
class DeviceBayFilterForm(DeviceComponentFilterForm):
|
||||
model = DeviceBay
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'label', name=_('Attributes')),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
@@ -1615,7 +1633,7 @@ class DeviceBayFilterForm(DeviceComponentFilterForm):
|
||||
class InventoryItemFilterForm(DeviceComponentFilterForm):
|
||||
model = InventoryItem
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet(
|
||||
'name', 'label', 'status', 'role_id', 'manufacturer_id', 'serial', 'asset_tag', 'discovered',
|
||||
name=_('Attributes')
|
||||
@@ -1663,8 +1681,11 @@ class InventoryItemFilterForm(DeviceComponentFilterForm):
|
||||
# Device component roles
|
||||
#
|
||||
|
||||
class InventoryItemRoleFilterForm(NetBoxModelFilterSetForm):
|
||||
class InventoryItemRoleFilterForm(OrganizationalModelFilterSetForm):
|
||||
model = InventoryItemRole
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
@@ -1672,10 +1693,10 @@ class InventoryItemRoleFilterForm(NetBoxModelFilterSetForm):
|
||||
# Addressing
|
||||
#
|
||||
|
||||
class MACAddressFilterForm(NetBoxModelFilterSetForm):
|
||||
class MACAddressFilterForm(PrimaryModelFilterSetForm):
|
||||
model = MACAddress
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('mac_address', 'device_id', 'virtual_machine_id', name=_('MAC address')),
|
||||
)
|
||||
selector_fields = ('filter_id', 'q', 'device_id', 'virtual_machine_id')
|
||||
|
||||
@@ -10,13 +10,13 @@ from dcim.models import *
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.choices import VLANQinQRoleChoices
|
||||
from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF
|
||||
from netbox.forms import NetBoxModelForm
|
||||
from netbox.forms.mixins import ChangelogMessageMixin
|
||||
from netbox.forms import NestedGroupModelForm, NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
|
||||
from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin
|
||||
from tenancy.forms import TenancyForm
|
||||
from users.models import User
|
||||
from utilities.forms import add_blank_choice, get_field_value
|
||||
from utilities.forms.fields import (
|
||||
CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField,
|
||||
DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField,
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups
|
||||
from utilities.forms.widgets import APISelect, ClearableFileInput, HTMXSelect, NumberWithOptions, SelectWithPK
|
||||
@@ -75,14 +75,12 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class RegionForm(NetBoxModelForm):
|
||||
class RegionForm(NestedGroupModelForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=Region.objects.all(),
|
||||
required=False
|
||||
)
|
||||
slug = SlugField()
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('parent', 'name', 'slug', 'description', 'tags'),
|
||||
@@ -91,18 +89,16 @@ class RegionForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Region
|
||||
fields = (
|
||||
'parent', 'name', 'slug', 'description', 'tags', 'comments',
|
||||
'parent', 'name', 'slug', 'description', 'owner', 'tags', 'comments',
|
||||
)
|
||||
|
||||
|
||||
class SiteGroupForm(NetBoxModelForm):
|
||||
class SiteGroupForm(NestedGroupModelForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=SiteGroup.objects.all(),
|
||||
required=False
|
||||
)
|
||||
slug = SlugField()
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('parent', 'name', 'slug', 'description', 'tags'),
|
||||
@@ -111,11 +107,11 @@ class SiteGroupForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = SiteGroup
|
||||
fields = (
|
||||
'parent', 'name', 'slug', 'description', 'comments', 'tags',
|
||||
'parent', 'name', 'slug', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class SiteForm(TenancyForm, NetBoxModelForm):
|
||||
class SiteForm(TenancyForm, PrimaryModelForm):
|
||||
region = DynamicModelChoiceField(
|
||||
label=_('Region'),
|
||||
queryset=Region.objects.all(),
|
||||
@@ -139,7 +135,6 @@ class SiteForm(TenancyForm, NetBoxModelForm):
|
||||
choices=add_blank_choice(TimeZoneFormField().choices),
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -154,7 +149,7 @@ class SiteForm(TenancyForm, NetBoxModelForm):
|
||||
model = Site
|
||||
fields = (
|
||||
'name', 'slug', 'status', 'region', 'group', 'tenant_group', 'tenant', 'facility', 'asns', 'time_zone',
|
||||
'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments', 'tags',
|
||||
'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'owner', 'comments', 'tags',
|
||||
)
|
||||
widgets = {
|
||||
'physical_address': forms.Textarea(
|
||||
@@ -170,7 +165,7 @@ class SiteForm(TenancyForm, NetBoxModelForm):
|
||||
}
|
||||
|
||||
|
||||
class LocationForm(TenancyForm, NetBoxModelForm):
|
||||
class LocationForm(TenancyForm, NestedGroupModelForm):
|
||||
site = DynamicModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -184,8 +179,6 @@ class LocationForm(TenancyForm, NetBoxModelForm):
|
||||
'site_id': '$site'
|
||||
}
|
||||
)
|
||||
slug = SlugField()
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('site', 'parent', 'name', 'slug', 'status', 'facility', 'description', 'tags', name=_('Location')),
|
||||
@@ -195,14 +188,12 @@ class LocationForm(TenancyForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Location
|
||||
fields = (
|
||||
'site', 'parent', 'name', 'slug', 'status', 'description', 'tenant_group', 'tenant',
|
||||
'facility', 'tags', 'comments',
|
||||
'site', 'parent', 'name', 'slug', 'status', 'description', 'tenant_group', 'tenant', 'facility', 'owner',
|
||||
'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class RackRoleForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class RackRoleForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Rack Role')),
|
||||
)
|
||||
@@ -210,17 +201,16 @@ class RackRoleForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = RackRole
|
||||
fields = [
|
||||
'name', 'slug', 'color', 'description', 'tags',
|
||||
'name', 'slug', 'color', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class RackTypeForm(NetBoxModelForm):
|
||||
class RackTypeForm(PrimaryModelForm):
|
||||
manufacturer = DynamicModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all(),
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
slug = SlugField(
|
||||
label=_('Slug'),
|
||||
slug_source='model'
|
||||
@@ -242,11 +232,11 @@ class RackTypeForm(NetBoxModelForm):
|
||||
fields = [
|
||||
'manufacturer', 'model', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units',
|
||||
'outer_width', 'outer_height', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight',
|
||||
'weight_unit', 'description', 'comments', 'tags',
|
||||
'weight_unit', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class RackForm(TenancyForm, NetBoxModelForm):
|
||||
class RackForm(TenancyForm, PrimaryModelForm):
|
||||
site = DynamicModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -271,7 +261,6 @@ class RackForm(TenancyForm, NetBoxModelForm):
|
||||
required=False,
|
||||
help_text=_("Select a pre-defined rack type, or set physical characteristics below.")
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -288,7 +277,7 @@ class RackForm(TenancyForm, NetBoxModelForm):
|
||||
'site', 'location', 'name', 'facility_id', 'tenant_group', 'tenant', 'status', 'role', 'serial',
|
||||
'asset_tag', 'rack_type', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width',
|
||||
'outer_height', 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', 'weight', 'max_weight',
|
||||
'weight_unit', 'description', 'comments', 'tags',
|
||||
'weight_unit', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -318,7 +307,7 @@ class RackForm(TenancyForm, NetBoxModelForm):
|
||||
)
|
||||
|
||||
|
||||
class RackReservationForm(TenancyForm, NetBoxModelForm):
|
||||
class RackReservationForm(TenancyForm, PrimaryModelForm):
|
||||
rack = DynamicModelChoiceField(
|
||||
label=_('Rack'),
|
||||
queryset=Rack.objects.all(),
|
||||
@@ -333,7 +322,6 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
|
||||
label=_('User'),
|
||||
queryset=User.objects.order_by('username')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('rack', 'units', 'status', 'user', 'description', 'tags', name=_('Reservation')),
|
||||
@@ -343,13 +331,11 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = RackReservation
|
||||
fields = [
|
||||
'rack', 'units', 'status', 'user', 'tenant_group', 'tenant', 'description', 'comments', 'tags',
|
||||
'rack', 'units', 'status', 'user', 'tenant_group', 'tenant', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class ManufacturerForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class ManufacturerForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'description', 'tags', name=_('Manufacturer')),
|
||||
)
|
||||
@@ -357,11 +343,11 @@ class ManufacturerForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Manufacturer
|
||||
fields = [
|
||||
'name', 'slug', 'description', 'tags',
|
||||
'name', 'slug', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class DeviceTypeForm(NetBoxModelForm):
|
||||
class DeviceTypeForm(PrimaryModelForm):
|
||||
manufacturer = DynamicModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all(),
|
||||
@@ -380,7 +366,6 @@ class DeviceTypeForm(NetBoxModelForm):
|
||||
label=_('Slug'),
|
||||
slug_source='model'
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('manufacturer', 'model', 'slug', 'default_platform', 'description', 'tags', name=_('Device Type')),
|
||||
@@ -396,7 +381,7 @@ class DeviceTypeForm(NetBoxModelForm):
|
||||
fields = [
|
||||
'manufacturer', 'model', 'slug', 'default_platform', 'part_number', 'u_height', 'exclude_from_utilization',
|
||||
'is_full_depth', 'subdevice_role', 'airflow', 'weight', 'weight_unit', 'front_image', 'rear_image',
|
||||
'description', 'comments', 'tags',
|
||||
'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'front_image': ClearableFileInput(attrs={
|
||||
@@ -408,13 +393,12 @@ class DeviceTypeForm(NetBoxModelForm):
|
||||
}
|
||||
|
||||
|
||||
class ModuleTypeProfileForm(NetBoxModelForm):
|
||||
class ModuleTypeProfileForm(PrimaryModelForm):
|
||||
schema = JSONField(
|
||||
label=_('Schema'),
|
||||
required=False,
|
||||
help_text=_("Enter a valid JSON schema to define supported attributes.")
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'description', 'schema', 'tags', name=_('Profile')),
|
||||
@@ -423,11 +407,11 @@ class ModuleTypeProfileForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = ModuleTypeProfile
|
||||
fields = [
|
||||
'name', 'description', 'schema', 'comments', 'tags',
|
||||
'name', 'description', 'schema', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class ModuleTypeForm(NetBoxModelForm):
|
||||
class ModuleTypeForm(PrimaryModelForm):
|
||||
profile = forms.ModelChoiceField(
|
||||
queryset=ModuleTypeProfile.objects.all(),
|
||||
label=_('Profile'),
|
||||
@@ -438,7 +422,6 @@ class ModuleTypeForm(NetBoxModelForm):
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all()
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
@property
|
||||
def fieldsets(self):
|
||||
@@ -452,7 +435,7 @@ class ModuleTypeForm(NetBoxModelForm):
|
||||
model = ModuleType
|
||||
fields = [
|
||||
'profile', 'manufacturer', 'model', 'part_number', 'description', 'airflow', 'weight', 'weight_unit',
|
||||
'comments', 'tags',
|
||||
'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -507,19 +490,17 @@ class ModuleTypeForm(NetBoxModelForm):
|
||||
return super()._post_clean()
|
||||
|
||||
|
||||
class DeviceRoleForm(NetBoxModelForm):
|
||||
class DeviceRoleForm(NestedGroupModelForm):
|
||||
config_template = DynamicModelChoiceField(
|
||||
label=_('Config template'),
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
required=False
|
||||
)
|
||||
slug = SlugField()
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=DeviceRole.objects.all(),
|
||||
required=False,
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -531,11 +512,11 @@ class DeviceRoleForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = DeviceRole
|
||||
fields = [
|
||||
'name', 'slug', 'parent', 'color', 'vm_role', 'config_template', 'description', 'comments', 'tags',
|
||||
'name', 'slug', 'parent', 'color', 'vm_role', 'config_template', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class PlatformForm(NetBoxModelForm):
|
||||
class PlatformForm(NestedGroupModelForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=Platform.objects.all(),
|
||||
@@ -556,7 +537,6 @@ class PlatformForm(NetBoxModelForm):
|
||||
label=_('Slug'),
|
||||
max_length=64
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -567,11 +547,11 @@ class PlatformForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Platform
|
||||
fields = [
|
||||
'name', 'slug', 'parent', 'manufacturer', 'config_template', 'description', 'comments', 'tags',
|
||||
'name', 'slug', 'parent', 'manufacturer', 'config_template', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class DeviceForm(TenancyForm, NetBoxModelForm):
|
||||
class DeviceForm(TenancyForm, PrimaryModelForm):
|
||||
site = DynamicModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -641,7 +621,6 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
|
||||
'site_id': ['$site', 'null']
|
||||
},
|
||||
)
|
||||
comments = CommentField()
|
||||
local_context_data = JSONField(
|
||||
required=False,
|
||||
label=''
|
||||
@@ -677,7 +656,7 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
|
||||
'name', 'role', 'device_type', 'serial', 'asset_tag', 'site', 'rack', 'location', 'position', 'face',
|
||||
'latitude', 'longitude', 'status', 'airflow', 'platform', 'primary_ip4', 'primary_ip6', 'oob_ip', 'cluster',
|
||||
'tenant_group', 'tenant', 'virtual_chassis', 'vc_position', 'vc_priority', 'description', 'config_template',
|
||||
'comments', 'tags', 'local_context_data',
|
||||
'owner', 'comments', 'tags', 'local_context_data',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -742,7 +721,7 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
|
||||
self.fields['position'].widget.choices = [(position, f'U{position}')]
|
||||
|
||||
|
||||
class ModuleForm(ModuleCommonForm, NetBoxModelForm):
|
||||
class ModuleForm(ModuleCommonForm, PrimaryModelForm):
|
||||
device = DynamicModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -765,7 +744,6 @@ class ModuleForm(ModuleCommonForm, NetBoxModelForm):
|
||||
},
|
||||
selector=True
|
||||
)
|
||||
comments = CommentField()
|
||||
replicate_components = forms.BooleanField(
|
||||
label=_('Replicate components'),
|
||||
required=False,
|
||||
@@ -788,7 +766,7 @@ class ModuleForm(ModuleCommonForm, NetBoxModelForm):
|
||||
model = Module
|
||||
fields = [
|
||||
'device', 'module_bay', 'module_type', 'status', 'serial', 'asset_tag', 'tags', 'replicate_components',
|
||||
'adopt_components', 'description', 'comments',
|
||||
'adopt_components', 'description', 'owner', 'comments',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -809,7 +787,7 @@ def get_termination_type_choices():
|
||||
])
|
||||
|
||||
|
||||
class CableForm(TenancyForm, NetBoxModelForm):
|
||||
class CableForm(TenancyForm, PrimaryModelForm):
|
||||
a_terminations_type = forms.ChoiceField(
|
||||
choices=get_termination_type_choices,
|
||||
required=False,
|
||||
@@ -822,17 +800,16 @@ class CableForm(TenancyForm, NetBoxModelForm):
|
||||
widget=HTMXSelect(),
|
||||
label=_('Type')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
class Meta:
|
||||
model = Cable
|
||||
fields = [
|
||||
'a_terminations_type', 'b_terminations_type', 'type', 'status', 'tenant_group', 'tenant', 'label', 'color',
|
||||
'length', 'length_unit', 'description', 'comments', 'tags',
|
||||
'length', 'length_unit', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class PowerPanelForm(NetBoxModelForm):
|
||||
class PowerPanelForm(PrimaryModelForm):
|
||||
site = DynamicModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -846,7 +823,6 @@ class PowerPanelForm(NetBoxModelForm):
|
||||
'site_id': '$site'
|
||||
}
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('site', 'location', 'name', 'description', 'tags', name=_('Power Panel')),
|
||||
@@ -855,11 +831,11 @@ class PowerPanelForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = PowerPanel
|
||||
fields = [
|
||||
'site', 'location', 'name', 'description', 'comments', 'tags',
|
||||
'site', 'location', 'name', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class PowerFeedForm(TenancyForm, NetBoxModelForm):
|
||||
class PowerFeedForm(TenancyForm, PrimaryModelForm):
|
||||
power_panel = DynamicModelChoiceField(
|
||||
label=_('Power panel'),
|
||||
queryset=PowerPanel.objects.all(),
|
||||
@@ -872,7 +848,6 @@ class PowerFeedForm(TenancyForm, NetBoxModelForm):
|
||||
required=False,
|
||||
selector=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -887,7 +862,7 @@ class PowerFeedForm(TenancyForm, NetBoxModelForm):
|
||||
model = PowerFeed
|
||||
fields = [
|
||||
'power_panel', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', 'phase', 'voltage', 'amperage',
|
||||
'max_utilization', 'tenant_group', 'tenant', 'description', 'comments', 'tags'
|
||||
'max_utilization', 'tenant_group', 'tenant', 'description', 'owner', 'comments', 'tags'
|
||||
]
|
||||
|
||||
|
||||
@@ -895,18 +870,17 @@ class PowerFeedForm(TenancyForm, NetBoxModelForm):
|
||||
# Virtual chassis
|
||||
#
|
||||
|
||||
class VirtualChassisForm(NetBoxModelForm):
|
||||
class VirtualChassisForm(PrimaryModelForm):
|
||||
master = forms.ModelChoiceField(
|
||||
label=_('Master'),
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
class Meta:
|
||||
model = VirtualChassis
|
||||
fields = [
|
||||
'name', 'domain', 'master', 'description', 'comments', 'tags',
|
||||
'name', 'domain', 'master', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'master': SelectWithPK(),
|
||||
@@ -1360,7 +1334,7 @@ class InventoryItemTemplateForm(ComponentTemplateForm):
|
||||
# Device components
|
||||
#
|
||||
|
||||
class DeviceComponentForm(NetBoxModelForm):
|
||||
class DeviceComponentForm(OwnerMixin, NetBoxModelForm):
|
||||
device = DynamicModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1396,7 +1370,7 @@ class ConsolePortForm(ModularDeviceComponentForm):
|
||||
class Meta:
|
||||
model = ConsolePort
|
||||
fields = [
|
||||
'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags',
|
||||
'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -1410,7 +1384,7 @@ class ConsoleServerPortForm(ModularDeviceComponentForm):
|
||||
class Meta:
|
||||
model = ConsoleServerPort
|
||||
fields = [
|
||||
'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags',
|
||||
'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -1426,7 +1400,7 @@ class PowerPortForm(ModularDeviceComponentForm):
|
||||
model = PowerPort
|
||||
fields = [
|
||||
'device', 'module', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'mark_connected',
|
||||
'description', 'tags',
|
||||
'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -1443,7 +1417,7 @@ class PowerOutletForm(ModularDeviceComponentForm):
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
'device', 'module', 'name', 'label', 'type', 'status', 'color', 'power_port', 'feed_leg', 'mark_connected',
|
||||
'description', 'tags',
|
||||
'description', 'owner', 'tags',
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1587,7 +1561,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
'lag', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description', 'poe_mode', 'poe_type', 'mode',
|
||||
'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'wireless_lans',
|
||||
'untagged_vlan', 'tagged_vlans', 'qinq_svlan', 'vlan_translation_policy', 'vrf', 'primary_mac_address',
|
||||
'tags',
|
||||
'owner', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'speed': NumberWithOptions(
|
||||
@@ -1619,7 +1593,7 @@ class FrontPortForm(ModularDeviceComponentForm):
|
||||
model = FrontPort
|
||||
fields = [
|
||||
'device', 'module', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'mark_connected',
|
||||
'description', 'tags',
|
||||
'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -1633,7 +1607,8 @@ class RearPortForm(ModularDeviceComponentForm):
|
||||
class Meta:
|
||||
model = RearPort
|
||||
fields = [
|
||||
'device', 'module', 'name', 'label', 'type', 'color', 'positions', 'mark_connected', 'description', 'tags',
|
||||
'device', 'module', 'name', 'label', 'type', 'color', 'positions', 'mark_connected', 'description', 'owner',
|
||||
'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -1645,7 +1620,7 @@ class ModuleBayForm(ModularDeviceComponentForm):
|
||||
class Meta:
|
||||
model = ModuleBay
|
||||
fields = [
|
||||
'device', 'module', 'name', 'label', 'position', 'description', 'tags',
|
||||
'device', 'module', 'name', 'label', 'position', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -1657,7 +1632,7 @@ class DeviceBayForm(DeviceComponentForm):
|
||||
class Meta:
|
||||
model = DeviceBay
|
||||
fields = [
|
||||
'device', 'name', 'label', 'description', 'tags',
|
||||
'device', 'name', 'label', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -1782,7 +1757,7 @@ class InventoryItemForm(DeviceComponentForm):
|
||||
model = InventoryItem
|
||||
fields = [
|
||||
'device', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id', 'serial', 'asset_tag',
|
||||
'status', 'description', 'tags',
|
||||
'status', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -1828,12 +1803,7 @@ class InventoryItemForm(DeviceComponentForm):
|
||||
self.instance.component = None
|
||||
|
||||
|
||||
# Device component roles
|
||||
#
|
||||
|
||||
class InventoryItemRoleForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class InventoryItemRoleForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Inventory Item Role')),
|
||||
)
|
||||
@@ -1841,11 +1811,11 @@ class InventoryItemRoleForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = InventoryItemRole
|
||||
fields = [
|
||||
'name', 'slug', 'color', 'description', 'tags',
|
||||
'name', 'slug', 'color', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm):
|
||||
class VirtualDeviceContextForm(TenancyForm, PrimaryModelForm):
|
||||
device = DynamicModelChoiceField(
|
||||
label=_('Device'),
|
||||
queryset=Device.objects.all(),
|
||||
@@ -1881,7 +1851,7 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = VirtualDeviceContext
|
||||
fields = [
|
||||
'device', 'name', 'status', 'identifier', 'primary_ip4', 'primary_ip6', 'tenant_group', 'tenant',
|
||||
'device', 'name', 'status', 'identifier', 'primary_ip4', 'primary_ip6', 'tenant_group', 'tenant', 'owner',
|
||||
'comments', 'tags'
|
||||
]
|
||||
|
||||
@@ -1890,7 +1860,7 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm):
|
||||
# Addressing
|
||||
#
|
||||
|
||||
class MACAddressForm(NetBoxModelForm):
|
||||
class MACAddressForm(PrimaryModelForm):
|
||||
mac_address = forms.CharField(
|
||||
required=True,
|
||||
label=_('MAC address')
|
||||
@@ -1929,7 +1899,7 @@ class MACAddressForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = MACAddress
|
||||
fields = [
|
||||
'mac_address', 'interface', 'vminterface', 'description', 'tags',
|
||||
'mac_address', 'interface', 'vminterface', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -434,8 +434,8 @@ class VirtualChassisCreateForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = VirtualChassis
|
||||
fields = [
|
||||
'name', 'domain', 'description', 'region', 'site_group', 'site', 'rack', 'members', 'initial_position',
|
||||
'tags',
|
||||
'name', 'domain', 'description', 'region', 'site_group', 'site', 'rack', 'owner', 'members',
|
||||
'initial_position', 'tags',
|
||||
]
|
||||
|
||||
def clean(self):
|
||||
|
||||
@@ -5,16 +5,13 @@ import strawberry_django
|
||||
|
||||
from core.graphql.mixins import ChangelogMixin
|
||||
from dcim import models
|
||||
from extras.graphql.mixins import (
|
||||
ConfigContextMixin,
|
||||
ContactsMixin,
|
||||
CustomFieldsMixin,
|
||||
ImageAttachmentsMixin,
|
||||
TagsMixin,
|
||||
)
|
||||
from extras.graphql.mixins import ConfigContextMixin, ContactsMixin, ImageAttachmentsMixin
|
||||
from ipam.graphql.mixins import IPAddressesMixin, VLANGroupsMixin
|
||||
from netbox.graphql.scalars import BigInt
|
||||
from netbox.graphql.types import BaseObjectType, NetBoxObjectType, OrganizationalObjectType
|
||||
from netbox.graphql.types import (
|
||||
BaseObjectType, NestedGroupObjectType, NetBoxObjectType, OrganizationalObjectType, PrimaryObjectType,
|
||||
)
|
||||
from users.graphql.mixins import OwnerMixin
|
||||
from .filters import *
|
||||
from .mixins import CabledObjectMixin, PathEndpointMixin
|
||||
|
||||
@@ -91,12 +88,7 @@ __all__ = (
|
||||
|
||||
|
||||
@strawberry.type
|
||||
class ComponentType(
|
||||
ChangelogMixin,
|
||||
CustomFieldsMixin,
|
||||
TagsMixin,
|
||||
BaseObjectType
|
||||
):
|
||||
class ComponentType(OwnerMixin, NetBoxObjectType):
|
||||
"""
|
||||
Base type for device/VM components
|
||||
"""
|
||||
@@ -159,7 +151,7 @@ class CableTerminationType(NetBoxObjectType):
|
||||
filters=CableFilter,
|
||||
pagination=True
|
||||
)
|
||||
class CableType(NetBoxObjectType):
|
||||
class CableType(PrimaryObjectType):
|
||||
color: str
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
|
||||
@@ -236,7 +228,7 @@ class ConsoleServerPortTemplateType(ModularComponentTemplateType):
|
||||
filters=DeviceFilter,
|
||||
pagination=True
|
||||
)
|
||||
class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
|
||||
class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, PrimaryObjectType):
|
||||
console_port_count: BigInt
|
||||
console_server_port_count: BigInt
|
||||
power_port_count: BigInt
|
||||
@@ -339,7 +331,7 @@ class InventoryItemTemplateType(ComponentTemplateType):
|
||||
filters=DeviceRoleFilter,
|
||||
pagination=True
|
||||
)
|
||||
class DeviceRoleType(OrganizationalObjectType):
|
||||
class DeviceRoleType(NestedGroupObjectType):
|
||||
parent: Annotated['DeviceRoleType', strawberry.lazy('dcim.graphql.types')] | None
|
||||
children: List[Annotated['DeviceRoleType', strawberry.lazy('dcim.graphql.types')]]
|
||||
color: str
|
||||
@@ -355,7 +347,7 @@ class DeviceRoleType(OrganizationalObjectType):
|
||||
filters=DeviceTypeFilter,
|
||||
pagination=True
|
||||
)
|
||||
class DeviceTypeType(NetBoxObjectType):
|
||||
class DeviceTypeType(PrimaryObjectType):
|
||||
console_port_template_count: BigInt
|
||||
console_server_port_template_count: BigInt
|
||||
power_port_template_count: BigInt
|
||||
@@ -412,7 +404,7 @@ class FrontPortTemplateType(ModularComponentTemplateType):
|
||||
filters=MACAddressFilter,
|
||||
pagination=True
|
||||
)
|
||||
class MACAddressType(NetBoxObjectType):
|
||||
class MACAddressType(PrimaryObjectType):
|
||||
mac_address: str
|
||||
|
||||
@strawberry_django.field
|
||||
@@ -512,7 +504,7 @@ class InventoryItemRoleType(OrganizationalObjectType):
|
||||
filters=LocationFilter,
|
||||
pagination=True
|
||||
)
|
||||
class LocationType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, OrganizationalObjectType):
|
||||
class LocationType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NestedGroupObjectType):
|
||||
site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
parent: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
@@ -555,7 +547,7 @@ class ManufacturerType(OrganizationalObjectType, ContactsMixin):
|
||||
filters=ModuleFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ModuleType(NetBoxObjectType):
|
||||
class ModuleType(PrimaryObjectType):
|
||||
device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]
|
||||
module_bay: Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')]
|
||||
module_type: Annotated["ModuleTypeType", strawberry.lazy('dcim.graphql.types')]
|
||||
@@ -602,7 +594,7 @@ class ModuleBayTemplateType(ModularComponentTemplateType):
|
||||
filters=ModuleTypeProfileFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ModuleTypeProfileType(NetBoxObjectType):
|
||||
class ModuleTypeProfileType(PrimaryObjectType):
|
||||
module_types: List[Annotated["ModuleType", strawberry.lazy('dcim.graphql.types')]]
|
||||
|
||||
|
||||
@@ -612,7 +604,7 @@ class ModuleTypeProfileType(NetBoxObjectType):
|
||||
filters=ModuleTypeFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ModuleTypeType(NetBoxObjectType):
|
||||
class ModuleTypeType(PrimaryObjectType):
|
||||
profile: Annotated["ModuleTypeProfileType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')]
|
||||
|
||||
@@ -632,7 +624,7 @@ class ModuleTypeType(NetBoxObjectType):
|
||||
filters=PlatformFilter,
|
||||
pagination=True
|
||||
)
|
||||
class PlatformType(OrganizationalObjectType):
|
||||
class PlatformType(NestedGroupObjectType):
|
||||
parent: Annotated['PlatformType', strawberry.lazy('dcim.graphql.types')] | None
|
||||
children: List[Annotated['PlatformType', strawberry.lazy('dcim.graphql.types')]]
|
||||
manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
@@ -648,7 +640,7 @@ class PlatformType(OrganizationalObjectType):
|
||||
filters=PowerFeedFilter,
|
||||
pagination=True
|
||||
)
|
||||
class PowerFeedType(NetBoxObjectType, CabledObjectMixin, PathEndpointMixin):
|
||||
class PowerFeedType(CabledObjectMixin, PathEndpointMixin, PrimaryObjectType):
|
||||
power_panel: Annotated["PowerPanelType", strawberry.lazy('dcim.graphql.types')]
|
||||
rack: Annotated["RackType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -682,7 +674,7 @@ class PowerOutletTemplateType(ModularComponentTemplateType):
|
||||
filters=PowerPanelFilter,
|
||||
pagination=True
|
||||
)
|
||||
class PowerPanelType(NetBoxObjectType, ContactsMixin):
|
||||
class PowerPanelType(ContactsMixin, PrimaryObjectType):
|
||||
site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]
|
||||
location: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
|
||||
@@ -716,7 +708,7 @@ class PowerPortTemplateType(ModularComponentTemplateType):
|
||||
filters=RackTypeFilter,
|
||||
pagination=True
|
||||
)
|
||||
class RackTypeType(NetBoxObjectType):
|
||||
class RackTypeType(PrimaryObjectType):
|
||||
manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')]
|
||||
|
||||
|
||||
@@ -726,7 +718,7 @@ class RackTypeType(NetBoxObjectType):
|
||||
filters=RackFilter,
|
||||
pagination=True
|
||||
)
|
||||
class RackType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
|
||||
class RackType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, PrimaryObjectType):
|
||||
site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]
|
||||
location: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -745,7 +737,7 @@ class RackType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObje
|
||||
filters=RackReservationFilter,
|
||||
pagination=True
|
||||
)
|
||||
class RackReservationType(NetBoxObjectType):
|
||||
class RackReservationType(PrimaryObjectType):
|
||||
units: List[int]
|
||||
rack: Annotated["RackType", strawberry.lazy('dcim.graphql.types')]
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -794,7 +786,7 @@ class RearPortTemplateType(ModularComponentTemplateType):
|
||||
filters=RegionFilter,
|
||||
pagination=True
|
||||
)
|
||||
class RegionType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
|
||||
class RegionType(VLANGroupsMixin, ContactsMixin, NestedGroupObjectType):
|
||||
|
||||
sites: List[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]]
|
||||
children: List[Annotated["RegionType", strawberry.lazy('dcim.graphql.types')]]
|
||||
@@ -820,7 +812,7 @@ class RegionType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
|
||||
filters=SiteFilter,
|
||||
pagination=True
|
||||
)
|
||||
class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
|
||||
class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, PrimaryObjectType):
|
||||
time_zone: str | None
|
||||
region: Annotated["RegionType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
group: Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
@@ -855,7 +847,7 @@ class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObje
|
||||
filters=SiteGroupFilter,
|
||||
pagination=True
|
||||
)
|
||||
class SiteGroupType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
|
||||
class SiteGroupType(VLANGroupsMixin, ContactsMixin, NestedGroupObjectType):
|
||||
|
||||
sites: List[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]]
|
||||
children: List[Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')]]
|
||||
@@ -881,7 +873,7 @@ class SiteGroupType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
|
||||
filters=VirtualChassisFilter,
|
||||
pagination=True
|
||||
)
|
||||
class VirtualChassisType(NetBoxObjectType):
|
||||
class VirtualChassisType(PrimaryObjectType):
|
||||
member_count: BigInt
|
||||
master: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
|
||||
@@ -894,7 +886,7 @@ class VirtualChassisType(NetBoxObjectType):
|
||||
filters=VirtualDeviceContextFilter,
|
||||
pagination=True
|
||||
)
|
||||
class VirtualDeviceContextType(NetBoxObjectType):
|
||||
class VirtualDeviceContextType(PrimaryObjectType):
|
||||
device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
primary_ip4: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
primary_ip6: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
|
||||
243
netbox/dcim/migrations/0217_owner.py
Normal file
243
netbox/dcim/migrations/0217_owner.py
Normal file
@@ -0,0 +1,243 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('dcim', '0216_poweroutlettemplate_color'),
|
||||
('users', '0015_owner'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cable',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='consoleport',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='consoleserverport',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='device',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='devicebay',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='devicerole',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='devicetype',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='frontport',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='interface',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventoryitem',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventoryitemrole',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='location',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='macaddress',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='manufacturer',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='module',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='modulebay',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='moduletype',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='moduletypeprofile',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='powerfeed',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='poweroutlet',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='powerpanel',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='powerport',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rack',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rackreservation',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rackrole',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='racktype',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rearport',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='region',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='site',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sitegroup',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='virtualchassis',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='virtualdevicecontext',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -14,6 +14,7 @@ from dcim.fields import WWNField
|
||||
from dcim.models.mixins import InterfaceValidationMixin
|
||||
from netbox.choices import ColorChoices
|
||||
from netbox.models import OrganizationalModel, NetBoxModel
|
||||
from netbox.models.mixins import OwnerMixin
|
||||
from utilities.fields import ColorField, NaturalOrderingField
|
||||
from utilities.mptt import TreeManager
|
||||
from utilities.ordering import naturalize_interface
|
||||
@@ -40,7 +41,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ComponentModel(NetBoxModel):
|
||||
class ComponentModel(OwnerMixin, NetBoxModel):
|
||||
"""
|
||||
An abstract model inherited by any model which has a parent Device.
|
||||
"""
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django_tables2.utils import Accessor
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_tables2.utils import Accessor
|
||||
|
||||
from dcim.models import Cable
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import PrimaryModelTable, columns
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
from .template_code import CABLE_LENGTH
|
||||
|
||||
@@ -48,7 +48,7 @@ class CableTerminationsColumn(tables.Column):
|
||||
# Cables
|
||||
#
|
||||
|
||||
class CableTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class CableTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
a_terminations = CableTerminationsColumn(
|
||||
cable_end='A',
|
||||
orderable=False,
|
||||
@@ -117,12 +117,11 @@ class CableTable(TenancyColumnsMixin, NetBoxTable):
|
||||
verbose_name=_('Color Name'),
|
||||
orderable=False
|
||||
)
|
||||
comments = columns.MarkdownColumn()
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:cable_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Cable
|
||||
fields = (
|
||||
'pk', 'id', 'label', 'a_terminations', 'b_terminations', 'device_a', 'device_b', 'rack_a', 'rack_b',
|
||||
|
||||
@@ -3,7 +3,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
from django_tables2.utils import Accessor
|
||||
|
||||
from dcim import models
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import NestedGroupModelTable, NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
from .template_code import *
|
||||
|
||||
@@ -58,15 +58,7 @@ MACADDRESS_COPY_BUTTON = """
|
||||
# Device roles
|
||||
#
|
||||
|
||||
class DeviceRoleTable(NetBoxTable):
|
||||
name = columns.MPTTColumn(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
)
|
||||
parent = tables.Column(
|
||||
verbose_name=_('Parent'),
|
||||
linkify=True,
|
||||
)
|
||||
class DeviceRoleTable(NestedGroupModelTable):
|
||||
device_count = columns.LinkedCountColumn(
|
||||
viewname='dcim:device_list',
|
||||
url_params={'role_id': 'pk'},
|
||||
@@ -89,7 +81,7 @@ class DeviceRoleTable(NetBoxTable):
|
||||
url_name='dcim:devicerole_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(NestedGroupModelTable.Meta):
|
||||
model = models.DeviceRole
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'parent', 'device_count', 'vm_count', 'color', 'vm_role', 'config_template',
|
||||
@@ -102,15 +94,7 @@ class DeviceRoleTable(NetBoxTable):
|
||||
# Platforms
|
||||
#
|
||||
|
||||
class PlatformTable(NetBoxTable):
|
||||
name = columns.MPTTColumn(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
)
|
||||
parent = tables.Column(
|
||||
verbose_name=_('Parent'),
|
||||
linkify=True,
|
||||
)
|
||||
class PlatformTable(NestedGroupModelTable):
|
||||
manufacturer = tables.Column(
|
||||
verbose_name=_('Manufacturer'),
|
||||
linkify=True
|
||||
@@ -133,7 +117,7 @@ class PlatformTable(NetBoxTable):
|
||||
url_name='dcim:platform_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(NestedGroupModelTable.Meta):
|
||||
model = models.Platform
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'parent', 'manufacturer', 'device_count', 'vm_count', 'slug', 'config_template',
|
||||
@@ -148,7 +132,7 @@ class PlatformTable(NetBoxTable):
|
||||
# Devices
|
||||
#
|
||||
|
||||
class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable):
|
||||
name = tables.TemplateColumn(
|
||||
verbose_name=_('Name'),
|
||||
template_code=DEVICE_LINK,
|
||||
@@ -249,7 +233,6 @@ class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
accessor='parent_bay',
|
||||
linkify=True
|
||||
)
|
||||
comments = columns.MarkdownColumn()
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:device_list'
|
||||
)
|
||||
@@ -284,7 +267,7 @@ class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
verbose_name=_('Inventory items')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = models.Device
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'status', 'tenant', 'tenant_group', 'role', 'manufacturer', 'device_type',
|
||||
@@ -1050,7 +1033,7 @@ class DeviceInventoryItemTable(InventoryItemTable):
|
||||
)
|
||||
|
||||
|
||||
class InventoryItemRoleTable(NetBoxTable):
|
||||
class InventoryItemRoleTable(OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -1067,7 +1050,7 @@ class InventoryItemRoleTable(NetBoxTable):
|
||||
url_name='dcim:inventoryitemrole_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = models.InventoryItemRole
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'inventoryitem_count', 'color', 'description', 'slug', 'tags', 'actions',
|
||||
@@ -1079,7 +1062,7 @@ class InventoryItemRoleTable(NetBoxTable):
|
||||
# Virtual chassis
|
||||
#
|
||||
|
||||
class VirtualChassisTable(NetBoxTable):
|
||||
class VirtualChassisTable(PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -1093,14 +1076,11 @@ class VirtualChassisTable(NetBoxTable):
|
||||
url_params={'virtual_chassis_id': 'pk'},
|
||||
verbose_name=_('Members')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:virtualchassis_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = models.VirtualChassis
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'domain', 'master', 'member_count', 'description', 'comments', 'tags', 'created',
|
||||
@@ -1109,7 +1089,7 @@ class VirtualChassisTable(NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'domain', 'master', 'member_count')
|
||||
|
||||
|
||||
class VirtualDeviceContextTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class VirtualDeviceContextTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -1140,14 +1120,11 @@ class VirtualDeviceContextTable(TenancyColumnsMixin, NetBoxTable):
|
||||
url_params={'vdc_id': 'pk'},
|
||||
verbose_name=_('Interfaces')
|
||||
)
|
||||
|
||||
comments = columns.MarkdownColumn()
|
||||
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:virtualdevicecontext_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = models.VirtualDeviceContext
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'status', 'identifier', 'tenant', 'tenant_group', 'primary_ip', 'primary_ip4',
|
||||
@@ -1158,7 +1135,7 @@ class VirtualDeviceContextTable(TenancyColumnsMixin, NetBoxTable):
|
||||
)
|
||||
|
||||
|
||||
class MACAddressTable(NetBoxTable):
|
||||
class MACAddressTable(PrimaryModelTable):
|
||||
mac_address = tables.TemplateColumn(
|
||||
template_code=MACADDRESS_LINK,
|
||||
verbose_name=_('MAC Address')
|
||||
@@ -1181,7 +1158,7 @@ class MACAddressTable(NetBoxTable):
|
||||
extra_buttons=MACADDRESS_COPY_BUTTON
|
||||
)
|
||||
|
||||
class Meta(DeviceComponentTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = models.MACAddress
|
||||
fields = (
|
||||
'pk', 'id', 'mac_address', 'assigned_object_parent', 'assigned_object', 'description', 'comments', 'tags',
|
||||
|
||||
@@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from dcim import models
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin
|
||||
from .template_code import MODULAR_COMPONENT_TEMPLATE_BUTTONS, WEIGHT
|
||||
|
||||
@@ -26,7 +26,7 @@ __all__ = (
|
||||
# Manufacturers
|
||||
#
|
||||
|
||||
class ManufacturerTable(ContactsColumnMixin, NetBoxTable):
|
||||
class ManufacturerTable(ContactsColumnMixin, OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -60,7 +60,7 @@ class ManufacturerTable(ContactsColumnMixin, NetBoxTable):
|
||||
url_name='dcim:manufacturer_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = models.Manufacturer
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'racktype_count', 'devicetype_count', 'moduletype_count', 'inventoryitem_count',
|
||||
@@ -76,7 +76,7 @@ class ManufacturerTable(ContactsColumnMixin, NetBoxTable):
|
||||
# Device types
|
||||
#
|
||||
|
||||
class DeviceTypeTable(NetBoxTable):
|
||||
class DeviceTypeTable(PrimaryModelTable):
|
||||
model = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Device Type')
|
||||
@@ -93,9 +93,6 @@ class DeviceTypeTable(NetBoxTable):
|
||||
verbose_name=_('Full Depth'),
|
||||
false_mark=None
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:devicetype_list'
|
||||
)
|
||||
@@ -148,7 +145,7 @@ class DeviceTypeTable(NetBoxTable):
|
||||
verbose_name=_('Inventory Items')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = models.DeviceType
|
||||
fields = (
|
||||
'pk', 'id', 'model', 'manufacturer', 'default_platform', 'slug', 'part_number', 'u_height',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from dcim.models import Module, ModuleType, ModuleTypeProfile
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import PrimaryModelTable, columns
|
||||
from .template_code import MODULETYPEPROFILE_ATTRIBUTES, WEIGHT
|
||||
|
||||
__all__ = (
|
||||
@@ -12,7 +12,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ModuleTypeProfileTable(NetBoxTable):
|
||||
class ModuleTypeProfileTable(PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -23,14 +23,11 @@ class ModuleTypeProfileTable(NetBoxTable):
|
||||
orderable=False,
|
||||
verbose_name=_('Attributes')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:moduletypeprofile_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = ModuleTypeProfile
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'description', 'comments', 'tags', 'created', 'last_updated',
|
||||
@@ -40,7 +37,7 @@ class ModuleTypeProfileTable(NetBoxTable):
|
||||
)
|
||||
|
||||
|
||||
class ModuleTypeTable(NetBoxTable):
|
||||
class ModuleTypeTable(PrimaryModelTable):
|
||||
profile = tables.Column(
|
||||
verbose_name=_('Profile'),
|
||||
linkify=True
|
||||
@@ -64,14 +61,11 @@ class ModuleTypeTable(NetBoxTable):
|
||||
url_params={'module_type_id': 'pk'},
|
||||
verbose_name=_('Instances')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:moduletype_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = ModuleType
|
||||
fields = (
|
||||
'pk', 'id', 'model', 'profile', 'manufacturer', 'part_number', 'airflow', 'weight', 'description',
|
||||
@@ -82,7 +76,7 @@ class ModuleTypeTable(NetBoxTable):
|
||||
)
|
||||
|
||||
|
||||
class ModuleTable(NetBoxTable):
|
||||
class ModuleTable(PrimaryModelTable):
|
||||
device = tables.Column(
|
||||
verbose_name=_('Device'),
|
||||
linkify=True
|
||||
@@ -103,14 +97,11 @@ class ModuleTable(NetBoxTable):
|
||||
status = columns.ChoiceFieldColumn(
|
||||
verbose_name=_('Status'),
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:module_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Module
|
||||
fields = (
|
||||
'pk', 'id', 'device', 'module_bay', 'manufacturer', 'module_type', 'status', 'serial', 'asset_tag',
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from dcim.models import PowerFeed, PowerPanel
|
||||
from netbox.tables import PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
|
||||
from .devices import CableTerminationTable
|
||||
|
||||
__all__ = (
|
||||
@@ -17,7 +16,7 @@ __all__ = (
|
||||
# Power panels
|
||||
#
|
||||
|
||||
class PowerPanelTable(ContactsColumnMixin, NetBoxTable):
|
||||
class PowerPanelTable(ContactsColumnMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -35,14 +34,11 @@ class PowerPanelTable(ContactsColumnMixin, NetBoxTable):
|
||||
url_params={'power_panel_id': 'pk'},
|
||||
verbose_name=_('Power Feeds')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:powerpanel_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = PowerPanel
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'site', 'location', 'powerfeed_count', 'contacts', 'description', 'comments', 'tags',
|
||||
@@ -57,7 +53,7 @@ class PowerPanelTable(ContactsColumnMixin, NetBoxTable):
|
||||
|
||||
# We're not using PathEndpointTable for PowerFeed because power connections
|
||||
# cannot traverse pass-through ports.
|
||||
class PowerFeedTable(TenancyColumnsMixin, CableTerminationTable):
|
||||
class PowerFeedTable(TenancyColumnsMixin, CableTerminationTable, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -92,14 +88,11 @@ class PowerFeedTable(TenancyColumnsMixin, CableTerminationTable):
|
||||
linkify=True,
|
||||
verbose_name=_('Site'),
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:powerfeed_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(CableTerminationTable.Meta, PrimaryModelTable.Meta):
|
||||
model = PowerFeed
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'power_panel', 'site', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_tables2.utils import Accessor
|
||||
|
||||
from dcim.models import Rack, RackReservation, RackRole, RackType
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
from .template_code import OUTER_UNIT, WEIGHT
|
||||
|
||||
@@ -15,11 +15,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Rack roles
|
||||
#
|
||||
|
||||
class RackRoleTable(NetBoxTable):
|
||||
class RackRoleTable(OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -36,7 +32,7 @@ class RackRoleTable(NetBoxTable):
|
||||
url_name='dcim:rackrole_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = RackRole
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'rack_count', 'color', 'description', 'slug', 'tags', 'actions', 'created',
|
||||
@@ -45,11 +41,7 @@ class RackRoleTable(NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'rack_count', 'color', 'description')
|
||||
|
||||
|
||||
#
|
||||
# Rack Types
|
||||
#
|
||||
|
||||
class RackTypeTable(NetBoxTable):
|
||||
class RackTypeTable(PrimaryModelTable):
|
||||
model = tables.Column(
|
||||
verbose_name=_('Model'),
|
||||
linkify=True
|
||||
@@ -84,9 +76,6 @@ class RackTypeTable(NetBoxTable):
|
||||
template_code=WEIGHT,
|
||||
order_by=('_abs_max_weight', 'weight_unit')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
instance_count = columns.LinkedCountColumn(
|
||||
viewname='dcim:rack_list',
|
||||
url_params={'rack_type_id': 'pk'},
|
||||
@@ -96,7 +85,7 @@ class RackTypeTable(NetBoxTable):
|
||||
url_name='dcim:rack_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = RackType
|
||||
fields = (
|
||||
'pk', 'id', 'model', 'manufacturer', 'form_factor', 'u_height', 'starting_unit', 'width', 'outer_width',
|
||||
@@ -108,11 +97,7 @@ class RackTypeTable(NetBoxTable):
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Racks
|
||||
#
|
||||
|
||||
class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
class RackTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -144,9 +129,6 @@ class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
template_code="{{ value }}U",
|
||||
verbose_name=_('Height')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
device_count = columns.LinkedCountColumn(
|
||||
viewname='dcim:device_list',
|
||||
url_params={'rack_id': 'pk'},
|
||||
@@ -186,7 +168,7 @@ class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
order_by=('_abs_max_weight', 'weight_unit')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Rack
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'tenant_group', 'role',
|
||||
@@ -201,11 +183,7 @@ class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Rack reservations
|
||||
#
|
||||
|
||||
class RackReservationTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class RackReservationTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
reservation = tables.Column(
|
||||
verbose_name=_('Reservation'),
|
||||
accessor='pk',
|
||||
@@ -232,14 +210,11 @@ class RackReservationTable(TenancyColumnsMixin, NetBoxTable):
|
||||
status = columns.ChoiceFieldColumn(
|
||||
verbose_name=_('Status'),
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:rackreservation_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = RackReservation
|
||||
fields = (
|
||||
'pk', 'id', 'reservation', 'site', 'location', 'rack', 'unit_list', 'status', 'user', 'created', 'tenant',
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from dcim.models import Location, Region, Site, SiteGroup
|
||||
from netbox.tables import NestedGroupModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
|
||||
from .template_code import LOCATION_BUTTONS
|
||||
|
||||
__all__ = (
|
||||
@@ -15,19 +14,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Regions
|
||||
#
|
||||
|
||||
class RegionTable(ContactsColumnMixin, NetBoxTable):
|
||||
name = columns.MPTTColumn(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
)
|
||||
parent = tables.Column(
|
||||
verbose_name=_('Parent'),
|
||||
linkify=True,
|
||||
)
|
||||
class RegionTable(ContactsColumnMixin, NestedGroupModelTable):
|
||||
site_count = columns.LinkedCountColumn(
|
||||
viewname='dcim:site_list',
|
||||
url_params={'region_id': 'pk'},
|
||||
@@ -36,11 +23,8 @@ class RegionTable(ContactsColumnMixin, NetBoxTable):
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:region_list'
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(NestedGroupModelTable.Meta):
|
||||
model = Region
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'parent', 'slug', 'site_count', 'description', 'comments', 'contacts', 'tags',
|
||||
@@ -49,19 +33,7 @@ class RegionTable(ContactsColumnMixin, NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'site_count', 'description')
|
||||
|
||||
|
||||
#
|
||||
# Site groups
|
||||
#
|
||||
|
||||
class SiteGroupTable(ContactsColumnMixin, NetBoxTable):
|
||||
name = columns.MPTTColumn(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
)
|
||||
parent = tables.Column(
|
||||
verbose_name=_('Parent'),
|
||||
linkify=True,
|
||||
)
|
||||
class SiteGroupTable(ContactsColumnMixin, NestedGroupModelTable):
|
||||
site_count = columns.LinkedCountColumn(
|
||||
viewname='dcim:site_list',
|
||||
url_params={'group_id': 'pk'},
|
||||
@@ -70,11 +42,8 @@ class SiteGroupTable(ContactsColumnMixin, NetBoxTable):
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:sitegroup_list'
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(NestedGroupModelTable.Meta):
|
||||
model = SiteGroup
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'parent', 'slug', 'site_count', 'description', 'comments', 'contacts', 'tags',
|
||||
@@ -83,11 +52,7 @@ class SiteGroupTable(ContactsColumnMixin, NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'site_count', 'description')
|
||||
|
||||
|
||||
#
|
||||
# Sites
|
||||
#
|
||||
|
||||
class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -117,14 +82,11 @@ class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
url_params={'site_id': 'pk'},
|
||||
verbose_name=_('Devices')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:site_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Site
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'tenant_group', 'asns',
|
||||
@@ -134,19 +96,7 @@ class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'status', 'facility', 'region', 'group', 'tenant', 'description')
|
||||
|
||||
|
||||
#
|
||||
# Locations
|
||||
#
|
||||
|
||||
class LocationTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
name = columns.MPTTColumn(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
)
|
||||
parent = tables.Column(
|
||||
verbose_name=_('Parent'),
|
||||
linkify=True,
|
||||
)
|
||||
class LocationTable(TenancyColumnsMixin, ContactsColumnMixin, NestedGroupModelTable):
|
||||
site = tables.Column(
|
||||
verbose_name=_('Site'),
|
||||
linkify=True
|
||||
@@ -175,11 +125,8 @@ class LocationTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
actions = columns.ActionsColumn(
|
||||
extra_buttons=LOCATION_BUTTONS
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(NestedGroupModelTable.Meta):
|
||||
model = Location
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'parent', 'site', 'status', 'facility', 'tenant', 'tenant_group', 'rack_count',
|
||||
|
||||
@@ -8,7 +8,8 @@ from dcim.api.serializers_.sites import LocationSerializer, RegionSerializer, Si
|
||||
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
||||
from extras.models import ConfigContext, ConfigContextProfile, Tag
|
||||
from netbox.api.fields import SerializedPKRelatedField
|
||||
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
from netbox.api.serializers import ChangeLogMessageSerializer, PrimaryModelSerializer, ValidatedModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer, TenantGroupSerializer
|
||||
from tenancy.models import Tenant, TenantGroup
|
||||
from virtualization.api.serializers_.clusters import ClusterSerializer, ClusterGroupSerializer, ClusterTypeSerializer
|
||||
@@ -20,13 +21,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ConfigContextProfileSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
tags = serializers.SlugRelatedField(
|
||||
queryset=Tag.objects.all(),
|
||||
slug_field='slug',
|
||||
required=False,
|
||||
many=True
|
||||
)
|
||||
class ConfigContextProfileSerializer(PrimaryModelSerializer):
|
||||
data_source = DataSourceSerializer(
|
||||
nested=True,
|
||||
required=False
|
||||
@@ -39,13 +34,13 @@ class ConfigContextProfileSerializer(ChangeLogMessageSerializer, ValidatedModelS
|
||||
class Meta:
|
||||
model = ConfigContextProfile
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'description', 'schema', 'tags', 'comments', 'data_source',
|
||||
'data_path', 'data_file', 'data_synced', 'created', 'last_updated',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'description', 'schema', 'tags', 'owner', 'comments',
|
||||
'data_source', 'data_path', 'data_file', 'data_synced', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
|
||||
class ConfigContextSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
class ConfigContextSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
profile = ConfigContextProfileSerializer(
|
||||
nested=True,
|
||||
required=False,
|
||||
@@ -156,7 +151,7 @@ class ConfigContextSerializer(ChangeLogMessageSerializer, ValidatedModelSerializ
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'weight', 'profile', 'description', 'is_active', 'regions',
|
||||
'site_groups', 'sites', 'locations', 'device_types', 'roles', 'platforms', 'cluster_types',
|
||||
'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', 'data_source', 'data_path', 'data_file',
|
||||
'data_synced', 'data', 'created', 'last_updated',
|
||||
'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'owner', 'tags', 'data_source', 'data_path',
|
||||
'data_file', 'data_synced', 'data', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
@@ -2,13 +2,19 @@ from core.api.serializers_.data import DataFileSerializer, DataSourceSerializer
|
||||
from extras.models import ConfigTemplate
|
||||
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
from netbox.api.serializers.features import TaggableModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
|
||||
__all__ = (
|
||||
'ConfigTemplateSerializer',
|
||||
)
|
||||
|
||||
|
||||
class ConfigTemplateSerializer(ChangeLogMessageSerializer, TaggableModelSerializer, ValidatedModelSerializer):
|
||||
class ConfigTemplateSerializer(
|
||||
OwnerMixin,
|
||||
ChangeLogMessageSerializer,
|
||||
TaggableModelSerializer,
|
||||
ValidatedModelSerializer
|
||||
):
|
||||
data_source = DataSourceSerializer(
|
||||
nested=True,
|
||||
required=False
|
||||
@@ -23,6 +29,6 @@ class ConfigTemplateSerializer(ChangeLogMessageSerializer, TaggableModelSerializ
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'description', 'environment_params', 'template_code',
|
||||
'mime_type', 'file_name', 'file_extension', 'as_attachment', 'data_source', 'data_path', 'data_file',
|
||||
'data_synced', 'tags', 'created', 'last_updated',
|
||||
'data_synced', 'owner', 'tags', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
@@ -8,6 +8,7 @@ from extras.choices import *
|
||||
from extras.models import CustomField, CustomFieldChoiceSet
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField
|
||||
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
|
||||
__all__ = (
|
||||
'CustomFieldChoiceSetSerializer',
|
||||
@@ -15,7 +16,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class CustomFieldChoiceSetSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
class CustomFieldChoiceSetSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
base_choices = ChoiceField(
|
||||
choices=CustomFieldChoiceSetBaseChoices,
|
||||
required=False
|
||||
@@ -32,12 +33,12 @@ class CustomFieldChoiceSetSerializer(ChangeLogMessageSerializer, ValidatedModelS
|
||||
model = CustomFieldChoiceSet
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'description', 'base_choices', 'extra_choices',
|
||||
'order_alphabetically', 'choices_count', 'created', 'last_updated',
|
||||
'order_alphabetically', 'choices_count', 'owner', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description', 'choices_count')
|
||||
|
||||
|
||||
class CustomFieldSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
class CustomFieldSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
object_types = ContentTypeField(
|
||||
queryset=ObjectType.objects.with_feature('custom_fields'),
|
||||
many=True
|
||||
@@ -64,8 +65,8 @@ class CustomFieldSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
'id', 'url', 'display_url', 'display', 'object_types', 'type', 'related_object_type', 'data_type',
|
||||
'name', 'label', 'group_name', 'description', 'required', 'unique', 'search_weight', 'filter_logic',
|
||||
'ui_visible', 'ui_editable', 'is_cloneable', 'default', 'related_object_filter', 'weight',
|
||||
'validation_minimum', 'validation_maximum', 'validation_regex', 'choice_set', 'comments', 'created',
|
||||
'last_updated',
|
||||
'validation_minimum', 'validation_maximum', 'validation_regex', 'choice_set', 'owner', 'comments',
|
||||
'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@ from core.models import ObjectType
|
||||
from extras.models import CustomLink
|
||||
from netbox.api.fields import ContentTypeField
|
||||
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
|
||||
__all__ = (
|
||||
'CustomLinkSerializer',
|
||||
)
|
||||
|
||||
|
||||
class CustomLinkSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
class CustomLinkSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
object_types = ContentTypeField(
|
||||
queryset=ObjectType.objects.with_feature('custom_links'),
|
||||
many=True
|
||||
@@ -18,6 +19,6 @@ class CustomLinkSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer)
|
||||
model = CustomLink
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'object_types', 'name', 'enabled', 'link_text', 'link_url',
|
||||
'weight', 'group_name', 'button_class', 'new_window', 'created', 'last_updated',
|
||||
'weight', 'group_name', 'button_class', 'new_window', 'owner', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name')
|
||||
|
||||
@@ -7,6 +7,7 @@ from extras.choices import *
|
||||
from extras.models import EventRule, Webhook
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
from utilities.api import get_serializer_for_model
|
||||
from .scripts import ScriptSerializer
|
||||
|
||||
@@ -20,7 +21,7 @@ __all__ = (
|
||||
# Event Rules
|
||||
#
|
||||
|
||||
class EventRuleSerializer(NetBoxModelSerializer):
|
||||
class EventRuleSerializer(OwnerMixin, NetBoxModelSerializer):
|
||||
object_types = ContentTypeField(
|
||||
queryset=ObjectType.objects.with_feature('event_rules'),
|
||||
many=True
|
||||
@@ -36,7 +37,7 @@ class EventRuleSerializer(NetBoxModelSerializer):
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'object_types', 'name', 'enabled', 'event_types', 'conditions',
|
||||
'action_type', 'action_object_type', 'action_object_id', 'action_object', 'description', 'custom_fields',
|
||||
'tags', 'created', 'last_updated',
|
||||
'owner', 'tags', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
@@ -56,13 +57,13 @@ class EventRuleSerializer(NetBoxModelSerializer):
|
||||
# Webhooks
|
||||
#
|
||||
|
||||
class WebhookSerializer(NetBoxModelSerializer):
|
||||
class WebhookSerializer(OwnerMixin, NetBoxModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Webhook
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'description', 'payload_url', 'http_method',
|
||||
'http_content_type', 'additional_headers', 'body_template', 'secret', 'ssl_verification', 'ca_file_path',
|
||||
'custom_fields', 'tags', 'created', 'last_updated',
|
||||
'custom_fields', 'owner', 'tags', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
@@ -3,13 +3,14 @@ from core.models import ObjectType
|
||||
from extras.models import ExportTemplate
|
||||
from netbox.api.fields import ContentTypeField
|
||||
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
|
||||
__all__ = (
|
||||
'ExportTemplateSerializer',
|
||||
)
|
||||
|
||||
|
||||
class ExportTemplateSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
class ExportTemplateSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
object_types = ContentTypeField(
|
||||
queryset=ObjectType.objects.with_feature('export_templates'),
|
||||
many=True
|
||||
@@ -28,6 +29,6 @@ class ExportTemplateSerializer(ChangeLogMessageSerializer, ValidatedModelSeriali
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'object_types', 'name', 'description', 'environment_params',
|
||||
'template_code', 'mime_type', 'file_name', 'file_extension', 'as_attachment', 'data_source',
|
||||
'data_path', 'data_file', 'data_synced', 'created', 'last_updated',
|
||||
'data_path', 'data_file', 'data_synced', 'owner', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
@@ -2,13 +2,14 @@ from core.models import ObjectType
|
||||
from extras.models import SavedFilter
|
||||
from netbox.api.fields import ContentTypeField
|
||||
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
|
||||
__all__ = (
|
||||
'SavedFilterSerializer',
|
||||
)
|
||||
|
||||
|
||||
class SavedFilterSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
class SavedFilterSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
object_types = ContentTypeField(
|
||||
queryset=ObjectType.objects.all(),
|
||||
many=True
|
||||
@@ -18,6 +19,6 @@ class SavedFilterSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
model = SavedFilter
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'object_types', 'name', 'slug', 'description', 'user', 'weight',
|
||||
'enabled', 'shared', 'parameters', 'created', 'last_updated',
|
||||
'enabled', 'shared', 'parameters', 'owner', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description')
|
||||
|
||||
@@ -6,6 +6,7 @@ from extras.models import Tag, TaggedItem
|
||||
from netbox.api.exceptions import SerializerNotFound
|
||||
from netbox.api.fields import ContentTypeField, RelatedObjectCountField
|
||||
from netbox.api.serializers import BaseModelSerializer, ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
from utilities.api import get_serializer_for_model
|
||||
|
||||
__all__ = (
|
||||
@@ -14,7 +15,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class TagSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
class TagSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer):
|
||||
object_types = ContentTypeField(
|
||||
queryset=ObjectType.objects.with_feature('tags'),
|
||||
many=True,
|
||||
|
||||
@@ -5,8 +5,9 @@ from django.utils.translation import gettext as _
|
||||
|
||||
from core.models import DataSource, ObjectType
|
||||
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
||||
from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet
|
||||
from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet, PrimaryModelFilterSet
|
||||
from tenancy.models import Tenant, TenantGroup
|
||||
from users.filterset_mixins import OwnerFilterMixin
|
||||
from users.models import Group, User
|
||||
from utilities.filters import (
|
||||
ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter
|
||||
@@ -61,7 +62,7 @@ class ScriptFilterSet(BaseFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class WebhookFilterSet(NetBoxModelFilterSet):
|
||||
class WebhookFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -90,7 +91,7 @@ class WebhookFilterSet(NetBoxModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class EventRuleFilterSet(NetBoxModelFilterSet):
|
||||
class EventRuleFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -130,7 +131,7 @@ class EventRuleFilterSet(NetBoxModelFilterSet):
|
||||
return queryset.filter(event_types__overlap=value)
|
||||
|
||||
|
||||
class CustomFieldFilterSet(ChangeLoggedModelFilterSet):
|
||||
class CustomFieldFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -179,7 +180,7 @@ class CustomFieldFilterSet(ChangeLoggedModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class CustomFieldChoiceSetFilterSet(ChangeLoggedModelFilterSet):
|
||||
class CustomFieldChoiceSetFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -207,7 +208,7 @@ class CustomFieldChoiceSetFilterSet(ChangeLoggedModelFilterSet):
|
||||
return queryset.filter(extra_choices__overlap=value)
|
||||
|
||||
|
||||
class CustomLinkFilterSet(ChangeLoggedModelFilterSet):
|
||||
class CustomLinkFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -237,7 +238,7 @@ class CustomLinkFilterSet(ChangeLoggedModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class ExportTemplateFilterSet(ChangeLoggedModelFilterSet):
|
||||
class ExportTemplateFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -275,7 +276,7 @@ class ExportTemplateFilterSet(ChangeLoggedModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class SavedFilterFilterSet(ChangeLoggedModelFilterSet):
|
||||
class SavedFilterFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -494,7 +495,7 @@ class JournalEntryFilterSet(NetBoxModelFilterSet):
|
||||
return queryset.filter(comments__icontains=value)
|
||||
|
||||
|
||||
class TagFilterSet(ChangeLoggedModelFilterSet):
|
||||
class TagFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -589,7 +590,7 @@ class TaggedItemFilterSet(BaseFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class ConfigContextProfileFilterSet(NetBoxModelFilterSet):
|
||||
class ConfigContextProfileFilterSet(PrimaryModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -619,7 +620,7 @@ class ConfigContextProfileFilterSet(NetBoxModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
|
||||
class ConfigContextFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
@@ -788,7 +789,7 @@ class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class ConfigTemplateFilterSet(ChangeLoggedModelFilterSet):
|
||||
class ConfigTemplateFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
|
||||
@@ -4,8 +4,8 @@ from django.utils.translation import gettext_lazy as _
|
||||
from extras.choices import *
|
||||
from extras.models import *
|
||||
from netbox.events import get_event_type_choices
|
||||
from netbox.forms import NetBoxModelBulkEditForm
|
||||
from netbox.forms.mixins import ChangelogMessageMixin
|
||||
from netbox.forms import NetBoxModelBulkEditForm, PrimaryModelBulkEditForm
|
||||
from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin
|
||||
from utilities.forms import BulkEditForm, add_blank_choice
|
||||
from utilities.forms.fields import ColorField, CommentField, DynamicModelChoiceField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
@@ -30,7 +30,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class CustomFieldBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
class CustomFieldBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=CustomField.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -98,7 +98,7 @@ class CustomFieldBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
nullable_fields = ('group_name', 'description', 'choice_set')
|
||||
|
||||
|
||||
class CustomFieldChoiceSetBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
class CustomFieldChoiceSetBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=CustomFieldChoiceSet.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -118,7 +118,7 @@ class CustomFieldChoiceSetBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
nullable_fields = ('base_choices', 'description')
|
||||
|
||||
|
||||
class CustomLinkBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
class CustomLinkBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=CustomLink.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -144,7 +144,7 @@ class CustomLinkBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class ExportTemplateBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
class ExportTemplateBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=ExportTemplate.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -177,7 +177,7 @@ class ExportTemplateBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
nullable_fields = ('description', 'mime_type', 'file_name', 'file_extension')
|
||||
|
||||
|
||||
class SavedFilterBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
class SavedFilterBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=SavedFilter.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -233,7 +233,7 @@ class TableConfigBulkEditForm(BulkEditForm):
|
||||
nullable_fields = ('description',)
|
||||
|
||||
|
||||
class WebhookBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class WebhookBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm):
|
||||
model = Webhook
|
||||
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
@@ -271,7 +271,7 @@ class WebhookBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('secret', 'ca_file_path')
|
||||
|
||||
|
||||
class EventRuleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class EventRuleBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm):
|
||||
model = EventRule
|
||||
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
@@ -297,7 +297,7 @@ class EventRuleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('description', 'conditions')
|
||||
|
||||
|
||||
class TagBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
class TagBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -319,17 +319,11 @@ class TagBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
nullable_fields = ('description',)
|
||||
|
||||
|
||||
class ConfigContextProfileBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ConfigContextProfileBulkEditForm(PrimaryModelBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=ConfigContextProfile.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
required=False,
|
||||
max_length=100
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = ConfigContextProfile
|
||||
fieldsets = (
|
||||
@@ -338,7 +332,7 @@ class ConfigContextProfileBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('description',)
|
||||
|
||||
|
||||
class ConfigContextBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
class ConfigContextBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=ConfigContext.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -369,7 +363,7 @@ class ConfigContextBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
nullable_fields = ('profile', 'description')
|
||||
|
||||
|
||||
class ConfigTemplateBulkEditForm(ChangelogMessageMixin, BulkEditForm):
|
||||
class ConfigTemplateBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
|
||||
@@ -9,7 +9,7 @@ from core.models import ObjectType
|
||||
from extras.choices import *
|
||||
from extras.models import *
|
||||
from netbox.events import get_event_type_choices
|
||||
from netbox.forms import NetBoxModelImportForm
|
||||
from netbox.forms import NetBoxModelImportForm, OwnerCSVMixin, PrimaryModelImportForm
|
||||
from users.models import Group, User
|
||||
from utilities.forms import CSVModelForm
|
||||
from utilities.forms.fields import (
|
||||
@@ -33,7 +33,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class CustomFieldImportForm(CSVModelForm):
|
||||
class CustomFieldImportForm(OwnerCSVMixin, CSVModelForm):
|
||||
object_types = CSVMultipleContentTypeField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.with_feature('custom_fields'),
|
||||
@@ -75,11 +75,11 @@ class CustomFieldImportForm(CSVModelForm):
|
||||
fields = (
|
||||
'name', 'label', 'group_name', 'type', 'object_types', 'related_object_type', 'required', 'unique',
|
||||
'description', 'search_weight', 'filter_logic', 'default', 'choice_set', 'weight', 'validation_minimum',
|
||||
'validation_maximum', 'validation_regex', 'ui_visible', 'ui_editable', 'is_cloneable', 'comments',
|
||||
'validation_maximum', 'validation_regex', 'ui_visible', 'ui_editable', 'is_cloneable', 'owner', 'comments',
|
||||
)
|
||||
|
||||
|
||||
class CustomFieldChoiceSetImportForm(CSVModelForm):
|
||||
class CustomFieldChoiceSetImportForm(OwnerCSVMixin, CSVModelForm):
|
||||
base_choices = CSVChoiceField(
|
||||
choices=CustomFieldChoiceSetBaseChoices,
|
||||
required=False,
|
||||
@@ -97,7 +97,7 @@ class CustomFieldChoiceSetImportForm(CSVModelForm):
|
||||
class Meta:
|
||||
model = CustomFieldChoiceSet
|
||||
fields = (
|
||||
'name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically',
|
||||
'name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically', 'owner',
|
||||
)
|
||||
|
||||
def clean_extra_choices(self):
|
||||
@@ -114,7 +114,7 @@ class CustomFieldChoiceSetImportForm(CSVModelForm):
|
||||
return data
|
||||
|
||||
|
||||
class CustomLinkImportForm(CSVModelForm):
|
||||
class CustomLinkImportForm(OwnerCSVMixin, CSVModelForm):
|
||||
object_types = CSVMultipleContentTypeField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.with_feature('custom_links'),
|
||||
@@ -131,11 +131,11 @@ class CustomLinkImportForm(CSVModelForm):
|
||||
model = CustomLink
|
||||
fields = (
|
||||
'name', 'object_types', 'enabled', 'weight', 'group_name', 'button_class', 'new_window', 'link_text',
|
||||
'link_url',
|
||||
'link_url', 'owner',
|
||||
)
|
||||
|
||||
|
||||
class ExportTemplateImportForm(CSVModelForm):
|
||||
class ExportTemplateImportForm(OwnerCSVMixin, CSVModelForm):
|
||||
object_types = CSVMultipleContentTypeField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.with_feature('export_templates'),
|
||||
@@ -146,30 +146,30 @@ class ExportTemplateImportForm(CSVModelForm):
|
||||
model = ExportTemplate
|
||||
fields = (
|
||||
'name', 'object_types', 'description', 'environment_params', 'mime_type', 'file_name', 'file_extension',
|
||||
'as_attachment', 'template_code',
|
||||
'as_attachment', 'template_code', 'owner',
|
||||
)
|
||||
|
||||
|
||||
class ConfigContextProfileImportForm(NetBoxModelImportForm):
|
||||
class ConfigContextProfileImportForm(PrimaryModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ConfigContextProfile
|
||||
fields = [
|
||||
'name', 'description', 'schema', 'comments', 'tags',
|
||||
'name', 'description', 'schema', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class ConfigTemplateImportForm(CSVModelForm):
|
||||
class ConfigTemplateImportForm(OwnerCSVMixin, CSVModelForm):
|
||||
|
||||
class Meta:
|
||||
model = ConfigTemplate
|
||||
fields = (
|
||||
'name', 'description', 'template_code', 'environment_params', 'mime_type', 'file_name', 'file_extension',
|
||||
'as_attachment', 'tags',
|
||||
'as_attachment', 'owner', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class SavedFilterImportForm(CSVModelForm):
|
||||
class SavedFilterImportForm(OwnerCSVMixin, CSVModelForm):
|
||||
object_types = CSVMultipleContentTypeField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.all(),
|
||||
@@ -179,21 +179,21 @@ class SavedFilterImportForm(CSVModelForm):
|
||||
class Meta:
|
||||
model = SavedFilter
|
||||
fields = (
|
||||
'name', 'slug', 'object_types', 'description', 'weight', 'enabled', 'shared', 'parameters',
|
||||
'name', 'slug', 'object_types', 'description', 'weight', 'enabled', 'shared', 'parameters', 'owner',
|
||||
)
|
||||
|
||||
|
||||
class WebhookImportForm(NetBoxModelImportForm):
|
||||
class WebhookImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = Webhook
|
||||
fields = (
|
||||
'name', 'payload_url', 'http_method', 'http_content_type', 'additional_headers', 'body_template',
|
||||
'secret', 'ssl_verification', 'ca_file_path', 'description', 'tags'
|
||||
'secret', 'ssl_verification', 'ca_file_path', 'description', 'owner', 'tags'
|
||||
)
|
||||
|
||||
|
||||
class EventRuleImportForm(NetBoxModelImportForm):
|
||||
class EventRuleImportForm(OwnerCSVMixin, NetBoxModelImportForm):
|
||||
object_types = CSVMultipleContentTypeField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.with_feature('event_rules'),
|
||||
@@ -214,7 +214,7 @@ class EventRuleImportForm(NetBoxModelImportForm):
|
||||
model = EventRule
|
||||
fields = (
|
||||
'name', 'description', 'enabled', 'conditions', 'object_types', 'event_types', 'action_type',
|
||||
'comments', 'tags'
|
||||
'owner', 'comments', 'tags'
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
@@ -242,7 +242,7 @@ class EventRuleImportForm(NetBoxModelImportForm):
|
||||
self.instance.action_object_type = ObjectType.objects.get_for_model(script, for_concrete_model=False)
|
||||
|
||||
|
||||
class TagImportForm(CSVModelForm):
|
||||
class TagImportForm(OwnerCSVMixin, CSVModelForm):
|
||||
slug = SlugField()
|
||||
weight = forms.IntegerField(
|
||||
label=_('Weight'),
|
||||
@@ -258,7 +258,7 @@ class TagImportForm(CSVModelForm):
|
||||
class Meta:
|
||||
model = Tag
|
||||
fields = (
|
||||
'name', 'slug', 'color', 'weight', 'description', 'object_types',
|
||||
'name', 'slug', 'color', 'weight', 'description', 'object_types', 'owner',
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -6,13 +6,14 @@ from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site
|
||||
from extras.choices import *
|
||||
from extras.models import *
|
||||
from netbox.events import get_event_type_choices
|
||||
from netbox.forms.base import NetBoxModelFilterSetForm
|
||||
from netbox.forms import NetBoxModelFilterSetForm, PrimaryModelFilterSetForm
|
||||
from netbox.forms.mixins import SavedFiltersMixin
|
||||
from tenancy.models import Tenant, TenantGroup
|
||||
from users.models import Group, User
|
||||
from users.models import Group, Owner, User
|
||||
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
|
||||
from utilities.forms.fields import (
|
||||
ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField,
|
||||
ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
|
||||
TagFilterField,
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import DateTimePicker
|
||||
@@ -115,6 +116,11 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
|
||||
label=_('Validation regex'),
|
||||
required=False
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class CustomFieldChoiceSetFilterForm(SavedFiltersMixin, FilterForm):
|
||||
@@ -130,6 +136,11 @@ class CustomFieldChoiceSetFilterForm(SavedFiltersMixin, FilterForm):
|
||||
choice = forms.CharField(
|
||||
required=False
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class CustomLinkFilterForm(SavedFiltersMixin, FilterForm):
|
||||
@@ -161,6 +172,11 @@ class CustomLinkFilterForm(SavedFiltersMixin, FilterForm):
|
||||
label=_('Weight'),
|
||||
required=False
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
|
||||
@@ -207,6 +223,11 @@ class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
|
||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||
)
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class ImageAttachmentFilterForm(SavedFiltersMixin, FilterForm):
|
||||
@@ -255,6 +276,11 @@ class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
|
||||
label=_('Weight'),
|
||||
required=False
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class TableConfigFilterForm(SavedFiltersMixin, FilterForm):
|
||||
@@ -290,7 +316,7 @@ class TableConfigFilterForm(SavedFiltersMixin, FilterForm):
|
||||
class WebhookFilterForm(NetBoxModelFilterSetForm):
|
||||
model = Webhook
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('payload_url', 'http_method', 'http_content_type', name=_('Attributes')),
|
||||
)
|
||||
http_content_type = forms.CharField(
|
||||
@@ -306,15 +332,18 @@ class WebhookFilterForm(NetBoxModelFilterSetForm):
|
||||
required=False,
|
||||
label=_('HTTP method')
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class EventRuleFilterForm(NetBoxModelFilterSetForm):
|
||||
model = EventRule
|
||||
tag = TagFilterField(model)
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('object_type_id', 'event_type', 'action_type', 'enabled', name=_('Attributes')),
|
||||
)
|
||||
object_type_id = ContentTypeMultipleChoiceField(
|
||||
@@ -339,6 +368,12 @@ class EventRuleFilterForm(NetBoxModelFilterSetForm):
|
||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||
)
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class TagFilterForm(SavedFiltersMixin, FilterForm):
|
||||
@@ -353,9 +388,14 @@ class TagFilterForm(SavedFiltersMixin, FilterForm):
|
||||
required=False,
|
||||
label=_('Allowed object type')
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class ConfigContextProfileFilterForm(SavedFiltersMixin, FilterForm):
|
||||
class ConfigContextProfileFilterForm(PrimaryModelFilterSetForm):
|
||||
model = ConfigContextProfile
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id'),
|
||||
@@ -470,6 +510,11 @@ class ConfigContextFilterForm(SavedFiltersMixin, FilterForm):
|
||||
required=False,
|
||||
label=_('Tags')
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class ConfigTemplateFilterForm(SavedFiltersMixin, FilterForm):
|
||||
@@ -512,6 +557,11 @@ class ConfigTemplateFilterForm(SavedFiltersMixin, FilterForm):
|
||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||
)
|
||||
)
|
||||
owner_id = DynamicModelChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
required=False,
|
||||
label=_('Owner'),
|
||||
)
|
||||
|
||||
|
||||
class LocalConfigContextFilterForm(forms.Form):
|
||||
|
||||
@@ -12,8 +12,8 @@ from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site
|
||||
from extras.choices import *
|
||||
from extras.models import *
|
||||
from netbox.events import get_event_type_choices
|
||||
from netbox.forms import NetBoxModelForm
|
||||
from netbox.forms.mixins import ChangelogMessageMixin
|
||||
from netbox.forms import NetBoxModelForm, PrimaryModelForm
|
||||
from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin
|
||||
from tenancy.models import Tenant, TenantGroup
|
||||
from users.models import Group, User
|
||||
from utilities.forms import get_field_value
|
||||
@@ -47,7 +47,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class CustomFieldForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
class CustomFieldForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
|
||||
object_types = ContentTypeMultipleChoiceField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.with_feature('custom_fields'),
|
||||
@@ -166,7 +166,7 @@ class CustomFieldForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
del self.fields['choice_set']
|
||||
|
||||
|
||||
class CustomFieldChoiceSetForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
class CustomFieldChoiceSetForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
|
||||
# TODO: The extra_choices field definition diverge from the CustomFieldChoiceSet model
|
||||
extra_choices = forms.CharField(
|
||||
widget=ChoicesWidget(),
|
||||
@@ -179,7 +179,7 @@ class CustomFieldChoiceSetForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = CustomFieldChoiceSet
|
||||
fields = ('name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically')
|
||||
fields = ('name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically', 'owner')
|
||||
|
||||
def __init__(self, *args, initial=None, **kwargs):
|
||||
super().__init__(*args, initial=initial, **kwargs)
|
||||
@@ -219,7 +219,7 @@ class CustomFieldChoiceSetForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
return data
|
||||
|
||||
|
||||
class CustomLinkForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
class CustomLinkForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
|
||||
object_types = ContentTypeMultipleChoiceField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.with_feature('custom_links')
|
||||
@@ -251,7 +251,7 @@ class CustomLinkForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
}
|
||||
|
||||
|
||||
class ExportTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm):
|
||||
class ExportTemplateForm(ChangelogMessageMixin, SyncedDataMixin, OwnerMixin, forms.ModelForm):
|
||||
object_types = ContentTypeMultipleChoiceField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.with_feature('export_templates')
|
||||
@@ -293,7 +293,7 @@ class ExportTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
class SavedFilterForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
class SavedFilterForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
|
||||
slug = SlugField()
|
||||
object_types = ContentTypeMultipleChoiceField(
|
||||
label=_('Object types'),
|
||||
@@ -427,7 +427,7 @@ class SubscriptionForm(forms.ModelForm):
|
||||
fields = ('object_type', 'object_id')
|
||||
|
||||
|
||||
class WebhookForm(NetBoxModelForm):
|
||||
class WebhookForm(OwnerMixin, NetBoxModelForm):
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'description', 'tags', name=_('Webhook')),
|
||||
@@ -447,7 +447,7 @@ class WebhookForm(NetBoxModelForm):
|
||||
}
|
||||
|
||||
|
||||
class EventRuleForm(NetBoxModelForm):
|
||||
class EventRuleForm(OwnerMixin, NetBoxModelForm):
|
||||
object_types = ContentTypeMultipleChoiceField(
|
||||
label=_('Object types'),
|
||||
queryset=ObjectType.objects.with_feature('event_rules'),
|
||||
@@ -480,7 +480,7 @@ class EventRuleForm(NetBoxModelForm):
|
||||
model = EventRule
|
||||
fields = (
|
||||
'object_types', 'name', 'description', 'enabled', 'event_types', 'conditions', 'action_type',
|
||||
'action_object_type', 'action_object_id', 'action_data', 'comments', 'tags'
|
||||
'action_object_type', 'action_object_id', 'action_data', 'owner', 'comments', 'tags'
|
||||
)
|
||||
widgets = {
|
||||
'conditions': forms.Textarea(attrs={'class': 'font-monospace'}),
|
||||
@@ -563,7 +563,7 @@ class EventRuleForm(NetBoxModelForm):
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
class TagForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
class TagForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
|
||||
slug = SlugField()
|
||||
object_types = ContentTypeMultipleChoiceField(
|
||||
label=_('Object types'),
|
||||
@@ -582,11 +582,11 @@ class TagForm(ChangelogMessageMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = Tag
|
||||
fields = [
|
||||
'name', 'slug', 'color', 'weight', 'description', 'object_types',
|
||||
'name', 'slug', 'color', 'weight', 'description', 'object_types', 'owner',
|
||||
]
|
||||
|
||||
|
||||
class ConfigContextProfileForm(SyncedDataMixin, NetBoxModelForm):
|
||||
class ConfigContextProfileForm(SyncedDataMixin, PrimaryModelForm):
|
||||
schema = JSONField(
|
||||
label=_('Schema'),
|
||||
required=False,
|
||||
@@ -606,11 +606,12 @@ class ConfigContextProfileForm(SyncedDataMixin, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = ConfigContextProfile
|
||||
fields = (
|
||||
'name', 'description', 'schema', 'data_source', 'data_file', 'auto_sync_enabled', 'comments', 'tags',
|
||||
'name', 'description', 'schema', 'data_source', 'data_file', 'auto_sync_enabled', 'owner', 'comments',
|
||||
'tags',
|
||||
)
|
||||
|
||||
|
||||
class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm):
|
||||
class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, OwnerMixin, forms.ModelForm):
|
||||
profile = DynamicModelChoiceField(
|
||||
label=_('Profile'),
|
||||
queryset=ConfigContextProfile.objects.all(),
|
||||
@@ -701,7 +702,7 @@ class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm)
|
||||
fields = (
|
||||
'name', 'weight', 'profile', 'description', 'data', 'is_active', 'regions', 'site_groups', 'sites',
|
||||
'locations', 'roles', 'device_types', 'platforms', 'cluster_types', 'cluster_groups', 'clusters',
|
||||
'tenant_groups', 'tenants', 'tags', 'data_source', 'data_file', 'auto_sync_enabled',
|
||||
'tenant_groups', 'tenants', 'owner', 'tags', 'data_source', 'data_file', 'auto_sync_enabled',
|
||||
)
|
||||
|
||||
def __init__(self, *args, initial=None, **kwargs):
|
||||
@@ -727,7 +728,7 @@ class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm)
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
class ConfigTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm):
|
||||
class ConfigTemplateForm(ChangelogMessageMixin, SyncedDataMixin, OwnerMixin, forms.ModelForm):
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
label=_('Tags'),
|
||||
queryset=Tag.objects.all(),
|
||||
|
||||
@@ -6,7 +6,8 @@ import strawberry_django
|
||||
from core.graphql.mixins import SyncedDataMixin
|
||||
from extras import models
|
||||
from extras.graphql.mixins import CustomFieldsMixin, TagsMixin
|
||||
from netbox.graphql.types import BaseObjectType, ContentTypeType, NetBoxObjectType, ObjectType, OrganizationalObjectType
|
||||
from netbox.graphql.types import BaseObjectType, ContentTypeType, ObjectType, PrimaryObjectType
|
||||
from users.graphql.mixins import OwnerMixin
|
||||
from .filters import *
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -51,7 +52,7 @@ __all__ = (
|
||||
filters=ConfigContextProfileFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ConfigContextProfileType(SyncedDataMixin, NetBoxObjectType):
|
||||
class ConfigContextProfileType(SyncedDataMixin, PrimaryObjectType):
|
||||
pass
|
||||
|
||||
|
||||
@@ -61,7 +62,7 @@ class ConfigContextProfileType(SyncedDataMixin, NetBoxObjectType):
|
||||
filters=ConfigContextFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ConfigContextType(SyncedDataMixin, ObjectType):
|
||||
class ConfigContextType(SyncedDataMixin, OwnerMixin, ObjectType):
|
||||
profile: ConfigContextProfileType | None
|
||||
roles: List[Annotated["DeviceRoleType", strawberry.lazy('dcim.graphql.types')]]
|
||||
device_types: List[Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')]]
|
||||
@@ -84,7 +85,7 @@ class ConfigContextType(SyncedDataMixin, ObjectType):
|
||||
filters=ConfigTemplateFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ConfigTemplateType(SyncedDataMixin, TagsMixin, ObjectType):
|
||||
class ConfigTemplateType(SyncedDataMixin, OwnerMixin, TagsMixin, ObjectType):
|
||||
virtualmachines: List[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]]
|
||||
devices: List[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]]
|
||||
platforms: List[Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')]]
|
||||
@@ -97,7 +98,7 @@ class ConfigTemplateType(SyncedDataMixin, TagsMixin, ObjectType):
|
||||
filters=CustomFieldFilter,
|
||||
pagination=True
|
||||
)
|
||||
class CustomFieldType(ObjectType):
|
||||
class CustomFieldType(OwnerMixin, ObjectType):
|
||||
related_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
|
||||
choice_set: Annotated["CustomFieldChoiceSetType", strawberry.lazy('extras.graphql.types')] | None
|
||||
|
||||
@@ -108,7 +109,7 @@ class CustomFieldType(ObjectType):
|
||||
filters=CustomFieldChoiceSetFilter,
|
||||
pagination=True
|
||||
)
|
||||
class CustomFieldChoiceSetType(ObjectType):
|
||||
class CustomFieldChoiceSetType(OwnerMixin, ObjectType):
|
||||
|
||||
choices_for: List[Annotated["CustomFieldType", strawberry.lazy('extras.graphql.types')]]
|
||||
extra_choices: List[List[str]] | None
|
||||
@@ -120,7 +121,7 @@ class CustomFieldChoiceSetType(ObjectType):
|
||||
filters=CustomLinkFilter,
|
||||
pagination=True
|
||||
)
|
||||
class CustomLinkType(ObjectType):
|
||||
class CustomLinkType(OwnerMixin, ObjectType):
|
||||
pass
|
||||
|
||||
|
||||
@@ -130,7 +131,7 @@ class CustomLinkType(ObjectType):
|
||||
filters=ExportTemplateFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ExportTemplateType(SyncedDataMixin, ObjectType):
|
||||
class ExportTemplateType(SyncedDataMixin, OwnerMixin, ObjectType):
|
||||
pass
|
||||
|
||||
|
||||
@@ -180,7 +181,7 @@ class NotificationGroupType(ObjectType):
|
||||
filters=SavedFilterFilter,
|
||||
pagination=True
|
||||
)
|
||||
class SavedFilterType(ObjectType):
|
||||
class SavedFilterType(OwnerMixin, ObjectType):
|
||||
user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
|
||||
|
||||
|
||||
@@ -209,7 +210,7 @@ class TableConfigType(ObjectType):
|
||||
filters=TagFilter,
|
||||
pagination=True
|
||||
)
|
||||
class TagType(ObjectType):
|
||||
class TagType(OwnerMixin, ObjectType):
|
||||
color: str
|
||||
|
||||
object_types: List[ContentTypeType]
|
||||
@@ -221,7 +222,7 @@ class TagType(ObjectType):
|
||||
filters=WebhookFilter,
|
||||
pagination=True
|
||||
)
|
||||
class WebhookType(OrganizationalObjectType):
|
||||
class WebhookType(OwnerMixin, CustomFieldsMixin, TagsMixin, ObjectType):
|
||||
pass
|
||||
|
||||
|
||||
@@ -231,5 +232,5 @@ class WebhookType(OrganizationalObjectType):
|
||||
filters=EventRuleFilter,
|
||||
pagination=True
|
||||
)
|
||||
class EventRuleType(OrganizationalObjectType):
|
||||
class EventRuleType(OwnerMixin, CustomFieldsMixin, TagsMixin, ObjectType):
|
||||
action_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
|
||||
|
||||
89
netbox/extras/migrations/0134_owner.py
Normal file
89
netbox/extras/migrations/0134_owner.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('extras', '0133_make_cf_minmax_decimal'),
|
||||
('users', '0015_owner'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='configcontext',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='configcontextprofile',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='configtemplate',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customfield',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customfieldchoiceset',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customlink',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventrule',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exporttemplate',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='savedfilter',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tag',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='webhook',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -13,6 +13,7 @@ from extras.models.mixins import RenderTemplateMixin
|
||||
from extras.querysets import ConfigContextQuerySet
|
||||
from netbox.models import ChangeLoggedModel, PrimaryModel
|
||||
from netbox.models.features import CloningMixin, CustomLinksMixin, ExportTemplatesMixin, SyncedDataMixin, TagsMixin
|
||||
from netbox.models.mixins import OwnerMixin
|
||||
from utilities.data import deepmerge
|
||||
from utilities.jsonschema import validate_schema
|
||||
|
||||
@@ -68,7 +69,7 @@ class ConfigContextProfile(SyncedDataMixin, PrimaryModel):
|
||||
sync_data.alters_data = True
|
||||
|
||||
|
||||
class ConfigContext(SyncedDataMixin, CloningMixin, CustomLinksMixin, ChangeLoggedModel):
|
||||
class ConfigContext(SyncedDataMixin, CloningMixin, CustomLinksMixin, OwnerMixin, ChangeLoggedModel):
|
||||
"""
|
||||
A ConfigContext represents a set of arbitrary data available to any Device or VirtualMachine matching its assigned
|
||||
qualifiers (region, site, etc.). For example, the data stored in a ConfigContext assigned to site A and tenant B
|
||||
@@ -266,7 +267,13 @@ class ConfigContextModel(models.Model):
|
||||
#
|
||||
|
||||
class ConfigTemplate(
|
||||
RenderTemplateMixin, SyncedDataMixin, CustomLinksMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel
|
||||
RenderTemplateMixin,
|
||||
SyncedDataMixin,
|
||||
CustomLinksMixin,
|
||||
ExportTemplatesMixin,
|
||||
OwnerMixin,
|
||||
TagsMixin,
|
||||
ChangeLoggedModel,
|
||||
):
|
||||
name = models.CharField(
|
||||
verbose_name=_('name'),
|
||||
|
||||
@@ -21,6 +21,7 @@ from extras.choices import *
|
||||
from extras.data import CHOICE_SETS
|
||||
from netbox.models import ChangeLoggedModel
|
||||
from netbox.models.features import CloningMixin, ExportTemplatesMixin
|
||||
from netbox.models.mixins import OwnerMixin
|
||||
from netbox.search import FieldTypes
|
||||
from utilities import filters
|
||||
from utilities.datetime import datetime_from_timestamp
|
||||
@@ -70,7 +71,7 @@ class CustomFieldManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
||||
}
|
||||
|
||||
|
||||
class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
|
||||
class CustomField(CloningMixin, ExportTemplatesMixin, OwnerMixin, ChangeLoggedModel):
|
||||
object_types = models.ManyToManyField(
|
||||
to='contenttypes.ContentType',
|
||||
related_name='custom_fields',
|
||||
@@ -773,7 +774,7 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
|
||||
raise ValidationError(_("Required field cannot be empty."))
|
||||
|
||||
|
||||
class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
|
||||
class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, OwnerMixin, ChangeLoggedModel):
|
||||
"""
|
||||
Represents a set of choices available for choice and multi-choice custom fields.
|
||||
"""
|
||||
|
||||
@@ -25,6 +25,7 @@ from netbox.models import ChangeLoggedModel
|
||||
from netbox.models.features import (
|
||||
CloningMixin, CustomFieldsMixin, CustomLinksMixin, ExportTemplatesMixin, SyncedDataMixin, TagsMixin, has_feature
|
||||
)
|
||||
from netbox.models.mixins import OwnerMixin
|
||||
from utilities.html import clean_html
|
||||
from utilities.jinja2 import render_jinja2
|
||||
from utilities.querydict import dict_to_querydict
|
||||
@@ -44,7 +45,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel):
|
||||
class EventRule(CustomFieldsMixin, ExportTemplatesMixin, OwnerMixin, TagsMixin, ChangeLoggedModel):
|
||||
"""
|
||||
An EventRule defines an action to be taken automatically in response to a specific set of events, such as when a
|
||||
specific type of object is created, modified, or deleted. The action to be taken might entail transmitting a
|
||||
@@ -155,7 +156,7 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
|
||||
return False
|
||||
|
||||
|
||||
class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel):
|
||||
class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, OwnerMixin, ChangeLoggedModel):
|
||||
"""
|
||||
A Webhook defines a request that will be sent to a remote application when an object is created, updated, and/or
|
||||
delete in NetBox. The request will contain a representation of the object, which the remote application can act on.
|
||||
@@ -294,7 +295,7 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedMo
|
||||
return render_jinja2(self.payload_url, context)
|
||||
|
||||
|
||||
class CustomLink(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
|
||||
class CustomLink(CloningMixin, ExportTemplatesMixin, OwnerMixin, ChangeLoggedModel):
|
||||
"""
|
||||
A custom link to an external representation of a NetBox object. The link text and URL fields accept Jinja2 template
|
||||
code to be rendered with an object as context.
|
||||
@@ -394,7 +395,14 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
|
||||
}
|
||||
|
||||
|
||||
class ExportTemplate(SyncedDataMixin, CloningMixin, ExportTemplatesMixin, ChangeLoggedModel, RenderTemplateMixin):
|
||||
class ExportTemplate(
|
||||
SyncedDataMixin,
|
||||
CloningMixin,
|
||||
ExportTemplatesMixin,
|
||||
OwnerMixin,
|
||||
ChangeLoggedModel,
|
||||
RenderTemplateMixin,
|
||||
):
|
||||
object_types = models.ManyToManyField(
|
||||
to='contenttypes.ContentType',
|
||||
related_name='export_templates',
|
||||
@@ -456,7 +464,7 @@ class ExportTemplate(SyncedDataMixin, CloningMixin, ExportTemplatesMixin, Change
|
||||
return _context
|
||||
|
||||
|
||||
class SavedFilter(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
|
||||
class SavedFilter(CloningMixin, ExportTemplatesMixin, OwnerMixin, ChangeLoggedModel):
|
||||
"""
|
||||
A set of predefined keyword parameters that can be reused to filter for specific objects.
|
||||
"""
|
||||
|
||||
@@ -8,6 +8,7 @@ from taggit.models import TagBase, GenericTaggedItemBase
|
||||
from netbox.choices import ColorChoices
|
||||
from netbox.models import ChangeLoggedModel
|
||||
from netbox.models.features import CloningMixin, ExportTemplatesMixin
|
||||
from netbox.models.mixins import OwnerMixin
|
||||
from utilities.fields import ColorField
|
||||
from utilities.querysets import RestrictedQuerySet
|
||||
|
||||
@@ -21,7 +22,7 @@ __all__ = (
|
||||
# Tags
|
||||
#
|
||||
|
||||
class Tag(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel, TagBase):
|
||||
class Tag(CloningMixin, ExportTemplatesMixin, OwnerMixin, ChangeLoggedModel, TagBase):
|
||||
id = models.BigAutoField(
|
||||
primary_key=True
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ from core.tables import JobTable
|
||||
from core.models import Job
|
||||
from netbox.constants import EMPTY_TABLE_TEXT
|
||||
from netbox.events import get_event_text
|
||||
from netbox.tables import BaseTable, NetBoxTable, columns
|
||||
from netbox.tables import BaseTable, NetBoxTable, PrimaryModelTable, columns
|
||||
from .columns import NotificationActionsColumn
|
||||
|
||||
__all__ = (
|
||||
@@ -109,6 +109,10 @@ class CustomFieldTable(NetBoxTable):
|
||||
validation_regex = tables.Column(
|
||||
verbose_name=_('Validation Regex'),
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = CustomField
|
||||
@@ -146,6 +150,10 @@ class CustomFieldChoiceSetTable(NetBoxTable):
|
||||
verbose_name=_('Order Alphabetically'),
|
||||
false_mark=None
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = CustomFieldChoiceSet
|
||||
@@ -171,6 +179,10 @@ class CustomLinkTable(NetBoxTable):
|
||||
verbose_name=_('New Window'),
|
||||
false_mark=None
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = CustomLink
|
||||
@@ -214,6 +226,10 @@ class ExportTemplateTable(NetBoxTable):
|
||||
orderable=False,
|
||||
verbose_name=_('Synced')
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = ExportTemplate
|
||||
@@ -294,6 +310,10 @@ class SavedFilterTable(NetBoxTable):
|
||||
verbose_name=_('Shared'),
|
||||
false_mark=None
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
|
||||
def value_parameters(self, value):
|
||||
return json.dumps(value)
|
||||
@@ -450,6 +470,10 @@ class WebhookTable(NetBoxTable):
|
||||
ssl_validation = columns.BooleanColumn(
|
||||
verbose_name=_('SSL Validation')
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='extras:webhook_list'
|
||||
)
|
||||
@@ -488,6 +512,10 @@ class EventRuleTable(NetBoxTable):
|
||||
func=get_event_text,
|
||||
orderable=False
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='extras:webhook_list'
|
||||
)
|
||||
@@ -514,6 +542,10 @@ class TagTable(NetBoxTable):
|
||||
object_types = columns.ContentTypesColumn(
|
||||
verbose_name=_('Object Types'),
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Tag
|
||||
@@ -547,7 +579,7 @@ class TaggedItemTable(NetBoxTable):
|
||||
fields = ('id', 'content_type', 'content_object')
|
||||
|
||||
|
||||
class ConfigContextProfileTable(NetBoxTable):
|
||||
class ConfigContextProfileTable(PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -568,7 +600,7 @@ class ConfigContextProfileTable(NetBoxTable):
|
||||
url_name='extras:configcontextprofile_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = ConfigContextProfile
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'description', 'comments', 'data_source', 'data_file', 'is_synced', 'tags', 'created',
|
||||
@@ -601,6 +633,10 @@ class ConfigContextTable(NetBoxTable):
|
||||
orderable=False,
|
||||
verbose_name=_('Synced')
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='extras:configcontext_list'
|
||||
)
|
||||
@@ -645,6 +681,10 @@ class ConfigTemplateTable(NetBoxTable):
|
||||
verbose_name=_('As Attachment'),
|
||||
false_mark=None
|
||||
)
|
||||
owner = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Owner')
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='extras:configtemplate_list'
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ from rest_framework import serializers
|
||||
|
||||
from ipam.models import ASN, ASNRange, RIR
|
||||
from netbox.api.fields import RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import OrganizationalModelSerializer, PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
|
||||
__all__ = (
|
||||
@@ -13,7 +13,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class RIRSerializer(NetBoxModelSerializer):
|
||||
class RIRSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
aggregate_count = RelatedObjectCountField('aggregates')
|
||||
@@ -21,13 +21,13 @@ class RIRSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = RIR
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'is_private', 'description', 'tags',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'is_private', 'description', 'owner', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'aggregate_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'aggregate_count')
|
||||
|
||||
|
||||
class ASNRangeSerializer(NetBoxModelSerializer):
|
||||
class ASNRangeSerializer(OrganizationalModelSerializer):
|
||||
rir = RIRSerializer(nested=True)
|
||||
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
||||
asn_count = serializers.IntegerField(read_only=True)
|
||||
@@ -36,12 +36,12 @@ class ASNRangeSerializer(NetBoxModelSerializer):
|
||||
model = ASNRange
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'rir', 'start', 'end', 'tenant', 'description',
|
||||
'tags', 'custom_fields', 'created', 'last_updated', 'asn_count',
|
||||
'owner', 'tags', 'custom_fields', 'created', 'last_updated', 'asn_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
|
||||
class ASNSerializer(NetBoxModelSerializer):
|
||||
class ASNSerializer(PrimaryModelSerializer):
|
||||
rir = RIRSerializer(nested=True, required=False, allow_null=True)
|
||||
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
||||
|
||||
@@ -52,7 +52,7 @@ class ASNSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = ASN
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'asn', 'rir', 'tenant', 'description', 'comments', 'tags',
|
||||
'id', 'url', 'display_url', 'display', 'asn', 'rir', 'tenant', 'description', 'owner', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'site_count', 'provider_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'asn', 'description')
|
||||
|
||||
@@ -4,7 +4,7 @@ from rest_framework import serializers
|
||||
|
||||
from ipam.models import FHRPGroup, FHRPGroupAssignment
|
||||
from netbox.api.fields import ContentTypeField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import NetBoxModelSerializer, PrimaryModelSerializer
|
||||
from utilities.api import get_serializer_for_model
|
||||
from .ip import IPAddressSerializer
|
||||
|
||||
@@ -14,14 +14,14 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class FHRPGroupSerializer(NetBoxModelSerializer):
|
||||
class FHRPGroupSerializer(PrimaryModelSerializer):
|
||||
ip_addresses = IPAddressSerializer(nested=True, many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = FHRPGroup
|
||||
fields = [
|
||||
'id', 'name', 'url', 'display_url', 'display', 'protocol', 'group_id', 'auth_type', 'auth_key',
|
||||
'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'ip_addresses',
|
||||
'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'ip_addresses',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'protocol', 'group_id', 'description')
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from ipam.choices import *
|
||||
from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS
|
||||
from ipam.models import Aggregate, IPAddress, IPRange, Prefix
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from utilities.api import get_serializer_for_model
|
||||
from .asns import RIRSerializer
|
||||
@@ -28,7 +28,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class AggregateSerializer(NetBoxModelSerializer):
|
||||
class AggregateSerializer(PrimaryModelSerializer):
|
||||
family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
|
||||
rir = RIRSerializer(nested=True)
|
||||
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
||||
@@ -38,12 +38,12 @@ class AggregateSerializer(NetBoxModelSerializer):
|
||||
model = Aggregate
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'family', 'prefix', 'rir', 'tenant', 'date_added', 'description',
|
||||
'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'description')
|
||||
|
||||
|
||||
class PrefixSerializer(NetBoxModelSerializer):
|
||||
class PrefixSerializer(PrimaryModelSerializer):
|
||||
family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
|
||||
vrf = VRFSerializer(nested=True, required=False, allow_null=True)
|
||||
scope_type = ContentTypeField(
|
||||
@@ -68,7 +68,7 @@ class PrefixSerializer(NetBoxModelSerializer):
|
||||
model = Prefix
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'family', 'prefix', 'vrf', 'scope_type', 'scope_id', 'scope',
|
||||
'tenant', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'description', 'comments', 'tags',
|
||||
'tenant', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'description', 'owner', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'children', '_depth',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'description', '_depth')
|
||||
@@ -133,7 +133,7 @@ class AvailablePrefixSerializer(serializers.Serializer):
|
||||
# IP ranges
|
||||
#
|
||||
|
||||
class IPRangeSerializer(NetBoxModelSerializer):
|
||||
class IPRangeSerializer(PrimaryModelSerializer):
|
||||
family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
|
||||
start_address = IPAddressField()
|
||||
end_address = IPAddressField()
|
||||
@@ -146,7 +146,7 @@ class IPRangeSerializer(NetBoxModelSerializer):
|
||||
model = IPRange
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'family', 'start_address', 'end_address', 'size', 'vrf', 'tenant',
|
||||
'status', 'role', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'status', 'role', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'mark_populated', 'mark_utilized',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'family', 'start_address', 'end_address', 'description')
|
||||
@@ -156,7 +156,7 @@ class IPRangeSerializer(NetBoxModelSerializer):
|
||||
# IP addresses
|
||||
#
|
||||
|
||||
class IPAddressSerializer(NetBoxModelSerializer):
|
||||
class IPAddressSerializer(PrimaryModelSerializer):
|
||||
family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
|
||||
address = IPAddressField()
|
||||
vrf = VRFSerializer(nested=True, required=False, allow_null=True)
|
||||
@@ -177,7 +177,7 @@ class IPAddressSerializer(NetBoxModelSerializer):
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'family', 'address', 'vrf', 'tenant', 'status', 'role',
|
||||
'assigned_object_type', 'assigned_object_id', 'assigned_object', 'nat_inside', 'nat_outside',
|
||||
'dns_name', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'dns_name', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'family', 'address', 'description')
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
from ipam.models import Role
|
||||
from netbox.api.fields import RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import OrganizationalModelSerializer
|
||||
|
||||
__all__ = (
|
||||
'RoleSerializer',
|
||||
)
|
||||
|
||||
|
||||
class RoleSerializer(NetBoxModelSerializer):
|
||||
class RoleSerializer(OrganizationalModelSerializer):
|
||||
|
||||
# Related object counts
|
||||
prefix_count = RelatedObjectCountField('prefixes')
|
||||
@@ -16,7 +16,7 @@ class RoleSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'weight', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'prefix_count', 'vlan_count',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'weight', 'description', 'owner', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'prefix_count', 'vlan_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'prefix_count', 'vlan_count')
|
||||
|
||||
@@ -6,7 +6,7 @@ from ipam.choices import *
|
||||
from ipam.constants import SERVICE_ASSIGNMENT_MODELS
|
||||
from ipam.models import IPAddress, Service, ServiceTemplate
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from utilities.api import get_serializer_for_model
|
||||
from .ip import IPAddressSerializer
|
||||
|
||||
@@ -16,19 +16,19 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ServiceTemplateSerializer(NetBoxModelSerializer):
|
||||
class ServiceTemplateSerializer(PrimaryModelSerializer):
|
||||
protocol = ChoiceField(choices=ServiceProtocolChoices, required=False)
|
||||
|
||||
class Meta:
|
||||
model = ServiceTemplate
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'protocol', 'ports', 'description', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'protocol', 'ports', 'description', 'owner', 'comments',
|
||||
'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'protocol', 'ports', 'description')
|
||||
|
||||
|
||||
class ServiceSerializer(NetBoxModelSerializer):
|
||||
class ServiceSerializer(PrimaryModelSerializer):
|
||||
protocol = ChoiceField(choices=ServiceProtocolChoices, required=False)
|
||||
ipaddresses = SerializedPKRelatedField(
|
||||
queryset=IPAddress.objects.all(),
|
||||
@@ -46,7 +46,7 @@ class ServiceSerializer(NetBoxModelSerializer):
|
||||
model = Service
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'parent_object_type', 'parent_object_id', 'parent', 'name',
|
||||
'protocol', 'ports', 'ipaddresses', 'description', 'comments', 'tags', 'custom_fields',
|
||||
'protocol', 'ports', 'ipaddresses', 'description', 'owner', 'comments', 'tags', 'custom_fields',
|
||||
'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'protocol', 'ports', 'description')
|
||||
|
||||
@@ -7,7 +7,7 @@ from ipam.choices import *
|
||||
from ipam.constants import VLANGROUP_SCOPE_TYPES
|
||||
from ipam.models import VLAN, VLANGroup, VLANTranslationPolicy, VLANTranslationRule
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField, IntegerRangeSerializer, RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
from utilities.api import get_serializer_for_model
|
||||
from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer
|
||||
@@ -24,7 +24,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class VLANGroupSerializer(NetBoxModelSerializer):
|
||||
class VLANGroupSerializer(OrganizationalModelSerializer):
|
||||
scope_type = ContentTypeField(
|
||||
queryset=ContentType.objects.filter(
|
||||
model__in=VLANGROUP_SCOPE_TYPES
|
||||
@@ -46,7 +46,8 @@ class VLANGroupSerializer(NetBoxModelSerializer):
|
||||
model = VLANGroup
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'scope_type', 'scope_id', 'scope', 'vid_ranges',
|
||||
'tenant', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'vlan_count', 'utilization'
|
||||
'tenant', 'description', 'owner', 'tags', 'custom_fields', 'created', 'last_updated', 'vlan_count',
|
||||
'utilization',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'vlan_count')
|
||||
validators = []
|
||||
@@ -60,7 +61,7 @@ class VLANGroupSerializer(NetBoxModelSerializer):
|
||||
return serializer(obj.scope, nested=True, context=context).data
|
||||
|
||||
|
||||
class VLANSerializer(NetBoxModelSerializer):
|
||||
class VLANSerializer(PrimaryModelSerializer):
|
||||
site = SiteSerializer(nested=True, required=False, allow_null=True)
|
||||
group = VLANGroupSerializer(nested=True, required=False, allow_null=True, default=None)
|
||||
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
||||
@@ -77,7 +78,7 @@ class VLANSerializer(NetBoxModelSerializer):
|
||||
model = VLAN
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role',
|
||||
'description', 'qinq_role', 'qinq_svlan', 'comments', 'l2vpn_termination', 'tags', 'custom_fields',
|
||||
'description', 'qinq_role', 'qinq_svlan', 'owner', 'comments', 'l2vpn_termination', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'prefix_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'vid', 'name', 'description')
|
||||
@@ -125,10 +126,10 @@ class VLANTranslationRuleSerializer(NetBoxModelSerializer):
|
||||
fields = ['id', 'url', 'display', 'policy', 'local_vid', 'remote_vid', 'description']
|
||||
|
||||
|
||||
class VLANTranslationPolicySerializer(NetBoxModelSerializer):
|
||||
class VLANTranslationPolicySerializer(PrimaryModelSerializer):
|
||||
rules = VLANTranslationRuleSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = VLANTranslationPolicy
|
||||
fields = ['id', 'url', 'display', 'name', 'description', 'display', 'rules']
|
||||
fields = ['id', 'url', 'display', 'name', 'description', 'display', 'rules', 'owner', 'comments']
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from ipam.models import RouteTarget, VRF
|
||||
from netbox.api.fields import RelatedObjectCountField, SerializedPKRelatedField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from tenancy.api.serializers_.tenants import TenantSerializer
|
||||
|
||||
__all__ = (
|
||||
@@ -9,19 +9,19 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class RouteTargetSerializer(NetBoxModelSerializer):
|
||||
class RouteTargetSerializer(PrimaryModelSerializer):
|
||||
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = RouteTarget
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'tenant', 'description', 'comments', 'tags',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'tenant', 'description', 'owner', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
|
||||
|
||||
class VRFSerializer(NetBoxModelSerializer):
|
||||
class VRFSerializer(PrimaryModelSerializer):
|
||||
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
||||
import_targets = SerializedPKRelatedField(
|
||||
queryset=RouteTarget.objects.all(),
|
||||
@@ -43,8 +43,8 @@ class VRFSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = VRF
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'comments',
|
||||
'import_targets', 'export_targets', 'tags', 'custom_fields', 'created', 'last_updated', 'ipaddress_count',
|
||||
'prefix_count',
|
||||
'id', 'url', 'display_url', 'display', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'owner',
|
||||
'comments', 'import_targets', 'export_targets', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'ipaddress_count', 'prefix_count',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'rd', 'description', 'prefix_count')
|
||||
|
||||
@@ -11,7 +11,9 @@ from netaddr.core import AddrFormatError
|
||||
|
||||
from circuits.models import Provider
|
||||
from dcim.models import Device, Interface, Region, Site, SiteGroup
|
||||
from netbox.filtersets import ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet
|
||||
from netbox.filtersets import (
|
||||
ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet, PrimaryModelFilterSet,
|
||||
)
|
||||
from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet
|
||||
|
||||
from utilities.filters import (
|
||||
@@ -45,7 +47,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class VRFFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
class VRFFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
|
||||
import_target_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='import_targets',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
@@ -83,7 +85,7 @@ class VRFFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
fields = ('id', 'name', 'rd', 'enforce_unique', 'description')
|
||||
|
||||
|
||||
class RouteTargetFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
class RouteTargetFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
|
||||
importing_vrf_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='importing_vrfs',
|
||||
queryset=VRF.objects.all(),
|
||||
@@ -149,7 +151,7 @@ class RIRFilterSet(OrganizationalModelFilterSet):
|
||||
fields = ('id', 'name', 'slug', 'is_private', 'description')
|
||||
|
||||
|
||||
class AggregateFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
class AggregateFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
family = django_filters.NumberFilter(
|
||||
field_name='prefix',
|
||||
lookup_expr='family'
|
||||
@@ -221,7 +223,7 @@ class ASNRangeFilterSet(OrganizationalModelFilterSet, TenancyFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class ASNFilterSet(OrganizationalModelFilterSet, TenancyFilterSet):
|
||||
class ASNFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
|
||||
rir_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=RIR.objects.all(),
|
||||
label=_('RIR (ID)'),
|
||||
@@ -290,7 +292,7 @@ class RoleFilterSet(OrganizationalModelFilterSet):
|
||||
fields = ('id', 'name', 'slug', 'description', 'weight')
|
||||
|
||||
|
||||
class PrefixFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
class PrefixFilterSet(PrimaryModelFilterSet, ScopedFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
family = django_filters.NumberFilter(
|
||||
field_name='prefix',
|
||||
lookup_expr='family'
|
||||
@@ -456,7 +458,7 @@ class PrefixFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet, C
|
||||
).distinct()
|
||||
|
||||
|
||||
class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
class IPRangeFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
family = django_filters.NumberFilter(
|
||||
field_name='start_address',
|
||||
lookup_expr='family'
|
||||
@@ -548,7 +550,7 @@ class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet, ContactModelFilte
|
||||
return queryset.filter(q)
|
||||
|
||||
|
||||
class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
class IPAddressFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
family = django_filters.NumberFilter(
|
||||
field_name='address',
|
||||
lookup_expr='family'
|
||||
@@ -784,7 +786,7 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFil
|
||||
)
|
||||
|
||||
|
||||
class FHRPGroupFilterSet(NetBoxModelFilterSet):
|
||||
class FHRPGroupFilterSet(PrimaryModelFilterSet):
|
||||
protocol = django_filters.MultipleChoiceFilter(
|
||||
choices=FHRPGroupProtocolChoices
|
||||
)
|
||||
@@ -934,7 +936,7 @@ class VLANGroupFilterSet(OrganizationalModelFilterSet, TenancyFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
class VLANFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
|
||||
region_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
@@ -1085,7 +1087,7 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
).distinct()
|
||||
|
||||
|
||||
class VLANTranslationPolicyFilterSet(NetBoxModelFilterSet):
|
||||
class VLANTranslationPolicyFilterSet(PrimaryModelFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = VLANTranslationPolicy
|
||||
@@ -1132,7 +1134,7 @@ class VLANTranslationRuleFilterSet(NetBoxModelFilterSet):
|
||||
return queryset.filter(qs_filter)
|
||||
|
||||
|
||||
class ServiceTemplateFilterSet(NetBoxModelFilterSet):
|
||||
class ServiceTemplateFilterSet(PrimaryModelFilterSet):
|
||||
port = NumericArrayFilter(
|
||||
field_name='ports',
|
||||
lookup_expr='contains'
|
||||
@@ -1152,7 +1154,7 @@ class ServiceTemplateFilterSet(NetBoxModelFilterSet):
|
||||
return queryset.filter(qs_filter)
|
||||
|
||||
|
||||
class ServiceFilterSet(ContactModelFilterSet, NetBoxModelFilterSet):
|
||||
class ServiceFilterSet(ContactModelFilterSet, PrimaryModelFilterSet):
|
||||
parent_object_type = ContentTypeFilter()
|
||||
device = MultiValueCharFilter(
|
||||
method='filter_device',
|
||||
|
||||
@@ -9,11 +9,11 @@ from ipam.choices import *
|
||||
from ipam.constants import *
|
||||
from ipam.models import *
|
||||
from ipam.models import ASN
|
||||
from netbox.forms import NetBoxModelBulkEditForm
|
||||
from netbox.forms import NetBoxModelBulkEditForm, OrganizationalModelBulkEditForm, PrimaryModelBulkEditForm
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms import add_blank_choice, get_field_value
|
||||
from utilities.forms.fields import (
|
||||
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
|
||||
ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
|
||||
NumericRangeArrayField,
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet
|
||||
@@ -41,7 +41,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class VRFBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VRFBulkEditForm(PrimaryModelBulkEditForm):
|
||||
tenant = DynamicModelChoiceField(
|
||||
label=_('Tenant'),
|
||||
queryset=Tenant.objects.all(),
|
||||
@@ -52,12 +52,6 @@ class VRFBulkEditForm(NetBoxModelBulkEditForm):
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label=_('Enforce unique space')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = VRF
|
||||
fieldsets = (
|
||||
@@ -66,18 +60,12 @@ class VRFBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('tenant', 'description', 'comments')
|
||||
|
||||
|
||||
class RouteTargetBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class RouteTargetBulkEditForm(PrimaryModelBulkEditForm):
|
||||
tenant = DynamicModelChoiceField(
|
||||
label=_('Tenant'),
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = RouteTarget
|
||||
fieldsets = (
|
||||
@@ -86,17 +74,12 @@ class RouteTargetBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('tenant', 'description', 'comments')
|
||||
|
||||
|
||||
class RIRBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class RIRBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
is_private = forms.NullBooleanField(
|
||||
label=_('Is private'),
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
model = RIR
|
||||
fieldsets = (
|
||||
@@ -105,7 +88,7 @@ class RIRBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('is_private', 'description')
|
||||
|
||||
|
||||
class ASNRangeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ASNRangeBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
required=False,
|
||||
@@ -116,11 +99,6 @@ class ASNRangeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
model = ASNRange
|
||||
fieldsets = (
|
||||
@@ -129,7 +107,7 @@ class ASNRangeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('description',)
|
||||
|
||||
|
||||
class ASNBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ASNBulkEditForm(PrimaryModelBulkEditForm):
|
||||
sites = DynamicModelMultipleChoiceField(
|
||||
label=_('Sites'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -145,12 +123,6 @@ class ASNBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = ASN
|
||||
fieldsets = (
|
||||
@@ -159,7 +131,7 @@ class ASNBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('tenant', 'description', 'comments')
|
||||
|
||||
|
||||
class AggregateBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class AggregateBulkEditForm(PrimaryModelBulkEditForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
required=False,
|
||||
@@ -174,12 +146,6 @@ class AggregateBulkEditForm(NetBoxModelBulkEditForm):
|
||||
label=_('Date added'),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Aggregate
|
||||
fieldsets = (
|
||||
@@ -188,16 +154,11 @@ class AggregateBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('date_added', 'description', 'comments')
|
||||
|
||||
|
||||
class RoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class RoleBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
weight = forms.IntegerField(
|
||||
label=_('Weight'),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
model = Role
|
||||
fieldsets = (
|
||||
@@ -206,7 +167,7 @@ class RoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('description',)
|
||||
|
||||
|
||||
class PrefixBulkEditForm(ScopedBulkEditForm, NetBoxModelBulkEditForm):
|
||||
class PrefixBulkEditForm(ScopedBulkEditForm, PrimaryModelBulkEditForm):
|
||||
vlan_group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
@@ -256,12 +217,6 @@ class PrefixBulkEditForm(ScopedBulkEditForm, NetBoxModelBulkEditForm):
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label=_('Treat as fully utilized')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = Prefix
|
||||
fieldsets = (
|
||||
@@ -275,7 +230,7 @@ class PrefixBulkEditForm(ScopedBulkEditForm, NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class IPRangeBulkEditForm(PrimaryModelBulkEditForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
@@ -306,12 +261,6 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label=_('Treat as fully utilized')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = IPRange
|
||||
fieldsets = (
|
||||
@@ -322,7 +271,7 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class IPAddressBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class IPAddressBulkEditForm(PrimaryModelBulkEditForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
@@ -354,12 +303,6 @@ class IPAddressBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
label=_('DNS name')
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = IPAddress
|
||||
fieldsets = (
|
||||
@@ -371,7 +314,7 @@ class IPAddressBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class FHRPGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class FHRPGroupBulkEditForm(PrimaryModelBulkEditForm):
|
||||
protocol = forms.ChoiceField(
|
||||
label=_('Protocol'),
|
||||
choices=add_blank_choice(FHRPGroupProtocolChoices),
|
||||
@@ -397,12 +340,6 @@ class FHRPGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
max_length=100,
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = FHRPGroup
|
||||
fieldsets = (
|
||||
@@ -412,12 +349,7 @@ class FHRPGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('auth_type', 'auth_key', 'name', 'description', 'comments')
|
||||
|
||||
|
||||
class VLANGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
class VLANGroupBulkEditForm(OrganizationalModelBulkEditForm):
|
||||
scope_type = ContentTypeChoiceField(
|
||||
queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES),
|
||||
widget=HTMXSelect(method='post', attrs={'hx-select': '#form_fields'}),
|
||||
@@ -464,7 +396,7 @@ class VLANGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
pass
|
||||
|
||||
|
||||
class VLANBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class VLANBulkEditForm(PrimaryModelBulkEditForm):
|
||||
region = DynamicModelChoiceField(
|
||||
label=_('Region'),
|
||||
queryset=Region.objects.all(),
|
||||
@@ -507,11 +439,6 @@ class VLANBulkEditForm(NetBoxModelBulkEditForm):
|
||||
queryset=Role.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
qinq_role = forms.ChoiceField(
|
||||
label=_('Q-in-Q role'),
|
||||
choices=add_blank_choice(VLANQinQRoleChoices),
|
||||
@@ -525,7 +452,6 @@ class VLANBulkEditForm(NetBoxModelBulkEditForm):
|
||||
'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE,
|
||||
}
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = VLAN
|
||||
fieldsets = (
|
||||
@@ -538,13 +464,7 @@ class VLANBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
|
||||
class VLANTranslationPolicyBulkEditForm(NetBoxModelBulkEditForm):
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
class VLANTranslationPolicyBulkEditForm(PrimaryModelBulkEditForm):
|
||||
model = VLANTranslationPolicy
|
||||
fieldsets = (
|
||||
FieldSet('description'),
|
||||
@@ -568,7 +488,7 @@ class VLANTranslationRuleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
fields = ('policy', 'local_vid', 'remote_vid')
|
||||
|
||||
|
||||
class ServiceTemplateBulkEditForm(NetBoxModelBulkEditForm):
|
||||
class ServiceTemplateBulkEditForm(PrimaryModelBulkEditForm):
|
||||
protocol = forms.ChoiceField(
|
||||
label=_('Protocol'),
|
||||
choices=add_blank_choice(ServiceProtocolChoices),
|
||||
@@ -582,12 +502,6 @@ class ServiceTemplateBulkEditForm(NetBoxModelBulkEditForm):
|
||||
),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = ServiceTemplate
|
||||
fieldsets = (
|
||||
|
||||
@@ -7,7 +7,7 @@ from dcim.forms.mixins import ScopedImportForm
|
||||
from ipam.choices import *
|
||||
from ipam.constants import *
|
||||
from ipam.models import *
|
||||
from netbox.forms import NetBoxModelImportForm
|
||||
from netbox.forms import NetBoxModelImportForm, OrganizationalModelImportForm, PrimaryModelImportForm
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms.fields import (
|
||||
CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVModelMultipleChoiceField, SlugField,
|
||||
@@ -36,7 +36,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class VRFImportForm(NetBoxModelImportForm):
|
||||
class VRFImportForm(PrimaryModelImportForm):
|
||||
tenant = CSVModelChoiceField(
|
||||
label=_('Tenant'),
|
||||
queryset=Tenant.objects.all(),
|
||||
@@ -60,12 +60,12 @@ class VRFImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = VRF
|
||||
fields = (
|
||||
'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'comments',
|
||||
'tags',
|
||||
'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'owner',
|
||||
'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class RouteTargetImportForm(NetBoxModelImportForm):
|
||||
class RouteTargetImportForm(PrimaryModelImportForm):
|
||||
tenant = CSVModelChoiceField(
|
||||
label=_('Tenant'),
|
||||
queryset=Tenant.objects.all(),
|
||||
@@ -76,18 +76,18 @@ class RouteTargetImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = RouteTarget
|
||||
fields = ('name', 'tenant', 'description', 'comments', 'tags')
|
||||
fields = ('name', 'tenant', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class RIRImportForm(NetBoxModelImportForm):
|
||||
class RIRImportForm(OrganizationalModelImportForm):
|
||||
slug = SlugField()
|
||||
|
||||
class Meta:
|
||||
model = RIR
|
||||
fields = ('name', 'slug', 'is_private', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'is_private', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class AggregateImportForm(NetBoxModelImportForm):
|
||||
class AggregateImportForm(PrimaryModelImportForm):
|
||||
rir = CSVModelChoiceField(
|
||||
label=_('RIR'),
|
||||
queryset=RIR.objects.all(),
|
||||
@@ -104,10 +104,10 @@ class AggregateImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = Aggregate
|
||||
fields = ('prefix', 'rir', 'tenant', 'date_added', 'description', 'comments', 'tags')
|
||||
fields = ('prefix', 'rir', 'tenant', 'date_added', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class ASNRangeImportForm(NetBoxModelImportForm):
|
||||
class ASNRangeImportForm(OrganizationalModelImportForm):
|
||||
rir = CSVModelChoiceField(
|
||||
label=_('RIR'),
|
||||
queryset=RIR.objects.all(),
|
||||
@@ -124,10 +124,10 @@ class ASNRangeImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ASNRange
|
||||
fields = ('name', 'slug', 'rir', 'start', 'end', 'tenant', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'rir', 'start', 'end', 'tenant', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class ASNImportForm(NetBoxModelImportForm):
|
||||
class ASNImportForm(PrimaryModelImportForm):
|
||||
rir = CSVModelChoiceField(
|
||||
label=_('RIR'),
|
||||
queryset=RIR.objects.all(),
|
||||
@@ -144,18 +144,17 @@ class ASNImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ASN
|
||||
fields = ('asn', 'rir', 'tenant', 'description', 'comments', 'tags')
|
||||
fields = ('asn', 'rir', 'tenant', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class RoleImportForm(NetBoxModelImportForm):
|
||||
slug = SlugField()
|
||||
class RoleImportForm(OrganizationalModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = ('name', 'slug', 'weight', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'weight', 'description', 'owner', 'tags')
|
||||
|
||||
|
||||
class PrefixImportForm(ScopedImportForm, NetBoxModelImportForm):
|
||||
class PrefixImportForm(ScopedImportForm, PrimaryModelImportForm):
|
||||
vrf = CSVModelChoiceField(
|
||||
label=_('VRF'),
|
||||
queryset=VRF.objects.all(),
|
||||
@@ -208,7 +207,7 @@ class PrefixImportForm(ScopedImportForm, NetBoxModelImportForm):
|
||||
model = Prefix
|
||||
fields = (
|
||||
'prefix', 'vrf', 'tenant', 'vlan_group', 'vlan_site', 'vlan', 'status', 'role', 'scope_type', 'scope_id',
|
||||
'is_pool', 'mark_utilized', 'description', 'comments', 'tags',
|
||||
'is_pool', 'mark_utilized', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
labels = {
|
||||
'scope_id': _('Scope ID'),
|
||||
@@ -244,7 +243,7 @@ class PrefixImportForm(ScopedImportForm, NetBoxModelImportForm):
|
||||
self.fields['vlan'].queryset = queryset
|
||||
|
||||
|
||||
class IPRangeImportForm(NetBoxModelImportForm):
|
||||
class IPRangeImportForm(PrimaryModelImportForm):
|
||||
vrf = CSVModelChoiceField(
|
||||
label=_('VRF'),
|
||||
queryset=VRF.objects.all(),
|
||||
@@ -276,11 +275,11 @@ class IPRangeImportForm(NetBoxModelImportForm):
|
||||
model = IPRange
|
||||
fields = (
|
||||
'start_address', 'end_address', 'vrf', 'tenant', 'status', 'role', 'mark_populated', 'mark_utilized',
|
||||
'description', 'comments', 'tags',
|
||||
'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class IPAddressImportForm(NetBoxModelImportForm):
|
||||
class IPAddressImportForm(PrimaryModelImportForm):
|
||||
vrf = CSVModelChoiceField(
|
||||
label=_('VRF'),
|
||||
queryset=VRF.objects.all(),
|
||||
@@ -349,7 +348,7 @@ class IPAddressImportForm(NetBoxModelImportForm):
|
||||
model = IPAddress
|
||||
fields = [
|
||||
'address', 'vrf', 'tenant', 'status', 'role', 'device', 'virtual_machine', 'interface', 'fhrp_group',
|
||||
'is_primary', 'is_oob', 'dns_name', 'description', 'comments', 'tags',
|
||||
'is_primary', 'is_oob', 'dns_name', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
@@ -428,7 +427,7 @@ class IPAddressImportForm(NetBoxModelImportForm):
|
||||
return ipaddress
|
||||
|
||||
|
||||
class FHRPGroupImportForm(NetBoxModelImportForm):
|
||||
class FHRPGroupImportForm(PrimaryModelImportForm):
|
||||
protocol = CSVChoiceField(
|
||||
label=_('Protocol'),
|
||||
choices=FHRPGroupProtocolChoices
|
||||
@@ -441,11 +440,10 @@ class FHRPGroupImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = FHRPGroup
|
||||
fields = ('protocol', 'group_id', 'auth_type', 'auth_key', 'name', 'description', 'comments', 'tags')
|
||||
fields = ('protocol', 'group_id', 'auth_type', 'auth_key', 'name', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class VLANGroupImportForm(NetBoxModelImportForm):
|
||||
slug = SlugField()
|
||||
class VLANGroupImportForm(OrganizationalModelImportForm):
|
||||
scope_type = CSVContentTypeField(
|
||||
queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES),
|
||||
required=False,
|
||||
@@ -464,13 +462,13 @@ class VLANGroupImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = VLANGroup
|
||||
fields = ('name', 'slug', 'scope_type', 'scope_id', 'vid_ranges', 'tenant', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'scope_type', 'scope_id', 'vid_ranges', 'tenant', 'description', 'owner', 'tags')
|
||||
labels = {
|
||||
'scope_id': 'Scope ID',
|
||||
}
|
||||
|
||||
|
||||
class VLANImportForm(NetBoxModelImportForm):
|
||||
class VLANImportForm(PrimaryModelImportForm):
|
||||
site = CSVModelChoiceField(
|
||||
label=_('Site'),
|
||||
queryset=Site.objects.all(),
|
||||
@@ -522,15 +520,15 @@ class VLANImportForm(NetBoxModelImportForm):
|
||||
model = VLAN
|
||||
fields = (
|
||||
'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'qinq_role', 'qinq_svlan',
|
||||
'comments', 'tags',
|
||||
'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class VLANTranslationPolicyImportForm(NetBoxModelImportForm):
|
||||
class VLANTranslationPolicyImportForm(PrimaryModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = VLANTranslationPolicy
|
||||
fields = ('name', 'description', 'tags')
|
||||
fields = ('name', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class VLANTranslationRuleImportForm(NetBoxModelImportForm):
|
||||
@@ -546,7 +544,7 @@ class VLANTranslationRuleImportForm(NetBoxModelImportForm):
|
||||
fields = ('policy', 'local_vid', 'remote_vid')
|
||||
|
||||
|
||||
class ServiceTemplateImportForm(NetBoxModelImportForm):
|
||||
class ServiceTemplateImportForm(PrimaryModelImportForm):
|
||||
protocol = CSVChoiceField(
|
||||
label=_('Protocol'),
|
||||
choices=ServiceProtocolChoices,
|
||||
@@ -555,10 +553,10 @@ class ServiceTemplateImportForm(NetBoxModelImportForm):
|
||||
|
||||
class Meta:
|
||||
model = ServiceTemplate
|
||||
fields = ('name', 'protocol', 'ports', 'description', 'comments', 'tags')
|
||||
fields = ('name', 'protocol', 'ports', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class ServiceImportForm(NetBoxModelImportForm):
|
||||
class ServiceImportForm(PrimaryModelImportForm):
|
||||
parent_object_type = CSVContentTypeField(
|
||||
queryset=ContentType.objects.filter(SERVICE_ASSIGNMENT_MODELS),
|
||||
required=True,
|
||||
@@ -590,7 +588,7 @@ class ServiceImportForm(NetBoxModelImportForm):
|
||||
class Meta:
|
||||
model = Service
|
||||
fields = (
|
||||
'ipaddresses', 'name', 'protocol', 'ports', 'description', 'comments', 'tags',
|
||||
'ipaddresses', 'name', 'protocol', 'ports', 'description', 'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
def __init__(self, data=None, *args, **kwargs):
|
||||
|
||||
@@ -5,7 +5,7 @@ from dcim.models import Location, Rack, Region, Site, SiteGroup, Device
|
||||
from ipam.choices import *
|
||||
from ipam.constants import *
|
||||
from ipam.models import *
|
||||
from netbox.forms import NetBoxModelFilterSetForm
|
||||
from netbox.forms import NetBoxModelFilterSetForm, OrganizationalModelFilterSetForm, PrimaryModelFilterSetForm
|
||||
from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
|
||||
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, add_blank_choice
|
||||
from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, TagFilterField
|
||||
@@ -42,10 +42,10 @@ IPADDRESS_MASK_LENGTH_CHOICES = add_blank_choice([
|
||||
])
|
||||
|
||||
|
||||
class VRFFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class VRFFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = VRF
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('import_target_id', 'export_target_id', name=_('Route Targets')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
@@ -62,10 +62,10 @@ class VRFFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class RouteTargetFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class RouteTargetFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = RouteTarget
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('importing_vrf_id', 'exporting_vrf_id', name=_('VRF')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
@@ -82,8 +82,12 @@ class RouteTargetFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class RIRFilterForm(NetBoxModelFilterSetForm):
|
||||
class RIRFilterForm(OrganizationalModelFilterSetForm):
|
||||
model = RIR
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('is_private', name=_('RIR')),
|
||||
)
|
||||
is_private = forms.NullBooleanField(
|
||||
required=False,
|
||||
label=_('Private'),
|
||||
@@ -94,10 +98,10 @@ class RIRFilterForm(NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class AggregateFilterForm(ContactModelFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class AggregateFilterForm(ContactModelFilterForm, TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = Aggregate
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('family', 'rir_id', name=_('Attributes')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
@@ -115,10 +119,10 @@ class AggregateFilterForm(ContactModelFilterForm, TenancyFilterForm, NetBoxModel
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class ASNRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class ASNRangeFilterForm(TenancyFilterForm, OrganizationalModelFilterSetForm):
|
||||
model = ASNRange
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('rir_id', 'start', 'end', name=_('Range')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
@@ -138,10 +142,10 @@ class ASNRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class ASNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class ASNFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = ASN
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('rir_id', 'site_group_id', 'site_id', name=_('Assignment')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
@@ -163,15 +167,18 @@ class ASNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class RoleFilterForm(NetBoxModelFilterSetForm):
|
||||
class RoleFilterForm(OrganizationalModelFilterSetForm):
|
||||
model = Role
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class PrefixFilterForm(ContactModelFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm, ):
|
||||
class PrefixFilterForm(ContactModelFilterForm, TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = Prefix
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet(
|
||||
'within_include', 'family', 'status', 'role_id', 'mask_length', 'is_pool', 'mark_utilized',
|
||||
name=_('Addressing')
|
||||
@@ -274,10 +281,10 @@ class PrefixFilterForm(ContactModelFilterForm, TenancyFilterForm, NetBoxModelFil
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class IPRangeFilterForm(ContactModelFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class IPRangeFilterForm(ContactModelFilterForm, TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = IPRange
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('family', 'vrf_id', 'status', 'role_id', 'mark_populated', 'mark_utilized', name=_('Attributes')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
@@ -321,10 +328,10 @@ class IPRangeFilterForm(ContactModelFilterForm, TenancyFilterForm, NetBoxModelFi
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class IPAddressFilterForm(ContactModelFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class IPAddressFilterForm(ContactModelFilterForm, TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = IPAddress
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet(
|
||||
'parent', 'family', 'status', 'role', 'mask_length', 'assigned_to_interface', 'dns_name',
|
||||
name=_('Attributes')
|
||||
@@ -399,10 +406,10 @@ class IPAddressFilterForm(ContactModelFilterForm, TenancyFilterForm, NetBoxModel
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class FHRPGroupFilterForm(NetBoxModelFilterSetForm):
|
||||
class FHRPGroupFilterForm(PrimaryModelFilterSetForm):
|
||||
model = FHRPGroup
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', 'protocol', 'group_id', name=_('Attributes')),
|
||||
FieldSet('auth_type', 'auth_key', name=_('Authentication')),
|
||||
)
|
||||
@@ -432,9 +439,9 @@ class FHRPGroupFilterForm(NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class VLANGroupFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class VLANGroupFilterForm(TenancyFilterForm, OrganizationalModelFilterSetForm):
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region', 'site_group', 'site', 'location', 'rack', name=_('Location')),
|
||||
FieldSet('cluster_group', 'cluster', name=_('Cluster')),
|
||||
FieldSet('contains_vid', name=_('VLANs')),
|
||||
@@ -485,10 +492,10 @@ class VLANGroupFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class VLANTranslationPolicyFilterForm(NetBoxModelFilterSetForm):
|
||||
class VLANTranslationPolicyFilterForm(PrimaryModelFilterSetForm):
|
||||
model = VLANTranslationPolicy
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('name', name=_('Attributes')),
|
||||
)
|
||||
name = forms.CharField(
|
||||
@@ -522,10 +529,10 @@ class VLANTranslationRuleFilterForm(NetBoxModelFilterSetForm):
|
||||
)
|
||||
|
||||
|
||||
class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
class VLANFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
model = VLAN
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')),
|
||||
FieldSet('group_id', 'status', 'role_id', 'vid', 'l2vpn_id', name=_('Attributes')),
|
||||
FieldSet('qinq_role', 'qinq_svlan_id', name=_('Q-in-Q/802.1ad')),
|
||||
@@ -594,10 +601,10 @@ class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class ServiceTemplateFilterForm(NetBoxModelFilterSetForm):
|
||||
class ServiceTemplateFilterForm(PrimaryModelFilterSetForm):
|
||||
model = ServiceTemplate
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('protocol', 'port', name=_('Attributes')),
|
||||
)
|
||||
protocol = forms.ChoiceField(
|
||||
@@ -615,7 +622,7 @@ class ServiceTemplateFilterForm(NetBoxModelFilterSetForm):
|
||||
class ServiceFilterForm(ContactModelFilterForm, ServiceTemplateFilterForm):
|
||||
model = Service
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('q', 'filter_id', 'tag', 'owner_id'),
|
||||
FieldSet('protocol', 'port', name=_('Attributes')),
|
||||
FieldSet('device_id', 'virtual_machine_id', 'fhrpgroup_id', name=_('Assignment')),
|
||||
FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
|
||||
|
||||
@@ -9,13 +9,13 @@ from ipam.choices import *
|
||||
from ipam.constants import *
|
||||
from ipam.formfields import IPNetworkFormField
|
||||
from ipam.models import *
|
||||
from netbox.forms import NetBoxModelForm
|
||||
from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
|
||||
from tenancy.forms import TenancyForm
|
||||
from utilities.exceptions import PermissionsViolation
|
||||
from utilities.forms import add_blank_choice
|
||||
from utilities.forms.fields import (
|
||||
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
|
||||
NumericRangeArrayField, SlugField
|
||||
ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
|
||||
NumericRangeArrayField,
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups
|
||||
from utilities.forms.utils import get_field_value
|
||||
@@ -49,7 +49,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class VRFForm(TenancyForm, NetBoxModelForm):
|
||||
class VRFForm(TenancyForm, PrimaryModelForm):
|
||||
import_targets = DynamicModelMultipleChoiceField(
|
||||
label=_('Import targets'),
|
||||
queryset=RouteTarget.objects.all(),
|
||||
@@ -60,7 +60,6 @@ class VRFForm(TenancyForm, NetBoxModelForm):
|
||||
queryset=RouteTarget.objects.all(),
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'rd', 'enforce_unique', 'description', 'tags', name=_('VRF')),
|
||||
@@ -72,30 +71,27 @@ class VRFForm(TenancyForm, NetBoxModelForm):
|
||||
model = VRF
|
||||
fields = [
|
||||
'name', 'rd', 'enforce_unique', 'import_targets', 'export_targets', 'tenant_group', 'tenant', 'description',
|
||||
'comments', 'tags',
|
||||
'owner', 'comments', 'tags',
|
||||
]
|
||||
labels = {
|
||||
'rd': "RD",
|
||||
}
|
||||
|
||||
|
||||
class RouteTargetForm(TenancyForm, NetBoxModelForm):
|
||||
class RouteTargetForm(TenancyForm, PrimaryModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'description', 'tags', name=_('Route Target')),
|
||||
FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
class Meta:
|
||||
model = RouteTarget
|
||||
fields = [
|
||||
'name', 'tenant_group', 'tenant', 'description', 'comments', 'tags',
|
||||
'name', 'tenant_group', 'tenant', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class RIRForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class RIRForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'is_private', 'description', 'tags', name=_('RIR')),
|
||||
)
|
||||
@@ -103,17 +99,16 @@ class RIRForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = RIR
|
||||
fields = [
|
||||
'name', 'slug', 'is_private', 'description', 'tags',
|
||||
'name', 'slug', 'is_private', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class AggregateForm(TenancyForm, NetBoxModelForm):
|
||||
class AggregateForm(TenancyForm, PrimaryModelForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
label=_('RIR'),
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('prefix', 'rir', 'date_added', 'description', 'tags', name=_('Aggregate')),
|
||||
@@ -123,20 +118,19 @@ class AggregateForm(TenancyForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Aggregate
|
||||
fields = [
|
||||
'prefix', 'rir', 'date_added', 'tenant_group', 'tenant', 'description', 'comments', 'tags',
|
||||
'prefix', 'rir', 'date_added', 'tenant_group', 'tenant', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'date_added': DatePicker(),
|
||||
}
|
||||
|
||||
|
||||
class ASNRangeForm(TenancyForm, NetBoxModelForm):
|
||||
class ASNRangeForm(TenancyForm, OrganizationalModelForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
label=_('RIR'),
|
||||
quick_add=True
|
||||
)
|
||||
slug = SlugField()
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'rir', 'start', 'end', 'description', 'tags', name=_('ASN Range')),
|
||||
FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
|
||||
@@ -145,11 +139,11 @@ class ASNRangeForm(TenancyForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = ASNRange
|
||||
fields = [
|
||||
'name', 'slug', 'rir', 'start', 'end', 'tenant_group', 'tenant', 'description', 'tags'
|
||||
'name', 'slug', 'rir', 'start', 'end', 'tenant_group', 'tenant', 'owner', 'description', 'tags'
|
||||
]
|
||||
|
||||
|
||||
class ASNForm(TenancyForm, NetBoxModelForm):
|
||||
class ASNForm(TenancyForm, PrimaryModelForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
label=_('RIR'),
|
||||
@@ -160,7 +154,6 @@ class ASNForm(TenancyForm, NetBoxModelForm):
|
||||
label=_('Sites'),
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('asn', 'rir', 'sites', 'description', 'tags', name=_('ASN')),
|
||||
@@ -170,7 +163,7 @@ class ASNForm(TenancyForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = ASN
|
||||
fields = [
|
||||
'asn', 'rir', 'sites', 'tenant_group', 'tenant', 'description', 'comments', 'tags'
|
||||
'asn', 'rir', 'sites', 'tenant_group', 'tenant', 'description', 'owner', 'comments', 'tags'
|
||||
]
|
||||
widgets = {
|
||||
'date_added': DatePicker(),
|
||||
@@ -188,9 +181,7 @@ class ASNForm(TenancyForm, NetBoxModelForm):
|
||||
return instance
|
||||
|
||||
|
||||
class RoleForm(NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
|
||||
class RoleForm(OrganizationalModelForm):
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'weight', 'description', 'tags', name=_('Role')),
|
||||
)
|
||||
@@ -198,11 +189,11 @@ class RoleForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = [
|
||||
'name', 'slug', 'weight', 'description', 'tags',
|
||||
'name', 'slug', 'weight', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm):
|
||||
class PrefixForm(TenancyForm, ScopedForm, PrimaryModelForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
@@ -223,7 +214,6 @@ class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm):
|
||||
required=False,
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -238,7 +228,7 @@ class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm):
|
||||
model = Prefix
|
||||
fields = [
|
||||
'prefix', 'vrf', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'scope_type', 'tenant_group',
|
||||
'tenant', 'description', 'comments', 'tags',
|
||||
'tenant', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -250,7 +240,7 @@ class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm):
|
||||
self.fields['vlan'].widget.attrs.pop('data-dynamic-params', None)
|
||||
|
||||
|
||||
class IPRangeForm(TenancyForm, NetBoxModelForm):
|
||||
class IPRangeForm(TenancyForm, PrimaryModelForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
@@ -262,7 +252,6 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
|
||||
required=False,
|
||||
quick_add=True
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -276,11 +265,11 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
|
||||
model = IPRange
|
||||
fields = [
|
||||
'vrf', 'start_address', 'end_address', 'status', 'role', 'tenant_group', 'tenant', 'mark_populated',
|
||||
'mark_utilized', 'description', 'comments', 'tags',
|
||||
'mark_utilized', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
class IPAddressForm(TenancyForm, PrimaryModelForm):
|
||||
interface = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
@@ -324,7 +313,6 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
required=False,
|
||||
label=_('Make this the out-of-band IP for the device')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('address', 'status', 'role', 'vrf', 'dns_name', 'description', 'tags', name=_('IP Address')),
|
||||
@@ -344,7 +332,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
model = IPAddress
|
||||
fields = [
|
||||
'address', 'vrf', 'status', 'role', 'dns_name', 'primary_for_parent', 'oob_for_parent', 'nat_inside',
|
||||
'tenant_group', 'tenant', 'description', 'comments', 'tags',
|
||||
'tenant_group', 'tenant', 'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -494,7 +482,7 @@ class IPAddressAssignForm(forms.Form):
|
||||
)
|
||||
|
||||
|
||||
class FHRPGroupForm(NetBoxModelForm):
|
||||
class FHRPGroupForm(PrimaryModelForm):
|
||||
|
||||
# Optionally create a new IPAddress along with the FHRPGroup
|
||||
ip_vrf = DynamicModelChoiceField(
|
||||
@@ -511,7 +499,6 @@ class FHRPGroupForm(NetBoxModelForm):
|
||||
required=False,
|
||||
label=_('Status')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('protocol', 'group_id', 'name', 'description', 'tags', name=_('FHRP Group')),
|
||||
@@ -523,7 +510,7 @@ class FHRPGroupForm(NetBoxModelForm):
|
||||
model = FHRPGroup
|
||||
fields = (
|
||||
'protocol', 'group_id', 'auth_type', 'auth_key', 'name', 'ip_vrf', 'ip_address', 'ip_status', 'description',
|
||||
'comments', 'tags',
|
||||
'owner', 'comments', 'tags',
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
@@ -599,8 +586,7 @@ class FHRPGroupAssignmentForm(forms.ModelForm):
|
||||
return group
|
||||
|
||||
|
||||
class VLANGroupForm(TenancyForm, NetBoxModelForm):
|
||||
slug = SlugField()
|
||||
class VLANGroupForm(TenancyForm, OrganizationalModelForm):
|
||||
vid_ranges = NumericRangeArrayField(
|
||||
label=_('VLAN IDs')
|
||||
)
|
||||
@@ -628,7 +614,7 @@ class VLANGroupForm(TenancyForm, NetBoxModelForm):
|
||||
class Meta:
|
||||
model = VLANGroup
|
||||
fields = [
|
||||
'name', 'slug', 'description', 'vid_ranges', 'scope_type', 'tenant_group', 'tenant', 'tags',
|
||||
'name', 'slug', 'description', 'vid_ranges', 'scope_type', 'tenant_group', 'tenant', 'owner', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -662,7 +648,7 @@ class VLANGroupForm(TenancyForm, NetBoxModelForm):
|
||||
self.instance.scope = self.cleaned_data.get('scope')
|
||||
|
||||
|
||||
class VLANForm(TenancyForm, NetBoxModelForm):
|
||||
class VLANForm(TenancyForm, PrimaryModelForm):
|
||||
group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
@@ -698,17 +684,16 @@ class VLANForm(TenancyForm, NetBoxModelForm):
|
||||
'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE,
|
||||
}
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
class Meta:
|
||||
model = VLAN
|
||||
fields = [
|
||||
'site', 'group', 'vid', 'name', 'status', 'role', 'tenant_group', 'tenant', 'qinq_role', 'qinq_svlan',
|
||||
'description', 'comments', 'tags',
|
||||
'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class VLANTranslationPolicyForm(NetBoxModelForm):
|
||||
class VLANTranslationPolicyForm(PrimaryModelForm):
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'description', 'tags', name=_('VLAN Translation Policy')),
|
||||
@@ -717,7 +702,7 @@ class VLANTranslationPolicyForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = VLANTranslationPolicy
|
||||
fields = [
|
||||
'name', 'description', 'tags',
|
||||
'name', 'description', 'owner', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -739,7 +724,7 @@ class VLANTranslationRuleForm(NetBoxModelForm):
|
||||
]
|
||||
|
||||
|
||||
class ServiceTemplateForm(NetBoxModelForm):
|
||||
class ServiceTemplateForm(PrimaryModelForm):
|
||||
ports = NumericArrayField(
|
||||
label=_('Ports'),
|
||||
base_field=forms.IntegerField(
|
||||
@@ -748,7 +733,6 @@ class ServiceTemplateForm(NetBoxModelForm):
|
||||
),
|
||||
help_text=_("Comma-separated list of one or more port numbers. A range may be specified using a hyphen.")
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'protocol', 'ports', 'description', 'tags', name=_('Application Service Template')),
|
||||
@@ -756,10 +740,10 @@ class ServiceTemplateForm(NetBoxModelForm):
|
||||
|
||||
class Meta:
|
||||
model = ServiceTemplate
|
||||
fields = ('name', 'protocol', 'ports', 'description', 'comments', 'tags')
|
||||
fields = ('name', 'protocol', 'ports', 'description', 'owner', 'comments', 'tags')
|
||||
|
||||
|
||||
class ServiceForm(NetBoxModelForm):
|
||||
class ServiceForm(PrimaryModelForm):
|
||||
parent_object_type = ContentTypeChoiceField(
|
||||
queryset=ContentType.objects.filter(SERVICE_ASSIGNMENT_MODELS),
|
||||
widget=HTMXSelect(),
|
||||
@@ -786,7 +770,6 @@ class ServiceForm(NetBoxModelForm):
|
||||
required=False,
|
||||
label=_('IP Addresses'),
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet(
|
||||
@@ -799,7 +782,7 @@ class ServiceForm(NetBoxModelForm):
|
||||
class Meta:
|
||||
model = Service
|
||||
fields = [
|
||||
'name', 'protocol', 'ports', 'ipaddresses', 'description', 'comments', 'tags',
|
||||
'name', 'protocol', 'ports', 'ipaddresses', 'description', 'owner', 'comments', 'tags',
|
||||
'parent_object_type',
|
||||
]
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from dcim.graphql.types import SiteType
|
||||
from extras.graphql.mixins import ContactsMixin
|
||||
from ipam import models
|
||||
from netbox.graphql.scalars import BigInt
|
||||
from netbox.graphql.types import BaseObjectType, NetBoxObjectType, OrganizationalObjectType
|
||||
from netbox.graphql.types import BaseObjectType, NetBoxObjectType, OrganizationalObjectType, PrimaryObjectType
|
||||
from .filters import *
|
||||
from .mixins import IPAddressesMixin
|
||||
|
||||
@@ -74,7 +74,7 @@ class BaseIPAddressFamilyType:
|
||||
filters=ASNFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ASNType(NetBoxObjectType, ContactsMixin):
|
||||
class ASNType(ContactsMixin, PrimaryObjectType):
|
||||
asn: BigInt
|
||||
rir: Annotated["RIRType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -89,7 +89,7 @@ class ASNType(NetBoxObjectType, ContactsMixin):
|
||||
filters=ASNRangeFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ASNRangeType(NetBoxObjectType):
|
||||
class ASNRangeType(OrganizationalObjectType):
|
||||
start: BigInt
|
||||
end: BigInt
|
||||
rir: Annotated["RIRType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
@@ -102,7 +102,7 @@ class ASNRangeType(NetBoxObjectType):
|
||||
filters=AggregateFilter,
|
||||
pagination=True
|
||||
)
|
||||
class AggregateType(NetBoxObjectType, ContactsMixin, BaseIPAddressFamilyType):
|
||||
class AggregateType(ContactsMixin, BaseIPAddressFamilyType, PrimaryObjectType):
|
||||
prefix: str
|
||||
rir: Annotated["RIRType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -114,8 +114,7 @@ class AggregateType(NetBoxObjectType, ContactsMixin, BaseIPAddressFamilyType):
|
||||
filters=FHRPGroupFilter,
|
||||
pagination=True
|
||||
)
|
||||
class FHRPGroupType(NetBoxObjectType, IPAddressesMixin):
|
||||
|
||||
class FHRPGroupType(IPAddressesMixin, PrimaryObjectType):
|
||||
fhrpgroupassignment_set: List[Annotated["FHRPGroupAssignmentType", strawberry.lazy('ipam.graphql.types')]]
|
||||
|
||||
|
||||
@@ -142,7 +141,7 @@ class FHRPGroupAssignmentType(BaseObjectType):
|
||||
filters=IPAddressFilter,
|
||||
pagination=True
|
||||
)
|
||||
class IPAddressType(NetBoxObjectType, ContactsMixin, BaseIPAddressFamilyType):
|
||||
class IPAddressType(ContactsMixin, BaseIPAddressFamilyType, PrimaryObjectType):
|
||||
address: str
|
||||
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -167,7 +166,7 @@ class IPAddressType(NetBoxObjectType, ContactsMixin, BaseIPAddressFamilyType):
|
||||
filters=IPRangeFilter,
|
||||
pagination=True
|
||||
)
|
||||
class IPRangeType(NetBoxObjectType, ContactsMixin):
|
||||
class IPRangeType(ContactsMixin, PrimaryObjectType):
|
||||
start_address: str
|
||||
end_address: str
|
||||
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
@@ -181,7 +180,7 @@ class IPRangeType(NetBoxObjectType, ContactsMixin):
|
||||
filters=PrefixFilter,
|
||||
pagination=True
|
||||
)
|
||||
class PrefixType(NetBoxObjectType, ContactsMixin, BaseIPAddressFamilyType):
|
||||
class PrefixType(ContactsMixin, BaseIPAddressFamilyType, PrimaryObjectType):
|
||||
prefix: str
|
||||
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -230,7 +229,7 @@ class RoleType(OrganizationalObjectType):
|
||||
filters=RouteTargetFilter,
|
||||
pagination=True
|
||||
)
|
||||
class RouteTargetType(NetBoxObjectType):
|
||||
class RouteTargetType(PrimaryObjectType):
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
|
||||
importing_l2vpns: List[Annotated["L2VPNType", strawberry.lazy('vpn.graphql.types')]]
|
||||
@@ -245,7 +244,7 @@ class RouteTargetType(NetBoxObjectType):
|
||||
filters=ServiceFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ServiceType(NetBoxObjectType, ContactsMixin):
|
||||
class ServiceType(ContactsMixin, PrimaryObjectType):
|
||||
ports: List[int]
|
||||
ipaddresses: List[Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')]]
|
||||
|
||||
@@ -264,7 +263,7 @@ class ServiceType(NetBoxObjectType, ContactsMixin):
|
||||
filters=ServiceTemplateFilter,
|
||||
pagination=True
|
||||
)
|
||||
class ServiceTemplateType(NetBoxObjectType):
|
||||
class ServiceTemplateType(PrimaryObjectType):
|
||||
ports: List[int]
|
||||
|
||||
|
||||
@@ -274,7 +273,7 @@ class ServiceTemplateType(NetBoxObjectType):
|
||||
filters=VLANFilter,
|
||||
pagination=True
|
||||
)
|
||||
class VLANType(NetBoxObjectType):
|
||||
class VLANType(PrimaryObjectType):
|
||||
site: Annotated["SiteType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
group: Annotated["VLANGroupType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
@@ -323,7 +322,7 @@ class VLANGroupType(OrganizationalObjectType):
|
||||
filters=VLANTranslationPolicyFilter,
|
||||
pagination=True
|
||||
)
|
||||
class VLANTranslationPolicyType(NetBoxObjectType):
|
||||
class VLANTranslationPolicyType(PrimaryObjectType):
|
||||
rules: List[Annotated["VLANTranslationRuleType", strawberry.lazy('ipam.graphql.types')]]
|
||||
|
||||
|
||||
@@ -346,7 +345,7 @@ class VLANTranslationRuleType(NetBoxObjectType):
|
||||
filters=VRFFilter,
|
||||
pagination=True
|
||||
)
|
||||
class VRFType(NetBoxObjectType):
|
||||
class VRFType(PrimaryObjectType):
|
||||
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
|
||||
|
||||
interfaces: List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]
|
||||
|
||||
124
netbox/ipam/migrations/0083_owner.py
Normal file
124
netbox/ipam/migrations/0083_owner.py
Normal file
@@ -0,0 +1,124 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('ipam', '0082_add_prefix_network_containment_indexes'),
|
||||
('users', '0015_owner'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='aggregate',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asn',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asnrange',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='fhrpgroup',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ipaddress',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='iprange',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='prefix',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rir',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='routetarget',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='service',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='servicetemplate',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vlan',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vlangroup',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vlantranslationpolicy',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vrf',
|
||||
name='owner',
|
||||
field=models.ForeignKey(
|
||||
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='users.owner'
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
|
||||
__all__ = (
|
||||
@@ -11,7 +11,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ASNRangeTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class ASNRangeTable(TenancyColumnsMixin, OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -27,7 +27,7 @@ class ASNRangeTable(TenancyColumnsMixin, NetBoxTable):
|
||||
verbose_name=_('ASNs')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = ASNRange
|
||||
fields = (
|
||||
'pk', 'name', 'slug', 'rir', 'start', 'end', 'asn_count', 'tenant', 'tenant_group', 'description', 'tags',
|
||||
@@ -36,7 +36,7 @@ class ASNRangeTable(TenancyColumnsMixin, NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'rir', 'start', 'end', 'tenant', 'asn_count', 'description')
|
||||
|
||||
|
||||
class ASNTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class ASNTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
asn = tables.Column(
|
||||
verbose_name=_('ASN'),
|
||||
linkify=True
|
||||
@@ -65,14 +65,11 @@ class ASNTable(TenancyColumnsMixin, NetBoxTable):
|
||||
linkify_item=True,
|
||||
verbose_name=_('Sites')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:asn_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = ASN
|
||||
fields = (
|
||||
'pk', 'asn', 'asn_asdot', 'rir', 'site_count', 'provider_count', 'tenant', 'tenant_group', 'description',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import NetBoxTable, PrimaryModelTable, columns
|
||||
|
||||
__all__ = (
|
||||
'FHRPGroupTable',
|
||||
@@ -17,7 +17,7 @@ IPADDRESSES = """
|
||||
"""
|
||||
|
||||
|
||||
class FHRPGroupTable(NetBoxTable):
|
||||
class FHRPGroupTable(PrimaryModelTable):
|
||||
group_id = tables.Column(
|
||||
verbose_name=_('Group ID'),
|
||||
linkify=True
|
||||
@@ -30,9 +30,6 @@ class FHRPGroupTable(NetBoxTable):
|
||||
member_count = tables.Column(
|
||||
verbose_name=_('Members')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:fhrpgroup_list'
|
||||
)
|
||||
@@ -40,7 +37,7 @@ class FHRPGroupTable(NetBoxTable):
|
||||
def value_ip_addresses(self, value):
|
||||
return ",".join([str(obj.address) for obj in value.all()])
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = FHRPGroup
|
||||
fields = (
|
||||
'pk', 'group_id', 'protocol', 'name', 'auth_type', 'auth_key', 'description', 'comments', 'ip_addresses',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_tables2.utils import Accessor
|
||||
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import TenancyColumnsMixin, TenantColumn
|
||||
from .template_code import *
|
||||
|
||||
@@ -27,7 +27,7 @@ AVAILABLE_LABEL = mark_safe('<span class="badge text-bg-success">Available</span
|
||||
# RIRs
|
||||
#
|
||||
|
||||
class RIRTable(NetBoxTable):
|
||||
class RIRTable(OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -45,7 +45,7 @@ class RIRTable(NetBoxTable):
|
||||
url_name='ipam:rir_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = RIR
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'slug', 'is_private', 'aggregate_count', 'description', 'tags', 'created',
|
||||
@@ -58,7 +58,7 @@ class RIRTable(NetBoxTable):
|
||||
# Aggregates
|
||||
#
|
||||
|
||||
class AggregateTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class AggregateTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
prefix = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Aggregate'),
|
||||
@@ -79,9 +79,6 @@ class AggregateTable(TenancyColumnsMixin, NetBoxTable):
|
||||
accessor='get_utilization',
|
||||
orderable=False
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:aggregate_list'
|
||||
)
|
||||
@@ -89,7 +86,7 @@ class AggregateTable(TenancyColumnsMixin, NetBoxTable):
|
||||
extra_buttons=AGGREGATE_COPY_BUTTON
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Aggregate
|
||||
fields = (
|
||||
'pk', 'id', 'prefix', 'rir', 'tenant', 'tenant_group', 'child_count', 'utilization', 'date_added',
|
||||
@@ -102,7 +99,7 @@ class AggregateTable(TenancyColumnsMixin, NetBoxTable):
|
||||
# Roles
|
||||
#
|
||||
|
||||
class RoleTable(NetBoxTable):
|
||||
class RoleTable(OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -126,7 +123,7 @@ class RoleTable(NetBoxTable):
|
||||
url_name='ipam:role_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = Role
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'slug', 'prefix_count', 'iprange_count', 'vlan_count', 'description', 'weight', 'tags',
|
||||
@@ -154,7 +151,7 @@ class PrefixUtilizationColumn(columns.UtilizationColumn):
|
||||
"""
|
||||
|
||||
|
||||
class PrefixTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class PrefixTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
prefix = columns.TemplateColumn(
|
||||
verbose_name=_('Prefix'),
|
||||
template_code=PREFIX_LINK_WITH_DEPTH,
|
||||
@@ -223,9 +220,6 @@ class PrefixTable(TenancyColumnsMixin, NetBoxTable):
|
||||
accessor='get_utilization',
|
||||
orderable=False
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:prefix_list'
|
||||
)
|
||||
@@ -233,7 +227,7 @@ class PrefixTable(TenancyColumnsMixin, NetBoxTable):
|
||||
extra_buttons=PREFIX_COPY_BUTTON
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Prefix
|
||||
fields = (
|
||||
'pk', 'id', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'tenant_group',
|
||||
@@ -252,7 +246,7 @@ class PrefixTable(TenancyColumnsMixin, NetBoxTable):
|
||||
#
|
||||
# IP ranges
|
||||
#
|
||||
class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class IPRangeTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
start_address = tables.Column(
|
||||
verbose_name=_('Start address'),
|
||||
linkify=True
|
||||
@@ -282,14 +276,11 @@ class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
|
||||
accessor='utilization',
|
||||
orderable=False
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:iprange_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = IPRange
|
||||
fields = (
|
||||
'pk', 'id', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'tenant_group',
|
||||
@@ -308,7 +299,7 @@ class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
|
||||
# IPAddresses
|
||||
#
|
||||
|
||||
class IPAddressTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class IPAddressTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
address = tables.TemplateColumn(
|
||||
template_code=IPADDRESS_LINK,
|
||||
verbose_name=_('IP Address')
|
||||
@@ -351,9 +342,6 @@ class IPAddressTable(TenancyColumnsMixin, NetBoxTable):
|
||||
verbose_name=_('Assigned'),
|
||||
false_mark=None
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:ipaddress_list'
|
||||
)
|
||||
@@ -361,7 +349,7 @@ class IPAddressTable(TenancyColumnsMixin, NetBoxTable):
|
||||
extra_buttons=IPADDRESS_COPY_BUTTON
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = IPAddress
|
||||
fields = (
|
||||
'pk', 'id', 'address', 'vrf', 'status', 'role', 'tenant', 'tenant_group', 'nat_inside', 'nat_outside',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import PrimaryModelTable, columns
|
||||
|
||||
__all__ = (
|
||||
'ServiceTable',
|
||||
@@ -10,7 +10,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ServiceTemplateTable(NetBoxTable):
|
||||
class ServiceTemplateTable(PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -20,14 +20,11 @@ class ServiceTemplateTable(NetBoxTable):
|
||||
accessor=tables.A('port_list'),
|
||||
order_by=tables.A('ports'),
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:servicetemplate_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = ServiceTemplate
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'protocol', 'ports', 'description', 'comments', 'tags', 'created', 'last_updated',
|
||||
@@ -35,7 +32,7 @@ class ServiceTemplateTable(NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'protocol', 'ports', 'description')
|
||||
|
||||
|
||||
class ServiceTable(NetBoxTable):
|
||||
class ServiceTable(PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -50,14 +47,11 @@ class ServiceTable(NetBoxTable):
|
||||
accessor=tables.A('port_list'),
|
||||
order_by=tables.A('ports'),
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:service_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = Service
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'parent', 'protocol', 'ports', 'ipaddresses', 'description', 'comments', 'tags',
|
||||
|
||||
@@ -5,7 +5,7 @@ from django_tables2.utils import Accessor
|
||||
|
||||
from dcim.models import Interface
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns
|
||||
from tenancy.tables import TenancyColumnsMixin, TenantColumn
|
||||
from virtualization.models import VMInterface
|
||||
from .template_code import *
|
||||
@@ -28,7 +28,7 @@ AVAILABLE_LABEL = mark_safe('<span class="badge text-bg-success">Available</span
|
||||
# VLAN groups
|
||||
#
|
||||
|
||||
class VLANGroupTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class VLANGroupTable(TenancyColumnsMixin, OrganizationalModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -62,7 +62,7 @@ class VLANGroupTable(TenancyColumnsMixin, NetBoxTable):
|
||||
extra_buttons=VLANGROUP_BUTTONS
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(OrganizationalModelTable.Meta):
|
||||
model = VLANGroup
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'scope_type', 'scope', 'vid_ranges_list', 'vlan_count', 'slug', 'description',
|
||||
@@ -77,7 +77,7 @@ class VLANGroupTable(TenancyColumnsMixin, NetBoxTable):
|
||||
# VLANs
|
||||
#
|
||||
|
||||
class VLANTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class VLANTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
vid = tables.TemplateColumn(
|
||||
template_code=VLAN_LINK,
|
||||
verbose_name=_('VID')
|
||||
@@ -120,14 +120,11 @@ class VLANTable(TenancyColumnsMixin, NetBoxTable):
|
||||
orderable=False,
|
||||
verbose_name=_('Prefixes')
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:vlan_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = VLAN
|
||||
fields = (
|
||||
'pk', 'id', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'tenant_group', 'status', 'role',
|
||||
@@ -229,7 +226,7 @@ class InterfaceVLANTable(NetBoxTable):
|
||||
# VLAN Translation
|
||||
#
|
||||
|
||||
class VLANTranslationPolicyTable(NetBoxTable):
|
||||
class VLANTranslationPolicyTable(PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -246,7 +243,7 @@ class VLANTranslationPolicyTable(NetBoxTable):
|
||||
url_name='ipam:vlantranslationpolicy_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = VLANTranslationPolicy
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'rule_count', 'description', 'tags', 'created', 'last_updated',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from netbox.tables import PrimaryModelTable, columns
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
|
||||
__all__ = (
|
||||
@@ -21,7 +21,7 @@ VRF_TARGETS = """
|
||||
# VRFs
|
||||
#
|
||||
|
||||
class VRFTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class VRFTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
@@ -43,14 +43,11 @@ class VRFTable(TenancyColumnsMixin, NetBoxTable):
|
||||
template_code=VRF_TARGETS,
|
||||
orderable=False
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:vrf_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = VRF
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'rd', 'tenant', 'tenant_group', 'enforce_unique', 'import_targets', 'export_targets',
|
||||
@@ -63,19 +60,16 @@ class VRFTable(TenancyColumnsMixin, NetBoxTable):
|
||||
# Route targets
|
||||
#
|
||||
|
||||
class RouteTargetTable(TenancyColumnsMixin, NetBoxTable):
|
||||
class RouteTargetTable(TenancyColumnsMixin, PrimaryModelTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:routetarget_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
class Meta(PrimaryModelTable.Meta):
|
||||
model = RouteTarget
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'tenant', 'tenant_group', 'description', 'comments', 'tags', 'created', 'last_updated',
|
||||
|
||||
@@ -1,33 +1,6 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .base import *
|
||||
from .features import *
|
||||
from .generic import *
|
||||
from .nested import *
|
||||
|
||||
|
||||
#
|
||||
# Base model serializers
|
||||
#
|
||||
|
||||
class NetBoxModelSerializer(
|
||||
ChangeLogMessageSerializer,
|
||||
TaggableModelSerializer,
|
||||
CustomFieldModelSerializer,
|
||||
ValidatedModelSerializer
|
||||
):
|
||||
"""
|
||||
Adds support for custom fields and tags.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NestedGroupModelSerializer(NetBoxModelSerializer):
|
||||
"""
|
||||
Extends PrimaryModelSerializer to include MPTT support.
|
||||
"""
|
||||
_depth = serializers.IntegerField(source='level', read_only=True)
|
||||
|
||||
|
||||
class BulkOperationSerializer(ChangeLogMessageSerializer):
|
||||
id = serializers.IntegerField()
|
||||
from .models import *
|
||||
from .bulk import *
|
||||
|
||||
11
netbox/netbox/api/serializers/bulk.py
Normal file
11
netbox/netbox/api/serializers/bulk.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .features import ChangeLogMessageSerializer
|
||||
|
||||
__all__ = (
|
||||
'BulkOperationSerializer',
|
||||
)
|
||||
|
||||
|
||||
class BulkOperationSerializer(ChangeLogMessageSerializer):
|
||||
id = serializers.IntegerField()
|
||||
@@ -2,11 +2,13 @@ from rest_framework import serializers
|
||||
from rest_framework.fields import CreateOnlyDefault
|
||||
|
||||
from extras.api.customfields import CustomFieldsDataField, CustomFieldDefaultValues
|
||||
from .base import ValidatedModelSerializer
|
||||
from .nested import NestedTagSerializer
|
||||
|
||||
__all__ = (
|
||||
'ChangeLogMessageSerializer',
|
||||
'CustomFieldModelSerializer',
|
||||
'NetBoxModelSerializer',
|
||||
'TaggableModelSerializer',
|
||||
)
|
||||
|
||||
@@ -76,3 +78,15 @@ class ChangeLogMessageSerializer(serializers.Serializer):
|
||||
if self.instance is not None:
|
||||
self.instance._changelog_message = self.validated_data.get('changelog_message')
|
||||
return super().save(**kwargs)
|
||||
|
||||
|
||||
class NetBoxModelSerializer(
|
||||
ChangeLogMessageSerializer,
|
||||
TaggableModelSerializer,
|
||||
CustomFieldModelSerializer,
|
||||
ValidatedModelSerializer
|
||||
):
|
||||
"""
|
||||
Adds support for custom fields and tags.
|
||||
"""
|
||||
pass
|
||||
|
||||
31
netbox/netbox/api/serializers/models.py
Normal file
31
netbox/netbox/api/serializers/models.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .features import NetBoxModelSerializer
|
||||
from users.api.serializers_.mixins import OwnerMixin
|
||||
|
||||
__all__ = (
|
||||
'NestedGroupModelSerializer',
|
||||
'OrganizationalModelSerializer',
|
||||
'PrimaryModelSerializer',
|
||||
)
|
||||
|
||||
|
||||
class PrimaryModelSerializer(OwnerMixin, NetBoxModelSerializer):
|
||||
"""
|
||||
Base serializer class for models inheriting from PrimaryModel.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NestedGroupModelSerializer(OwnerMixin, NetBoxModelSerializer):
|
||||
"""
|
||||
Base serializer class for models inheriting from NestedGroupModel.
|
||||
"""
|
||||
_depth = serializers.IntegerField(source='level', read_only=True)
|
||||
|
||||
|
||||
class OrganizationalModelSerializer(OwnerMixin, NetBoxModelSerializer):
|
||||
"""
|
||||
Base serializer class for models inheriting from OrganizationalModel.
|
||||
"""
|
||||
pass
|
||||
@@ -14,6 +14,7 @@ from core.models import ObjectChange
|
||||
from extras.choices import CustomFieldFilterLogicChoices
|
||||
from extras.filters import TagFilter, TagIDFilter
|
||||
from extras.models import CustomField, SavedFilter
|
||||
from users.filterset_mixins import OwnerFilterMixin
|
||||
from utilities.constants import (
|
||||
FILTER_CHAR_BASED_LOOKUP_MAP, FILTER_NEGATION_LOOKUP_MAP, FILTER_TREENODE_NEGATION_LOOKUP_MAP,
|
||||
FILTER_NUMERIC_BASED_LOOKUP_MAP
|
||||
@@ -25,8 +26,10 @@ __all__ = (
|
||||
'AttributeFiltersMixin',
|
||||
'BaseFilterSet',
|
||||
'ChangeLoggedModelFilterSet',
|
||||
'NestedGroupModelFilterSet',
|
||||
'NetBoxModelFilterSet',
|
||||
'OrganizationalModelFilterSet',
|
||||
'PrimaryModelFilterSet',
|
||||
)
|
||||
|
||||
STANDARD_LOOKUPS = (
|
||||
@@ -328,9 +331,16 @@ class NetBoxModelFilterSet(ChangeLoggedModelFilterSet):
|
||||
return queryset
|
||||
|
||||
|
||||
class OrganizationalModelFilterSet(NetBoxModelFilterSet):
|
||||
class PrimaryModelFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
|
||||
"""
|
||||
A base class for adding the search method to models which only expose the `name` and `slug` fields
|
||||
Base filterset for models inheriting from PrimaryModel.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class OrganizationalModelFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
|
||||
"""
|
||||
Base filterset for models inheriting from OrganizationalModel.
|
||||
"""
|
||||
def search(self, queryset, name, value):
|
||||
if not value.strip():
|
||||
@@ -342,9 +352,9 @@ class OrganizationalModelFilterSet(NetBoxModelFilterSet):
|
||||
)
|
||||
|
||||
|
||||
class NestedGroupModelFilterSet(NetBoxModelFilterSet):
|
||||
class NestedGroupModelFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
|
||||
"""
|
||||
A base FilterSet for models that inherit from NestedGroupModel
|
||||
Base filterset for models inheriting from NestedGroupModel.
|
||||
"""
|
||||
def search(self, queryset, name, value):
|
||||
if value.strip():
|
||||
|
||||
@@ -1,57 +1,5 @@
|
||||
import re
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from netbox.search import LookupTypes
|
||||
from netbox.search.backends import search_backend
|
||||
|
||||
from .base import *
|
||||
|
||||
LOOKUP_CHOICES = (
|
||||
('', _('Partial match')),
|
||||
(LookupTypes.EXACT, _('Exact match')),
|
||||
(LookupTypes.STARTSWITH, _('Starts with')),
|
||||
(LookupTypes.ENDSWITH, _('Ends with')),
|
||||
(LookupTypes.REGEX, _('Regex')),
|
||||
)
|
||||
|
||||
|
||||
class SearchForm(forms.Form):
|
||||
q = forms.CharField(
|
||||
label=_('Search'),
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'hx-get': '',
|
||||
'hx-target': '#object_list',
|
||||
'hx-trigger': 'keyup[target.value.length >= 3] changed delay:500ms',
|
||||
}
|
||||
)
|
||||
)
|
||||
obj_types = forms.MultipleChoiceField(
|
||||
choices=[],
|
||||
required=False,
|
||||
label=_('Object type(s)')
|
||||
)
|
||||
lookup = forms.ChoiceField(
|
||||
choices=LOOKUP_CHOICES,
|
||||
initial=LookupTypes.PARTIAL,
|
||||
required=False,
|
||||
label=_('Lookup')
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['obj_types'].choices = search_backend.get_object_types()
|
||||
|
||||
def clean(self):
|
||||
|
||||
# Validate regular expressions
|
||||
if self.cleaned_data['lookup'] == LookupTypes.REGEX:
|
||||
try:
|
||||
re.compile(self.cleaned_data['q'])
|
||||
except re.error as e:
|
||||
raise forms.ValidationError({
|
||||
'q': f'Invalid regular expression: {e}'
|
||||
})
|
||||
from .model_forms import *
|
||||
from .bulk_import import *
|
||||
from .bulk_edit import *
|
||||
from .filtersets import *
|
||||
from .search import *
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
import json
|
||||
|
||||
from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from core.models import ObjectType
|
||||
from extras.choices import *
|
||||
from extras.models import CustomField, Tag
|
||||
from utilities.forms import BulkEditForm, CSVModelForm
|
||||
from utilities.forms.fields import CSVModelMultipleChoiceField, DynamicModelMultipleChoiceField
|
||||
from utilities.forms.mixins import CheckLastUpdatedMixin
|
||||
from .mixins import ChangelogMessageMixin, CustomFieldsMixin, SavedFiltersMixin, TagsMixin
|
||||
|
||||
__all__ = (
|
||||
'NetBoxModelForm',
|
||||
'NetBoxModelImportForm',
|
||||
'NetBoxModelBulkEditForm',
|
||||
'NetBoxModelFilterSetForm',
|
||||
)
|
||||
|
||||
|
||||
class NetBoxModelForm(ChangelogMessageMixin, CheckLastUpdatedMixin, CustomFieldsMixin, TagsMixin, forms.ModelForm):
|
||||
"""
|
||||
Base form for creating & editing NetBox models. Extends Django's ModelForm to add support for custom fields.
|
||||
|
||||
Attributes:
|
||||
fieldsets: An iterable of FieldSets which define a name and set of fields to display per section of
|
||||
the rendered form (optional). If not defined, the all fields will be rendered as a single section.
|
||||
"""
|
||||
fieldsets = ()
|
||||
|
||||
def _get_content_type(self):
|
||||
return ContentType.objects.get_for_model(self._meta.model)
|
||||
|
||||
def _get_form_field(self, customfield):
|
||||
if self.instance.pk:
|
||||
form_field = customfield.to_form_field(set_initial=False)
|
||||
initial = self.instance.custom_field_data.get(customfield.name)
|
||||
if customfield.type == CustomFieldTypeChoices.TYPE_JSON:
|
||||
form_field.initial = json.dumps(initial)
|
||||
else:
|
||||
form_field.initial = initial
|
||||
return form_field
|
||||
|
||||
return customfield.to_form_field()
|
||||
|
||||
def clean(self):
|
||||
|
||||
# Save custom field data on instance
|
||||
for cf_name, customfield in self.custom_fields.items():
|
||||
if cf_name not in self.fields:
|
||||
# Custom fields may be absent when performing bulk updates via import
|
||||
continue
|
||||
key = cf_name[3:] # Strip "cf_" from field name
|
||||
value = self.cleaned_data.get(cf_name)
|
||||
|
||||
# Convert "empty" values to null
|
||||
if value in self.fields[cf_name].empty_values:
|
||||
self.instance.custom_field_data[key] = None
|
||||
else:
|
||||
if customfield.type == CustomFieldTypeChoices.TYPE_JSON and type(value) is str:
|
||||
value = json.loads(value)
|
||||
self.instance.custom_field_data[key] = customfield.serialize(value)
|
||||
|
||||
return super().clean()
|
||||
|
||||
def _post_clean(self):
|
||||
"""
|
||||
Override BaseModelForm's _post_clean() to store many-to-many field values on the model instance.
|
||||
"""
|
||||
self.instance._m2m_values = {}
|
||||
for field in self.instance._meta.local_many_to_many:
|
||||
if field.name in self.cleaned_data:
|
||||
self.instance._m2m_values[field.name] = list(self.cleaned_data[field.name])
|
||||
|
||||
return super()._post_clean()
|
||||
|
||||
|
||||
class NetBoxModelImportForm(CSVModelForm, NetBoxModelForm):
|
||||
"""
|
||||
Base form for creating a NetBox objects from CSV data. Used for bulk importing.
|
||||
"""
|
||||
tags = CSVModelMultipleChoiceField(
|
||||
label=_('Tags'),
|
||||
queryset=Tag.objects.all(),
|
||||
required=False,
|
||||
to_field_name='slug',
|
||||
help_text=_('Tag slugs separated by commas, encased with double quotes (e.g. "tag1,tag2,tag3")')
|
||||
)
|
||||
|
||||
def _get_custom_fields(self, content_type):
|
||||
return CustomField.objects.filter(
|
||||
object_types=content_type,
|
||||
ui_editable=CustomFieldUIEditableChoices.YES
|
||||
)
|
||||
|
||||
def _get_form_field(self, customfield):
|
||||
return customfield.to_form_field(for_csv_import=True)
|
||||
|
||||
|
||||
class NetBoxModelBulkEditForm(ChangelogMessageMixin, CustomFieldsMixin, BulkEditForm):
|
||||
"""
|
||||
Base form for modifying multiple NetBox objects (of the same type) in bulk via the UI. Adds support for custom
|
||||
fields and adding/removing tags.
|
||||
|
||||
Attributes:
|
||||
fieldsets: An iterable of two-tuples which define a heading and field set to display per section of
|
||||
the rendered form (optional). If not defined, the all fields will be rendered as a single section.
|
||||
"""
|
||||
fieldsets = None
|
||||
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=None, # Set from self.model on init
|
||||
widget=forms.MultipleHiddenInput
|
||||
)
|
||||
add_tags = DynamicModelMultipleChoiceField(
|
||||
label=_('Add tags'),
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
remove_tags = DynamicModelMultipleChoiceField(
|
||||
label=_('Remove tags'),
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['pk'].queryset = self.model.objects.all()
|
||||
|
||||
# Restrict tag fields by model
|
||||
object_type = ObjectType.objects.get_for_model(self.model)
|
||||
self.fields['add_tags'].widget.add_query_param('for_object_type_id', object_type.pk)
|
||||
self.fields['remove_tags'].widget.add_query_param('for_object_type_id', object_type.pk)
|
||||
|
||||
self._extend_nullable_fields()
|
||||
|
||||
def _get_form_field(self, customfield):
|
||||
return customfield.to_form_field(set_initial=False, enforce_required=False)
|
||||
|
||||
def _extend_nullable_fields(self):
|
||||
nullable_custom_fields = [
|
||||
name for name, customfield in self.custom_fields.items()
|
||||
if (not customfield.required and customfield.ui_editable == CustomFieldUIEditableChoices.YES)
|
||||
]
|
||||
self.nullable_fields = (*self.nullable_fields, *nullable_custom_fields)
|
||||
|
||||
|
||||
class NetBoxModelFilterSetForm(CustomFieldsMixin, SavedFiltersMixin, forms.Form):
|
||||
"""
|
||||
Base form for FilerSet forms. These are used to filter object lists in the NetBox UI. Note that the
|
||||
corresponding FilterSet *must* provide a `q` filter.
|
||||
|
||||
Attributes:
|
||||
model: The model class associated with the form
|
||||
fieldsets: An iterable of two-tuples which define a heading and field set to display per section of
|
||||
the rendered form (optional). If not defined, the all fields will be rendered as a single section.
|
||||
selector_fields: An iterable of names of fields to display by default when rendering the form as
|
||||
a selector widget
|
||||
"""
|
||||
q = forms.CharField(
|
||||
required=False,
|
||||
label=_('Search')
|
||||
)
|
||||
|
||||
selector_fields = ('filter_id', 'q')
|
||||
|
||||
def _get_custom_fields(self, content_type):
|
||||
return super()._get_custom_fields(content_type).exclude(
|
||||
Q(filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED) |
|
||||
Q(type=CustomFieldTypeChoices.TYPE_JSON)
|
||||
)
|
||||
|
||||
def _get_form_field(self, customfield):
|
||||
return customfield.to_form_field(set_initial=False, enforce_required=False, enforce_visibility=False)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user