Skip to content
19 changes: 19 additions & 0 deletions netbox/dcim/models/device_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,25 @@ def mac_address(self):
if self.primary_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(
InterfaceValidationMixin,
Expand Down
1 change: 1 addition & 0 deletions netbox/dcim/tables/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ class BaseInterfaceTable(NetBoxTable):
)
primary_mac_address = tables.Column(
verbose_name=_('MAC Address'),
accessor=Accessor('mac_address_display'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds significant overhead as currently implemented, triggering a count of MAC addresses for each interface in the table. Why don't we just introduce a non-default column that lists all assigned MAC addresses (perhaps annotating the primary), like we do for IP addresses? That seems much cleaner IMO, and it ensures the MAC addresses are efficiently prefetched.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, that's a better pattern. Done, also synchronized the vminterface.html MAC Address field HTML with interface.html which was overlooked before.

linkify=True
)

Expand Down
8 changes: 5 additions & 3 deletions netbox/templates/dcim/interface.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,11 @@ <h2 class="card-header">{% trans "Addressing" %}</h2>
<tr>
<th scope="row">{% trans "MAC Address" %}</th>
<td>
{% if object.primary_mac_address %}
<span class="font-monospace">{{ object.primary_mac_address|linkify }}</span>
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
{% if object.mac_address_display %}
<span class="font-monospace">{{ object.mac_address_display|linkify }}</span>
{% if object.primary_mac_address %}
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
{% endif %}
{% else %}
{{ ''|placeholder }}
{% endif %}
Expand Down
8 changes: 5 additions & 3 deletions netbox/templates/virtualization/vminterface.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ <h2 class="card-header">{% trans "Addressing" %}</h2>
<tr>
<th scope="row">{% trans "MAC Address" %}</th>
<td>
{% if object.mac_address %}
<span class="font-monospace">{{ object.mac_address }}</span>
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
{% if object.mac_address_display %}
<span class="font-monospace">{{ object.mac_address_display|linkify }}</span>
{% if object.primary_mac_address %}
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
{% endif %}
{% else %}
{{ ''|placeholder }}
{% endif %}
Expand Down