serializers.py 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. import decimal
  2. from django.contrib.contenttypes.models import ContentType
  3. from drf_yasg.utils import swagger_serializer_method
  4. from rest_framework import serializers
  5. from timezone_field.rest_framework import TimeZoneSerializerField
  6. from dcim.choices import *
  7. from dcim.constants import *
  8. from dcim.models import *
  9. from ipam.api.nested_serializers import (
  10. NestedASNSerializer, NestedIPAddressSerializer, NestedL2VPNTerminationSerializer, NestedVLANSerializer,
  11. NestedVRFSerializer,
  12. )
  13. from ipam.models import ASN, VLAN
  14. from netbox.api import ChoiceField, ContentTypeField, SerializedPKRelatedField
  15. from netbox.api.serializers import (
  16. NestedGroupModelSerializer, NetBoxModelSerializer, ValidatedModelSerializer, WritableNestedSerializer,
  17. )
  18. from netbox.config import ConfigItem
  19. from tenancy.api.nested_serializers import NestedTenantSerializer
  20. from users.api.nested_serializers import NestedUserSerializer
  21. from utilities.api import get_serializer_for_model
  22. from virtualization.api.nested_serializers import NestedClusterSerializer
  23. from wireless.api.nested_serializers import NestedWirelessLANSerializer, NestedWirelessLinkSerializer
  24. from wireless.choices import *
  25. from wireless.models import WirelessLAN
  26. from .nested_serializers import *
  27. class CabledObjectSerializer(serializers.ModelSerializer):
  28. cable = NestedCableSerializer(read_only=True)
  29. cable_end = serializers.CharField(read_only=True)
  30. link_peers_type = serializers.SerializerMethodField(read_only=True)
  31. link_peers = serializers.SerializerMethodField(read_only=True)
  32. _occupied = serializers.SerializerMethodField(read_only=True)
  33. def get_link_peers_type(self, obj):
  34. """
  35. Return the type of the peer link terminations, or None.
  36. """
  37. if not obj.cable:
  38. return None
  39. if obj.link_peers:
  40. return f'{obj.link_peers[0]._meta.app_label}.{obj.link_peers[0]._meta.model_name}'
  41. return None
  42. @swagger_serializer_method(serializer_or_field=serializers.ListField)
  43. def get_link_peers(self, obj):
  44. """
  45. Return the appropriate serializer for the link termination model.
  46. """
  47. if not obj.cable:
  48. return []
  49. # Return serialized peer termination objects
  50. if obj.link_peers:
  51. serializer = get_serializer_for_model(obj.link_peers[0], prefix='Nested')
  52. context = {'request': self.context['request']}
  53. return serializer(obj.link_peers, context=context, many=True).data
  54. return []
  55. @swagger_serializer_method(serializer_or_field=serializers.BooleanField)
  56. def get__occupied(self, obj):
  57. return obj._occupied
  58. class ConnectedEndpointsSerializer(serializers.ModelSerializer):
  59. """
  60. Legacy serializer for pre-v3.3 connections
  61. """
  62. connected_endpoints_type = serializers.SerializerMethodField(read_only=True)
  63. connected_endpoints = serializers.SerializerMethodField(read_only=True)
  64. connected_endpoints_reachable = serializers.SerializerMethodField(read_only=True)
  65. def get_connected_endpoints_type(self, obj):
  66. endpoints = obj.connected_endpoints
  67. if endpoints:
  68. return f'{endpoints[0]._meta.app_label}.{endpoints[0]._meta.model_name}'
  69. @swagger_serializer_method(serializer_or_field=serializers.ListField)
  70. def get_connected_endpoints(self, obj):
  71. """
  72. Return the appropriate serializer for the type of connected object.
  73. """
  74. endpoints = obj.connected_endpoints
  75. if endpoints:
  76. serializer = get_serializer_for_model(endpoints[0], prefix='Nested')
  77. context = {'request': self.context['request']}
  78. return serializer(endpoints, many=True, context=context).data
  79. @swagger_serializer_method(serializer_or_field=serializers.BooleanField)
  80. def get_connected_endpoints_reachable(self, obj):
  81. return obj._path and obj._path.is_complete and obj._path.is_active
  82. #
  83. # Regions/sites
  84. #
  85. class RegionSerializer(NestedGroupModelSerializer):
  86. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:region-detail')
  87. parent = NestedRegionSerializer(required=False, allow_null=True, default=None)
  88. site_count = serializers.IntegerField(read_only=True)
  89. class Meta:
  90. model = Region
  91. fields = [
  92. 'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created',
  93. 'last_updated', 'site_count', '_depth',
  94. ]
  95. class SiteGroupSerializer(NestedGroupModelSerializer):
  96. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:sitegroup-detail')
  97. parent = NestedSiteGroupSerializer(required=False, allow_null=True, default=None)
  98. site_count = serializers.IntegerField(read_only=True)
  99. class Meta:
  100. model = SiteGroup
  101. fields = [
  102. 'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created',
  103. 'last_updated', 'site_count', '_depth',
  104. ]
  105. class SiteSerializer(NetBoxModelSerializer):
  106. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:site-detail')
  107. status = ChoiceField(choices=SiteStatusChoices, required=False)
  108. region = NestedRegionSerializer(required=False, allow_null=True)
  109. group = NestedSiteGroupSerializer(required=False, allow_null=True)
  110. tenant = NestedTenantSerializer(required=False, allow_null=True)
  111. time_zone = TimeZoneSerializerField(required=False)
  112. asns = SerializedPKRelatedField(
  113. queryset=ASN.objects.all(),
  114. serializer=NestedASNSerializer,
  115. required=False,
  116. many=True
  117. )
  118. # Related object counts
  119. circuit_count = serializers.IntegerField(read_only=True)
  120. device_count = serializers.IntegerField(read_only=True)
  121. prefix_count = serializers.IntegerField(read_only=True)
  122. rack_count = serializers.IntegerField(read_only=True)
  123. virtualmachine_count = serializers.IntegerField(read_only=True)
  124. vlan_count = serializers.IntegerField(read_only=True)
  125. class Meta:
  126. model = Site
  127. fields = [
  128. 'id', 'url', 'display', 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'time_zone',
  129. 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments', 'asns', 'tags',
  130. 'custom_fields', 'created', 'last_updated', 'circuit_count', 'device_count', 'prefix_count', 'rack_count',
  131. 'virtualmachine_count', 'vlan_count',
  132. ]
  133. #
  134. # Racks
  135. #
  136. class LocationSerializer(NestedGroupModelSerializer):
  137. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:location-detail')
  138. site = NestedSiteSerializer()
  139. parent = NestedLocationSerializer(required=False, allow_null=True)
  140. status = ChoiceField(choices=LocationStatusChoices, required=False)
  141. tenant = NestedTenantSerializer(required=False, allow_null=True)
  142. rack_count = serializers.IntegerField(read_only=True)
  143. device_count = serializers.IntegerField(read_only=True)
  144. class Meta:
  145. model = Location
  146. fields = [
  147. 'id', 'url', 'display', 'name', 'slug', 'site', 'parent', 'status', 'tenant', 'description', 'tags',
  148. 'custom_fields', 'created', 'last_updated', 'rack_count', 'device_count', '_depth',
  149. ]
  150. class RackRoleSerializer(NetBoxModelSerializer):
  151. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackrole-detail')
  152. rack_count = serializers.IntegerField(read_only=True)
  153. class Meta:
  154. model = RackRole
  155. fields = [
  156. 'id', 'url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields', 'created',
  157. 'last_updated', 'rack_count',
  158. ]
  159. class RackSerializer(NetBoxModelSerializer):
  160. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rack-detail')
  161. site = NestedSiteSerializer()
  162. location = NestedLocationSerializer(required=False, allow_null=True, default=None)
  163. tenant = NestedTenantSerializer(required=False, allow_null=True)
  164. status = ChoiceField(choices=RackStatusChoices, required=False)
  165. role = NestedRackRoleSerializer(required=False, allow_null=True)
  166. type = ChoiceField(choices=RackTypeChoices, allow_blank=True, required=False)
  167. facility_id = serializers.CharField(max_length=50, allow_blank=True, allow_null=True, label='Facility ID',
  168. default=None)
  169. width = ChoiceField(choices=RackWidthChoices, required=False)
  170. outer_unit = ChoiceField(choices=RackDimensionUnitChoices, allow_blank=True, required=False)
  171. device_count = serializers.IntegerField(read_only=True)
  172. powerfeed_count = serializers.IntegerField(read_only=True)
  173. class Meta:
  174. model = Rack
  175. fields = [
  176. 'id', 'url', 'display', 'name', 'facility_id', 'site', 'location', 'tenant', 'status', 'role', 'serial',
  177. 'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit',
  178. 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'powerfeed_count',
  179. ]
  180. class RackUnitSerializer(serializers.Serializer):
  181. """
  182. A rack unit is an abstraction formed by the set (rack, position, face); it does not exist as a row in the database.
  183. """
  184. id = serializers.DecimalField(
  185. max_digits=4,
  186. decimal_places=1,
  187. read_only=True
  188. )
  189. name = serializers.CharField(read_only=True)
  190. face = ChoiceField(choices=DeviceFaceChoices, read_only=True)
  191. device = NestedDeviceSerializer(read_only=True)
  192. occupied = serializers.BooleanField(read_only=True)
  193. display = serializers.SerializerMethodField(read_only=True)
  194. def get_display(self, obj):
  195. return obj['name']
  196. class RackReservationSerializer(NetBoxModelSerializer):
  197. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackreservation-detail')
  198. rack = NestedRackSerializer()
  199. user = NestedUserSerializer()
  200. tenant = NestedTenantSerializer(required=False, allow_null=True)
  201. class Meta:
  202. model = RackReservation
  203. fields = [
  204. 'id', 'url', 'display', 'rack', 'units', 'created', 'last_updated', 'user', 'tenant', 'description', 'tags',
  205. 'custom_fields',
  206. ]
  207. class RackElevationDetailFilterSerializer(serializers.Serializer):
  208. q = serializers.CharField(
  209. required=False,
  210. default=None
  211. )
  212. face = serializers.ChoiceField(
  213. choices=DeviceFaceChoices,
  214. default=DeviceFaceChoices.FACE_FRONT
  215. )
  216. render = serializers.ChoiceField(
  217. choices=RackElevationDetailRenderChoices,
  218. default=RackElevationDetailRenderChoices.RENDER_JSON
  219. )
  220. unit_width = serializers.IntegerField(
  221. default=ConfigItem('RACK_ELEVATION_DEFAULT_UNIT_WIDTH')
  222. )
  223. unit_height = serializers.IntegerField(
  224. default=ConfigItem('RACK_ELEVATION_DEFAULT_UNIT_HEIGHT')
  225. )
  226. legend_width = serializers.IntegerField(
  227. default=RACK_ELEVATION_DEFAULT_LEGEND_WIDTH
  228. )
  229. margin_width = serializers.IntegerField(
  230. default=RACK_ELEVATION_DEFAULT_MARGIN_WIDTH
  231. )
  232. exclude = serializers.IntegerField(
  233. required=False,
  234. default=None
  235. )
  236. expand_devices = serializers.BooleanField(
  237. required=False,
  238. default=True
  239. )
  240. include_images = serializers.BooleanField(
  241. required=False,
  242. default=True
  243. )
  244. #
  245. # Device/module types
  246. #
  247. class ManufacturerSerializer(NetBoxModelSerializer):
  248. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:manufacturer-detail')
  249. devicetype_count = serializers.IntegerField(read_only=True)
  250. inventoryitem_count = serializers.IntegerField(read_only=True)
  251. platform_count = serializers.IntegerField(read_only=True)
  252. class Meta:
  253. model = Manufacturer
  254. fields = [
  255. 'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
  256. 'devicetype_count', 'inventoryitem_count', 'platform_count',
  257. ]
  258. class DeviceTypeSerializer(NetBoxModelSerializer):
  259. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicetype-detail')
  260. manufacturer = NestedManufacturerSerializer()
  261. u_height = serializers.DecimalField(
  262. max_digits=4,
  263. decimal_places=1,
  264. label='Position (U)',
  265. min_value=decimal.Decimal(0.5),
  266. default=1.0
  267. )
  268. subdevice_role = ChoiceField(choices=SubdeviceRoleChoices, allow_blank=True, required=False)
  269. airflow = ChoiceField(choices=DeviceAirflowChoices, allow_blank=True, required=False)
  270. device_count = serializers.IntegerField(read_only=True)
  271. class Meta:
  272. model = DeviceType
  273. fields = [
  274. 'id', 'url', 'display', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth',
  275. 'subdevice_role', 'airflow', 'front_image', 'rear_image', 'comments', 'tags', 'custom_fields', 'created',
  276. 'last_updated', 'device_count',
  277. ]
  278. class ModuleTypeSerializer(NetBoxModelSerializer):
  279. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:moduletype-detail')
  280. manufacturer = NestedManufacturerSerializer()
  281. # module_count = serializers.IntegerField(read_only=True)
  282. class Meta:
  283. model = ModuleType
  284. fields = [
  285. 'id', 'url', 'display', 'manufacturer', 'model', 'part_number', 'comments', 'tags', 'custom_fields',
  286. 'created', 'last_updated',
  287. ]
  288. #
  289. # Component templates
  290. #
  291. class ConsolePortTemplateSerializer(ValidatedModelSerializer):
  292. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleporttemplate-detail')
  293. device_type = NestedDeviceTypeSerializer(
  294. required=False,
  295. allow_null=True,
  296. default=None
  297. )
  298. module_type = NestedModuleTypeSerializer(
  299. required=False,
  300. allow_null=True,
  301. default=None
  302. )
  303. type = ChoiceField(
  304. choices=ConsolePortTypeChoices,
  305. allow_blank=True,
  306. required=False
  307. )
  308. class Meta:
  309. model = ConsolePortTemplate
  310. fields = [
  311. 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'description', 'created',
  312. 'last_updated',
  313. ]
  314. class ConsoleServerPortTemplateSerializer(ValidatedModelSerializer):
  315. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverporttemplate-detail')
  316. device_type = NestedDeviceTypeSerializer(
  317. required=False,
  318. allow_null=True,
  319. default=None
  320. )
  321. module_type = NestedModuleTypeSerializer(
  322. required=False,
  323. allow_null=True,
  324. default=None
  325. )
  326. type = ChoiceField(
  327. choices=ConsolePortTypeChoices,
  328. allow_blank=True,
  329. required=False
  330. )
  331. class Meta:
  332. model = ConsoleServerPortTemplate
  333. fields = [
  334. 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'description', 'created',
  335. 'last_updated',
  336. ]
  337. class PowerPortTemplateSerializer(ValidatedModelSerializer):
  338. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerporttemplate-detail')
  339. device_type = NestedDeviceTypeSerializer(
  340. required=False,
  341. allow_null=True,
  342. default=None
  343. )
  344. module_type = NestedModuleTypeSerializer(
  345. required=False,
  346. allow_null=True,
  347. default=None
  348. )
  349. type = ChoiceField(
  350. choices=PowerPortTypeChoices,
  351. allow_blank=True,
  352. required=False
  353. )
  354. class Meta:
  355. model = PowerPortTemplate
  356. fields = [
  357. 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'maximum_draw',
  358. 'allocated_draw', 'description', 'created', 'last_updated',
  359. ]
  360. class PowerOutletTemplateSerializer(ValidatedModelSerializer):
  361. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlettemplate-detail')
  362. device_type = NestedDeviceTypeSerializer(
  363. required=False,
  364. allow_null=True,
  365. default=None
  366. )
  367. module_type = NestedModuleTypeSerializer(
  368. required=False,
  369. allow_null=True,
  370. default=None
  371. )
  372. type = ChoiceField(
  373. choices=PowerOutletTypeChoices,
  374. allow_blank=True,
  375. required=False
  376. )
  377. power_port = NestedPowerPortTemplateSerializer(
  378. required=False,
  379. allow_null=True
  380. )
  381. feed_leg = ChoiceField(
  382. choices=PowerOutletFeedLegChoices,
  383. allow_blank=True,
  384. required=False
  385. )
  386. class Meta:
  387. model = PowerOutletTemplate
  388. fields = [
  389. 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'power_port', 'feed_leg',
  390. 'description', 'created', 'last_updated',
  391. ]
  392. class InterfaceTemplateSerializer(ValidatedModelSerializer):
  393. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interfacetemplate-detail')
  394. device_type = NestedDeviceTypeSerializer(
  395. required=False,
  396. allow_null=True,
  397. default=None
  398. )
  399. module_type = NestedModuleTypeSerializer(
  400. required=False,
  401. allow_null=True,
  402. default=None
  403. )
  404. type = ChoiceField(choices=InterfaceTypeChoices)
  405. class Meta:
  406. model = InterfaceTemplate
  407. fields = [
  408. 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'mgmt_only', 'description',
  409. 'created', 'last_updated',
  410. ]
  411. class RearPortTemplateSerializer(ValidatedModelSerializer):
  412. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearporttemplate-detail')
  413. device_type = NestedDeviceTypeSerializer(
  414. required=False,
  415. allow_null=True,
  416. default=None
  417. )
  418. module_type = NestedModuleTypeSerializer(
  419. required=False,
  420. allow_null=True,
  421. default=None
  422. )
  423. type = ChoiceField(choices=PortTypeChoices)
  424. class Meta:
  425. model = RearPortTemplate
  426. fields = [
  427. 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'color', 'positions',
  428. 'description', 'created', 'last_updated',
  429. ]
  430. class FrontPortTemplateSerializer(ValidatedModelSerializer):
  431. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontporttemplate-detail')
  432. device_type = NestedDeviceTypeSerializer(
  433. required=False,
  434. allow_null=True,
  435. default=None
  436. )
  437. module_type = NestedModuleTypeSerializer(
  438. required=False,
  439. allow_null=True,
  440. default=None
  441. )
  442. type = ChoiceField(choices=PortTypeChoices)
  443. rear_port = NestedRearPortTemplateSerializer()
  444. class Meta:
  445. model = FrontPortTemplate
  446. fields = [
  447. 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'color', 'rear_port',
  448. 'rear_port_position', 'description', 'created', 'last_updated',
  449. ]
  450. class ModuleBayTemplateSerializer(ValidatedModelSerializer):
  451. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:modulebaytemplate-detail')
  452. device_type = NestedDeviceTypeSerializer()
  453. class Meta:
  454. model = ModuleBayTemplate
  455. fields = [
  456. 'id', 'url', 'display', 'device_type', 'name', 'label', 'position', 'description', 'created',
  457. 'last_updated',
  458. ]
  459. class DeviceBayTemplateSerializer(ValidatedModelSerializer):
  460. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicebaytemplate-detail')
  461. device_type = NestedDeviceTypeSerializer()
  462. class Meta:
  463. model = DeviceBayTemplate
  464. fields = ['id', 'url', 'display', 'device_type', 'name', 'label', 'description', 'created', 'last_updated']
  465. class InventoryItemTemplateSerializer(ValidatedModelSerializer):
  466. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitemtemplate-detail')
  467. device_type = NestedDeviceTypeSerializer()
  468. parent = serializers.PrimaryKeyRelatedField(
  469. queryset=InventoryItemTemplate.objects.all(),
  470. allow_null=True,
  471. default=None
  472. )
  473. role = NestedInventoryItemRoleSerializer(required=False, allow_null=True)
  474. manufacturer = NestedManufacturerSerializer(required=False, allow_null=True, default=None)
  475. component_type = ContentTypeField(
  476. queryset=ContentType.objects.filter(MODULAR_COMPONENT_TEMPLATE_MODELS),
  477. required=False,
  478. allow_null=True
  479. )
  480. component = serializers.SerializerMethodField(read_only=True)
  481. _depth = serializers.IntegerField(source='level', read_only=True)
  482. class Meta:
  483. model = InventoryItemTemplate
  484. fields = [
  485. 'id', 'url', 'display', 'device_type', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id',
  486. 'description', 'component_type', 'component_id', 'component', 'created', 'last_updated', '_depth',
  487. ]
  488. @swagger_serializer_method(serializer_or_field=serializers.DictField)
  489. def get_component(self, obj):
  490. if obj.component is None:
  491. return None
  492. serializer = get_serializer_for_model(obj.component, prefix='Nested')
  493. context = {'request': self.context['request']}
  494. return serializer(obj.component, context=context).data
  495. #
  496. # Devices
  497. #
  498. class DeviceRoleSerializer(NetBoxModelSerializer):
  499. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicerole-detail')
  500. device_count = serializers.IntegerField(read_only=True)
  501. virtualmachine_count = serializers.IntegerField(read_only=True)
  502. class Meta:
  503. model = DeviceRole
  504. fields = [
  505. 'id', 'url', 'display', 'name', 'slug', 'color', 'vm_role', 'description', 'tags', 'custom_fields',
  506. 'created', 'last_updated', 'device_count', 'virtualmachine_count',
  507. ]
  508. class PlatformSerializer(NetBoxModelSerializer):
  509. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:platform-detail')
  510. manufacturer = NestedManufacturerSerializer(required=False, allow_null=True)
  511. device_count = serializers.IntegerField(read_only=True)
  512. virtualmachine_count = serializers.IntegerField(read_only=True)
  513. class Meta:
  514. model = Platform
  515. fields = [
  516. 'id', 'url', 'display', 'name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args', 'description',
  517. 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'virtualmachine_count',
  518. ]
  519. class DeviceSerializer(NetBoxModelSerializer):
  520. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail')
  521. device_type = NestedDeviceTypeSerializer()
  522. device_role = NestedDeviceRoleSerializer()
  523. tenant = NestedTenantSerializer(required=False, allow_null=True, default=None)
  524. platform = NestedPlatformSerializer(required=False, allow_null=True)
  525. site = NestedSiteSerializer()
  526. location = NestedLocationSerializer(required=False, allow_null=True, default=None)
  527. rack = NestedRackSerializer(required=False, allow_null=True, default=None)
  528. face = ChoiceField(choices=DeviceFaceChoices, allow_blank=True, default='')
  529. position = serializers.DecimalField(
  530. max_digits=4,
  531. decimal_places=1,
  532. allow_null=True,
  533. label='Position (U)',
  534. min_value=decimal.Decimal(0.5),
  535. default=None
  536. )
  537. status = ChoiceField(choices=DeviceStatusChoices, required=False)
  538. airflow = ChoiceField(choices=DeviceAirflowChoices, allow_blank=True, required=False)
  539. primary_ip = NestedIPAddressSerializer(read_only=True)
  540. primary_ip4 = NestedIPAddressSerializer(required=False, allow_null=True)
  541. primary_ip6 = NestedIPAddressSerializer(required=False, allow_null=True)
  542. parent_device = serializers.SerializerMethodField()
  543. cluster = NestedClusterSerializer(required=False, allow_null=True)
  544. virtual_chassis = NestedVirtualChassisSerializer(required=False, allow_null=True, default=None)
  545. vc_position = serializers.IntegerField(allow_null=True, max_value=255, min_value=0, default=None)
  546. class Meta:
  547. model = Device
  548. fields = [
  549. 'id', 'url', 'display', 'name', 'device_type', 'device_role', 'tenant', 'platform', 'serial', 'asset_tag',
  550. 'site', 'location', 'rack', 'position', 'face', 'parent_device', 'status', 'airflow', 'primary_ip',
  551. 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments',
  552. 'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated',
  553. ]
  554. @swagger_serializer_method(serializer_or_field=NestedDeviceSerializer)
  555. def get_parent_device(self, obj):
  556. try:
  557. device_bay = obj.parent_bay
  558. except DeviceBay.DoesNotExist:
  559. return None
  560. context = {'request': self.context['request']}
  561. data = NestedDeviceSerializer(instance=device_bay.device, context=context).data
  562. data['device_bay'] = NestedDeviceBaySerializer(instance=device_bay, context=context).data
  563. return data
  564. class ModuleSerializer(NetBoxModelSerializer):
  565. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:module-detail')
  566. device = NestedDeviceSerializer()
  567. module_bay = NestedModuleBaySerializer()
  568. module_type = NestedModuleTypeSerializer()
  569. class Meta:
  570. model = Module
  571. fields = [
  572. 'id', 'url', 'display', 'device', 'module_bay', 'module_type', 'serial', 'asset_tag', 'comments', 'tags',
  573. 'custom_fields', 'created', 'last_updated',
  574. ]
  575. class DeviceWithConfigContextSerializer(DeviceSerializer):
  576. config_context = serializers.SerializerMethodField()
  577. class Meta(DeviceSerializer.Meta):
  578. fields = [
  579. 'id', 'url', 'display', 'name', 'device_type', 'device_role', 'tenant', 'platform', 'serial', 'asset_tag',
  580. 'site', 'location', 'rack', 'position', 'face', 'parent_device', 'status', 'airflow', 'primary_ip',
  581. 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments',
  582. 'local_context_data', 'tags', 'custom_fields', 'config_context', 'created', 'last_updated',
  583. ]
  584. @swagger_serializer_method(serializer_or_field=serializers.DictField)
  585. def get_config_context(self, obj):
  586. return obj.get_config_context()
  587. class DeviceNAPALMSerializer(serializers.Serializer):
  588. method = serializers.DictField()
  589. #
  590. # Device components
  591. #
  592. class ConsoleServerPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
  593. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverport-detail')
  594. device = NestedDeviceSerializer()
  595. module = ComponentNestedModuleSerializer(
  596. required=False,
  597. allow_null=True
  598. )
  599. type = ChoiceField(
  600. choices=ConsolePortTypeChoices,
  601. allow_blank=True,
  602. required=False
  603. )
  604. speed = ChoiceField(
  605. choices=ConsolePortSpeedChoices,
  606. allow_null=True,
  607. required=False
  608. )
  609. class Meta:
  610. model = ConsoleServerPort
  611. fields = [
  612. 'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'speed', 'description',
  613. 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type', 'connected_endpoints',
  614. 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created',
  615. 'last_updated', '_occupied',
  616. ]
  617. class ConsolePortSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
  618. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleport-detail')
  619. device = NestedDeviceSerializer()
  620. module = ComponentNestedModuleSerializer(
  621. required=False,
  622. allow_null=True
  623. )
  624. type = ChoiceField(
  625. choices=ConsolePortTypeChoices,
  626. allow_blank=True,
  627. required=False
  628. )
  629. speed = ChoiceField(
  630. choices=ConsolePortSpeedChoices,
  631. allow_null=True,
  632. required=False
  633. )
  634. class Meta:
  635. model = ConsolePort
  636. fields = [
  637. 'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'speed', 'description',
  638. 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type', 'connected_endpoints',
  639. 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created',
  640. 'last_updated', '_occupied',
  641. ]
  642. class PowerOutletSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
  643. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlet-detail')
  644. device = NestedDeviceSerializer()
  645. module = ComponentNestedModuleSerializer(
  646. required=False,
  647. allow_null=True
  648. )
  649. type = ChoiceField(
  650. choices=PowerOutletTypeChoices,
  651. allow_blank=True,
  652. required=False
  653. )
  654. power_port = NestedPowerPortSerializer(
  655. required=False,
  656. allow_null=True
  657. )
  658. feed_leg = ChoiceField(
  659. choices=PowerOutletFeedLegChoices,
  660. allow_blank=True,
  661. required=False
  662. )
  663. class Meta:
  664. model = PowerOutlet
  665. fields = [
  666. 'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'power_port', 'feed_leg',
  667. 'description', 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type',
  668. 'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields',
  669. 'created', 'last_updated', '_occupied',
  670. ]
  671. class PowerPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
  672. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerport-detail')
  673. device = NestedDeviceSerializer()
  674. module = ComponentNestedModuleSerializer(
  675. required=False,
  676. allow_null=True
  677. )
  678. type = ChoiceField(
  679. choices=PowerPortTypeChoices,
  680. allow_blank=True,
  681. required=False
  682. )
  683. class Meta:
  684. model = PowerPort
  685. fields = [
  686. 'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw',
  687. 'description', 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type',
  688. 'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields',
  689. 'created', 'last_updated', '_occupied',
  690. ]
  691. class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
  692. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
  693. device = NestedDeviceSerializer()
  694. module = ComponentNestedModuleSerializer(
  695. required=False,
  696. allow_null=True
  697. )
  698. type = ChoiceField(choices=InterfaceTypeChoices)
  699. parent = NestedInterfaceSerializer(required=False, allow_null=True)
  700. bridge = NestedInterfaceSerializer(required=False, allow_null=True)
  701. lag = NestedInterfaceSerializer(required=False, allow_null=True)
  702. mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_blank=True)
  703. duplex = ChoiceField(choices=InterfaceDuplexChoices, required=False, allow_blank=True)
  704. rf_role = ChoiceField(choices=WirelessRoleChoices, required=False, allow_blank=True)
  705. rf_channel = ChoiceField(choices=WirelessChannelChoices, required=False, allow_blank=True)
  706. poe_mode = ChoiceField(choices=InterfacePoEModeChoices, required=False, allow_blank=True)
  707. poe_type = ChoiceField(choices=InterfacePoETypeChoices, required=False, allow_blank=True)
  708. untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
  709. tagged_vlans = SerializedPKRelatedField(
  710. queryset=VLAN.objects.all(),
  711. serializer=NestedVLANSerializer,
  712. required=False,
  713. many=True
  714. )
  715. vrf = NestedVRFSerializer(required=False, allow_null=True)
  716. l2vpn_termination = NestedL2VPNTerminationSerializer(read_only=True)
  717. wireless_link = NestedWirelessLinkSerializer(read_only=True)
  718. wireless_lans = SerializedPKRelatedField(
  719. queryset=WirelessLAN.objects.all(),
  720. serializer=NestedWirelessLANSerializer,
  721. required=False,
  722. many=True
  723. )
  724. count_ipaddresses = serializers.IntegerField(read_only=True)
  725. count_fhrp_groups = serializers.IntegerField(read_only=True)
  726. class Meta:
  727. model = Interface
  728. fields = [
  729. 'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'enabled', 'parent', 'bridge', 'lag',
  730. 'mtu', 'mac_address', 'speed', 'duplex', 'wwn', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel',
  731. 'poe_mode', 'poe_type', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'untagged_vlan',
  732. 'tagged_vlans', 'mark_connected', 'cable', 'cable_end', 'wireless_link', 'link_peers', 'link_peers_type',
  733. 'wireless_lans', 'vrf', 'l2vpn_termination', 'connected_endpoints', 'connected_endpoints_type',
  734. 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created', 'last_updated', 'count_ipaddresses',
  735. 'count_fhrp_groups', '_occupied',
  736. ]
  737. def validate(self, data):
  738. # Validate many-to-many VLAN assignments
  739. device = self.instance.device if self.instance else data.get('device')
  740. for vlan in data.get('tagged_vlans', []):
  741. if vlan.site not in [device.site, None]:
  742. raise serializers.ValidationError({
  743. 'tagged_vlans': f"VLAN {vlan} must belong to the same site as the interface's parent device, or "
  744. f"it must be global."
  745. })
  746. return super().validate(data)
  747. class RearPortSerializer(NetBoxModelSerializer, CabledObjectSerializer):
  748. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearport-detail')
  749. device = NestedDeviceSerializer()
  750. module = ComponentNestedModuleSerializer(
  751. required=False,
  752. allow_null=True
  753. )
  754. type = ChoiceField(choices=PortTypeChoices)
  755. class Meta:
  756. model = RearPort
  757. fields = [
  758. 'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'color', 'positions', 'description',
  759. 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type', 'tags', 'custom_fields', 'created',
  760. 'last_updated', '_occupied',
  761. ]
  762. class FrontPortRearPortSerializer(WritableNestedSerializer):
  763. """
  764. NestedRearPortSerializer but with parent device omitted (since front and rear ports must belong to same device)
  765. """
  766. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearport-detail')
  767. class Meta:
  768. model = RearPort
  769. fields = ['id', 'url', 'display', 'name', 'label']
  770. class FrontPortSerializer(NetBoxModelSerializer, CabledObjectSerializer):
  771. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontport-detail')
  772. device = NestedDeviceSerializer()
  773. module = ComponentNestedModuleSerializer(
  774. required=False,
  775. allow_null=True
  776. )
  777. type = ChoiceField(choices=PortTypeChoices)
  778. rear_port = FrontPortRearPortSerializer()
  779. class Meta:
  780. model = FrontPort
  781. fields = [
  782. 'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'color', 'rear_port',
  783. 'rear_port_position', 'description', 'mark_connected', 'cable', 'cable_end', 'link_peers',
  784. 'link_peers_type', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied',
  785. ]
  786. class ModuleBaySerializer(NetBoxModelSerializer):
  787. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:modulebay-detail')
  788. device = NestedDeviceSerializer()
  789. installed_module = ModuleBayNestedModuleSerializer(required=False, allow_null=True)
  790. class Meta:
  791. model = ModuleBay
  792. fields = [
  793. 'id', 'url', 'display', 'device', 'name', 'installed_module', 'label', 'position', 'description', 'tags', 'custom_fields',
  794. 'created', 'last_updated',
  795. ]
  796. class DeviceBaySerializer(NetBoxModelSerializer):
  797. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicebay-detail')
  798. device = NestedDeviceSerializer()
  799. installed_device = NestedDeviceSerializer(required=False, allow_null=True)
  800. class Meta:
  801. model = DeviceBay
  802. fields = [
  803. 'id', 'url', 'display', 'device', 'name', 'label', 'description', 'installed_device', 'tags',
  804. 'custom_fields', 'created', 'last_updated',
  805. ]
  806. class InventoryItemSerializer(NetBoxModelSerializer):
  807. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitem-detail')
  808. device = NestedDeviceSerializer()
  809. parent = serializers.PrimaryKeyRelatedField(queryset=InventoryItem.objects.all(), allow_null=True, default=None)
  810. role = NestedInventoryItemRoleSerializer(required=False, allow_null=True)
  811. manufacturer = NestedManufacturerSerializer(required=False, allow_null=True, default=None)
  812. component_type = ContentTypeField(
  813. queryset=ContentType.objects.filter(MODULAR_COMPONENT_MODELS),
  814. required=False,
  815. allow_null=True
  816. )
  817. component = serializers.SerializerMethodField(read_only=True)
  818. _depth = serializers.IntegerField(source='level', read_only=True)
  819. class Meta:
  820. model = InventoryItem
  821. fields = [
  822. 'id', 'url', 'display', 'device', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id', 'serial',
  823. 'asset_tag', 'discovered', 'description', 'component_type', 'component_id', 'component', 'tags',
  824. 'custom_fields', 'created', 'last_updated', '_depth',
  825. ]
  826. @swagger_serializer_method(serializer_or_field=serializers.DictField)
  827. def get_component(self, obj):
  828. if obj.component is None:
  829. return None
  830. serializer = get_serializer_for_model(obj.component, prefix='Nested')
  831. context = {'request': self.context['request']}
  832. return serializer(obj.component, context=context).data
  833. #
  834. # Device component roles
  835. #
  836. class InventoryItemRoleSerializer(NetBoxModelSerializer):
  837. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitemrole-detail')
  838. inventoryitem_count = serializers.IntegerField(read_only=True)
  839. class Meta:
  840. model = InventoryItemRole
  841. fields = [
  842. 'id', 'url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields', 'created',
  843. 'last_updated', 'inventoryitem_count',
  844. ]
  845. #
  846. # Cables
  847. #
  848. class CableSerializer(NetBoxModelSerializer):
  849. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail')
  850. a_terminations_type = serializers.SerializerMethodField(read_only=True)
  851. b_terminations_type = serializers.SerializerMethodField(read_only=True)
  852. a_terminations = serializers.SerializerMethodField(read_only=True)
  853. b_terminations = serializers.SerializerMethodField(read_only=True)
  854. status = ChoiceField(choices=LinkStatusChoices, required=False)
  855. tenant = NestedTenantSerializer(required=False, allow_null=True)
  856. length_unit = ChoiceField(choices=CableLengthUnitChoices, allow_blank=True, required=False)
  857. class Meta:
  858. model = Cable
  859. fields = [
  860. 'id', 'url', 'display', 'type', 'a_terminations_type', 'a_terminations', 'b_terminations_type',
  861. 'b_terminations', 'status', 'tenant', 'label', 'color', 'length', 'length_unit', 'tags', 'custom_fields',
  862. 'created', 'last_updated',
  863. ]
  864. def _get_terminations_type(self, obj, side):
  865. assert side.lower() in ('a', 'b')
  866. terms = [t.termination for t in obj.terminations.all() if t.cable_end == side.upper()]
  867. if terms:
  868. ct = ContentType.objects.get_for_model(terms[0])
  869. return f"{ct.app_label}.{ct.model}"
  870. def _get_terminations(self, obj, side):
  871. assert side.lower() in ('a', 'b')
  872. terms = [t.termination for t in obj.terminations.all() if t.cable_end == side.upper()]
  873. if not terms:
  874. return []
  875. termination_type = ContentType.objects.get_for_model(terms[0])
  876. serializer = get_serializer_for_model(termination_type.model_class(), prefix='Nested')
  877. context = {'request': self.context['request']}
  878. data = serializer(terms, context=context, many=True).data
  879. return data
  880. @swagger_serializer_method(serializer_or_field=serializers.CharField)
  881. def get_a_terminations_type(self, obj):
  882. return self._get_terminations_type(obj, 'a')
  883. @swagger_serializer_method(serializer_or_field=serializers.CharField)
  884. def get_b_terminations_type(self, obj):
  885. return self._get_terminations_type(obj, 'b')
  886. @swagger_serializer_method(serializer_or_field=serializers.DictField)
  887. def get_a_terminations(self, obj):
  888. return self._get_terminations(obj, 'a')
  889. @swagger_serializer_method(serializer_or_field=serializers.DictField)
  890. def get_b_terminations(self, obj):
  891. return self._get_terminations(obj, 'b')
  892. class TracedCableSerializer(serializers.ModelSerializer):
  893. """
  894. Used only while tracing a cable path.
  895. """
  896. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail')
  897. class Meta:
  898. model = Cable
  899. fields = [
  900. 'id', 'url', 'type', 'status', 'label', 'color', 'length', 'length_unit',
  901. ]
  902. class CableTerminationSerializer(NetBoxModelSerializer):
  903. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail')
  904. termination_type = ContentTypeField(
  905. queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)
  906. )
  907. termination = serializers.SerializerMethodField(read_only=True)
  908. class Meta:
  909. model = CableTermination
  910. fields = [
  911. 'id', 'url', 'display', 'cable', 'cable_end', 'termination_type', 'termination_id', 'termination'
  912. ]
  913. @swagger_serializer_method(serializer_or_field=serializers.DictField)
  914. def get_termination(self, obj):
  915. serializer = get_serializer_for_model(obj.termination, prefix='Nested')
  916. context = {'request': self.context['request']}
  917. return serializer(obj.termination, context=context).data
  918. class CablePathSerializer(serializers.ModelSerializer):
  919. origin_type = ContentTypeField(read_only=True)
  920. origin = serializers.SerializerMethodField(read_only=True)
  921. destination_type = ContentTypeField(read_only=True)
  922. destination = serializers.SerializerMethodField(read_only=True)
  923. path = serializers.SerializerMethodField(read_only=True)
  924. class Meta:
  925. model = CablePath
  926. fields = [
  927. 'id', 'origin_type', 'origin', 'destination_type', 'destination', 'path', 'is_active', 'is_split',
  928. ]
  929. @swagger_serializer_method(serializer_or_field=serializers.DictField)
  930. def get_origin(self, obj):
  931. """
  932. Return the appropriate serializer for the origin.
  933. """
  934. serializer = get_serializer_for_model(obj.origin, prefix='Nested')
  935. context = {'request': self.context['request']}
  936. return serializer(obj.origin, context=context).data
  937. @swagger_serializer_method(serializer_or_field=serializers.DictField)
  938. def get_destination(self, obj):
  939. """
  940. Return the appropriate serializer for the destination, if any.
  941. """
  942. if obj.destination_id is not None:
  943. serializer = get_serializer_for_model(obj.destination, prefix='Nested')
  944. context = {'request': self.context['request']}
  945. return serializer(obj.destination, context=context).data
  946. return None
  947. @swagger_serializer_method(serializer_or_field=serializers.ListField)
  948. def get_path(self, obj):
  949. ret = []
  950. for node in obj.path_objects():
  951. serializer = get_serializer_for_model(node, prefix='Nested')
  952. context = {'request': self.context['request']}
  953. ret.append(serializer(node, context=context).data)
  954. return ret
  955. #
  956. # Virtual chassis
  957. #
  958. class VirtualChassisSerializer(NetBoxModelSerializer):
  959. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualchassis-detail')
  960. master = NestedDeviceSerializer(required=False)
  961. member_count = serializers.IntegerField(read_only=True)
  962. class Meta:
  963. model = VirtualChassis
  964. fields = [
  965. 'id', 'url', 'display', 'name', 'domain', 'master', 'tags', 'custom_fields', 'member_count',
  966. 'created', 'last_updated',
  967. ]
  968. #
  969. # Power panels
  970. #
  971. class PowerPanelSerializer(NetBoxModelSerializer):
  972. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerpanel-detail')
  973. site = NestedSiteSerializer()
  974. location = NestedLocationSerializer(
  975. required=False,
  976. allow_null=True,
  977. default=None
  978. )
  979. powerfeed_count = serializers.IntegerField(read_only=True)
  980. class Meta:
  981. model = PowerPanel
  982. fields = [
  983. 'id', 'url', 'display', 'site', 'location', 'name', 'tags', 'custom_fields', 'powerfeed_count',
  984. 'created', 'last_updated',
  985. ]
  986. class PowerFeedSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
  987. url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerfeed-detail')
  988. power_panel = NestedPowerPanelSerializer()
  989. rack = NestedRackSerializer(
  990. required=False,
  991. allow_null=True,
  992. default=None
  993. )
  994. type = ChoiceField(
  995. choices=PowerFeedTypeChoices,
  996. default=PowerFeedTypeChoices.TYPE_PRIMARY
  997. )
  998. status = ChoiceField(
  999. choices=PowerFeedStatusChoices,
  1000. default=PowerFeedStatusChoices.STATUS_ACTIVE
  1001. )
  1002. supply = ChoiceField(
  1003. choices=PowerFeedSupplyChoices,
  1004. default=PowerFeedSupplyChoices.SUPPLY_AC
  1005. )
  1006. phase = ChoiceField(
  1007. choices=PowerFeedPhaseChoices,
  1008. default=PowerFeedPhaseChoices.PHASE_SINGLE
  1009. )
  1010. class Meta:
  1011. model = PowerFeed
  1012. fields = [
  1013. 'id', 'url', 'display', 'power_panel', 'rack', 'name', 'status', 'type', 'supply', 'phase', 'voltage',
  1014. 'amperage', 'max_utilization', 'comments', 'mark_connected', 'cable', 'cable_end', 'link_peers',
  1015. 'link_peers_type', 'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable',
  1016. 'tags', 'custom_fields', 'created', 'last_updated', '_occupied',
  1017. ]