devices.py 24 KB

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