panels.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. from django.contrib.contenttypes.models import ContentType
  2. from django.template.loader import render_to_string
  3. from django.utils.translation import gettext_lazy as _
  4. from netbox.ui import actions, attrs, panels
  5. class SitePanel(panels.ObjectAttributesPanel):
  6. region = attrs.NestedObjectAttr('region', linkify=True)
  7. group = attrs.NestedObjectAttr('group', linkify=True)
  8. name = attrs.TextAttr('name')
  9. status = attrs.ChoiceAttr('status')
  10. tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
  11. facility = attrs.TextAttr('facility')
  12. description = attrs.TextAttr('description')
  13. timezone = attrs.TimezoneAttr('time_zone')
  14. physical_address = attrs.AddressAttr('physical_address', map_url=True)
  15. shipping_address = attrs.AddressAttr('shipping_address', map_url=True)
  16. gps_coordinates = attrs.GPSCoordinatesAttr()
  17. class LocationPanel(panels.NestedGroupObjectPanel):
  18. site = attrs.RelatedObjectAttr('site', linkify=True, grouped_by='group')
  19. status = attrs.ChoiceAttr('status')
  20. tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
  21. facility = attrs.TextAttr('facility')
  22. class RackDimensionsPanel(panels.ObjectAttributesPanel):
  23. form_factor = attrs.ChoiceAttr('form_factor')
  24. width = attrs.ChoiceAttr('width')
  25. height = attrs.TextAttr('u_height', format_string='{}U', label=_('Height'))
  26. outer_width = attrs.NumericAttr('outer_width', unit_accessor='get_outer_unit_display')
  27. outer_height = attrs.NumericAttr('outer_height', unit_accessor='get_outer_unit_display')
  28. outer_depth = attrs.NumericAttr('outer_depth', unit_accessor='get_outer_unit_display')
  29. mounting_depth = attrs.TextAttr('mounting_depth', format_string=_('{} millimeters'))
  30. class RackNumberingPanel(panels.ObjectAttributesPanel):
  31. starting_unit = attrs.TextAttr('starting_unit')
  32. desc_units = attrs.BooleanAttr('desc_units', label=_('Descending units'))
  33. class RackPanel(panels.ObjectAttributesPanel):
  34. region = attrs.NestedObjectAttr('site.region', linkify=True)
  35. site = attrs.RelatedObjectAttr('site', linkify=True, grouped_by='group')
  36. location = attrs.NestedObjectAttr('location', linkify=True)
  37. name = attrs.TextAttr('name')
  38. facility_id = attrs.TextAttr('facility_id', label=_('Facility ID'))
  39. tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
  40. status = attrs.ChoiceAttr('status')
  41. rack_type = attrs.RelatedObjectAttr('rack_type', linkify=True, grouped_by='manufacturer')
  42. role = attrs.RelatedObjectAttr('role', linkify=True)
  43. description = attrs.TextAttr('description')
  44. serial = attrs.TextAttr('serial', label=_('Serial number'), style='font-monospace', copy_button=True)
  45. asset_tag = attrs.TextAttr('asset_tag', style='font-monospace', copy_button=True)
  46. airflow = attrs.ChoiceAttr('airflow')
  47. space_utilization = attrs.UtilizationAttr('get_utilization')
  48. power_utilization = attrs.UtilizationAttr('get_power_utilization')
  49. class RackWeightPanel(panels.ObjectAttributesPanel):
  50. weight = attrs.NumericAttr('weight', unit_accessor='get_weight_unit_display')
  51. max_weight = attrs.NumericAttr('max_weight', unit_accessor='get_weight_unit_display', label=_('Maximum weight'))
  52. total_weight = attrs.TemplatedAttr('total_weight', template_name='dcim/rack/attrs/total_weight.html')
  53. class RackRolePanel(panels.OrganizationalObjectPanel):
  54. color = attrs.ColorAttr('color')
  55. class RackReservationPanel(panels.ObjectAttributesPanel):
  56. units = attrs.TextAttr('unit_list')
  57. status = attrs.ChoiceAttr('status')
  58. tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
  59. user = attrs.RelatedObjectAttr('user')
  60. description = attrs.TextAttr('description')
  61. class RackTypePanel(panels.ObjectAttributesPanel):
  62. manufacturer = attrs.RelatedObjectAttr('manufacturer', linkify=True)
  63. model = attrs.TextAttr('model')
  64. description = attrs.TextAttr('description')
  65. class DevicePanel(panels.ObjectAttributesPanel):
  66. region = attrs.NestedObjectAttr('site.region', linkify=True)
  67. site = attrs.RelatedObjectAttr('site', linkify=True, grouped_by='group')
  68. location = attrs.NestedObjectAttr('location', linkify=True)
  69. rack = attrs.TemplatedAttr('rack', template_name='dcim/device/attrs/rack.html')
  70. virtual_chassis = attrs.RelatedObjectAttr('virtual_chassis', linkify=True)
  71. parent_device = attrs.TemplatedAttr('parent_bay', template_name='dcim/device/attrs/parent_device.html')
  72. gps_coordinates = attrs.GPSCoordinatesAttr()
  73. tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
  74. description = attrs.TextAttr('description')
  75. airflow = attrs.ChoiceAttr('airflow')
  76. serial = attrs.TextAttr('serial', label=_('Serial number'), style='font-monospace', copy_button=True)
  77. asset_tag = attrs.TextAttr('asset_tag', style='font-monospace', copy_button=True)
  78. config_template = attrs.RelatedObjectAttr('config_template', linkify=True)
  79. class DeviceManagementPanel(panels.ObjectAttributesPanel):
  80. title = _('Management')
  81. status = attrs.ChoiceAttr('status')
  82. role = attrs.NestedObjectAttr('role', linkify=True, max_depth=3)
  83. platform = attrs.NestedObjectAttr('platform', linkify=True, max_depth=3)
  84. primary_ip4 = attrs.TemplatedAttr(
  85. 'primary_ip4',
  86. label=_('Primary IPv4'),
  87. template_name='dcim/device/attrs/ipaddress.html',
  88. )
  89. primary_ip6 = attrs.TemplatedAttr(
  90. 'primary_ip6',
  91. label=_('Primary IPv6'),
  92. template_name='dcim/device/attrs/ipaddress.html',
  93. )
  94. oob_ip = attrs.TemplatedAttr(
  95. 'oob_ip',
  96. label=_('Out-of-band IP'),
  97. template_name='dcim/device/attrs/ipaddress.html',
  98. )
  99. cluster = attrs.RelatedObjectAttr('cluster', linkify=True)
  100. class DeviceDeviceTypePanel(panels.ObjectAttributesPanel):
  101. title = _('Device Type')
  102. manufacturer = attrs.RelatedObjectAttr('device_type.manufacturer', linkify=True)
  103. model = attrs.RelatedObjectAttr('device_type', linkify=True)
  104. height = attrs.TemplatedAttr('device_type.u_height', template_name='dcim/devicetype/attrs/height.html')
  105. front_image = attrs.ImageAttr('device_type.front_image')
  106. rear_image = attrs.ImageAttr('device_type.rear_image')
  107. class DeviceDimensionsPanel(panels.ObjectAttributesPanel):
  108. title = _('Dimensions')
  109. total_weight = attrs.TemplatedAttr('total_weight', template_name='dcim/device/attrs/total_weight.html')
  110. class DeviceRolePanel(panels.NestedGroupObjectPanel):
  111. color = attrs.ColorAttr('color')
  112. vm_role = attrs.BooleanAttr('vm_role', label=_('VM role'))
  113. config_template = attrs.RelatedObjectAttr('config_template', linkify=True)
  114. class DeviceTypePanel(panels.ObjectAttributesPanel):
  115. manufacturer = attrs.RelatedObjectAttr('manufacturer', linkify=True)
  116. model = attrs.TextAttr('model')
  117. part_number = attrs.TextAttr('part_number')
  118. default_platform = attrs.RelatedObjectAttr('default_platform', linkify=True)
  119. description = attrs.TextAttr('description')
  120. height = attrs.TemplatedAttr('u_height', template_name='dcim/devicetype/attrs/height.html')
  121. exclude_from_utilization = attrs.BooleanAttr('exclude_from_utilization')
  122. full_depth = attrs.BooleanAttr('is_full_depth')
  123. weight = attrs.NumericAttr('weight', unit_accessor='get_weight_unit_display')
  124. subdevice_role = attrs.ChoiceAttr('subdevice_role', label=_('Parent/child'))
  125. airflow = attrs.ChoiceAttr('airflow')
  126. front_image = attrs.ImageAttr('front_image')
  127. rear_image = attrs.ImageAttr('rear_image')
  128. class ModulePanel(panels.ObjectAttributesPanel):
  129. device = attrs.RelatedObjectAttr('device', linkify=True)
  130. device_type = attrs.RelatedObjectAttr('device.device_type', linkify=True, grouped_by='manufacturer')
  131. module_bay = attrs.NestedObjectAttr('module_bay', linkify=True)
  132. status = attrs.ChoiceAttr('status')
  133. description = attrs.TextAttr('description')
  134. serial = attrs.TextAttr('serial', label=_('Serial number'), style='font-monospace', copy_button=True)
  135. asset_tag = attrs.TextAttr('asset_tag', style='font-monospace', copy_button=True)
  136. class ModuleTypeProfilePanel(panels.ObjectAttributesPanel):
  137. name = attrs.TextAttr('name')
  138. description = attrs.TextAttr('description')
  139. class ModuleTypePanel(panels.ObjectAttributesPanel):
  140. profile = attrs.RelatedObjectAttr('profile', linkify=True)
  141. manufacturer = attrs.RelatedObjectAttr('manufacturer', linkify=True)
  142. model = attrs.TextAttr('model', label=_('Model name'))
  143. part_number = attrs.TextAttr('part_number')
  144. description = attrs.TextAttr('description')
  145. airflow = attrs.ChoiceAttr('airflow')
  146. weight = attrs.NumericAttr('weight', unit_accessor='get_weight_unit_display')
  147. class PlatformPanel(panels.NestedGroupObjectPanel):
  148. manufacturer = attrs.RelatedObjectAttr('manufacturer', linkify=True)
  149. config_template = attrs.RelatedObjectAttr('config_template', linkify=True)
  150. class ConsolePortPanel(panels.ObjectAttributesPanel):
  151. device = attrs.RelatedObjectAttr('device', linkify=True)
  152. module = attrs.RelatedObjectAttr('module', linkify=True)
  153. name = attrs.TextAttr('name')
  154. label = attrs.TextAttr('label')
  155. type = attrs.ChoiceAttr('type')
  156. speed = attrs.ChoiceAttr('speed')
  157. description = attrs.TextAttr('description')
  158. class ConsoleServerPortPanel(panels.ObjectAttributesPanel):
  159. device = attrs.RelatedObjectAttr('device', linkify=True)
  160. module = attrs.RelatedObjectAttr('module', linkify=True)
  161. name = attrs.TextAttr('name')
  162. label = attrs.TextAttr('label')
  163. type = attrs.ChoiceAttr('type')
  164. speed = attrs.ChoiceAttr('speed')
  165. description = attrs.TextAttr('description')
  166. class PowerPortPanel(panels.ObjectAttributesPanel):
  167. device = attrs.RelatedObjectAttr('device', linkify=True)
  168. module = attrs.RelatedObjectAttr('module', linkify=True)
  169. name = attrs.TextAttr('name')
  170. label = attrs.TextAttr('label')
  171. type = attrs.ChoiceAttr('type')
  172. description = attrs.TextAttr('description')
  173. maximum_draw = attrs.TextAttr('maximum_draw')
  174. allocated_draw = attrs.TextAttr('allocated_draw')
  175. class PowerOutletPanel(panels.ObjectAttributesPanel):
  176. device = attrs.RelatedObjectAttr('device', linkify=True)
  177. module = attrs.RelatedObjectAttr('module', linkify=True)
  178. name = attrs.TextAttr('name')
  179. label = attrs.TextAttr('label')
  180. type = attrs.ChoiceAttr('type')
  181. status = attrs.ChoiceAttr('status')
  182. description = attrs.TextAttr('description')
  183. color = attrs.ColorAttr('color')
  184. power_port = attrs.RelatedObjectAttr('power_port', linkify=True)
  185. feed_leg = attrs.ChoiceAttr('feed_leg')
  186. class FrontPortPanel(panels.ObjectAttributesPanel):
  187. device = attrs.RelatedObjectAttr('device', linkify=True)
  188. module = attrs.RelatedObjectAttr('module', linkify=True)
  189. name = attrs.TextAttr('name')
  190. label = attrs.TextAttr('label')
  191. type = attrs.ChoiceAttr('type')
  192. color = attrs.ColorAttr('color')
  193. positions = attrs.TextAttr('positions')
  194. description = attrs.TextAttr('description')
  195. class RearPortPanel(panels.ObjectAttributesPanel):
  196. device = attrs.RelatedObjectAttr('device', linkify=True)
  197. module = attrs.RelatedObjectAttr('module', linkify=True)
  198. name = attrs.TextAttr('name')
  199. label = attrs.TextAttr('label')
  200. type = attrs.ChoiceAttr('type')
  201. color = attrs.ColorAttr('color')
  202. positions = attrs.TextAttr('positions')
  203. description = attrs.TextAttr('description')
  204. class ModuleBayPanel(panels.ObjectAttributesPanel):
  205. device = attrs.RelatedObjectAttr('device', linkify=True)
  206. module = attrs.RelatedObjectAttr('module', linkify=True)
  207. name = attrs.TextAttr('name')
  208. label = attrs.TextAttr('label')
  209. position = attrs.TextAttr('position')
  210. description = attrs.TextAttr('description')
  211. class DeviceBayPanel(panels.ObjectAttributesPanel):
  212. device = attrs.RelatedObjectAttr('device', linkify=True)
  213. name = attrs.TextAttr('name')
  214. label = attrs.TextAttr('label')
  215. description = attrs.TextAttr('description')
  216. class InventoryItemPanel(panels.ObjectAttributesPanel):
  217. device = attrs.RelatedObjectAttr('device', linkify=True)
  218. parent = attrs.RelatedObjectAttr('parent', linkify=True, label=_('Parent item'))
  219. name = attrs.TextAttr('name')
  220. label = attrs.TextAttr('label')
  221. status = attrs.ChoiceAttr('status')
  222. role = attrs.RelatedObjectAttr('role', linkify=True)
  223. component = attrs.GenericForeignKeyAttr('component', linkify=True)
  224. manufacturer = attrs.RelatedObjectAttr('manufacturer', linkify=True)
  225. part_id = attrs.TextAttr('part_id', label=_('Part ID'))
  226. serial = attrs.TextAttr('serial')
  227. asset_tag = attrs.TextAttr('asset_tag')
  228. description = attrs.TextAttr('description')
  229. class InventoryItemRolePanel(panels.OrganizationalObjectPanel):
  230. color = attrs.ColorAttr('color')
  231. class CablePanel(panels.ObjectAttributesPanel):
  232. type = attrs.ChoiceAttr('type')
  233. status = attrs.ChoiceAttr('status')
  234. profile = attrs.ChoiceAttr('profile')
  235. tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
  236. label = attrs.TextAttr('label')
  237. description = attrs.TextAttr('description')
  238. color = attrs.ColorAttr('color')
  239. length = attrs.NumericAttr('length', unit_accessor='get_length_unit_display')
  240. class VirtualChassisPanel(panels.ObjectAttributesPanel):
  241. domain = attrs.TextAttr('domain')
  242. master = attrs.RelatedObjectAttr('master', linkify=True)
  243. description = attrs.TextAttr('description')
  244. class PowerPanelPanel(panels.ObjectAttributesPanel):
  245. site = attrs.RelatedObjectAttr('site', linkify=True)
  246. location = attrs.NestedObjectAttr('location', linkify=True)
  247. description = attrs.TextAttr('description')
  248. class PowerFeedPanel(panels.ObjectAttributesPanel):
  249. power_panel = attrs.RelatedObjectAttr('power_panel', linkify=True)
  250. rack = attrs.RelatedObjectAttr('rack', linkify=True)
  251. type = attrs.ChoiceAttr('type')
  252. status = attrs.ChoiceAttr('status')
  253. description = attrs.TextAttr('description')
  254. tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
  255. connected_device = attrs.TemplatedAttr(
  256. 'connected_endpoints',
  257. label=_('Connected device'),
  258. template_name='dcim/powerfeed/attrs/connected_device.html',
  259. )
  260. utilization = attrs.TemplatedAttr(
  261. 'connected_endpoints',
  262. label=_('Utilization (allocated)'),
  263. template_name='dcim/powerfeed/attrs/utilization.html',
  264. )
  265. class PowerFeedElectricalPanel(panels.ObjectAttributesPanel):
  266. title = _('Electrical Characteristics')
  267. supply = attrs.ChoiceAttr('supply')
  268. voltage = attrs.TextAttr('voltage', format_string=_('{}V'))
  269. amperage = attrs.TextAttr('amperage', format_string=_('{}A'))
  270. phase = attrs.ChoiceAttr('phase')
  271. max_utilization = attrs.TextAttr('max_utilization', format_string='{}%')
  272. class VirtualDeviceContextPanel(panels.ObjectAttributesPanel):
  273. name = attrs.TextAttr('name')
  274. device = attrs.RelatedObjectAttr('device', linkify=True)
  275. identifier = attrs.TextAttr('identifier')
  276. status = attrs.ChoiceAttr('status')
  277. primary_ip4 = attrs.TemplatedAttr(
  278. 'primary_ip4',
  279. label=_('Primary IPv4'),
  280. template_name='dcim/device/attrs/ipaddress.html',
  281. )
  282. primary_ip6 = attrs.TemplatedAttr(
  283. 'primary_ip6',
  284. label=_('Primary IPv6'),
  285. template_name='dcim/device/attrs/ipaddress.html',
  286. )
  287. tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
  288. class MACAddressPanel(panels.ObjectAttributesPanel):
  289. mac_address = attrs.TextAttr('mac_address', label=_('MAC address'), style='font-monospace', copy_button=True)
  290. description = attrs.TextAttr('description')
  291. assignment = attrs.RelatedObjectAttr('assigned_object', linkify=True, grouped_by='parent_object')
  292. is_primary = attrs.BooleanAttr('is_primary', label=_('Primary for interface'))
  293. class ConnectionPanel(panels.ObjectPanel):
  294. """
  295. A panel which displays connection information for a cabled object.
  296. """
  297. template_name = 'dcim/panels/connection.html'
  298. title = _('Connection')
  299. def __init__(self, trace_url_name, connect_options=None, show_endpoints=True, **kwargs):
  300. super().__init__(**kwargs)
  301. self.trace_url_name = trace_url_name
  302. self.connect_options = connect_options or []
  303. self.show_endpoints = show_endpoints
  304. def get_context(self, context):
  305. return {
  306. **super().get_context(context),
  307. 'trace_url_name': self.trace_url_name,
  308. 'connect_options': self.connect_options,
  309. 'show_endpoints': self.show_endpoints,
  310. }
  311. def render(self, context):
  312. ctx = self.get_context(context)
  313. return render_to_string(self.template_name, ctx, request=ctx.get('request'))
  314. class InventoryItemsPanel(panels.ObjectPanel):
  315. """
  316. A panel which displays inventory items associated with a component.
  317. """
  318. template_name = 'dcim/panels/component_inventory_items.html'
  319. title = _('Inventory Items')
  320. actions = [
  321. actions.AddObject(
  322. 'dcim.inventoryitem',
  323. url_params={
  324. 'component_type': lambda ctx: ContentType.objects.get_for_model(ctx['object']).pk,
  325. 'component_id': lambda ctx: ctx['object'].pk,
  326. },
  327. ),
  328. ]
  329. def render(self, context):
  330. ctx = self.get_context(context)
  331. return render_to_string(self.template_name, ctx, request=ctx.get('request'))
  332. class VirtualChassisMembersPanel(panels.ObjectPanel):
  333. """
  334. A panel which lists all members of a virtual chassis.
  335. """
  336. template_name = 'dcim/panels/virtual_chassis_members.html'
  337. title = _('Virtual Chassis Members')
  338. actions = [
  339. actions.AddObject(
  340. 'dcim.device',
  341. url_params={
  342. 'site': lambda ctx: ctx['object'].master.site_id if ctx['object'].master else '',
  343. 'rack': lambda ctx: ctx['object'].master.rack_id if ctx['object'].master else '',
  344. },
  345. ),
  346. ]
  347. def get_context(self, context):
  348. return {
  349. **super().get_context(context),
  350. 'virtual_chassis': context.get('virtual_chassis'),
  351. 'vc_members': context.get('vc_members'),
  352. }
  353. def render(self, context):
  354. if not context.get('vc_members'):
  355. return ''
  356. return super().render(context)
  357. class PowerUtilizationPanel(panels.ObjectPanel):
  358. """
  359. A panel which displays the power utilization statistics for a device.
  360. """
  361. template_name = 'dcim/panels/power_utilization.html'
  362. title = _('Power Utilization')
  363. def get_context(self, context):
  364. return {
  365. **super().get_context(context),
  366. 'vc_members': context.get('vc_members'),
  367. }
  368. def render(self, context):
  369. obj = context['object']
  370. if not obj.powerports.exists() or not obj.poweroutlets.exists():
  371. return ''
  372. return super().render(context)
  373. class InterfacePanel(panels.ObjectAttributesPanel):
  374. device = attrs.RelatedObjectAttr('device', linkify=True)
  375. module = attrs.RelatedObjectAttr('module', linkify=True)
  376. name = attrs.TextAttr('name')
  377. label = attrs.TextAttr('label')
  378. type = attrs.ChoiceAttr('type')
  379. speed = attrs.TemplatedAttr('speed', template_name='dcim/interface/attrs/speed.html', label=_('Speed'))
  380. duplex = attrs.ChoiceAttr('duplex')
  381. mtu = attrs.TextAttr('mtu', label=_('MTU'))
  382. enabled = attrs.BooleanAttr('enabled')
  383. mgmt_only = attrs.BooleanAttr('mgmt_only', label=_('Management only'))
  384. description = attrs.TextAttr('description')
  385. poe_mode = attrs.ChoiceAttr('poe_mode', label=_('PoE mode'))
  386. poe_type = attrs.ChoiceAttr('poe_type', label=_('PoE type'))
  387. mode = attrs.ChoiceAttr('mode', label=_('802.1Q mode'))
  388. qinq_svlan = attrs.RelatedObjectAttr('qinq_svlan', linkify=True, label=_('Q-in-Q SVLAN'))
  389. untagged_vlan = attrs.RelatedObjectAttr('untagged_vlan', linkify=True, label=_('Untagged VLAN'))
  390. tx_power = attrs.TextAttr('tx_power', label=_('Transmit power (dBm)'))
  391. tunnel = attrs.RelatedObjectAttr('tunnel_termination.tunnel', linkify=True, label=_('Tunnel'))
  392. l2vpn = attrs.RelatedObjectAttr('l2vpn_termination.l2vpn', linkify=True, label=_('L2VPN'))
  393. class RelatedInterfacesPanel(panels.ObjectAttributesPanel):
  394. title = _('Related Interfaces')
  395. parent = attrs.RelatedObjectAttr('parent', linkify=True)
  396. bridge = attrs.RelatedObjectAttr('bridge', linkify=True)
  397. lag = attrs.RelatedObjectAttr('lag', linkify=True, label=_('LAG'))
  398. class InterfaceAddressingPanel(panels.ObjectAttributesPanel):
  399. title = _('Addressing')
  400. mac_address = attrs.TemplatedAttr(
  401. 'primary_mac_address',
  402. template_name='dcim/interface/attrs/mac_address.html',
  403. label=_('MAC address'),
  404. )
  405. wwn = attrs.TextAttr('wwn', style='font-monospace', label=_('WWN'))
  406. vrf = attrs.RelatedObjectAttr('vrf', linkify=True, label=_('VRF'))
  407. vlan_translation = attrs.RelatedObjectAttr('vlan_translation_policy', linkify=True, label=_('VLAN translation'))
  408. class InterfaceConnectionPanel(panels.ObjectPanel):
  409. """
  410. A connection panel for interfaces, which handles cable, wireless link, and virtual circuit cases.
  411. """
  412. template_name = 'dcim/panels/interface_connection.html'
  413. title = _('Connection')
  414. def render(self, context):
  415. obj = context.get('object')
  416. if obj and obj.is_virtual:
  417. return ''
  418. ctx = self.get_context(context)
  419. return render_to_string(self.template_name, ctx, request=ctx.get('request'))
  420. class VirtualCircuitPanel(panels.ObjectPanel):
  421. """
  422. A panel which displays virtual circuit information for a virtual interface.
  423. """
  424. template_name = 'dcim/panels/interface_virtual_circuit.html'
  425. title = _('Virtual Circuit')
  426. def render(self, context):
  427. obj = context.get('object')
  428. if not obj or not obj.is_virtual or not obj.virtual_circuit_termination:
  429. return ''
  430. ctx = self.get_context(context)
  431. return render_to_string(self.template_name, ctx, request=ctx.get('request'))
  432. class InterfaceWirelessPanel(panels.ObjectPanel):
  433. """
  434. A panel which displays wireless RF attributes for an interface, comparing local and peer values.
  435. """
  436. template_name = 'dcim/panels/interface_wireless.html'
  437. title = _('Wireless')
  438. def render(self, context):
  439. obj = context.get('object')
  440. if not obj or not obj.is_wireless:
  441. return ''
  442. ctx = self.get_context(context)
  443. return render_to_string(self.template_name, ctx, request=ctx.get('request'))
  444. class WirelessLANsPanel(panels.ObjectPanel):
  445. """
  446. A panel which lists the wireless LANs associated with an interface.
  447. """
  448. template_name = 'dcim/panels/interface_wireless_lans.html'
  449. title = _('Wireless LANs')
  450. def render(self, context):
  451. obj = context.get('object')
  452. if not obj or not obj.is_wireless:
  453. return ''
  454. ctx = self.get_context(context)
  455. return render_to_string(self.template_name, ctx, request=ctx.get('request'))