devices.py 21 KB

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