4867 multiple mac addresses (#17902)

* Create MACAddress model and migrations to convert existing .mac_address fields to standalone objects

* Add migrations

* All views/filtering working and documentation done; no unit tests yet

* Redo migrations following VLAN Translation

* Remove mac_address filter fields and add table columns for device/vm

* Remove unnecessary "bulk rename"

* Fix filterset tests for Device

* Fix filterset tests for Interface

* Fix tests on single-object forms

* Fix serializer tests

* Fix filterset tests for VMInterface

* Fix filterset tests for Device and VirtualMachine

* Move new field check into lookup_map iteration

* Fix general MACAddress filter tests

* Add GraphQL types/filters/schema

* Fix bulk edit/create tests (bulk editing Interfaces will be unsupported because of inheritance from ComponentBulkEditForm)

* Make mac_address read_only on InterfaceSerializer/VMInterfaceSerializer

* Undo unrelated work

* Cleanup unused IPAddress derived stuff

* API endpoints

* Add serializer objects to interface serializers

* Clean up unnecessary bulk create forms/views/routes

* Add SearchIndex and adjust indexable fields for Interface and VMInterface

* Reorganize MACAddress classes out of association with DeviceComponents

* Move MACAddressSerializer

* Enforce saving only a single is_primary MACAddress per interface/vminterface

* Perform is_primary validation on MACAddress model and just check if one already exists for the interface

* Remove form-level validation

* Fix check for current is_primary setting when reassigning

* Model cleanup

* Documentation notes and cleanup

* Simplify serializer and add ip_addresses

* Add to VMInterfaceSerializer too

* Style cleanup

* Standardize "MAC Address" instead of "MAC"

* Remove unused views

* Add is_primary field for bulk edit

* HTML cleanup and add copy-to-clipboard button

* Remove mac_address from Interface and VMInterface bulk-edit forms

* Add device and VM filtering

* Use combined assigned_object_parent in table to match structure of IPAddressTable

* Add GFK fields to MACAddressSerializer

* Reorganize "Addressing" sections to remove from proximity to "Device Components" and related groupings

* Clean up migrations

* Misc cleanup

* Add filterset test

* Remove mac_address field from interface forms

* Designate primary MAC address via a ForeignKey on the interface models

* Add serializer fields for primary_mac_address

* Update docs

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
bctiemann
2024-11-18 15:11:24 -05:00
committed by GitHub
parent b4f15092db
commit 353214098b
46 changed files with 1156 additions and 173 deletions

View File

@@ -23,6 +23,7 @@ __all__ = (
'InventoryItemFilter',
'InventoryItemRoleFilter',
'LocationFilter',
'MACAddressFilter',
'ManufacturerFilter',
'ModuleFilter',
'ModuleBayFilter',
@@ -133,6 +134,12 @@ class FrontPortTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.MACAddress, lookups=True)
@autotype_decorator(filtersets.MACAddressFilterSet)
class MACAddressFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Interface, lookups=True)
@autotype_decorator(filtersets.InterfaceFilterSet)
class InterfaceFilter(BaseFilterMixin):

View File

@@ -44,6 +44,9 @@ class DCIMQuery:
front_port_template: FrontPortTemplateType = strawberry_django.field()
front_port_template_list: List[FrontPortTemplateType] = strawberry_django.field()
mac_address: MACAddressType = strawberry_django.field()
mac_address_list: List[MACAddressType] = strawberry_django.field()
interface: InterfaceType = strawberry_django.field()
interface_list: List[InterfaceType] = strawberry_django.field()

View File

@@ -34,6 +34,7 @@ __all__ = (
'InventoryItemRoleType',
'InventoryItemTemplateType',
'LocationType',
'MACAddressType',
'ManufacturerType',
'ModularComponentType',
'ModuleType',
@@ -366,6 +367,22 @@ class FrontPortTemplateType(ModularComponentTemplateType):
rear_port: Annotated["RearPortTemplateType", strawberry.lazy('dcim.graphql.types')]
@strawberry_django.type(
models.MACAddress,
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,
exclude=('_path',),
@@ -373,7 +390,6 @@ class FrontPortTemplateType(ModularComponentTemplateType):
)
class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, PathEndpointMixin):
_name: str
mac_address: str | None
wwn: str | None
parent: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None
bridge: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None
@@ -381,6 +397,7 @@ class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, P
wireless_link: Annotated["WirelessLinkType", strawberry.lazy('wireless.graphql.types')] | None
untagged_vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
primary_mac_address: Annotated["MACAddressType", strawberry.lazy('dcim.graphql.types')] | None
qinq_svlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
vlan_translation_policy: Annotated["VLANTranslationPolicyType", strawberry.lazy('ipam.graphql.types')] | None
@@ -390,6 +407,7 @@ class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, P
wireless_lans: List[Annotated["WirelessLANType", strawberry.lazy('wireless.graphql.types')]]
member_interfaces: List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]
child_interfaces: List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]
mac_addresses: List[Annotated["MACAddressType", strawberry.lazy('dcim.graphql.types')]]
@strawberry_django.type(