diff --git a/netbox/ipam/api/serializers_/vlans.py b/netbox/ipam/api/serializers_/vlans.py index 9b5501dc5..a6f428343 100644 --- a/netbox/ipam/api/serializers_/vlans.py +++ b/netbox/ipam/api/serializers_/vlans.py @@ -37,6 +37,7 @@ class VLANGroupSerializer(NetBoxModelSerializer): scope = serializers.SerializerMethodField(read_only=True) vid_ranges = IntegerRangeSerializer(many=True, required=False) utilization = serializers.CharField(read_only=True) + tenant = TenantSerializer(nested=True, required=False, allow_null=True) # Related object counts vlan_count = RelatedObjectCountField('vlans') @@ -45,7 +46,7 @@ class VLANGroupSerializer(NetBoxModelSerializer): model = VLANGroup fields = [ 'id', 'url', 'display_url', 'display', 'name', 'slug', 'scope_type', 'scope_id', 'scope', 'vid_ranges', - 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'vlan_count', 'utilization' + 'tenant', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'vlan_count', 'utilization' ] brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'vlan_count') validators = [] diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index 81cbd2ef8..d9507ec2e 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -857,7 +857,7 @@ class FHRPGroupAssignmentFilterSet(ChangeLoggedModelFilterSet): ) -class VLANGroupFilterSet(OrganizationalModelFilterSet): +class VLANGroupFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): scope_type = ContentTypeFilter() region = django_filters.NumberFilter( method='filter_scope' diff --git a/netbox/ipam/forms/bulk_edit.py b/netbox/ipam/forms/bulk_edit.py index 7f3216cfd..f1aa6d845 100644 --- a/netbox/ipam/forms/bulk_edit.py +++ b/netbox/ipam/forms/bulk_edit.py @@ -430,11 +430,17 @@ class VLANGroupBulkEditForm(NetBoxModelBulkEditForm): label=_('VLAN ID ranges'), required=False ) + tenant = DynamicModelChoiceField( + label=_('Tenant'), + queryset=Tenant.objects.all(), + required=False + ) model = VLANGroup fieldsets = ( FieldSet('site', 'vid_ranges', 'description'), FieldSet('scope_type', 'scope', name=_('Scope')), + FieldSet('tenant', name=_('Tenancy')), ) nullable_fields = ('description', 'scope') diff --git a/netbox/ipam/forms/bulk_import.py b/netbox/ipam/forms/bulk_import.py index c1f2dedd7..85583ca18 100644 --- a/netbox/ipam/forms/bulk_import.py +++ b/netbox/ipam/forms/bulk_import.py @@ -438,10 +438,17 @@ class VLANGroupImportForm(NetBoxModelImportForm): vid_ranges = NumericRangeArrayField( required=False ) + tenant = CSVModelChoiceField( + label=_('Tenant'), + queryset=Tenant.objects.all(), + required=False, + to_field_name='name', + help_text=_('Assigned tenant') + ) class Meta: model = VLANGroup - fields = ('name', 'slug', 'scope_type', 'scope_id', 'vid_ranges', 'description', 'tags') + fields = ('name', 'slug', 'scope_type', 'scope_id', 'vid_ranges', 'tenant', 'description', 'tags') labels = { 'scope_id': 'Scope ID', } diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py index c381f99c9..22f98f6f0 100644 --- a/netbox/ipam/forms/model_forms.py +++ b/netbox/ipam/forms/model_forms.py @@ -598,7 +598,7 @@ class FHRPGroupAssignmentForm(forms.ModelForm): return group -class VLANGroupForm(NetBoxModelForm): +class VLANGroupForm(TenancyForm, NetBoxModelForm): slug = SlugField() vid_ranges = NumericRangeArrayField( label=_('VLAN IDs') @@ -621,12 +621,13 @@ class VLANGroupForm(NetBoxModelForm): FieldSet('name', 'slug', 'description', 'tags', name=_('VLAN Group')), FieldSet('vid_ranges', name=_('Child VLANs')), FieldSet('scope_type', 'scope', name=_('Scope')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: model = VLANGroup fields = [ - 'name', 'slug', 'description', 'vid_ranges', 'scope_type', 'tags', + 'name', 'slug', 'description', 'vid_ranges', 'scope_type', 'tenant_group', 'tenant', 'tags', ] def __init__(self, *args, **kwargs): diff --git a/netbox/ipam/graphql/types.py b/netbox/ipam/graphql/types.py index e6ecca984..b16cf29fe 100644 --- a/netbox/ipam/graphql/types.py +++ b/netbox/ipam/graphql/types.py @@ -266,6 +266,7 @@ class VLANGroupType(OrganizationalObjectType): vlans: List[VLANType] vid_ranges: List[str] + tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None @strawberry_django.field def scope(self) -> Annotated[Union[ diff --git a/netbox/ipam/tables/vlans.py b/netbox/ipam/tables/vlans.py index aa1900e41..3f245c225 100644 --- a/netbox/ipam/tables/vlans.py +++ b/netbox/ipam/tables/vlans.py @@ -65,9 +65,11 @@ class VLANGroupTable(NetBoxTable): model = VLANGroup fields = ( 'pk', 'id', 'name', 'scope_type', 'scope', 'vid_ranges_list', 'vlan_count', 'slug', 'description', - 'tags', 'created', 'last_updated', 'actions', 'utilization', + 'tenant', 'tenant_group', 'tags', 'created', 'last_updated', 'actions', 'utilization', + ) + default_columns = ( + 'pk', 'name', 'scope_type', 'scope', 'vlan_count', 'utilization', 'tenant', 'tenant_group', 'description' ) - default_columns = ('pk', 'name', 'scope_type', 'scope', 'vlan_count', 'utilization', 'description') #