devices.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import decimal
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.utils.translation import gettext as _
  4. from drf_spectacular.utils import extend_schema_field
  5. from rest_framework import serializers
  6. from dcim.choices import *
  7. from dcim.constants import MACADDRESS_ASSIGNMENT_MODELS
  8. from dcim.models import Device, DeviceBay, MACAddress, Module, VirtualDeviceContext
  9. from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
  10. from ipam.api.serializers_.ip import IPAddressSerializer
  11. from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
  12. from netbox.api.serializers import NetBoxModelSerializer
  13. from tenancy.api.serializers_.tenants import TenantSerializer
  14. from utilities.api import get_serializer_for_model
  15. from virtualization.api.serializers_.clusters import ClusterSerializer
  16. from .devicetypes import *
  17. from .platforms import PlatformSerializer
  18. from .racks import RackSerializer
  19. from .roles import DeviceRoleSerializer
  20. from .nested import NestedDeviceBaySerializer, NestedDeviceSerializer, NestedModuleBaySerializer
  21. from .sites import LocationSerializer, SiteSerializer
  22. from .virtualchassis import VirtualChassisSerializer
  23. __all__ = (
  24. 'DeviceSerializer',
  25. 'DeviceWithConfigContextSerializer',
  26. 'MACAddressSerializer',
  27. 'ModuleSerializer',
  28. 'VirtualDeviceContextSerializer',
  29. )
  30. class DeviceSerializer(NetBoxModelSerializer):
  31. device_type = DeviceTypeSerializer(nested=True)
  32. role = DeviceRoleSerializer(nested=True)
  33. tenant = TenantSerializer(
  34. nested=True,
  35. required=False,
  36. allow_null=True,
  37. default=None
  38. )
  39. platform = PlatformSerializer(nested=True, required=False, allow_null=True)
  40. site = SiteSerializer(nested=True)
  41. location = LocationSerializer(nested=True, required=False, allow_null=True, default=None)
  42. rack = RackSerializer(nested=True, required=False, allow_null=True, default=None)
  43. face = ChoiceField(choices=DeviceFaceChoices, allow_blank=True, default=lambda: '')
  44. position = serializers.DecimalField(
  45. max_digits=4,
  46. decimal_places=1,
  47. allow_null=True,
  48. label=_('Position (U)'),
  49. min_value=decimal.Decimal(0.5),
  50. default=None
  51. )
  52. status = ChoiceField(choices=DeviceStatusChoices, required=False)
  53. airflow = ChoiceField(choices=DeviceAirflowChoices, allow_blank=True, required=False)
  54. primary_ip = IPAddressSerializer(nested=True, read_only=True, allow_null=True)
  55. primary_ip4 = IPAddressSerializer(nested=True, required=False, allow_null=True)
  56. primary_ip6 = IPAddressSerializer(nested=True, required=False, allow_null=True)
  57. oob_ip = IPAddressSerializer(nested=True, required=False, allow_null=True)
  58. parent_device = serializers.SerializerMethodField()
  59. cluster = ClusterSerializer(nested=True, required=False, allow_null=True)
  60. virtual_chassis = VirtualChassisSerializer(nested=True, required=False, allow_null=True, default=None)
  61. vc_position = serializers.IntegerField(allow_null=True, max_value=255, min_value=0, default=None)
  62. config_template = ConfigTemplateSerializer(nested=True, required=False, allow_null=True, default=None)
  63. # Counter fields
  64. console_port_count = serializers.IntegerField(read_only=True)
  65. console_server_port_count = serializers.IntegerField(read_only=True)
  66. power_port_count = serializers.IntegerField(read_only=True)
  67. power_outlet_count = serializers.IntegerField(read_only=True)
  68. interface_count = serializers.IntegerField(read_only=True)
  69. front_port_count = serializers.IntegerField(read_only=True)
  70. rear_port_count = serializers.IntegerField(read_only=True)
  71. device_bay_count = serializers.IntegerField(read_only=True)
  72. module_bay_count = serializers.IntegerField(read_only=True)
  73. inventory_item_count = serializers.IntegerField(read_only=True)
  74. class Meta:
  75. model = Device
  76. fields = [
  77. 'id', 'url', 'display_url', 'display', 'name', 'device_type', 'role', 'tenant', 'platform', 'serial',
  78. 'asset_tag', 'site', 'location', 'rack', 'position', 'face', 'latitude', 'longitude', 'parent_device',
  79. 'status', 'airflow', 'primary_ip', 'primary_ip4', 'primary_ip6', 'oob_ip', 'cluster', 'virtual_chassis',
  80. 'vc_position', 'vc_priority', 'description', 'comments', 'config_template', 'local_context_data', 'tags',
  81. 'custom_fields', 'created', 'last_updated', 'console_port_count', 'console_server_port_count',
  82. 'power_port_count', 'power_outlet_count', 'interface_count', 'front_port_count', 'rear_port_count',
  83. 'device_bay_count', 'module_bay_count', 'inventory_item_count',
  84. ]
  85. brief_fields = ('id', 'url', 'display', 'name', 'description')
  86. @extend_schema_field(NestedDeviceSerializer(allow_null=True))
  87. def get_parent_device(self, obj):
  88. try:
  89. device_bay = obj.parent_bay
  90. except DeviceBay.DoesNotExist:
  91. return None
  92. context = {'request': self.context['request']}
  93. data = NestedDeviceSerializer(instance=device_bay.device, context=context).data
  94. data['device_bay'] = NestedDeviceBaySerializer(instance=device_bay, context=context).data
  95. return data
  96. class DeviceWithConfigContextSerializer(DeviceSerializer):
  97. config_context = serializers.SerializerMethodField(read_only=True, allow_null=True)
  98. class Meta(DeviceSerializer.Meta):
  99. fields = [
  100. 'id', 'url', 'display_url', 'display', 'name', 'device_type', 'role', 'tenant', 'platform', 'serial',
  101. 'asset_tag', 'site', 'location', 'rack', 'position', 'face', 'latitude', 'longitude', 'parent_device',
  102. 'status', 'airflow', 'primary_ip', 'primary_ip4', 'primary_ip6', 'oob_ip', 'cluster', 'virtual_chassis',
  103. 'vc_position', 'vc_priority', 'description', 'comments', 'config_template', 'config_context',
  104. 'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated', 'console_port_count',
  105. 'console_server_port_count', 'power_port_count', 'power_outlet_count', 'interface_count',
  106. 'front_port_count', 'rear_port_count', 'device_bay_count', 'module_bay_count', 'inventory_item_count',
  107. ]
  108. @extend_schema_field(serializers.JSONField(allow_null=True))
  109. def get_config_context(self, obj):
  110. return obj.get_config_context()
  111. class VirtualDeviceContextSerializer(NetBoxModelSerializer):
  112. device = DeviceSerializer(nested=True)
  113. identifier = serializers.IntegerField(allow_null=True, max_value=32767, min_value=0, required=False, default=None)
  114. tenant = TenantSerializer(nested=True, required=False, allow_null=True, default=None)
  115. primary_ip = IPAddressSerializer(nested=True, read_only=True, allow_null=True)
  116. primary_ip4 = IPAddressSerializer(nested=True, required=False, allow_null=True)
  117. primary_ip6 = IPAddressSerializer(nested=True, required=False, allow_null=True)
  118. status = ChoiceField(choices=VirtualDeviceContextStatusChoices)
  119. # Related object counts
  120. interface_count = RelatedObjectCountField('interfaces')
  121. class Meta:
  122. model = VirtualDeviceContext
  123. fields = [
  124. 'id', 'url', 'display_url', 'display', 'name', 'device', 'identifier', 'tenant', 'primary_ip',
  125. 'primary_ip4', 'primary_ip6', 'status', 'description', 'comments', 'tags', 'custom_fields',
  126. 'created', 'last_updated', 'interface_count',
  127. ]
  128. brief_fields = ('id', 'url', 'display', 'name', 'identifier', 'device', 'description')
  129. class ModuleSerializer(NetBoxModelSerializer):
  130. device = DeviceSerializer(nested=True)
  131. module_bay = NestedModuleBaySerializer()
  132. module_type = ModuleTypeSerializer(nested=True)
  133. status = ChoiceField(choices=ModuleStatusChoices, required=False)
  134. class Meta:
  135. model = Module
  136. fields = [
  137. 'id', 'url', 'display_url', 'display', 'device', 'module_bay', 'module_type', 'status', 'serial',
  138. 'asset_tag', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
  139. ]
  140. brief_fields = ('id', 'url', 'display', 'device', 'module_bay', 'module_type', 'description')
  141. class MACAddressSerializer(NetBoxModelSerializer):
  142. assigned_object_type = ContentTypeField(
  143. queryset=ContentType.objects.filter(MACADDRESS_ASSIGNMENT_MODELS),
  144. required=False,
  145. allow_null=True
  146. )
  147. assigned_object = serializers.SerializerMethodField(read_only=True)
  148. class Meta:
  149. model = MACAddress
  150. fields = [
  151. 'id', 'url', 'display_url', 'display', 'mac_address', 'assigned_object_type', 'assigned_object_id',
  152. 'assigned_object', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
  153. ]
  154. brief_fields = ('id', 'url', 'display', 'mac_address', 'description')
  155. @extend_schema_field(serializers.JSONField(allow_null=True))
  156. def get_assigned_object(self, obj):
  157. if obj.assigned_object is None:
  158. return None
  159. serializer = get_serializer_for_model(obj.assigned_object)
  160. context = {'request': self.context['request']}
  161. return serializer(obj.assigned_object, nested=True, context=context).data