Skip to content

Commit d051db5

Browse files
Merge pull request #7827 from rhyser9/7424_virtualchassis_id_filter
Fix #7424: Add virtual_chassis_id filter for device components
2 parents 98cc36c + 68b544c commit d051db5

File tree

5 files changed

+38
-11
lines changed

5 files changed

+38
-11
lines changed

netbox/dcim/api/nested_serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ class NestedVirtualChassisSerializer(WritableNestedSerializer):
340340

341341
class Meta:
342342
model = models.VirtualChassis
343-
fields = ['id', 'name', 'url', 'master', 'member_count']
343+
fields = ['id', 'url', 'display', 'name', 'master', 'member_count']
344344

345345

346346
#

netbox/dcim/filtersets.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,17 @@ class DeviceComponentFilterSet(django_filters.FilterSet):
861861
to_field_name='name',
862862
label='Device (name)',
863863
)
864+
virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
865+
field_name='device__virtual_chassis',
866+
queryset=VirtualChassis.objects.all(),
867+
label='Virtual Chassis (ID)'
868+
)
869+
virtual_chassis = django_filters.ModelMultipleChoiceFilter(
870+
field_name='device__virtual_chassis__name',
871+
queryset=VirtualChassis.objects.all(),
872+
to_field_name='name',
873+
label='Virtual Chassis',
874+
)
864875
tag = TagFilter()
865876

866877
def search(self, queryset, name, value):

netbox/dcim/forms/filtersets.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,19 @@ class DeviceComponentFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
9292
label=_('Location'),
9393
fetch_trigger='open'
9494
)
95+
virtual_chassis_id = DynamicModelMultipleChoiceField(
96+
queryset=VirtualChassis.objects.all(),
97+
required=False,
98+
label=_('Virtual Chassis'),
99+
fetch_trigger='open'
100+
)
95101
device_id = DynamicModelMultipleChoiceField(
96102
queryset=Device.objects.all(),
97103
required=False,
98104
query_params={
99105
'site_id': '$site_id',
100106
'location_id': '$location_id',
107+
'virtual_chassis_id': '$virtual_chassis_id'
101108
},
102109
label=_('Device'),
103110
fetch_trigger='open'
@@ -888,7 +895,7 @@ class ConsolePortFilterForm(DeviceComponentFilterForm):
888895
field_groups = [
889896
['q', 'tag'],
890897
['name', 'label', 'type', 'speed'],
891-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
898+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
892899
]
893900
type = forms.MultipleChoiceField(
894901
choices=ConsolePortTypeChoices,
@@ -908,7 +915,7 @@ class ConsoleServerPortFilterForm(DeviceComponentFilterForm):
908915
field_groups = [
909916
['q', 'tag'],
910917
['name', 'label', 'type', 'speed'],
911-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
918+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
912919
]
913920
type = forms.MultipleChoiceField(
914921
choices=ConsolePortTypeChoices,
@@ -928,7 +935,7 @@ class PowerPortFilterForm(DeviceComponentFilterForm):
928935
field_groups = [
929936
['q', 'tag'],
930937
['name', 'label', 'type'],
931-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
938+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
932939
]
933940
type = forms.MultipleChoiceField(
934941
choices=PowerPortTypeChoices,
@@ -943,7 +950,7 @@ class PowerOutletFilterForm(DeviceComponentFilterForm):
943950
field_groups = [
944951
['q', 'tag'],
945952
['name', 'label', 'type'],
946-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
953+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
947954
]
948955
type = forms.MultipleChoiceField(
949956
choices=PowerOutletTypeChoices,
@@ -958,7 +965,7 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
958965
field_groups = [
959966
['q', 'tag'],
960967
['name', 'label', 'kind', 'type', 'enabled', 'mgmt_only', 'mac_address'],
961-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
968+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
962969
]
963970
kind = forms.MultipleChoiceField(
964971
choices=InterfaceKindChoices,
@@ -993,7 +1000,7 @@ class FrontPortFilterForm(DeviceComponentFilterForm):
9931000
field_groups = [
9941001
['q', 'tag'],
9951002
['name', 'label', 'type', 'color'],
996-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
1003+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
9971004
]
9981005
model = FrontPort
9991006
type = forms.MultipleChoiceField(
@@ -1012,7 +1019,7 @@ class RearPortFilterForm(DeviceComponentFilterForm):
10121019
field_groups = [
10131020
['q', 'tag'],
10141021
['name', 'label', 'type', 'color'],
1015-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
1022+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
10161023
]
10171024
type = forms.MultipleChoiceField(
10181025
choices=PortTypeChoices,
@@ -1030,7 +1037,7 @@ class DeviceBayFilterForm(DeviceComponentFilterForm):
10301037
field_groups = [
10311038
['q', 'tag'],
10321039
['name', 'label'],
1033-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
1040+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
10341041
]
10351042
tag = TagFilterField(model)
10361043

@@ -1040,7 +1047,7 @@ class InventoryItemFilterForm(DeviceComponentFilterForm):
10401047
field_groups = [
10411048
['q', 'tag'],
10421049
['name', 'label', 'manufacturer_id', 'serial', 'asset_tag', 'discovered'],
1043-
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
1050+
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
10441051
]
10451052
manufacturer_id = DynamicModelMultipleChoiceField(
10461053
queryset=Manufacturer.objects.all(),

netbox/dcim/tests/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1524,7 +1524,7 @@ def test_get_connected_device(self):
15241524

15251525
class VirtualChassisTest(APIViewTestCases.APIViewTestCase):
15261526
model = VirtualChassis
1527-
brief_fields = ['id', 'master', 'member_count', 'name', 'url']
1527+
brief_fields = ['display', 'id', 'master', 'member_count', 'name', 'url']
15281528

15291529
@classmethod
15301530
def setUpTestData(cls):

netbox/dcim/tests/test_filtersets.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,11 @@ def setUpTestData(cls):
20482048
)
20492049
Device.objects.bulk_create(devices)
20502050

2051+
# VirtualChassis assignment for filtering
2052+
virtual_chassis = VirtualChassis.objects.create(master=devices[0])
2053+
Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=virtual_chassis, vc_position=1, vc_priority=1)
2054+
Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis, vc_position=2, vc_priority=2)
2055+
20512056
interfaces = (
20522057
Interface(device=devices[0], name='Interface 1', label='A', type=InterfaceTypeChoices.TYPE_1GE_SFP, enabled=True, mgmt_only=True, mtu=100, mode=InterfaceModeChoices.MODE_ACCESS, mac_address='00-00-00-00-00-01', description='First'),
20532058
Interface(device=devices[1], name='Interface 2', label='B', type=InterfaceTypeChoices.TYPE_1GE_GBIC, enabled=True, mgmt_only=True, mtu=200, mode=InterfaceModeChoices.MODE_TAGGED, mac_address='00-00-00-00-00-02', description='Second'),
@@ -2157,6 +2162,10 @@ def test_location(self):
21572162
params = {'location': [locations[0].slug, locations[1].slug]}
21582163
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
21592164

2165+
def test_virtual_chassis_id(self):
2166+
params = {'virtual_chassis_id': [VirtualChassis.objects.first().pk]}
2167+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
2168+
21602169
def test_device(self):
21612170
devices = Device.objects.all()[:2]
21622171
params = {'device_id': [devices[0].pk, devices[1].pk]}

0 commit comments

Comments
 (0)