devices.py 26 KB

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