mirror of
https://github.com/netbox-community/netbox.git
synced 2026-02-03 22:06:26 -06:00
Simplify Multiple MAC addresses with additional selectable column for tables in list view and detail view
This commit is contained in:
@@ -732,25 +732,6 @@ class BaseInterface(models.Model):
|
|||||||
if self.primary_mac_address:
|
if self.primary_mac_address:
|
||||||
return self.primary_mac_address.mac_address
|
return self.primary_mac_address.mac_address
|
||||||
|
|
||||||
@property
|
|
||||||
def mac_address_display(self):
|
|
||||||
"""
|
|
||||||
Rich representation of MAC addresses for use in table columns (e.g. InterfaceTable).
|
|
||||||
Handles various configurations of MAC addresses for an interface:
|
|
||||||
11:22:33:44:55:66 <-- Single MAC address on interface, assigned as primary
|
|
||||||
11:22:33:44:55:66 (2) <-- Multiple MAC addresses on interface, one assigned as primary
|
|
||||||
2 available <-- 1 or more MAC addresses on interface, none assigned as primary
|
|
||||||
- <-- No MAC addresses on interface
|
|
||||||
"""
|
|
||||||
available_mac_count = self.mac_addresses.count()
|
|
||||||
if self.primary_mac_address:
|
|
||||||
if available_mac_count > 1:
|
|
||||||
return f"{self.primary_mac_address} ({available_mac_count})"
|
|
||||||
return self.primary_mac_address
|
|
||||||
if available_mac_count:
|
|
||||||
return f"{available_mac_count} available"
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class Interface(
|
class Interface(
|
||||||
InterfaceValidationMixin,
|
InterfaceValidationMixin,
|
||||||
|
|||||||
@@ -583,6 +583,15 @@ class BaseInterfaceTable(NetBoxTable):
|
|||||||
orderable=False,
|
orderable=False,
|
||||||
verbose_name=_('IP Addresses')
|
verbose_name=_('IP Addresses')
|
||||||
)
|
)
|
||||||
|
primary_mac_address = tables.Column(
|
||||||
|
verbose_name=_('MAC Address'),
|
||||||
|
linkify=True
|
||||||
|
)
|
||||||
|
mac_addresses = tables.TemplateColumn(
|
||||||
|
template_code=INTERFACE_MACADDRESSES,
|
||||||
|
orderable=False,
|
||||||
|
verbose_name=_('MAC Addresses')
|
||||||
|
)
|
||||||
fhrp_groups = tables.TemplateColumn(
|
fhrp_groups = tables.TemplateColumn(
|
||||||
accessor=Accessor('fhrp_group_assignments'),
|
accessor=Accessor('fhrp_group_assignments'),
|
||||||
template_code=INTERFACE_FHRPGROUPS,
|
template_code=INTERFACE_FHRPGROUPS,
|
||||||
@@ -614,11 +623,6 @@ class BaseInterfaceTable(NetBoxTable):
|
|||||||
verbose_name=_('Q-in-Q SVLAN'),
|
verbose_name=_('Q-in-Q SVLAN'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
primary_mac_address = tables.Column(
|
|
||||||
verbose_name=_('MAC Address'),
|
|
||||||
accessor=Accessor('mac_address_display'),
|
|
||||||
linkify=True
|
|
||||||
)
|
|
||||||
|
|
||||||
def value_ip_addresses(self, value):
|
def value_ip_addresses(self, value):
|
||||||
return ",".join([str(obj.address) for obj in value.all()])
|
return ",".join([str(obj.address) for obj in value.all()])
|
||||||
@@ -681,11 +685,12 @@ class InterfaceTable(BaseInterfaceTable, ModularDeviceComponentTable, PathEndpoi
|
|||||||
model = models.Interface
|
model = models.Interface
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'enabled', 'type', 'mgmt_only', 'mtu',
|
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'enabled', 'type', 'mgmt_only', 'mtu',
|
||||||
'speed', 'speed_formatted', 'duplex', 'mode', 'primary_mac_address', 'wwn', 'poe_mode', 'poe_type',
|
'speed', 'speed_formatted', 'duplex', 'mode', 'mac_addresses', 'primary_mac_address', 'wwn',
|
||||||
'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description',
|
'poe_mode', 'poe_type', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power',
|
||||||
'mark_connected', 'cable', 'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection',
|
'description', 'mark_connected', 'cable', 'cable_color', 'wireless_link', 'wireless_lans', 'link_peer',
|
||||||
'tags', 'vdcs', 'vrf', 'l2vpn', 'tunnel', 'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans',
|
'connection', 'tags', 'vdcs', 'vrf', 'l2vpn', 'tunnel', 'ip_addresses', 'fhrp_groups',
|
||||||
'qinq_svlan', 'inventory_items', 'created', 'last_updated', 'vlan_translation_policy'
|
'untagged_vlan', 'tagged_vlans', 'qinq_svlan', 'inventory_items', 'created', 'last_updated',
|
||||||
|
'vlan_translation_policy',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'name', 'device', 'label', 'enabled', 'type', 'description')
|
default_columns = ('pk', 'name', 'device', 'label', 'enabled', 'type', 'description')
|
||||||
|
|
||||||
@@ -719,10 +724,11 @@ class DeviceInterfaceTable(InterfaceTable):
|
|||||||
model = models.Interface
|
model = models.Interface
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'enabled', 'type', 'parent', 'bridge', 'lag',
|
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'enabled', 'type', 'parent', 'bridge', 'lag',
|
||||||
'mgmt_only', 'mtu', 'mode', 'primary_mac_address', 'wwn', 'rf_role', 'rf_channel', 'rf_channel_frequency',
|
'mgmt_only', 'mtu', 'mode', 'mac_addresses', 'primary_mac_address', 'wwn', 'rf_role', 'rf_channel',
|
||||||
'rf_channel_width', 'tx_power', 'description', 'mark_connected', 'cable', 'cable_color', 'wireless_link',
|
'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', 'mark_connected', 'cable',
|
||||||
'wireless_lans', 'link_peer', 'connection', 'tags', 'vdcs', 'vrf', 'l2vpn', 'tunnel', 'ip_addresses',
|
'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection', 'tags', 'vdcs', 'vrf',
|
||||||
'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'qinq_svlan', 'actions',
|
'l2vpn', 'tunnel', 'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'qinq_svlan',
|
||||||
|
'actions',
|
||||||
)
|
)
|
||||||
default_columns = (
|
default_columns = (
|
||||||
'pk', 'name', 'label', 'enabled', 'type', 'parent', 'lag', 'mtu', 'mode', 'description', 'ip_addresses',
|
'pk', 'name', 'label', 'enabled', 'type', 'parent', 'lag', 'mtu', 'mode', 'description', 'ip_addresses',
|
||||||
@@ -1172,4 +1178,6 @@ class MACAddressTable(PrimaryModelTable):
|
|||||||
'pk', 'id', 'mac_address', 'assigned_object_parent', 'assigned_object', 'description', 'is_primary',
|
'pk', 'id', 'mac_address', 'assigned_object_parent', 'assigned_object', 'description', 'is_primary',
|
||||||
'comments', 'tags', 'created', 'last_updated',
|
'comments', 'tags', 'created', 'last_updated',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'mac_address', 'assigned_object_parent', 'assigned_object', 'description')
|
default_columns = (
|
||||||
|
'pk', 'mac_address', 'is_primary', 'assigned_object_parent', 'assigned_object', 'description',
|
||||||
|
)
|
||||||
|
|||||||
@@ -62,6 +62,16 @@ INTERFACE_IPADDRESSES = """
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
INTERFACE_MACADDRESSES = """
|
||||||
|
{% if value.count > 3 %}
|
||||||
|
<a href="{% url 'ipam:macaddress_list' %}?{{ record|meta:"model_name" }}_id={{ record.pk }}">{{ value.count }}</a>
|
||||||
|
{% else %}
|
||||||
|
{% for mac in value.all %}
|
||||||
|
<a href="{{ mac.get_absolute_url }}">{{ mac }}</a>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
"""
|
||||||
|
|
||||||
INTERFACE_FHRPGROUPS = """
|
INTERFACE_FHRPGROUPS = """
|
||||||
{% for assignment in value.all %}
|
{% for assignment in value.all %}
|
||||||
<a href="{{ assignment.group.get_absolute_url }}">{{ assignment.group }}</a>
|
<a href="{{ assignment.group.get_absolute_url }}">{{ assignment.group }}</a>
|
||||||
|
|||||||
@@ -143,11 +143,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{% trans "MAC Address" %}</th>
|
<th scope="row">{% trans "MAC Address" %}</th>
|
||||||
<td>
|
<td>
|
||||||
{% if object.mac_address_display %}
|
{% if object.primary_mac_address %}
|
||||||
<span class="font-monospace">{{ object.mac_address_display|linkify }}</span>
|
<span class="font-monospace">{{ object.primary_mac_address|linkify }}</span>
|
||||||
{% if object.primary_mac_address %}
|
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
|
||||||
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ ''|placeholder }}
|
{{ ''|placeholder }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -78,11 +78,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{% trans "MAC Address" %}</th>
|
<th scope="row">{% trans "MAC Address" %}</th>
|
||||||
<td>
|
<td>
|
||||||
{% if object.mac_address_display %}
|
{% if object.primary_mac_address %}
|
||||||
<span class="font-monospace">{{ object.mac_address_display|linkify }}</span>
|
<span class="font-monospace">{{ object.primary_mac_address|linkify }}</span>
|
||||||
{% if object.primary_mac_address %}
|
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
|
||||||
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ ''|placeholder }}
|
{{ ''|placeholder }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
Reference in New Issue
Block a user