devices.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  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, INTERFACE_IPADDRESSES,
  14. INTERFACE_TAGGED_VLANS, POWEROUTLET_BUTTONS, POWERPORT_BUTTONS,
  15. )
  16. __all__ = (
  17. 'ConsolePortTable',
  18. 'ConsoleServerPortTable',
  19. 'DeviceBayTable',
  20. 'DeviceConsolePortTable',
  21. 'DeviceConsoleServerPortTable',
  22. 'DeviceImportTable',
  23. 'DevicePowerPortTable',
  24. 'DevicePowerOutletTable',
  25. 'DeviceRoleTable',
  26. 'DeviceTable',
  27. 'FrontPortTable',
  28. 'InterfaceTable',
  29. 'InventoryItemTable',
  30. 'PlatformTable',
  31. 'PowerOutletTable',
  32. 'PowerPortTable',
  33. 'RearPortTable',
  34. 'VirtualChassisTable',
  35. )
  36. #
  37. # Device roles
  38. #
  39. class DeviceRoleTable(BaseTable):
  40. pk = ToggleColumn()
  41. device_count = LinkedCountColumn(
  42. viewname='dcim:device_list',
  43. url_params={'role': 'slug'},
  44. verbose_name='Devices'
  45. )
  46. vm_count = LinkedCountColumn(
  47. viewname='virtualization:virtualmachine_list',
  48. url_params={'role': 'slug'},
  49. verbose_name='VMs'
  50. )
  51. color = ColorColumn()
  52. vm_role = BooleanColumn()
  53. actions = ButtonsColumn(DeviceRole, pk_field='slug')
  54. class Meta(BaseTable.Meta):
  55. model = DeviceRole
  56. fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions')
  57. default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'actions')
  58. #
  59. # Platforms
  60. #
  61. class PlatformTable(BaseTable):
  62. pk = ToggleColumn()
  63. device_count = LinkedCountColumn(
  64. viewname='dcim:device_list',
  65. url_params={'platform': 'slug'},
  66. verbose_name='Devices'
  67. )
  68. vm_count = LinkedCountColumn(
  69. viewname='virtualization:virtualmachine_list',
  70. url_params={'platform': 'slug'},
  71. verbose_name='VMs'
  72. )
  73. actions = ButtonsColumn(Platform, pk_field='slug')
  74. class Meta(BaseTable.Meta):
  75. model = Platform
  76. fields = (
  77. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args',
  78. 'description', 'actions',
  79. )
  80. default_columns = (
  81. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'napalm_driver', 'description', 'actions',
  82. )
  83. #
  84. # Devices
  85. #
  86. class DeviceTable(BaseTable):
  87. pk = ToggleColumn()
  88. name = tables.TemplateColumn(
  89. order_by=('_name',),
  90. template_code=DEVICE_LINK
  91. )
  92. status = ChoiceFieldColumn()
  93. tenant = tables.TemplateColumn(
  94. template_code=COL_TENANT
  95. )
  96. site = tables.Column(
  97. linkify=True
  98. )
  99. rack = tables.Column(
  100. linkify=True
  101. )
  102. device_role = ColoredLabelColumn(
  103. verbose_name='Role'
  104. )
  105. device_type = tables.LinkColumn(
  106. viewname='dcim:devicetype',
  107. args=[Accessor('device_type__pk')],
  108. verbose_name='Type',
  109. text=lambda record: record.device_type.display_name
  110. )
  111. primary_ip = tables.Column(
  112. linkify=True,
  113. verbose_name='IP Address'
  114. )
  115. primary_ip4 = tables.Column(
  116. linkify=True,
  117. verbose_name='IPv4 Address'
  118. )
  119. primary_ip6 = tables.Column(
  120. linkify=True,
  121. verbose_name='IPv6 Address'
  122. )
  123. cluster = tables.LinkColumn(
  124. viewname='virtualization:cluster',
  125. args=[Accessor('cluster__pk')]
  126. )
  127. virtual_chassis = tables.LinkColumn(
  128. viewname='dcim:virtualchassis',
  129. args=[Accessor('virtual_chassis__pk')]
  130. )
  131. vc_position = tables.Column(
  132. verbose_name='VC Position'
  133. )
  134. vc_priority = tables.Column(
  135. verbose_name='VC Priority'
  136. )
  137. tags = TagColumn(
  138. url_name='dcim:device_list'
  139. )
  140. class Meta(BaseTable.Meta):
  141. model = Device
  142. fields = (
  143. 'pk', 'name', 'status', 'tenant', 'device_role', 'device_type', 'platform', 'serial', 'asset_tag', 'site',
  144. 'rack', 'position', 'face', 'primary_ip', 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis',
  145. 'vc_position', 'vc_priority', 'tags',
  146. )
  147. default_columns = (
  148. 'pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip',
  149. )
  150. class DeviceImportTable(BaseTable):
  151. name = tables.TemplateColumn(
  152. template_code=DEVICE_LINK
  153. )
  154. status = ChoiceFieldColumn()
  155. tenant = tables.TemplateColumn(
  156. template_code=COL_TENANT
  157. )
  158. site = tables.Column(
  159. linkify=True
  160. )
  161. rack = tables.Column(
  162. linkify=True
  163. )
  164. device_role = tables.Column(
  165. verbose_name='Role'
  166. )
  167. device_type = tables.Column(
  168. verbose_name='Type'
  169. )
  170. class Meta(BaseTable.Meta):
  171. model = Device
  172. fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
  173. empty_text = False
  174. #
  175. # Device components
  176. #
  177. class DeviceComponentTable(BaseTable):
  178. pk = ToggleColumn()
  179. device = tables.Column(
  180. linkify=True
  181. )
  182. name = tables.Column(
  183. linkify=True,
  184. order_by=('_name',)
  185. )
  186. cable = tables.Column(
  187. linkify=True
  188. )
  189. class Meta(BaseTable.Meta):
  190. order_by = ('device', 'name')
  191. class CableTerminationTable(BaseTable):
  192. cable = tables.Column(
  193. linkify=True
  194. )
  195. cable_peer = tables.TemplateColumn(
  196. accessor='get_cable_peer',
  197. template_code=CABLETERMINATION,
  198. orderable=False
  199. )
  200. class PathEndpointTable(CableTerminationTable):
  201. connection = tables.TemplateColumn(
  202. accessor='_path.destination',
  203. template_code=CABLETERMINATION,
  204. verbose_name='Connection',
  205. orderable=False
  206. )
  207. class ConsolePortTable(DeviceComponentTable, PathEndpointTable):
  208. tags = TagColumn(
  209. url_name='dcim:consoleport_list'
  210. )
  211. class Meta(DeviceComponentTable.Meta):
  212. model = ConsolePort
  213. fields = (
  214. 'pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags',
  215. )
  216. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  217. class DeviceConsolePortTable(ConsolePortTable):
  218. name = tables.TemplateColumn(
  219. template_code='<i class="fa fa-keyboard-o"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  220. )
  221. actions = ButtonsColumn(
  222. model=ConsolePort,
  223. buttons=('edit', 'delete'),
  224. prepend_template=CONSOLEPORT_BUTTONS
  225. )
  226. class Meta(DeviceComponentTable.Meta):
  227. model = ConsolePort
  228. fields = (
  229. 'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions'
  230. )
  231. default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'actions')
  232. row_attrs = {
  233. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  234. }
  235. class ConsoleServerPortTable(DeviceComponentTable, PathEndpointTable):
  236. tags = TagColumn(
  237. url_name='dcim:consoleserverport_list'
  238. )
  239. class Meta(DeviceComponentTable.Meta):
  240. model = ConsoleServerPort
  241. fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags')
  242. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  243. class DeviceConsoleServerPortTable(ConsoleServerPortTable):
  244. name = tables.TemplateColumn(
  245. template_code='<i class="fa fa-keyboard-o"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  246. )
  247. actions = ButtonsColumn(
  248. model=ConsoleServerPort,
  249. buttons=('edit', 'delete'),
  250. prepend_template=CONSOLESERVERPORT_BUTTONS
  251. )
  252. class Meta(DeviceComponentTable.Meta):
  253. model = ConsoleServerPort
  254. fields = (
  255. 'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions'
  256. )
  257. default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'actions')
  258. row_attrs = {
  259. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  260. }
  261. class PowerPortTable(DeviceComponentTable, PathEndpointTable):
  262. tags = TagColumn(
  263. url_name='dcim:powerport_list'
  264. )
  265. class Meta(DeviceComponentTable.Meta):
  266. model = PowerPort
  267. fields = (
  268. 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable',
  269. 'cable_peer', 'connection', 'tags',
  270. )
  271. default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
  272. class DevicePowerPortTable(PowerPortTable):
  273. name = tables.TemplateColumn(
  274. template_code='<i class="fa fa-bolt"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  275. )
  276. actions = ButtonsColumn(
  277. model=PowerPort,
  278. buttons=('edit', 'delete'),
  279. prepend_template=POWERPORT_BUTTONS
  280. )
  281. class Meta(DeviceComponentTable.Meta):
  282. model = PowerPort
  283. fields = (
  284. 'pk', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable', 'cable_peer',
  285. 'connection', 'tags', 'actions',
  286. )
  287. default_columns = (
  288. 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'cable_peer',
  289. 'actions',
  290. )
  291. row_attrs = {
  292. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  293. }
  294. class PowerOutletTable(DeviceComponentTable, PathEndpointTable):
  295. tags = TagColumn(
  296. url_name='dcim:poweroutlet_list'
  297. )
  298. class Meta(DeviceComponentTable.Meta):
  299. model = PowerOutlet
  300. fields = (
  301. 'pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'cable_peer',
  302. 'connection', 'tags',
  303. )
  304. default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description')
  305. class DevicePowerOutletTable(PowerOutletTable):
  306. name = tables.TemplateColumn(
  307. template_code='<i class="fa fa-bolt"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>'
  308. )
  309. actions = ButtonsColumn(
  310. model=PowerOutlet,
  311. buttons=('edit', 'delete'),
  312. prepend_template=POWEROUTLET_BUTTONS
  313. )
  314. class Meta(DeviceComponentTable.Meta):
  315. model = PowerOutlet
  316. fields = (
  317. 'pk', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'cable_peer', 'connection',
  318. 'tags', 'actions',
  319. )
  320. default_columns = (
  321. 'pk', 'name', 'label', 'type', 'maximum_draw', 'power_port', 'feed_leg', 'cable', 'cable_peer', 'actions',
  322. )
  323. row_attrs = {
  324. 'class': lambda record: record.cable.get_status_class() if record.cable else ''
  325. }
  326. class BaseInterfaceTable(BaseTable):
  327. enabled = BooleanColumn()
  328. ip_addresses = tables.TemplateColumn(
  329. template_code=INTERFACE_IPADDRESSES,
  330. orderable=False,
  331. verbose_name='IP Addresses'
  332. )
  333. untagged_vlan = tables.Column(linkify=True)
  334. tagged_vlans = tables.TemplateColumn(
  335. template_code=INTERFACE_TAGGED_VLANS,
  336. orderable=False,
  337. verbose_name='Tagged VLANs'
  338. )
  339. class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable):
  340. tags = TagColumn(
  341. url_name='dcim:interface_list'
  342. )
  343. class Meta(DeviceComponentTable.Meta):
  344. model = Interface
  345. fields = (
  346. 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address',
  347. 'description', 'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans',
  348. )
  349. default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description')
  350. class FrontPortTable(DeviceComponentTable, CableTerminationTable):
  351. rear_port_position = tables.Column(
  352. verbose_name='Position'
  353. )
  354. tags = TagColumn(
  355. url_name='dcim:frontport_list'
  356. )
  357. class Meta(DeviceComponentTable.Meta):
  358. model = FrontPort
  359. fields = (
  360. 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable',
  361. 'cable_peer', 'tags',
  362. )
  363. default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description')
  364. class RearPortTable(DeviceComponentTable, CableTerminationTable):
  365. tags = TagColumn(
  366. url_name='dcim:rearport_list'
  367. )
  368. class Meta(DeviceComponentTable.Meta):
  369. model = RearPort
  370. fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags')
  371. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  372. class DeviceBayTable(DeviceComponentTable):
  373. installed_device = tables.Column(
  374. linkify=True
  375. )
  376. tags = TagColumn(
  377. url_name='dcim:devicebay_list'
  378. )
  379. class Meta(DeviceComponentTable.Meta):
  380. model = DeviceBay
  381. fields = ('pk', 'device', 'name', 'label', 'installed_device', 'description', 'tags')
  382. default_columns = ('pk', 'device', 'name', 'label', 'installed_device', 'description')
  383. class InventoryItemTable(DeviceComponentTable):
  384. manufacturer = tables.Column(
  385. linkify=True
  386. )
  387. discovered = BooleanColumn()
  388. tags = TagColumn(
  389. url_name='dcim:inventoryitem_list'
  390. )
  391. cable = None # Override DeviceComponentTable
  392. class Meta(DeviceComponentTable.Meta):
  393. model = InventoryItem
  394. fields = (
  395. 'pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description',
  396. 'discovered', 'tags',
  397. )
  398. default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag')
  399. #
  400. # Virtual chassis
  401. #
  402. class VirtualChassisTable(BaseTable):
  403. pk = ToggleColumn()
  404. name = tables.Column(
  405. linkify=True
  406. )
  407. master = tables.Column(
  408. linkify=True
  409. )
  410. member_count = LinkedCountColumn(
  411. viewname='dcim:device_list',
  412. url_params={'virtual_chassis_id': 'pk'},
  413. verbose_name='Members'
  414. )
  415. tags = TagColumn(
  416. url_name='dcim:virtualchassis_list'
  417. )
  418. class Meta(BaseTable.Meta):
  419. model = VirtualChassis
  420. fields = ('pk', 'name', 'domain', 'master', 'member_count', 'tags')
  421. default_columns = ('pk', 'name', 'domain', 'master', 'member_count')