Przeglądaj źródła

Closes #7606: Model transmit power for interfaces

jeremystretch 4 lat temu
rodzic
commit
a173083e5b

+ 3 - 1
docs/release-notes/version-3.1.md

@@ -6,7 +6,7 @@
 ### Breaking Changes
 
 * The `tenant` and `tenant_id` filters for the Cable model now filter on the tenant assigned directly to each cable, rather than on the parent object of either termination.
-* The `cable_peer` and `cable_peer_type` attributes of the interface model has been renamed to `link_peer` and `link_peer_type`, respectively, to accommodate wireless links.
+* The `cable_peer` and `cable_peer_type` attributes of cable termination models have been renamed to `link_peer` and `link_peer_type`, respectively, to accommodate wireless links between interfaces.
 
 ### New Features
 
@@ -68,6 +68,7 @@ Multiple interfaces can be bridged to a single virtual interface to effect a bri
 * [#6874](https://github.com/netbox-community/netbox/issues/6874) - Add tenant assignment for locations
 * [#7354](https://github.com/netbox-community/netbox/issues/7354) - Relax uniqueness constraints on region, site group, and location names
 * [#7530](https://github.com/netbox-community/netbox/issues/7530) - Move device type component lists to separate views
+* [#7606](https://github.com/netbox-community/netbox/issues/7606) - Model transmit power for interfaces
 
 ### Other Changes
 
@@ -113,6 +114,7 @@ Multiple interfaces can be bridged to a single virtual interface to effect a bri
     * Added `rf_channel` field
     * Added `rf_channel_frequency` field
     * Added `rf_chanel_width` field
+    * Added `tx_power` field
     * Added `wwn` field
     * `cable_peer` has been renamed to `link_peer`
     * `cable_peer_type` has been renamed to `link_peer_type`

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

@@ -628,7 +628,7 @@ class InterfaceSerializer(PrimaryModelSerializer, LinkTerminationSerializer, Con
         fields = [
             'id', 'url', 'display', 'device', 'name', 'label', 'type', 'enabled', 'parent', 'bridge', 'lag', 'mtu',
             'mac_address', 'wwn', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency',
-            'rf_channel_width', 'untagged_vlan', 'tagged_vlans', 'mark_connected', 'cable', 'wireless_link',
+            'rf_channel_width', 'tx_power', 'untagged_vlan', 'tagged_vlans', 'mark_connected', 'cable', 'wireless_link',
             'link_peer', 'link_peer_type', 'connected_endpoint', 'connected_endpoint_type',
             'connected_endpoint_reachable', 'tags', 'custom_fields', 'created', 'last_updated', 'count_ipaddresses',
             '_occupied',

+ 1 - 1
netbox/dcim/filtersets.py

@@ -1011,7 +1011,7 @@ class InterfaceFilterSet(PrimaryModelFilterSet, DeviceComponentFilterSet, CableT
         model = Interface
         fields = [
             'id', 'name', 'label', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'rf_role', 'rf_channel',
-            'rf_channel_frequency', 'rf_channel_width', 'description',
+            'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description',
         ]
 
     def filter_device(self, queryset, name, value):

+ 2 - 2
netbox/dcim/forms/bulk_edit.py

@@ -940,7 +940,7 @@ class PowerOutletBulkEditForm(
 class InterfaceBulkEditForm(
     form_from_model(Interface, [
         'label', 'type', 'parent', 'bridge', 'lag', 'mac_address', 'wwn', 'mtu', 'mgmt_only', 'mark_connected',
-        'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width',
+        'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power',
     ]),
     BootstrapMixin,
     AddRemoveTagsForm,
@@ -996,7 +996,7 @@ class InterfaceBulkEditForm(
     class Meta:
         nullable_fields = [
             'label', 'parent', 'bridge', 'lag', 'mac_address', 'wwn', 'mtu', 'description', 'mode', 'rf_channel',
-            'rf_channel_frequency', 'rf_channel_width', 'untagged_vlan', 'tagged_vlans',
+            'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'untagged_vlan', 'tagged_vlans',
         ]
 
     def __init__(self, *args, **kwargs):

+ 1 - 1
netbox/dcim/forms/bulk_import.py

@@ -602,7 +602,7 @@ class InterfaceCSVForm(CustomFieldModelCSVForm):
         fields = (
             'device', 'name', 'label', 'parent', 'bridge', 'lag', 'type', 'enabled', 'mark_connected', 'mac_address',
             'wwn', 'mtu', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency',
-            'rf_channel_width',
+            'rf_channel_width', 'tx_power',
         )
 
     def clean_enabled(self):

+ 7 - 1
netbox/dcim/forms/filtersets.py

@@ -957,7 +957,7 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
     field_groups = [
         ['q', 'tag'],
         ['name', 'label', 'kind', 'type', 'enabled', 'mgmt_only', 'mac_address', 'wwn'],
-        ['rf_role', 'rf_channel', 'rf_channel_width'],
+        ['rf_role', 'rf_channel', 'rf_channel_width', 'tx_power'],
         ['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
     ]
     kind = forms.MultipleChoiceField(
@@ -1010,6 +1010,12 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
         required=False,
         label='Channel width (MHz)'
     )
+    tx_power = forms.IntegerField(
+        required=False,
+        label='Transmit power (dBm)',
+        min_value=0,
+        max_value=127
+    )
     tag = TagFilterField(model)
 
 

+ 1 - 1
netbox/dcim/forms/models.py

@@ -1150,7 +1150,7 @@ class InterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm):
         fields = [
             'device', 'name', 'label', 'type', 'enabled', 'parent', 'bridge', 'lag', 'mac_address', 'wwn', 'mtu',
             'mgmt_only', 'mark_connected', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency',
-            'rf_channel_width', 'wireless_lans', 'untagged_vlan', 'tagged_vlans', 'tags',
+            'rf_channel_width', 'tx_power', 'wireless_lans', 'untagged_vlan', 'tagged_vlans', 'tags',
         ]
         widgets = {
             'device': forms.HiddenInput(),

+ 6 - 0
netbox/dcim/migrations/0140_wireless.py

@@ -1,4 +1,5 @@
 from django.db import migrations, models
+import django.core.validators
 import django.db.models.deletion
 
 
@@ -30,6 +31,11 @@ class Migration(migrations.Migration):
             name='rf_channel_width',
             field=models.DecimalField(blank=True, decimal_places=3, max_digits=7, null=True),
         ),
+        migrations.AddField(
+            model_name='interface',
+            name='tx_power',
+            field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(127)]),
+        ),
         migrations.AddField(
             model_name='interface',
             name='wireless_lans',

+ 6 - 0
netbox/dcim/models/device_components.py

@@ -560,6 +560,12 @@ class Interface(ComponentModel, BaseInterface, LinkTermination, PathEndpoint):
         null=True,
         verbose_name='Channel width (MHz)'
     )
+    tx_power = models.PositiveSmallIntegerField(
+        blank=True,
+        null=True,
+        validators=(MaxValueValidator(127),),
+        verbose_name='Transmit power (dBm)'
+    )
     wireless_link = models.ForeignKey(
         to='wireless.WirelessLink',
         on_delete=models.SET_NULL,

+ 6 - 6
netbox/dcim/tables/devices.py

@@ -498,9 +498,9 @@ class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable
         model = Interface
         fields = (
             'pk', 'name', 'device', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address', 'wwn',
-            'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'description', 'mark_connected',
-            'cable', 'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection', 'tags', 'ip_addresses',
-            'untagged_vlan', 'tagged_vlans',
+            'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description',
+            'mark_connected', 'cable', 'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection',
+            'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans',
         )
         default_columns = ('pk', 'name', 'device', 'label', 'enabled', 'type', 'description')
 
@@ -533,9 +533,9 @@ class DeviceInterfaceTable(InterfaceTable):
         model = Interface
         fields = (
             'pk', 'name', 'label', 'enabled', 'type', 'parent', 'bridge', 'lag', 'mgmt_only', 'mtu', 'mode',
-            'mac_address', 'wwn', 'rf_role', 'rf_channel', 'rf_channel_width', 'description', 'mark_connected', 'cable',
-            'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection', 'tags', 'ip_addresses',
-            'untagged_vlan', 'tagged_vlans', 'actions',
+            'mac_address', 'wwn', 'rf_role', 'rf_channel', 'rf_channel_width', 'tx_power', 'description',
+            'mark_connected', 'cable', 'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection',
+            'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', 'actions',
         )
         order_by = ('name',)
         default_columns = (

+ 3 - 0
netbox/dcim/tests/test_api.py

@@ -1198,6 +1198,7 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase
                 'name': 'Interface 4',
                 'type': '1000base-t',
                 'mode': InterfaceModeChoices.MODE_TAGGED,
+                'tx_power': 10,
                 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
                 'untagged_vlan': vlans[2].pk,
             },
@@ -1207,6 +1208,7 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase
                 'type': '1000base-t',
                 'mode': InterfaceModeChoices.MODE_TAGGED,
                 'bridge': interfaces[0].pk,
+                'tx_power': 10,
                 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
                 'untagged_vlan': vlans[2].pk,
             },
@@ -1216,6 +1218,7 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase
                 'type': 'virtual',
                 'mode': InterfaceModeChoices.MODE_TAGGED,
                 'parent': interfaces[1].pk,
+                'tx_power': 10,
                 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
                 'untagged_vlan': vlans[2].pk,
             },

+ 7 - 3
netbox/dcim/tests/test_filtersets.py

@@ -2061,9 +2061,9 @@ class InterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
             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[2], name='Interface 3', label='C', type=InterfaceTypeChoices.TYPE_1GE_FIXED, enabled=False, mgmt_only=False, mtu=300, mode=InterfaceModeChoices.MODE_TAGGED_ALL, mac_address='00-00-00-00-00-03', description='Third'),
-            Interface(device=devices[3], name='Interface 4', label='D', type=InterfaceTypeChoices.TYPE_OTHER, enabled=True, mgmt_only=True),
-            Interface(device=devices[3], name='Interface 5', label='E', type=InterfaceTypeChoices.TYPE_OTHER, enabled=True, mgmt_only=True),
-            Interface(device=devices[3], name='Interface 6', label='F', type=InterfaceTypeChoices.TYPE_OTHER, enabled=False, mgmt_only=False),
+            Interface(device=devices[3], name='Interface 4', label='D', type=InterfaceTypeChoices.TYPE_OTHER, enabled=True, mgmt_only=True, tx_power=40),
+            Interface(device=devices[3], name='Interface 5', label='E', type=InterfaceTypeChoices.TYPE_OTHER, enabled=True, mgmt_only=True, tx_power=40),
+            Interface(device=devices[3], name='Interface 6', label='F', type=InterfaceTypeChoices.TYPE_OTHER, enabled=False, mgmt_only=False, tx_power=40),
             Interface(device=devices[3], name='Interface 7', type=InterfaceTypeChoices.TYPE_80211AC, rf_role=WirelessRoleChoices.ROLE_AP, rf_channel=WirelessChannelChoices.CHANNEL_24G_1, rf_channel_frequency=2412, rf_channel_width=22),
             Interface(device=devices[3], name='Interface 8', type=InterfaceTypeChoices.TYPE_80211AC, rf_role=WirelessRoleChoices.ROLE_STATION, rf_channel=WirelessChannelChoices.CHANNEL_5G_32, rf_channel_frequency=5160, rf_channel_width=20),
         )
@@ -2224,6 +2224,10 @@ class InterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
         params = {'rf_channel_width': [22, 20]}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
+    def test_tx_power(self):
+        params = {'tx_power': [40]}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
+
 
 class FrontPortTestCase(TestCase, ChangeLoggedFilterSetTests):
     queryset = FrontPort.objects.all()

+ 2 - 0
netbox/dcim/tests/test_views.py

@@ -1608,6 +1608,7 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
             'mgmt_only': True,
             'description': 'A front port',
             'mode': InterfaceModeChoices.MODE_TAGGED,
+            'tx_power': 10,
             'untagged_vlan': vlans[0].pk,
             'tagged_vlans': [v.pk for v in vlans[1:4]],
             'tags': [t.pk for t in tags],
@@ -1641,6 +1642,7 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
             'mgmt_only': True,
             'description': 'New description',
             'mode': InterfaceModeChoices.MODE_TAGGED,
+            'tx_power': 10,
             'untagged_vlan': vlans[0].pk,
             'tagged_vlans': [v.pk for v in vlans[1:4]],
         }

+ 4 - 0
netbox/templates/dcim/interface.html

@@ -105,6 +105,10 @@
                             <th scope="row">WWN</th>
                             <td><span class="text-monospace">{{ object.wwn|placeholder }}</span></td>
                         </tr>
+                        <tr>
+                            <th scope="row">Transmit power (dBm)</th>
+                            <td>{{ object.tx_power|placeholder }}</td>
+                        </tr>
                         <tr>
                             <th scope="row">802.1Q Mode</th>
                             <td>{{ object.get_mode_display|placeholder }}</td>

+ 1 - 0
netbox/templates/dcim/interface_edit.html

@@ -23,6 +23,7 @@
         {% render_field form.mac_address %}
         {% render_field form.wwn %}
         {% render_field form.mtu %}
+        {% render_field form.tx_power %}
         {% render_field form.description %}
         {% render_field form.tags %}
         {% render_field form.enabled %}