1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Add rf_role to Interface

This commit is contained in:
jeremystretch
2021-10-13 20:16:36 -04:00
parent 01f791a44e
commit 438b4b4758
14 changed files with 86 additions and 30 deletions

View File

@ -632,6 +632,7 @@ class InterfaceSerializer(PrimaryModelSerializer, LinkTerminationSerializer, Con
parent = NestedInterfaceSerializer(required=False, allow_null=True)
lag = NestedInterfaceSerializer(required=False, allow_null=True)
mode = ChoiceField(choices=InterfaceModeChoices, allow_blank=True, required=False)
rf_role = ChoiceField(choices=WirelessRoleChoices, required=False, allow_null=True)
rf_channel = ChoiceField(choices=WirelessChannelChoices, required=False)
rf_channel_width = ChoiceField(choices=WirelessChannelWidthChoices, required=False, allow_null=True)
untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
@ -648,7 +649,7 @@ class InterfaceSerializer(PrimaryModelSerializer, LinkTerminationSerializer, Con
model = Interface
fields = [
'id', 'url', 'display', 'device', 'name', 'label', 'type', 'enabled', 'parent', 'lag', 'mtu', 'mac_address',
'wwn', 'mgmt_only', 'description', 'mode', 'rf_channel', 'rf_channel_width', 'untagged_vlan',
'wwn', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_width', 'untagged_vlan',
'tagged_vlans', 'mark_connected', 'cable', 'link_peer', 'link_peer_type', 'connected_endpoint',
'connected_endpoint_type', 'connected_endpoint_reachable', 'tags', 'custom_fields', 'created',
'last_updated', 'count_ipaddresses', '_occupied',

View File

@ -1139,6 +1139,16 @@ class CableLengthUnitChoices(ChoiceSet):
# Wireless
#
class WirelessRoleChoices(ChoiceSet):
ROLE_AP = 'ap'
ROLE_STATION = 'station'
CHOICES = (
(ROLE_AP, 'Access point'),
(ROLE_STATION, 'Station'),
)
class WirelessChannelChoices(ChoiceSet):
CHANNEL_AUTO = 'auto'

View File

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

View File

@ -926,7 +926,7 @@ class PowerOutletBulkEditForm(
class InterfaceBulkEditForm(
form_from_model(Interface, [
'label', 'type', 'parent', 'lag', 'mac_address', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description',
'mode', 'rf_channel', 'rf_channel_width',
'mode', 'rf_role', 'rf_channel', 'rf_channel_width',
]),
BootstrapMixin,
AddRemoveTagsForm,

View File

@ -579,12 +579,17 @@ class InterfaceCSVForm(CustomFieldModelCSVForm):
required=False,
help_text='IEEE 802.1Q operational mode (for L2 interfaces)'
)
rf_role = CSVChoiceField(
choices=WirelessRoleChoices,
required=False,
help_text='Wireless role (AP/station)'
)
class Meta:
model = Interface
fields = (
'device', 'name', 'label', 'parent', 'lag', 'type', 'enabled', 'mark_connected', 'mac_address', 'wwn',
'mtu', 'mgmt_only', 'description', 'mode', 'rf_channel', 'rf_channel_width',
'mtu', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_width',
)
def __init__(self, *args, **kwargs):

View File

@ -963,7 +963,7 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
field_groups = [
['q', 'tag'],
['name', 'label', 'type', 'enabled', 'mgmt_only', 'mac_address', 'wwn'],
['rf_channel', 'rf_channel_width'],
['rf_role', 'rf_channel', 'rf_channel_width'],
['region_id', 'site_group_id', 'site_id', 'location_id', 'device_id'],
]
type = forms.MultipleChoiceField(
@ -991,15 +991,23 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
required=False,
label='WWN'
)
rf_role = forms.MultipleChoiceField(
choices=WirelessRoleChoices,
required=False,
widget=StaticSelectMultiple(),
label='Wireless role'
)
rf_channel = forms.MultipleChoiceField(
choices=WirelessChannelChoices,
required=False,
widget=StaticSelectMultiple()
widget=StaticSelectMultiple(),
label='Wireless channel'
)
rf_channel_width = forms.MultipleChoiceField(
choices=WirelessChannelWidthChoices,
required=False,
widget=StaticSelectMultiple()
widget=StaticSelectMultiple(),
label='Channel width'
)
tag = TagFilterField(model)

View File

@ -1104,13 +1104,14 @@ class InterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm):
model = Interface
fields = [
'device', 'name', 'label', 'type', 'enabled', 'parent', 'lag', 'mac_address', 'wwn', 'mtu', 'mgmt_only',
'mark_connected', 'description', 'mode', 'rf_channel', 'rf_channel_width', 'wireless_lans', 'untagged_vlan',
'tagged_vlans', 'tags',
'mark_connected', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_width', 'wireless_lans',
'untagged_vlan', 'tagged_vlans', 'tags',
]
widgets = {
'device': forms.HiddenInput(),
'type': StaticSelect(),
'mode': StaticSelect(),
'rf_role': StaticSelect(),
'rf_channel': StaticSelect(),
'rf_channel_width': StaticSelect(),
}

View File

@ -467,6 +467,12 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm):
required=False,
widget=StaticSelect()
)
rf_role = forms.ChoiceField(
choices=add_blank_choice(WirelessRoleChoices),
required=False,
widget=StaticSelect(),
label='Wireless role'
)
rf_channel = forms.ChoiceField(
choices=add_blank_choice(WirelessChannelChoices),
required=False,
@ -489,8 +495,8 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm):
)
field_order = (
'device', 'name_pattern', 'label_pattern', 'type', 'enabled', 'parent', 'lag', 'mtu', 'mac_address',
'description', 'mgmt_only', 'mark_connected', 'rf_channel', 'rf_channel_width', 'mode' 'untagged_vlan',
'tagged_vlans', 'tags'
'description', 'mgmt_only', 'mark_connected', 'rf_role', 'rf_channel', 'rf_channel_width', 'mode',
'untagged_vlan', 'tagged_vlans', 'tags'
)
def __init__(self, *args, **kwargs):

View File

@ -206,6 +206,9 @@ class InterfaceType(IPAddressesMixin, ComponentObjectType):
def resolve_mode(self, info):
return self.mode or None
def resolve_rf_role(self, info):
return self.rf_role or None
def resolve_rf_channel(self, info):
return self.rf_channel or None

View File

@ -1,5 +1,3 @@
# Generated by Django 3.2.8 on 2021-10-13 13:44
from django.db import migrations, models
@ -10,6 +8,11 @@ class Migration(migrations.Migration):
]
operations = [
migrations.AddField(
model_name='interface',
name='rf_role',
field=models.CharField(blank=True, max_length=30),
),
migrations.AddField(
model_name='interface',
name='rf_channel',

View File

@ -524,6 +524,12 @@ class Interface(ComponentModel, BaseInterface, LinkTermination, PathEndpoint):
verbose_name='WWN',
help_text='64-bit World Wide Name'
)
rf_role = models.CharField(
max_length=30,
choices=WirelessRoleChoices,
blank=True,
verbose_name='Wireless role'
)
rf_channel = models.CharField(
max_length=50,
choices=WirelessChannelChoices,
@ -636,9 +642,11 @@ class Interface(ComponentModel, BaseInterface, LinkTermination, PathEndpoint):
raise ValidationError({'lag': "A LAG interface cannot be its own parent."})
# RF channel attributes may be set only for wireless interfaces
if self.rf_channel and self.type not in WIRELESS_IFACE_TYPES:
if self.rf_role and not self.is_wireless:
raise ValidationError({'rf_role': "Wireless role may be set only on wireless interfaces."})
if self.rf_channel and not self.is_wireless:
raise ValidationError({'rf_channel': "Channel may be set only on wireless interfaces."})
if self.rf_channel_width and self.type not in WIRELESS_IFACE_TYPES:
if self.rf_channel_width and not self.is_wireless:
raise ValidationError({'rf_channel_width': "Channel width may be set only on wireless interfaces."})
# Validate untagged VLAN

View File

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

View File

@ -39,16 +39,6 @@
<th scope="row">Type</th>
<td>{{ object.get_type_display }}</td>
</tr>
{% if object.is_wireless %}
<tr>
<th scope="row">Channel</th>
<td>{{ object.get_rf_channel_display|placeholder }}</td>
</tr>
<tr>
<th scope="row">Channel Width</th>
<td>{{ object.get_rf_channel_width_display|placeholder }}</td>
</tr>
{% endif %}
<tr>
<th scope="row">Enabled</th>
<td>
@ -274,6 +264,25 @@
</div>
{% endif %}
{% if object.is_wireless %}
<div class="card">
<h5 class="card-header">Wireless</h5>
<div class="card-body">
<table class="table table-hover">
<tr>
<th scope="row">Role</th>
<td>{{ object.get_rf_role_display|placeholder }}</td>
</tr>
<tr>
<th scope="row">Channel</th>
<td>{{ object.get_rf_channel_display|placeholder }}</td>
</tr>
<tr>
<th scope="row">Channel Width</th>
<td>{{ object.get_rf_channel_width_display|placeholder }}</td>
</tr>
</table>
</div>
</div>
<div class="card">
<h5 class="card-header">Wireless LANs</h5>
<div class="card-body">

View File

@ -34,6 +34,7 @@
<div class="row mb-2">
<h5 class="offset-sm-3">Wireless</h5>
</div>
{% render_field form.rf_role %}
{% render_field form.rf_channel %}
{% render_field form.rf_channel_width %}
{% render_field form.wireless_lans %}