Просмотр исходного кода

Merge pull request #7827 from rhyser9/7424_virtualchassis_id_filter

Fix #7424: Add virtual_chassis_id filter for device components
Jeremy Stretch 4 лет назад
Родитель
Сommit
d051db5083

+ 1 - 1
netbox/dcim/api/nested_serializers.py

@@ -340,7 +340,7 @@ class NestedVirtualChassisSerializer(WritableNestedSerializer):
 
 
     class Meta:
     class Meta:
         model = models.VirtualChassis
         model = models.VirtualChassis
-        fields = ['id', 'name', 'url', 'master', 'member_count']
+        fields = ['id', 'url', 'display', 'name', 'master', 'member_count']
 
 
 
 
 #
 #

+ 11 - 0
netbox/dcim/filtersets.py

@@ -861,6 +861,17 @@ class DeviceComponentFilterSet(django_filters.FilterSet):
         to_field_name='name',
         to_field_name='name',
         label='Device (name)',
         label='Device (name)',
     )
     )
+    virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
+        field_name='device__virtual_chassis',
+        queryset=VirtualChassis.objects.all(),
+        label='Virtual Chassis (ID)'
+    )
+    virtual_chassis = django_filters.ModelMultipleChoiceFilter(
+        field_name='device__virtual_chassis__name',
+        queryset=VirtualChassis.objects.all(),
+        to_field_name='name',
+        label='Virtual Chassis',
+    )
     tag = TagFilter()
     tag = TagFilter()
 
 
     def search(self, queryset, name, value):
     def search(self, queryset, name, value):

+ 16 - 9
netbox/dcim/forms/filtersets.py

@@ -92,12 +92,19 @@ class DeviceComponentFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
         label=_('Location'),
         label=_('Location'),
         fetch_trigger='open'
         fetch_trigger='open'
     )
     )
+    virtual_chassis_id = DynamicModelMultipleChoiceField(
+        queryset=VirtualChassis.objects.all(),
+        required=False,
+        label=_('Virtual Chassis'),
+        fetch_trigger='open'
+    )
     device_id = DynamicModelMultipleChoiceField(
     device_id = DynamicModelMultipleChoiceField(
         queryset=Device.objects.all(),
         queryset=Device.objects.all(),
         required=False,
         required=False,
         query_params={
         query_params={
             'site_id': '$site_id',
             'site_id': '$site_id',
             'location_id': '$location_id',
             'location_id': '$location_id',
+            'virtual_chassis_id': '$virtual_chassis_id'
         },
         },
         label=_('Device'),
         label=_('Device'),
         fetch_trigger='open'
         fetch_trigger='open'
@@ -888,7 +895,7 @@ class ConsolePortFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label', 'type', 'speed'],
         ['name', 'label', 'type', 'speed'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     type = forms.MultipleChoiceField(
     type = forms.MultipleChoiceField(
         choices=ConsolePortTypeChoices,
         choices=ConsolePortTypeChoices,
@@ -908,7 +915,7 @@ class ConsoleServerPortFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label', 'type', 'speed'],
         ['name', 'label', 'type', 'speed'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     type = forms.MultipleChoiceField(
     type = forms.MultipleChoiceField(
         choices=ConsolePortTypeChoices,
         choices=ConsolePortTypeChoices,
@@ -928,7 +935,7 @@ class PowerPortFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label', 'type'],
         ['name', 'label', 'type'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     type = forms.MultipleChoiceField(
     type = forms.MultipleChoiceField(
         choices=PowerPortTypeChoices,
         choices=PowerPortTypeChoices,
@@ -943,7 +950,7 @@ class PowerOutletFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label', 'type'],
         ['name', 'label', 'type'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     type = forms.MultipleChoiceField(
     type = forms.MultipleChoiceField(
         choices=PowerOutletTypeChoices,
         choices=PowerOutletTypeChoices,
@@ -958,7 +965,7 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label', 'kind', 'type', 'enabled', 'mgmt_only', 'mac_address'],
         ['name', 'label', 'kind', 'type', 'enabled', 'mgmt_only', 'mac_address'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     kind = forms.MultipleChoiceField(
     kind = forms.MultipleChoiceField(
         choices=InterfaceKindChoices,
         choices=InterfaceKindChoices,
@@ -993,7 +1000,7 @@ class FrontPortFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label', 'type', 'color'],
         ['name', 'label', 'type', 'color'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     model = FrontPort
     model = FrontPort
     type = forms.MultipleChoiceField(
     type = forms.MultipleChoiceField(
@@ -1012,7 +1019,7 @@ class RearPortFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label', 'type', 'color'],
         ['name', 'label', 'type', 'color'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     type = forms.MultipleChoiceField(
     type = forms.MultipleChoiceField(
         choices=PortTypeChoices,
         choices=PortTypeChoices,
@@ -1030,7 +1037,7 @@ class DeviceBayFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label'],
         ['name', 'label'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     tag = TagFilterField(model)
     tag = TagFilterField(model)
 
 
@@ -1040,7 +1047,7 @@ class InventoryItemFilterForm(DeviceComponentFilterForm):
     field_groups = [
     field_groups = [
         ['q', 'tag'],
         ['q', 'tag'],
         ['name', 'label', 'manufacturer_id', 'serial', 'asset_tag', 'discovered'],
         ['name', 'label', 'manufacturer_id', 'serial', 'asset_tag', 'discovered'],
-        ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
+        ['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
     ]
     ]
     manufacturer_id = DynamicModelMultipleChoiceField(
     manufacturer_id = DynamicModelMultipleChoiceField(
         queryset=Manufacturer.objects.all(),
         queryset=Manufacturer.objects.all(),

+ 1 - 1
netbox/dcim/tests/test_api.py

@@ -1524,7 +1524,7 @@ class ConnectedDeviceTest(APITestCase):
 
 
 class VirtualChassisTest(APIViewTestCases.APIViewTestCase):
 class VirtualChassisTest(APIViewTestCases.APIViewTestCase):
     model = VirtualChassis
     model = VirtualChassis
-    brief_fields = ['id', 'master', 'member_count', 'name', 'url']
+    brief_fields = ['display', 'id', 'master', 'member_count', 'name', 'url']
 
 
     @classmethod
     @classmethod
     def setUpTestData(cls):
     def setUpTestData(cls):

+ 9 - 0
netbox/dcim/tests/test_filtersets.py

@@ -2048,6 +2048,11 @@ class InterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
         )
         )
         Device.objects.bulk_create(devices)
         Device.objects.bulk_create(devices)
 
 
+        # VirtualChassis assignment for filtering
+        virtual_chassis = VirtualChassis.objects.create(master=devices[0])
+        Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=virtual_chassis, vc_position=1, vc_priority=1)
+        Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis, vc_position=2, vc_priority=2)
+
         interfaces = (
         interfaces = (
             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'),
             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'),
             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'),
             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 @@ class InterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
         params = {'location': [locations[0].slug, locations[1].slug]}
         params = {'location': [locations[0].slug, locations[1].slug]}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
 
+    def test_virtual_chassis_id(self):
+        params = {'virtual_chassis_id': [VirtualChassis.objects.first().pk]}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
+
     def test_device(self):
     def test_device(self):
         devices = Device.objects.all()[:2]
         devices = Device.objects.all()[:2]
         params = {'device_id': [devices[0].pk, devices[1].pk]}
         params = {'device_id': [devices[0].pk, devices[1].pk]}