Include cable_peer on CableTermination serializers

This commit is contained in:
Jeremy Stretch 2020-10-06 14:30:46 -04:00
parent c813ae4f04
commit 23cde6d1b8
4 changed files with 84 additions and 33 deletions

View File

@ -60,20 +60,35 @@ All end-to-end cable paths are now cached using the new CablePath model. This al
### REST API Changes ### REST API Changes
* Added support for `PUT`, `PATCH`, and `DELETE` operations on list endpoints * Added support for `PUT`, `PATCH`, and `DELETE` operations on list endpoints (bulk update and delete)
* circuits.CircuitTermination: Replaced `connection_status` with `connected_endpoint_reachable` (boolean) * circuits.CircuitTermination:
* Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
* Added `cable_peer`
* dcim.Cable: Added `custom_fields` * dcim.Cable: Added `custom_fields`
* dcim.ConsolePort: Replaced `connection_status` with `connected_endpoint_reachable` (boolean) * dcim.ConsolePort:
* dcim.ConsoleServerPort: Replaced `connection_status` with `connected_endpoint_reachable` (boolean) * Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
* dcim.FrontPort: Removed the `trace` endpoint * Added `cable_peer`
* dcim.Interface: Replaced `connection_status` with `connected_endpoint_reachable` (boolean) * dcim.ConsoleServerPort:
* Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
* Added `cable_peer`
* dcim.FrontPort:
* Removed the `trace` endpoint
* Added `cable_peer`
* dcim.Interface:
* Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
* Added `cable_peer`
* dcim.InventoryItem: The `_depth` field has been added to reflect MPTT positioning * dcim.InventoryItem: The `_depth` field has been added to reflect MPTT positioning
* dcim.PowerFeed: Add fields `connected_endpoint`, `connected_endpoint_type`, and `connected_endpoint_reachable` * dcim.PowerFeed: Add fields `connected_endpoint`, `connected_endpoint_type`, `connected_endpoint_reachable`, and `cable_peer`
* dcim.PowerOutlet: Replaced `connection_status` with `connected_endpoint_reachable` (boolean) * dcim.PowerOutlet:
* Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
* Added `cable_peer`
* dcim.PowerPanel: Added `custom_fields` * dcim.PowerPanel: Added `custom_fields`
* dcim.PowerPort: Replaced `connection_status` with `connected_endpoint_reachable` (boolean) * dcim.PowerPort
* Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
* Added `cable_peer`
* dcim.RackReservation: Added `custom_fields` * dcim.RackReservation: Added `custom_fields`
* dcim.RearPort: Removed the `trace` endpoint * dcim.RearPort:
* Removed the `trace` endpoint
* dcim.VirtualChassis: Added `custom_fields` * dcim.VirtualChassis: Added `custom_fields`
* extras.ExportTemplate: The `template_language` field has been removed * extras.ExportTemplate: The `template_language` field has been removed
* extras.Graph: This API endpoint has been removed (see #4349) * extras.Graph: This API endpoint has been removed (see #4349)

View File

@ -3,7 +3,7 @@ from rest_framework import serializers
from circuits.choices import CircuitStatusChoices from circuits.choices import CircuitStatusChoices
from circuits.models import Provider, Circuit, CircuitTermination, CircuitType from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
from dcim.api.nested_serializers import NestedCableSerializer, NestedInterfaceSerializer, NestedSiteSerializer from dcim.api.nested_serializers import NestedCableSerializer, NestedInterfaceSerializer, NestedSiteSerializer
from dcim.api.serializers import ConnectedEndpointSerializer from dcim.api.serializers import CableTerminationSerializer, ConnectedEndpointSerializer
from extras.api.customfields import CustomFieldModelSerializer from extras.api.customfields import CustomFieldModelSerializer
from extras.api.serializers import TaggedObjectSerializer from extras.api.serializers import TaggedObjectSerializer
from tenancy.api.nested_serializers import NestedTenantSerializer from tenancy.api.nested_serializers import NestedTenantSerializer
@ -67,7 +67,7 @@ class CircuitSerializer(TaggedObjectSerializer, CustomFieldModelSerializer):
] ]
class CircuitTerminationSerializer(ConnectedEndpointSerializer): class CircuitTerminationSerializer(CableTerminationSerializer, ConnectedEndpointSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuittermination-detail') url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuittermination-detail')
circuit = NestedCircuitSerializer() circuit = NestedCircuitSerializer()
site = NestedSiteSerializer() site = NestedSiteSerializer()

View File

@ -27,6 +27,27 @@ from virtualization.api.nested_serializers import NestedClusterSerializer
from .nested_serializers import * from .nested_serializers import *
class CableTerminationSerializer(serializers.ModelSerializer):
cable_peer_type = serializers.SerializerMethodField(read_only=True)
cable_peer = serializers.SerializerMethodField(read_only=True)
def get_cable_peer_type(self, obj):
if obj._cable_peer is not None:
return f'{obj._cable_peer._meta.app_label}.{obj._cable_peer._meta.model_name}'
return None
@swagger_serializer_method(serializer_or_field=serializers.DictField)
def get_cable_peer(self, obj):
"""
Return the appropriate serializer for the cable termination model.
"""
if obj._cable_peer is not None:
serializer = get_serializer_for_model(obj._cable_peer, prefix='Nested')
context = {'request': self.context['request']}
return serializer(obj._cable_peer, context=context).data
return None
class ConnectedEndpointSerializer(ValidatedModelSerializer): class ConnectedEndpointSerializer(ValidatedModelSerializer):
connected_endpoint_type = serializers.SerializerMethodField(read_only=True) connected_endpoint_type = serializers.SerializerMethodField(read_only=True)
connected_endpoint = serializers.SerializerMethodField(read_only=True) connected_endpoint = serializers.SerializerMethodField(read_only=True)
@ -452,7 +473,7 @@ class DeviceNAPALMSerializer(serializers.Serializer):
method = serializers.DictField() method = serializers.DictField()
class ConsoleServerPortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): class ConsoleServerPortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverport-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverport-detail')
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
type = ChoiceField( type = ChoiceField(
@ -466,11 +487,11 @@ class ConsoleServerPortSerializer(TaggedObjectSerializer, ConnectedEndpointSeria
model = ConsoleServerPort model = ConsoleServerPort
fields = [ fields = [
'id', 'url', 'device', 'name', 'label', 'type', 'description', 'connected_endpoint_type', 'id', 'url', 'device', 'name', 'label', 'type', 'description', 'connected_endpoint_type',
'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'tags', 'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'cable_peer', 'tags',
] ]
class ConsolePortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): class ConsolePortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleport-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleport-detail')
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
type = ChoiceField( type = ChoiceField(
@ -484,11 +505,11 @@ class ConsolePortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer)
model = ConsolePort model = ConsolePort
fields = [ fields = [
'id', 'url', 'device', 'name', 'label', 'type', 'description', 'connected_endpoint_type', 'id', 'url', 'device', 'name', 'label', 'type', 'description', 'connected_endpoint_type',
'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'tags', 'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'cable_peer', 'tags',
] ]
class PowerOutletSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): class PowerOutletSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlet-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlet-detail')
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
type = ChoiceField( type = ChoiceField(
@ -512,11 +533,12 @@ class PowerOutletSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer)
model = PowerOutlet model = PowerOutlet
fields = [ fields = [
'id', 'url', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'id', 'url', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description',
'connected_endpoint_type', 'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'tags', 'connected_endpoint_type', 'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'cable_peer',
'tags',
] ]
class PowerPortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): class PowerPortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerport-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerport-detail')
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
type = ChoiceField( type = ChoiceField(
@ -530,11 +552,12 @@ class PowerPortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer):
model = PowerPort model = PowerPort
fields = [ fields = [
'id', 'url', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'id', 'url', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description',
'connected_endpoint_type', 'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'tags', 'connected_endpoint_type', 'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'cable_peer',
'tags',
] ]
class InterfaceSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): class InterfaceSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
type = ChoiceField(choices=InterfaceTypeChoices) type = ChoiceField(choices=InterfaceTypeChoices)
@ -555,7 +578,7 @@ class InterfaceSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer):
fields = [ fields = [
'id', 'url', 'device', 'name', 'label', 'type', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only', 'id', 'url', 'device', 'name', 'label', 'type', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only',
'description', 'connected_endpoint_type', 'connected_endpoint', 'connected_endpoint_reachable', 'cable', 'description', 'connected_endpoint_type', 'connected_endpoint', 'connected_endpoint_reachable', 'cable',
'mode', 'untagged_vlan', 'tagged_vlans', 'tags', 'count_ipaddresses', 'cable_peer', 'mode', 'untagged_vlan', 'tagged_vlans', 'tags', 'count_ipaddresses',
] ]
# TODO: This validation should be handled by Interface.clean() # TODO: This validation should be handled by Interface.clean()
@ -579,7 +602,7 @@ class InterfaceSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer):
return super().validate(data) return super().validate(data)
class RearPortSerializer(TaggedObjectSerializer, ValidatedModelSerializer): class RearPortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ValidatedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearport-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearport-detail')
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
type = ChoiceField(choices=PortTypeChoices) type = ChoiceField(choices=PortTypeChoices)
@ -587,7 +610,9 @@ class RearPortSerializer(TaggedObjectSerializer, ValidatedModelSerializer):
class Meta: class Meta:
model = RearPort model = RearPort
fields = ['id', 'url', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'tags'] fields = [
'id', 'url', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags',
]
class FrontPortRearPortSerializer(WritableNestedSerializer): class FrontPortRearPortSerializer(WritableNestedSerializer):
@ -601,7 +626,7 @@ class FrontPortRearPortSerializer(WritableNestedSerializer):
fields = ['id', 'url', 'name', 'label'] fields = ['id', 'url', 'name', 'label']
class FrontPortSerializer(TaggedObjectSerializer, ValidatedModelSerializer): class FrontPortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ValidatedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontport-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontport-detail')
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
type = ChoiceField(choices=PortTypeChoices) type = ChoiceField(choices=PortTypeChoices)
@ -612,7 +637,7 @@ class FrontPortSerializer(TaggedObjectSerializer, ValidatedModelSerializer):
model = FrontPort model = FrontPort
fields = [ fields = [
'id', 'url', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'id', 'url', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable',
'tags', 'cable_peer', 'tags',
] ]
@ -760,7 +785,12 @@ class PowerPanelSerializer(TaggedObjectSerializer, CustomFieldModelSerializer):
fields = ['id', 'url', 'site', 'rack_group', 'name', 'tags', 'custom_fields', 'powerfeed_count'] fields = ['id', 'url', 'site', 'rack_group', 'name', 'tags', 'custom_fields', 'powerfeed_count']
class PowerFeedSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer, CustomFieldModelSerializer): class PowerFeedSerializer(
TaggedObjectSerializer,
CableTerminationSerializer,
ConnectedEndpointSerializer,
CustomFieldModelSerializer
):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerfeed-detail') url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerfeed-detail')
power_panel = NestedPowerPanelSerializer() power_panel = NestedPowerPanelSerializer()
rack = NestedRackSerializer( rack = NestedRackSerializer(

View File

@ -470,31 +470,35 @@ class DeviceViewSet(CustomFieldModelViewSet):
# #
class ConsolePortViewSet(PathEndpointMixin, ModelViewSet): class ConsolePortViewSet(PathEndpointMixin, ModelViewSet):
queryset = ConsolePort.objects.prefetch_related('device', '_path__destination', 'cable', 'tags') queryset = ConsolePort.objects.prefetch_related('device', '_path__destination', 'cable', '_cable_peer', 'tags')
serializer_class = serializers.ConsolePortSerializer serializer_class = serializers.ConsolePortSerializer
filterset_class = filters.ConsolePortFilterSet filterset_class = filters.ConsolePortFilterSet
class ConsoleServerPortViewSet(PathEndpointMixin, ModelViewSet): class ConsoleServerPortViewSet(PathEndpointMixin, ModelViewSet):
queryset = ConsoleServerPort.objects.prefetch_related('device', '_path__destination', 'cable', 'tags') queryset = ConsoleServerPort.objects.prefetch_related(
'device', '_path__destination', 'cable', '_cable_peer', 'tags'
)
serializer_class = serializers.ConsoleServerPortSerializer serializer_class = serializers.ConsoleServerPortSerializer
filterset_class = filters.ConsoleServerPortFilterSet filterset_class = filters.ConsoleServerPortFilterSet
class PowerPortViewSet(PathEndpointMixin, ModelViewSet): class PowerPortViewSet(PathEndpointMixin, ModelViewSet):
queryset = PowerPort.objects.prefetch_related('device', '_path__destination', 'cable', 'tags') queryset = PowerPort.objects.prefetch_related('device', '_path__destination', 'cable', '_cable_peer', 'tags')
serializer_class = serializers.PowerPortSerializer serializer_class = serializers.PowerPortSerializer
filterset_class = filters.PowerPortFilterSet filterset_class = filters.PowerPortFilterSet
class PowerOutletViewSet(PathEndpointMixin, ModelViewSet): class PowerOutletViewSet(PathEndpointMixin, ModelViewSet):
queryset = PowerOutlet.objects.prefetch_related('device', '_path__destination', 'cable', 'tags') queryset = PowerOutlet.objects.prefetch_related('device', '_path__destination', 'cable', '_cable_peer', 'tags')
serializer_class = serializers.PowerOutletSerializer serializer_class = serializers.PowerOutletSerializer
filterset_class = filters.PowerOutletFilterSet filterset_class = filters.PowerOutletFilterSet
class InterfaceViewSet(PathEndpointMixin, ModelViewSet): class InterfaceViewSet(PathEndpointMixin, ModelViewSet):
queryset = Interface.objects.prefetch_related('device', '_path__destination', 'cable', 'ip_addresses', 'tags') queryset = Interface.objects.prefetch_related(
'device', '_path__destination', 'cable', '_cable_peer', 'ip_addresses', 'tags'
)
serializer_class = serializers.InterfaceSerializer serializer_class = serializers.InterfaceSerializer
filterset_class = filters.InterfaceFilterSet filterset_class = filters.InterfaceFilterSet
@ -597,7 +601,9 @@ class PowerPanelViewSet(ModelViewSet):
# #
class PowerFeedViewSet(CustomFieldModelViewSet): class PowerFeedViewSet(CustomFieldModelViewSet):
queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack', '_path__destination', 'cable', 'tags') queryset = PowerFeed.objects.prefetch_related(
'power_panel', 'rack', '_path__destination', 'cable', '_cable_peer', 'tags'
)
serializer_class = serializers.PowerFeedSerializer serializer_class = serializers.PowerFeedSerializer
filterset_class = filters.PowerFeedFilterSet filterset_class = filters.PowerFeedFilterSet