devices.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. import django_tables2 as tables
  2. from django_tables2.utils import Accessor
  3. from django.conf import settings
  4. from dcim.models import (
  5. ConsolePort, ConsoleServerPort, Device, DeviceBay, DeviceRole, FrontPort, Interface, InventoryItem, Platform,
  6. PowerOutlet, PowerPort, RearPort, VirtualChassis,
  7. )
  8. from tenancy.tables import TenantColumn
  9. from utilities.tables import (
  10. BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn,
  11. TagColumn, ToggleColumn,
  12. )
  13. from .template_code import (
  14. CABLETERMINATION, CONSOLEPORT_BUTTONS, CONSOLESERVERPORT_BUTTONS, DEVICE_LINK, DEVICEBAY_BUTTONS, DEVICEBAY_STATUS,
  15. FRONTPORT_BUTTONS, INTERFACE_BUTTONS, INTERFACE_IPADDRESSES, INTERFACE_TAGGED_VLANS, POWEROUTLET_BUTTONS,
  16. POWERPORT_BUTTONS, REARPORT_BUTTONS,
  17. )
  18. __all__ = (
  19. 'ConsolePortTable',
  20. 'ConsoleServerPortTable',
  21. 'DeviceBayTable',
  22. 'DeviceConsolePortTable',
  23. 'DeviceConsoleServerPortTable',
  24. 'DeviceDeviceBayTable',
  25. 'DeviceFrontPortTable',
  26. 'DeviceImportTable',
  27. 'DeviceInterfaceTable',
  28. 'DeviceInventoryItemTable',
  29. 'DevicePowerPortTable',
  30. 'DevicePowerOutletTable',
  31. 'DeviceRearPortTable',
  32. 'DeviceRoleTable',
  33. 'DeviceTable',
  34. 'FrontPortTable',
  35. 'InterfaceTable',
  36. 'InventoryItemTable',
  37. 'PlatformTable',
  38. 'PowerOutletTable',
  39. 'PowerPortTable',
  40. 'RearPortTable',
  41. 'VirtualChassisTable',
  42. )
  43. def get_cabletermination_row_class(record):
  44. if record.mark_connected:
  45. return 'success'
  46. elif record.cable:
  47. return record.cable.get_status_class()
  48. return ''
  49. #
  50. # Device roles
  51. #
  52. class DeviceRoleTable(BaseTable):
  53. pk = ToggleColumn()
  54. name = tables.Column(
  55. linkify=True
  56. )
  57. device_count = LinkedCountColumn(
  58. viewname='dcim:device_list',
  59. url_params={'role_id': 'pk'},
  60. verbose_name='Devices'
  61. )
  62. vm_count = LinkedCountColumn(
  63. viewname='virtualization:virtualmachine_list',
  64. url_params={'role_id': 'pk'},
  65. verbose_name='VMs'
  66. )
  67. color = ColorColumn()
  68. vm_role = BooleanColumn()
  69. actions = ButtonsColumn(DeviceRole)
  70. class Meta(BaseTable.Meta):
  71. model = DeviceRole
  72. fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions')
  73. default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'actions')
  74. #
  75. # Platforms
  76. #
  77. class PlatformTable(BaseTable):
  78. pk = ToggleColumn()
  79. name = tables.Column(
  80. linkify=True
  81. )
  82. device_count = LinkedCountColumn(
  83. viewname='dcim:device_list',
  84. url_params={'platform_id': 'pk'},
  85. verbose_name='Devices'
  86. )
  87. vm_count = LinkedCountColumn(
  88. viewname='virtualization:virtualmachine_list',
  89. url_params={'platform_id': 'pk'},
  90. verbose_name='VMs'
  91. )
  92. actions = ButtonsColumn(Platform)
  93. class Meta(BaseTable.Meta):
  94. model = Platform
  95. fields = (
  96. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args',
  97. 'description', 'actions',
  98. )
  99. default_columns = (
  100. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'napalm_driver', 'description', 'actions',
  101. )
  102. #
  103. # Devices
  104. #
  105. class DeviceTable(BaseTable):
  106. pk = ToggleColumn()
  107. name = tables.TemplateColumn(
  108. order_by=('_name',),
  109. template_code=DEVICE_LINK
  110. )
  111. status = ChoiceFieldColumn()
  112. tenant = TenantColumn()
  113. site = tables.Column(
  114. linkify=True
  115. )
  116. location = tables.Column(
  117. linkify=True
  118. )
  119. rack = tables.Column(
  120. linkify=True
  121. )
  122. device_role = ColoredLabelColumn(
  123. verbose_name='Role'
  124. )
  125. manufacturer = tables.Column(
  126. accessor=Accessor('device_type__manufacturer'),
  127. linkify=True
  128. )
  129. device_type = tables.Column(
  130. linkify=True,
  131. verbose_name='Type'
  132. )
  133. if settings.PREFER_IPV4:
  134. primary_ip = tables.Column(
  135. linkify=True,
  136. order_by=('primary_ip4', 'primary_ip6'),
  137. verbose_name='IP Address'
  138. )
  139. else:
  140. primary_ip = tables.Column(
  141. linkify=True,
  142. order_by=('primary_ip6', 'primary_ip4'),
  143. verbose_name='IP Address'
  144. )
  145. primary_ip4 = tables.Column(
  146. linkify=True,
  147. verbose_name='IPv4 Address'
  148. )
  149. primary_ip6 = tables.Column(
  150. linkify=True,
  151. verbose_name='IPv6 Address'
  152. )
  153. cluster = tables.Column(
  154. linkify=True
  155. )
  156. virtual_chassis = tables.Column(
  157. linkify=True
  158. )
  159. vc_position = tables.Column(
  160. verbose_name='VC Position'
  161. )
  162. vc_priority = tables.Column(
  163. verbose_name='VC Priority'
  164. )
  165. tags = TagColumn(
  166. url_name='dcim:device_list'
  167. )
  168. class Meta(BaseTable.Meta):
  169. model = Device
  170. fields = (
  171. 'pk', 'name', 'status', 'tenant', 'device_role', 'manufacturer', 'device_type', 'platform', 'serial',
  172. 'asset_tag', 'site', 'location', 'rack', 'position', 'face', 'primary_ip', 'primary_ip4', 'primary_ip6',
  173. 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'tags',
  174. )
  175. default_columns = (
  176. 'pk', 'name', 'status', 'tenant', 'site', 'location', 'rack', 'device_role', 'manufacturer', 'device_type',
  177. 'primary_ip',
  178. )
  179. class DeviceImportTable(BaseTable):
  180. name = tables.TemplateColumn(
  181. template_code=DEVICE_LINK
  182. )
  183. status = ChoiceFieldColumn()
  184. tenant = TenantColumn()
  185. site = tables.Column(
  186. linkify=True
  187. )
  188. rack = tables.Column(
  189. linkify=True
  190. )
  191. device_role = tables.Column(
  192. verbose_name='Role'
  193. )
  194. device_type = tables.Column(
  195. verbose_name='Type'
  196. )
  197. class Meta(BaseTable.Meta):
  198. model = Device
  199. fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
  200. empty_text = False
  201. #
  202. # Device components
  203. #
  204. class DeviceComponentTable(BaseTable):
  205. pk = ToggleColumn()
  206. device = tables.Column(
  207. linkify=True
  208. )
  209. name = tables.Column(
  210. linkify=True,
  211. order_by=('_name',)
  212. )
  213. cable = tables.Column(
  214. linkify=True
  215. )
  216. mark_connected = BooleanColumn()
  217. class Meta(BaseTable.Meta):
  218. order_by = ('device', 'name')
  219. class CableTerminationTable(BaseTable):
  220. cable = tables.Column(
  221. linkify=True
  222. )
  223. cable_color = ColorColumn(
  224. accessor='cable.color',
  225. orderable=False,
  226. verbose_name='Cable Color'
  227. )
  228. cable_peer = tables.TemplateColumn(
  229. accessor='_cable_peer',
  230. template_code=CABLETERMINATION,
  231. orderable=False,
  232. verbose_name='Cable Peer'
  233. )
  234. mark_connected = BooleanColumn()
  235. class PathEndpointTable(CableTerminationTable):
  236. connection = tables.TemplateColumn(
  237. accessor='_path.last_node',
  238. template_code=CABLETERMINATION,
  239. verbose_name='Connection',
  240. orderable=False
  241. )
  242. class ConsolePortTable(DeviceComponentTable, PathEndpointTable):
  243. device = tables.Column(
  244. linkify={
  245. 'viewname': 'dcim:device_consoleports',
  246. 'args': [Accessor('device_id')],
  247. }
  248. )
  249. tags = TagColumn(
  250. url_name='dcim:consoleport_list'
  251. )
  252. class Meta(DeviceComponentTable.Meta):
  253. model = ConsolePort
  254. fields = (
  255. 'pk', 'device', 'name', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
  256. 'cable_peer', 'connection', 'tags',
  257. )
  258. default_columns = ('pk', 'device', 'name', 'label', 'type', 'speed', 'description')
  259. class DeviceConsolePortTable(ConsolePortTable):
  260. name = tables.TemplateColumn(
  261. template_code='<i class="mdi mdi-console"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
  262. order_by=Accessor('_name'),
  263. attrs={'td': {'class': 'text-nowrap'}}
  264. )
  265. actions = ButtonsColumn(
  266. model=ConsolePort,
  267. buttons=('edit', 'delete'),
  268. prepend_template=CONSOLEPORT_BUTTONS
  269. )
  270. class Meta(DeviceComponentTable.Meta):
  271. model = ConsolePort
  272. fields = (
  273. 'pk', 'name', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
  274. 'cable_peer', 'connection', 'tags', 'actions'
  275. )
  276. default_columns = ('pk', 'name', 'label', 'type', 'speed', 'description', 'cable', 'connection', 'actions')
  277. row_attrs = {
  278. 'class': get_cabletermination_row_class
  279. }
  280. class ConsoleServerPortTable(DeviceComponentTable, PathEndpointTable):
  281. device = tables.Column(
  282. linkify={
  283. 'viewname': 'dcim:device_consoleserverports',
  284. 'args': [Accessor('device_id')],
  285. }
  286. )
  287. tags = TagColumn(
  288. url_name='dcim:consoleserverport_list'
  289. )
  290. class Meta(DeviceComponentTable.Meta):
  291. model = ConsoleServerPort
  292. fields = (
  293. 'pk', 'device', 'name', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
  294. 'cable_peer', 'connection', 'tags',
  295. )
  296. default_columns = ('pk', 'device', 'name', 'label', 'type', 'speed', 'description')
  297. class DeviceConsoleServerPortTable(ConsoleServerPortTable):
  298. name = tables.TemplateColumn(
  299. template_code='<i class="mdi mdi-console-network-outline"></i> '
  300. '<a href="{{ record.get_absolute_url }}">{{ value }}</a>',
  301. order_by=Accessor('_name'),
  302. attrs={'td': {'class': 'text-nowrap'}}
  303. )
  304. actions = ButtonsColumn(
  305. model=ConsoleServerPort,
  306. buttons=('edit', 'delete'),
  307. prepend_template=CONSOLESERVERPORT_BUTTONS
  308. )
  309. class Meta(DeviceComponentTable.Meta):
  310. model = ConsoleServerPort
  311. fields = (
  312. 'pk', 'name', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
  313. 'cable_peer', 'connection', 'tags', 'actions',
  314. )
  315. default_columns = ('pk', 'name', 'label', 'type', 'speed', 'description', 'cable', 'connection', 'actions')
  316. row_attrs = {
  317. 'class': get_cabletermination_row_class
  318. }
  319. class PowerPortTable(DeviceComponentTable, PathEndpointTable):
  320. device = tables.Column(
  321. linkify={
  322. 'viewname': 'dcim:device_powerports',
  323. 'args': [Accessor('device_id')],
  324. }
  325. )
  326. tags = TagColumn(
  327. url_name='dcim:powerport_list'
  328. )
  329. class Meta(DeviceComponentTable.Meta):
  330. model = PowerPort
  331. fields = (
  332. 'pk', 'device', 'name', 'label', 'type', 'description', 'mark_connected', 'maximum_draw', 'allocated_draw',
  333. 'cable', 'cable_color', 'cable_peer', 'connection', 'tags',
  334. )
  335. default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
  336. class DevicePowerPortTable(PowerPortTable):
  337. name = tables.TemplateColumn(
  338. template_code='<i class="mdi mdi-power-plug-outline"></i> <a href="{{ record.get_absolute_url }}">'
  339. '{{ value }}</a>',
  340. order_by=Accessor('_name'),
  341. attrs={'td': {'class': 'text-nowrap'}}
  342. )
  343. actions = ButtonsColumn(
  344. model=PowerPort,
  345. buttons=('edit', 'delete'),
  346. prepend_template=POWERPORT_BUTTONS
  347. )
  348. class Meta(DeviceComponentTable.Meta):
  349. model = PowerPort
  350. fields = (
  351. 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'mark_connected', 'cable',
  352. 'cable_color', 'cable_peer', 'connection', 'tags', 'actions',
  353. )
  354. default_columns = (
  355. 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'connection',
  356. 'actions',
  357. )
  358. row_attrs = {
  359. 'class': get_cabletermination_row_class
  360. }
  361. class PowerOutletTable(DeviceComponentTable, PathEndpointTable):
  362. device = tables.Column(
  363. linkify={
  364. 'viewname': 'dcim:device_poweroutlets',
  365. 'args': [Accessor('device_id')],
  366. }
  367. )
  368. power_port = tables.Column(
  369. linkify=True
  370. )
  371. tags = TagColumn(
  372. url_name='dcim:poweroutlet_list'
  373. )
  374. class Meta(DeviceComponentTable.Meta):
  375. model = PowerOutlet
  376. fields = (
  377. 'pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'mark_connected', 'cable',
  378. 'cable_color', 'cable_peer', 'connection', 'tags',
  379. )
  380. default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description')
  381. class DevicePowerOutletTable(PowerOutletTable):
  382. name = tables.TemplateColumn(
  383. template_code='<i class="mdi mdi-power-socket"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
  384. order_by=Accessor('_name'),
  385. attrs={'td': {'class': 'text-nowrap'}}
  386. )
  387. actions = ButtonsColumn(
  388. model=PowerOutlet,
  389. buttons=('edit', 'delete'),
  390. prepend_template=POWEROUTLET_BUTTONS
  391. )
  392. class Meta(DeviceComponentTable.Meta):
  393. model = PowerOutlet
  394. fields = (
  395. 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'mark_connected', 'cable',
  396. 'cable_color', 'cable_peer', 'connection', 'tags', 'actions',
  397. )
  398. default_columns = (
  399. 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'connection', 'actions',
  400. )
  401. row_attrs = {
  402. 'class': get_cabletermination_row_class
  403. }
  404. class BaseInterfaceTable(BaseTable):
  405. enabled = BooleanColumn()
  406. ip_addresses = tables.TemplateColumn(
  407. template_code=INTERFACE_IPADDRESSES,
  408. orderable=False,
  409. verbose_name='IP Addresses'
  410. )
  411. untagged_vlan = tables.Column(linkify=True)
  412. tagged_vlans = tables.TemplateColumn(
  413. template_code=INTERFACE_TAGGED_VLANS,
  414. orderable=False,
  415. verbose_name='Tagged VLANs'
  416. )
  417. class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable):
  418. device = tables.Column(
  419. linkify={
  420. 'viewname': 'dcim:device_interfaces',
  421. 'args': [Accessor('device_id')],
  422. }
  423. )
  424. mgmt_only = BooleanColumn()
  425. tags = TagColumn(
  426. url_name='dcim:interface_list'
  427. )
  428. class Meta(DeviceComponentTable.Meta):
  429. model = Interface
  430. fields = (
  431. 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address',
  432. 'description', 'mark_connected', 'cable', 'cable_color', 'cable_peer', 'connection', 'tags', 'ip_addresses',
  433. 'untagged_vlan', 'tagged_vlans',
  434. )
  435. default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description')
  436. class DeviceInterfaceTable(InterfaceTable):
  437. name = tables.TemplateColumn(
  438. template_code='<i class="mdi mdi-{% if iface.mgmt_only %}wrench{% elif iface.is_lag %}drag-horizontal-variant'
  439. '{% elif iface.is_virtual %}circle{% elif iface.is_wireless %}wifi{% else %}ethernet'
  440. '{% endif %}"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
  441. order_by=Accessor('_name'),
  442. attrs={'td': {'class': 'text-nowrap'}}
  443. )
  444. parent = tables.Column(
  445. linkify=True,
  446. verbose_name='Parent'
  447. )
  448. lag = tables.Column(
  449. linkify=True,
  450. verbose_name='LAG'
  451. )
  452. actions = ButtonsColumn(
  453. model=Interface,
  454. buttons=('edit', 'delete'),
  455. prepend_template=INTERFACE_BUTTONS
  456. )
  457. class Meta(DeviceComponentTable.Meta):
  458. model = Interface
  459. fields = (
  460. 'pk', 'name', 'label', 'enabled', 'type', 'parent', 'lag', 'mgmt_only', 'mtu', 'mode', 'mac_address',
  461. 'description', 'mark_connected', 'cable', 'cable_color', 'cable_peer', 'connection', 'tags', 'ip_addresses',
  462. 'untagged_vlan', 'tagged_vlans', 'actions',
  463. )
  464. order_by = ('name',)
  465. default_columns = (
  466. 'pk', 'name', 'label', 'enabled', 'type', 'parent', 'lag', 'mtu', 'mode', 'description', 'ip_addresses',
  467. 'cable', 'connection', 'actions',
  468. )
  469. row_attrs = {
  470. 'class': get_cabletermination_row_class,
  471. 'data-name': lambda record: record.name,
  472. }
  473. class FrontPortTable(DeviceComponentTable, CableTerminationTable):
  474. device = tables.Column(
  475. linkify={
  476. 'viewname': 'dcim:device_frontports',
  477. 'args': [Accessor('device_id')],
  478. }
  479. )
  480. rear_port_position = tables.Column(
  481. verbose_name='Position'
  482. )
  483. rear_port = tables.Column(
  484. linkify=True
  485. )
  486. tags = TagColumn(
  487. url_name='dcim:frontport_list'
  488. )
  489. class Meta(DeviceComponentTable.Meta):
  490. model = FrontPort
  491. fields = (
  492. 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'mark_connected',
  493. 'cable', 'cable_color', 'cable_peer', 'tags',
  494. )
  495. default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description')
  496. class DeviceFrontPortTable(FrontPortTable):
  497. name = tables.TemplateColumn(
  498. template_code='<i class="mdi mdi-square-rounded{% if not record.cable %}-outline{% endif %}"></i> '
  499. '<a href="{{ record.get_absolute_url }}">{{ value }}</a>',
  500. order_by=Accessor('_name'),
  501. attrs={'td': {'class': 'text-nowrap'}}
  502. )
  503. actions = ButtonsColumn(
  504. model=FrontPort,
  505. buttons=('edit', 'delete'),
  506. prepend_template=FRONTPORT_BUTTONS
  507. )
  508. class Meta(DeviceComponentTable.Meta):
  509. model = FrontPort
  510. fields = (
  511. 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'mark_connected', 'cable',
  512. 'cable_color', 'cable_peer', 'tags', 'actions',
  513. )
  514. default_columns = (
  515. 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer',
  516. 'actions',
  517. )
  518. row_attrs = {
  519. 'class': get_cabletermination_row_class
  520. }
  521. class RearPortTable(DeviceComponentTable, CableTerminationTable):
  522. device = tables.Column(
  523. linkify={
  524. 'viewname': 'dcim:device_rearports',
  525. 'args': [Accessor('device_id')],
  526. }
  527. )
  528. tags = TagColumn(
  529. url_name='dcim:rearport_list'
  530. )
  531. class Meta(DeviceComponentTable.Meta):
  532. model = RearPort
  533. fields = (
  534. 'pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'mark_connected', 'cable',
  535. 'cable_color', 'cable_peer', 'tags',
  536. )
  537. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  538. class DeviceRearPortTable(RearPortTable):
  539. name = tables.TemplateColumn(
  540. template_code='<i class="mdi mdi-square-rounded{% if not record.cable %}-outline{% endif %}"></i> '
  541. '<a href="{{ record.get_absolute_url }}">{{ value }}</a>',
  542. order_by=Accessor('_name'),
  543. attrs={'td': {'class': 'text-nowrap'}}
  544. )
  545. actions = ButtonsColumn(
  546. model=RearPort,
  547. buttons=('edit', 'delete'),
  548. prepend_template=REARPORT_BUTTONS
  549. )
  550. class Meta(DeviceComponentTable.Meta):
  551. model = RearPort
  552. fields = (
  553. 'pk', 'name', 'label', 'type', 'positions', 'description', 'mark_connected', 'cable', 'cable_color',
  554. 'cable_peer', 'tags', 'actions',
  555. )
  556. default_columns = (
  557. 'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'actions',
  558. )
  559. row_attrs = {
  560. 'class': get_cabletermination_row_class
  561. }
  562. class DeviceBayTable(DeviceComponentTable):
  563. device = tables.Column(
  564. linkify={
  565. 'viewname': 'dcim:device_devicebays',
  566. 'args': [Accessor('device_id')],
  567. }
  568. )
  569. status = tables.TemplateColumn(
  570. template_code=DEVICEBAY_STATUS
  571. )
  572. installed_device = tables.Column(
  573. linkify=True
  574. )
  575. tags = TagColumn(
  576. url_name='dcim:devicebay_list'
  577. )
  578. class Meta(DeviceComponentTable.Meta):
  579. model = DeviceBay
  580. fields = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description', 'tags')
  581. default_columns = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description')
  582. class DeviceDeviceBayTable(DeviceBayTable):
  583. name = tables.TemplateColumn(
  584. template_code='<i class="mdi mdi-circle{% if record.installed_device %}slice-8{% else %}outline{% endif %}'
  585. '"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
  586. order_by=Accessor('_name'),
  587. attrs={'td': {'class': 'text-nowrap'}}
  588. )
  589. actions = ButtonsColumn(
  590. model=DeviceBay,
  591. buttons=('edit', 'delete'),
  592. prepend_template=DEVICEBAY_BUTTONS
  593. )
  594. class Meta(DeviceComponentTable.Meta):
  595. model = DeviceBay
  596. fields = (
  597. 'pk', 'name', 'label', 'status', 'installed_device', 'description', 'tags', 'actions',
  598. )
  599. default_columns = (
  600. 'pk', 'name', 'label', 'status', 'installed_device', 'description', 'actions',
  601. )
  602. class InventoryItemTable(DeviceComponentTable):
  603. device = tables.Column(
  604. linkify={
  605. 'viewname': 'dcim:device_inventory',
  606. 'args': [Accessor('device_id')],
  607. }
  608. )
  609. manufacturer = tables.Column(
  610. linkify=True
  611. )
  612. discovered = BooleanColumn()
  613. tags = TagColumn(
  614. url_name='dcim:inventoryitem_list'
  615. )
  616. cable = None # Override DeviceComponentTable
  617. class Meta(DeviceComponentTable.Meta):
  618. model = InventoryItem
  619. fields = (
  620. 'pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description',
  621. 'discovered', 'tags',
  622. )
  623. default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag')
  624. class DeviceInventoryItemTable(InventoryItemTable):
  625. name = tables.TemplateColumn(
  626. template_code='<a href="{{ record.get_absolute_url }}" style="padding-left: {{ record.level }}0px">'
  627. '{{ value }}</a>',
  628. order_by=Accessor('_name'),
  629. attrs={'td': {'class': 'text-nowrap'}}
  630. )
  631. actions = ButtonsColumn(
  632. model=InventoryItem,
  633. buttons=('edit', 'delete')
  634. )
  635. class Meta(DeviceComponentTable.Meta):
  636. model = InventoryItem
  637. fields = (
  638. 'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered',
  639. 'tags', 'actions',
  640. )
  641. default_columns = (
  642. 'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered',
  643. 'actions',
  644. )
  645. #
  646. # Virtual chassis
  647. #
  648. class VirtualChassisTable(BaseTable):
  649. pk = ToggleColumn()
  650. name = tables.Column(
  651. linkify=True
  652. )
  653. master = tables.Column(
  654. linkify=True
  655. )
  656. member_count = LinkedCountColumn(
  657. viewname='dcim:device_list',
  658. url_params={'virtual_chassis_id': 'pk'},
  659. verbose_name='Members'
  660. )
  661. tags = TagColumn(
  662. url_name='dcim:virtualchassis_list'
  663. )
  664. class Meta(BaseTable.Meta):
  665. model = VirtualChassis
  666. fields = ('pk', 'name', 'domain', 'master', 'member_count', 'tags')
  667. default_columns = ('pk', 'name', 'domain', 'master', 'member_count')