mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-29 03:46:25 -06:00
Misc cleanup
This commit is contained in:
parent
3183f376bd
commit
0575dfff85
@ -1,8 +1,8 @@
|
||||
# MAC Addresses
|
||||
|
||||
A MAC address object in NetBox comprises a single physical (hardware) address, and represents a MAC address as reported by or assigned to a network interface. MAC addresses can be assigned to [device](../dcim/device.md) and [virtual machine](../virtualization/virtualmachine.md) interfaces. A MAC address can be specified as the "primary" MAC address for a given interface or VM interface.
|
||||
A MAC address object in NetBox comprises a single Ethernet link layer address, and represents a MAC address as reported by or assigned to a network interface. MAC addresses can be assigned to [device](../dcim/device.md) and [virtual machine](../virtualization/virtualmachine.md) interfaces. A MAC address can be specified as the "primary" MAC address for a given interface or VM interface.
|
||||
|
||||
Most interfaces only have a single MAC address, hard-coded at the factory. However, on some devices (particularly virtual interfaces) it is possible to assign additional MAC addresses or change existing ones. For this reason NetBox allows multiple MACAddress objects to be assigned to a single interface. However, for convenience and backward compatibiility reasons, the value of the `mac_address` field of the primary (or single) MAC address on an interface is reflected as a simple property in the interface detail page.
|
||||
Most interfaces have only a single MAC address, hard-coded at the factory. However, on some devices (particularly virtual interfaces) it is possible to assign additional MAC addresses or change existing ones. For this reason NetBox allows multiple MACAddress objects to be assigned to a single interface. However, for convenience and backward compatibiility reasons, the value of the `mac_address` field of the primary (or single) MAC address on an interface is reflected as a simple property in the interface detail page.
|
||||
|
||||
## Fields
|
||||
|
||||
|
@ -10,7 +10,6 @@ from dcim.models import (
|
||||
)
|
||||
from ipam.api.serializers_.vlans import VLANSerializer, VLANTranslationPolicySerializer
|
||||
from ipam.api.serializers_.vrfs import VRFSerializer
|
||||
from ipam.api.serializers_.ip import IPAddressSerializer
|
||||
from ipam.models import VLAN
|
||||
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
|
||||
from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer
|
||||
@ -216,7 +215,6 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
|
||||
read_only=True
|
||||
)
|
||||
mac_addresses = MACAddressSerializer(many=True, nested=True, read_only=True, allow_null=True)
|
||||
ip_addresses = IPAddressSerializer(many=True, nested=True, read_only=True, allow_null=True)
|
||||
wwn = serializers.CharField(required=False, default=None, allow_blank=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
@ -229,7 +227,7 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
|
||||
'cable', 'cable_end', 'wireless_link', 'link_peers', 'link_peers_type', 'wireless_lans', 'vrf',
|
||||
'l2vpn_termination', 'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable',
|
||||
'tags', 'custom_fields', 'created', 'last_updated', 'count_ipaddresses', 'count_fhrp_groups', '_occupied',
|
||||
'mac_addresses', 'ip_addresses',
|
||||
'mac_addresses',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'device', 'name', 'description', 'cable', '_occupied')
|
||||
|
||||
|
@ -20,7 +20,7 @@ from utilities.filters import (
|
||||
ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
|
||||
NumericArrayFilter, TreeNodeMultipleChoiceFilter,
|
||||
)
|
||||
from virtualization.models import Cluster, ClusterGroup, VMInterface
|
||||
from virtualization.models import Cluster, ClusterGroup, VMInterface, VirtualMachine
|
||||
from vpn.models import L2VPN
|
||||
from wireless.choices import WirelessRoleChoices, WirelessChannelChoices
|
||||
from wireless.models import WirelessLAN, WirelessLink
|
||||
@ -1659,7 +1659,7 @@ class MACAddressFilterSet(NetBoxModelFilterSet):
|
||||
return queryset.filter(qs_filter)
|
||||
|
||||
def filter_device(self, queryset, name, value):
|
||||
devices = Device.objects.filter(**{'{}__in'.format(name): value})
|
||||
devices = Device.objects.filter(**{f'{name}__in': value})
|
||||
if not devices.exists():
|
||||
return queryset.none()
|
||||
interface_ids = []
|
||||
@ -1670,7 +1670,7 @@ class MACAddressFilterSet(NetBoxModelFilterSet):
|
||||
)
|
||||
|
||||
def filter_virtual_machine(self, queryset, name, value):
|
||||
virtual_machines = VirtualMachine.objects.filter(**{'{}__in'.format(name): value})
|
||||
virtual_machines = VirtualMachine.objects.filter(**{f'{name}__in': value})
|
||||
if not virtual_machines.exists():
|
||||
return queryset.none()
|
||||
interface_ids = []
|
||||
|
@ -1233,10 +1233,9 @@ class MACAddressImportForm(NetBoxModelImportForm):
|
||||
is_primary = self.cleaned_data.get('is_primary')
|
||||
|
||||
# Validate is_primary
|
||||
# TODO: scope to interface rather than device/VM
|
||||
if is_primary and not device and not virtual_machine:
|
||||
if interface and not device and not virtual_machine:
|
||||
raise forms.ValidationError({
|
||||
"is_primary": _("No device or virtual machine specified; cannot set as primary")
|
||||
"interface": _("Must specify the parent device or VM when assigning an interface")
|
||||
})
|
||||
if is_primary and not interface:
|
||||
raise forms.ValidationError({
|
||||
|
@ -1583,7 +1583,7 @@ class MACAddressFilterForm(NetBoxModelFilterSetForm):
|
||||
model = MACAddress
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('mac_address', name=_('Addressing')),
|
||||
FieldSet('mac_address', 'is_primary', name=_('Addressing')),
|
||||
FieldSet('device_id', 'virtual_machine_id', name=_('Device/VM')),
|
||||
)
|
||||
selector_fields = ('filter_id', 'q', 'device_id', 'virtual_machine_id')
|
||||
@ -1591,6 +1591,13 @@ class MACAddressFilterForm(NetBoxModelFilterSetForm):
|
||||
required=False,
|
||||
label=_('MAC address')
|
||||
)
|
||||
is_primary = forms.NullBooleanField(
|
||||
required=False,
|
||||
label=_('Is primary'),
|
||||
widget=forms.Select(
|
||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||
)
|
||||
)
|
||||
device_id = DynamicModelMultipleChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
|
@ -369,12 +369,19 @@ class FrontPortTemplateType(ModularComponentTemplateType):
|
||||
|
||||
@strawberry_django.type(
|
||||
models.MACAddress,
|
||||
fields='__all__',
|
||||
exclude=('assigned_object_type', 'assigned_object_id'),
|
||||
filters=MACAddressFilter
|
||||
)
|
||||
class MACAddressType(NetBoxObjectType):
|
||||
mac_address: str
|
||||
|
||||
@strawberry_django.field
|
||||
def assigned_object(self) -> Annotated[Union[
|
||||
Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')],
|
||||
Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')],
|
||||
], strawberry.union("MACAddressAssignmentType")] | None:
|
||||
return self.assigned_object
|
||||
|
||||
|
||||
@strawberry_django.type(
|
||||
models.Interface,
|
||||
|
@ -606,7 +606,7 @@ class BaseInterface(models.Model):
|
||||
|
||||
@cached_property
|
||||
def mac_address(self):
|
||||
if macaddress := self.mac_addresses.order_by('-is_primary').first():
|
||||
if macaddress := self.mac_addresses.order_by('-is_primary', 'mac_address').first():
|
||||
return macaddress.mac_address
|
||||
return None
|
||||
|
||||
|
@ -1516,7 +1516,12 @@ class MACAddress(PrimaryModel):
|
||||
super().clean()
|
||||
|
||||
if self.is_primary and self.assigned_object:
|
||||
if self.assigned_object.mac_addresses.filter(is_primary=True).exclude(pk=self.pk).exists():
|
||||
peer_macs = MACAddress.objects.exclude(pk=self.pk).filter(
|
||||
assigned_object_type=self.assigned_object_type,
|
||||
assigned_object_id=self.assigned_object_id,
|
||||
is_primary=True
|
||||
)
|
||||
if peer_macs.exists():
|
||||
raise ValidationError({
|
||||
'is_primary': _("There is already a primary MAC address for this interface.")
|
||||
'is_primary': _("A primary MAC address is already designated for this interface.")
|
||||
})
|
||||
|
@ -101,7 +101,6 @@ class VMInterfaceSerializer(NetBoxModelSerializer):
|
||||
read_only=True
|
||||
)
|
||||
mac_addresses = MACAddressSerializer(many=True, nested=True, read_only=True, allow_null=True)
|
||||
ip_addresses = IPAddressSerializer(many=True, nested=True, read_only=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = VMInterface
|
||||
@ -109,7 +108,7 @@ class VMInterfaceSerializer(NetBoxModelSerializer):
|
||||
'id', 'url', 'display_url', 'display', 'virtual_machine', 'name', 'enabled', 'parent', 'bridge', 'mtu',
|
||||
'mac_address', 'description', 'mode', 'untagged_vlan', 'tagged_vlans', 'qinq_svlan',
|
||||
'vlan_translation_policy', 'vrf', 'l2vpn_termination', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'count_ipaddresses', 'count_fhrp_groups', 'mac_addresses', 'ip_addresses',
|
||||
'count_ipaddresses', 'count_fhrp_groups', 'mac_addresses',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'virtual_machine', 'name', 'description')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user