devices.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  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 COL_TENANT
  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, pk_field='slug')
  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, pk_field='slug')
  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 = tables.TemplateColumn(
  100. template_code=COL_TENANT
  101. )
  102. site = tables.Column(
  103. linkify=True
  104. )
  105. rack = tables.Column(
  106. linkify=True
  107. )
  108. device_role = ColoredLabelColumn(
  109. verbose_name='Role'
  110. )
  111. device_type = tables.LinkColumn(
  112. viewname='dcim:devicetype',
  113. args=[Accessor('device_type__pk')],
  114. verbose_name='Type',
  115. text=lambda record: record.device_type.display_name
  116. )
  117. primary_ip = tables.Column(
  118. linkify=True,
  119. verbose_name='IP Address'
  120. )
  121. primary_ip4 = tables.Column(
  122. linkify=True,
  123. verbose_name='IPv4 Address'
  124. )
  125. primary_ip6 = tables.Column(
  126. linkify=True,
  127. verbose_name='IPv6 Address'
  128. )
  129. cluster = tables.LinkColumn(
  130. viewname='virtualization:cluster',
  131. args=[Accessor('cluster__pk')]
  132. )
  133. virtual_chassis = tables.LinkColumn(
  134. viewname='dcim:virtualchassis',
  135. args=[Accessor('virtual_chassis__pk')]
  136. )
  137. vc_position = tables.Column(
  138. verbose_name='VC Position'
  139. )
  140. vc_priority = tables.Column(
  141. verbose_name='VC Priority'
  142. )
  143. tags = TagColumn(
  144. url_name='dcim:device_list'
  145. )
  146. class Meta(BaseTable.Meta):
  147. model = Device
  148. fields = (
  149. 'pk', 'name', 'status', 'tenant', 'device_role', 'device_type', 'platform', 'serial', 'asset_tag', 'site',
  150. 'rack', 'position', 'face', 'primary_ip', 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis',
  151. 'vc_position', 'vc_priority', 'tags',
  152. )
  153. default_columns = (
  154. 'pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip',
  155. )
  156. class DeviceImportTable(BaseTable):
  157. name = tables.TemplateColumn(
  158. template_code=DEVICE_LINK
  159. )
  160. status = ChoiceFieldColumn()
  161. tenant = tables.TemplateColumn(
  162. template_code=COL_TENANT
  163. )
  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. class Meta(BaseTable.Meta):
  196. order_by = ('device', 'name')
  197. class CableTerminationTable(BaseTable):
  198. cable = tables.Column(
  199. linkify=True
  200. )
  201. cable_peer = tables.TemplateColumn(
  202. accessor='_cable_peer',
  203. template_code=CABLETERMINATION,
  204. orderable=False,
  205. verbose_name='Cable Peer'
  206. )
  207. class PathEndpointTable(CableTerminationTable):
  208. connection = tables.TemplateColumn(
  209. accessor='_path.destination',
  210. template_code=CABLETERMINATION,
  211. verbose_name='Connection',
  212. orderable=False
  213. )
  214. class ConsolePortTable(DeviceComponentTable, PathEndpointTable):
  215. tags = TagColumn(
  216. url_name='dcim:consoleport_list'
  217. )
  218. class Meta(DeviceComponentTable.Meta):
  219. model = ConsolePort
  220. fields = (
  221. 'pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags',
  222. )
  223. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  224. class DeviceConsolePortTable(ConsolePortTable):
  225. name = tables.TemplateColumn(
  226. template_code='<i class="mdi mdi-console"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  227. )
  228. actions = ButtonsColumn(
  229. model=ConsolePort,
  230. buttons=('edit', 'delete'),
  231. prepend_template=CONSOLEPORT_BUTTONS,
  232. return_url_extra='%23tab_consoleports'
  233. )
  234. class Meta(DeviceComponentTable.Meta):
  235. model = ConsolePort
  236. fields = (
  237. 'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions'
  238. )
  239. default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'connection', 'actions')
  240. row_attrs = {
  241. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  242. }
  243. class ConsoleServerPortTable(DeviceComponentTable, PathEndpointTable):
  244. tags = TagColumn(
  245. url_name='dcim:consoleserverport_list'
  246. )
  247. class Meta(DeviceComponentTable.Meta):
  248. model = ConsoleServerPort
  249. fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags')
  250. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  251. class DeviceConsoleServerPortTable(ConsoleServerPortTable):
  252. name = tables.TemplateColumn(
  253. template_code='<i class="mdi mdi-console-network-outline"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  254. )
  255. actions = ButtonsColumn(
  256. model=ConsoleServerPort,
  257. buttons=('edit', 'delete'),
  258. prepend_template=CONSOLESERVERPORT_BUTTONS,
  259. return_url_extra='%23tab_consoleserverports'
  260. )
  261. class Meta(DeviceComponentTable.Meta):
  262. model = ConsoleServerPort
  263. fields = (
  264. 'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions'
  265. )
  266. default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'connection', 'actions')
  267. row_attrs = {
  268. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  269. }
  270. class PowerPortTable(DeviceComponentTable, PathEndpointTable):
  271. tags = TagColumn(
  272. url_name='dcim:powerport_list'
  273. )
  274. class Meta(DeviceComponentTable.Meta):
  275. model = PowerPort
  276. fields = (
  277. 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable',
  278. 'cable_peer', 'connection', 'tags',
  279. )
  280. default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
  281. class DevicePowerPortTable(PowerPortTable):
  282. name = tables.TemplateColumn(
  283. template_code='<i class="mdi mdi-power-plug-outline"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  284. )
  285. actions = ButtonsColumn(
  286. model=PowerPort,
  287. buttons=('edit', 'delete'),
  288. prepend_template=POWERPORT_BUTTONS,
  289. return_url_extra='%23tab_powerports'
  290. )
  291. class Meta(DeviceComponentTable.Meta):
  292. model = PowerPort
  293. fields = (
  294. 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'cable_peer',
  295. 'connection', 'tags', 'actions',
  296. )
  297. default_columns = (
  298. 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'connection',
  299. 'actions',
  300. )
  301. row_attrs = {
  302. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  303. }
  304. class PowerOutletTable(DeviceComponentTable, PathEndpointTable):
  305. power_port = tables.Column(
  306. linkify=True
  307. )
  308. tags = TagColumn(
  309. url_name='dcim:poweroutlet_list'
  310. )
  311. class Meta(DeviceComponentTable.Meta):
  312. model = PowerOutlet
  313. fields = (
  314. 'pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'cable_peer',
  315. 'connection', 'tags',
  316. )
  317. default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description')
  318. class DevicePowerOutletTable(PowerOutletTable):
  319. name = tables.TemplateColumn(
  320. template_code='<i class="mdi mdi-power-socket"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  321. )
  322. actions = ButtonsColumn(
  323. model=PowerOutlet,
  324. buttons=('edit', 'delete'),
  325. prepend_template=POWEROUTLET_BUTTONS,
  326. return_url_extra='%23tab_poweroutlets'
  327. )
  328. class Meta(DeviceComponentTable.Meta):
  329. model = PowerOutlet
  330. fields = (
  331. 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'cable_peer', 'connection',
  332. 'tags', 'actions',
  333. )
  334. default_columns = (
  335. 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'connection', 'actions',
  336. )
  337. row_attrs = {
  338. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  339. }
  340. class BaseInterfaceTable(BaseTable):
  341. enabled = BooleanColumn()
  342. ip_addresses = tables.TemplateColumn(
  343. template_code=INTERFACE_IPADDRESSES,
  344. orderable=False,
  345. verbose_name='IP Addresses'
  346. )
  347. untagged_vlan = tables.Column(linkify=True)
  348. tagged_vlans = tables.TemplateColumn(
  349. template_code=INTERFACE_TAGGED_VLANS,
  350. orderable=False,
  351. verbose_name='Tagged VLANs'
  352. )
  353. class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable):
  354. tags = TagColumn(
  355. url_name='dcim:interface_list'
  356. )
  357. class Meta(DeviceComponentTable.Meta):
  358. model = Interface
  359. fields = (
  360. 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address',
  361. 'description', 'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans',
  362. )
  363. default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description')
  364. class DeviceInterfaceTable(InterfaceTable):
  365. name = tables.TemplateColumn(
  366. template_code='<i class="mdi mdi-{% if iface.mgmt_only %}wrench{% elif iface.is_lag %}drag-horizontal-variant'
  367. '{% elif iface.is_virtual %}circle{% elif iface.is_wireless %}wifi{% else %}ethernet'
  368. '{% endif %}"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  369. )
  370. lag = tables.Column(
  371. linkify=True,
  372. verbose_name='LAG'
  373. )
  374. actions = ButtonsColumn(
  375. model=Interface,
  376. buttons=('edit', 'delete'),
  377. prepend_template=INTERFACE_BUTTONS,
  378. return_url_extra='%23tab_interfaces'
  379. )
  380. class Meta(DeviceComponentTable.Meta):
  381. model = Interface
  382. fields = (
  383. 'pk', 'name', 'label', 'enabled', 'type', 'lag', 'mgmt_only', 'mtu', 'mode', 'mac_address', 'description',
  384. 'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', 'actions',
  385. )
  386. default_columns = (
  387. 'pk', 'name', 'label', 'enabled', 'type', 'lag', 'mtu', 'mode', 'description', 'ip_addresses', 'cable',
  388. 'connection', 'actions',
  389. )
  390. row_attrs = {
  391. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  392. }
  393. class FrontPortTable(DeviceComponentTable, CableTerminationTable):
  394. rear_port_position = tables.Column(
  395. verbose_name='Position'
  396. )
  397. rear_port = tables.Column(
  398. linkify=True
  399. )
  400. tags = TagColumn(
  401. url_name='dcim:frontport_list'
  402. )
  403. class Meta(DeviceComponentTable.Meta):
  404. model = FrontPort
  405. fields = (
  406. 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable',
  407. 'cable_peer', 'tags',
  408. )
  409. default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description')
  410. class DeviceFrontPortTable(FrontPortTable):
  411. name = tables.TemplateColumn(
  412. template_code='<i class="mdi mdi-square-rounded{% if not record.cable %}-outline{% endif %}"></i> '
  413. '<a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  414. )
  415. actions = ButtonsColumn(
  416. model=FrontPort,
  417. buttons=('edit', 'delete'),
  418. prepend_template=FRONTPORT_BUTTONS,
  419. return_url_extra='%23tab_frontports'
  420. )
  421. class Meta(DeviceComponentTable.Meta):
  422. model = FrontPort
  423. fields = (
  424. 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer',
  425. 'tags', 'actions',
  426. )
  427. default_columns = (
  428. 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer',
  429. 'actions',
  430. )
  431. row_attrs = {
  432. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  433. }
  434. class RearPortTable(DeviceComponentTable, CableTerminationTable):
  435. tags = TagColumn(
  436. url_name='dcim:rearport_list'
  437. )
  438. class Meta(DeviceComponentTable.Meta):
  439. model = RearPort
  440. fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags')
  441. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  442. class DeviceRearPortTable(RearPortTable):
  443. name = tables.TemplateColumn(
  444. template_code='<i class="fmdi mdi-square-rounded{% if not record.cable %}-outline{% endif %}"></i> '
  445. '<a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  446. )
  447. actions = ButtonsColumn(
  448. model=RearPort,
  449. buttons=('edit', 'delete'),
  450. prepend_template=REARPORT_BUTTONS,
  451. return_url_extra='%23tab_rearports'
  452. )
  453. class Meta(DeviceComponentTable.Meta):
  454. model = RearPort
  455. fields = (
  456. 'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags', 'actions',
  457. )
  458. default_columns = (
  459. 'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'actions',
  460. )
  461. row_attrs = {
  462. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  463. }
  464. class DeviceBayTable(DeviceComponentTable):
  465. status = tables.TemplateColumn(
  466. template_code=DEVICEBAY_STATUS
  467. )
  468. installed_device = tables.Column(
  469. linkify=True
  470. )
  471. tags = TagColumn(
  472. url_name='dcim:devicebay_list'
  473. )
  474. class Meta(DeviceComponentTable.Meta):
  475. model = DeviceBay
  476. fields = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description', 'tags')
  477. default_columns = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description')
  478. class DeviceDeviceBayTable(DeviceBayTable):
  479. name = tables.TemplateColumn(
  480. template_code='<i class="mdi mdi-circle{% if record.installed_device %}slice-8{% else %}outline{% endif %}'
  481. '"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  482. )
  483. actions = ButtonsColumn(
  484. model=DeviceBay,
  485. buttons=('edit', 'delete'),
  486. prepend_template=DEVICEBAY_BUTTONS,
  487. return_url_extra='%23tab_devicebays'
  488. )
  489. class Meta(DeviceComponentTable.Meta):
  490. model = DeviceBay
  491. fields = (
  492. 'pk', 'name', 'label', 'status', 'installed_device', 'description', 'tags', 'actions',
  493. )
  494. default_columns = (
  495. 'pk', 'name', 'label', 'status', 'installed_device', 'description', 'actions',
  496. )
  497. class InventoryItemTable(DeviceComponentTable):
  498. manufacturer = tables.Column(
  499. linkify=True
  500. )
  501. discovered = BooleanColumn()
  502. tags = TagColumn(
  503. url_name='dcim:inventoryitem_list'
  504. )
  505. cable = None # Override DeviceComponentTable
  506. class Meta(DeviceComponentTable.Meta):
  507. model = InventoryItem
  508. fields = (
  509. 'pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description',
  510. 'discovered', 'tags',
  511. )
  512. default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag')
  513. class DeviceInventoryItemTable(InventoryItemTable):
  514. name = tables.TemplateColumn(
  515. template_code='<a href="{{ record.get_absolute_url }}" style="padding-left: {{ record.level }}0px">'
  516. '{{ value }}</a>'
  517. )
  518. actions = ButtonsColumn(
  519. model=InventoryItem,
  520. buttons=('edit', 'delete'),
  521. return_url_extra='%23tab_inventoryitems'
  522. )
  523. class Meta(DeviceComponentTable.Meta):
  524. model = InventoryItem
  525. fields = (
  526. 'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered',
  527. 'tags', 'actions',
  528. )
  529. default_columns = (
  530. 'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered',
  531. 'actions',
  532. )
  533. #
  534. # Virtual chassis
  535. #
  536. class VirtualChassisTable(BaseTable):
  537. pk = ToggleColumn()
  538. name = tables.Column(
  539. linkify=True
  540. )
  541. master = tables.Column(
  542. linkify=True
  543. )
  544. member_count = LinkedCountColumn(
  545. viewname='dcim:device_list',
  546. url_params={'virtual_chassis_id': 'pk'},
  547. verbose_name='Members'
  548. )
  549. tags = TagColumn(
  550. url_name='dcim:virtualchassis_list'
  551. )
  552. class Meta(BaseTable.Meta):
  553. model = VirtualChassis
  554. fields = ('pk', 'name', 'domain', 'master', 'member_count', 'tags')
  555. default_columns = ('pk', 'name', 'domain', 'master', 'member_count')