tables.py 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. import django_tables2 as tables
  2. from django_tables2.utils import Accessor
  3. from tenancy.tables import COL_TENANT
  4. from utilities.tables import BaseTable, BooleanColumn, ColorColumn, ToggleColumn
  5. from .models import (
  6. Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
  7. DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate,
  8. InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort,
  9. PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
  10. VirtualChassis,
  11. )
  12. MPTT_LINK = """
  13. {% if record.get_children %}
  14. <span style="padding-left: {{ record.get_ancestors|length }}0px "><i class="fa fa-caret-right"></i>
  15. {% else %}
  16. <span style="padding-left: {{ record.get_ancestors|length }}9px">
  17. {% endif %}
  18. <a href="{{ record.get_absolute_url }}">{{ record.name }}</a>
  19. </span>
  20. """
  21. SITE_REGION_LINK = """
  22. {% if record.region %}
  23. <a href="{% url 'dcim:site_list' %}?region={{ record.region.slug }}">{{ record.region }}</a>
  24. {% else %}
  25. &mdash;
  26. {% endif %}
  27. """
  28. COLOR_LABEL = """
  29. {% load helpers %}
  30. <label class="label" style="color: {{ record.color|fgcolor }}; background-color: #{{ record.color }}">{{ record }}</label>
  31. """
  32. DEVICE_LINK = """
  33. <a href="{% url 'dcim:device' pk=record.pk %}">
  34. {{ record.name|default:'<span class="label label-info">Unnamed device</span>' }}
  35. </a>
  36. """
  37. REGION_ACTIONS = """
  38. <a href="{% url 'dcim:region_changelog' pk=record.pk %}" class="btn btn-default btn-xs" title="Change log">
  39. <i class="fa fa-history"></i>
  40. </a>
  41. {% if perms.dcim.change_region %}
  42. <a href="{% url 'dcim:region_edit' pk=record.pk %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  43. {% endif %}
  44. """
  45. RACKGROUP_ACTIONS = """
  46. <a href="{% url 'dcim:rackgroup_changelog' pk=record.pk %}" class="btn btn-default btn-xs" title="Change log">
  47. <i class="fa fa-history"></i>
  48. </a>
  49. <a href="{% url 'dcim:rack_elevation_list' %}?site={{ record.site.slug }}&group_id={{ record.pk }}" class="btn btn-xs btn-primary" title="View elevations">
  50. <i class="fa fa-eye"></i>
  51. </a>
  52. {% if perms.dcim.change_rackgroup %}
  53. <a href="{% url 'dcim:rackgroup_edit' pk=record.pk %}?return_url={{ request.path }}" class="btn btn-xs btn-warning" title="Edit">
  54. <i class="glyphicon glyphicon-pencil"></i>
  55. </a>
  56. {% endif %}
  57. """
  58. RACKROLE_ACTIONS = """
  59. <a href="{% url 'dcim:rackrole_changelog' pk=record.pk %}" class="btn btn-default btn-xs" title="Change log">
  60. <i class="fa fa-history"></i>
  61. </a>
  62. {% if perms.dcim.change_rackrole %}
  63. <a href="{% url 'dcim:rackrole_edit' pk=record.pk %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  64. {% endif %}
  65. """
  66. RACK_ROLE = """
  67. {% if record.role %}
  68. {% load helpers %}
  69. <label class="label" style="color: {{ record.role.color|fgcolor }}; background-color: #{{ record.role.color }}">{{ value }}</label>
  70. {% else %}
  71. &mdash;
  72. {% endif %}
  73. """
  74. RACK_DEVICE_COUNT = """
  75. <a href="{% url 'dcim:device_list' %}?rack_id={{ record.pk }}">{{ value }}</a>
  76. """
  77. RACKRESERVATION_ACTIONS = """
  78. <a href="{% url 'dcim:rackreservation_changelog' pk=record.pk %}" class="btn btn-default btn-xs" title="Change log">
  79. <i class="fa fa-history"></i>
  80. </a>
  81. {% if perms.dcim.change_rackreservation %}
  82. <a href="{% url 'dcim:rackreservation_edit' pk=record.pk %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  83. {% endif %}
  84. """
  85. MANUFACTURER_ACTIONS = """
  86. <a href="{% url 'dcim:manufacturer_changelog' slug=record.slug %}" class="btn btn-default btn-xs" title="Change log">
  87. <i class="fa fa-history"></i>
  88. </a>
  89. {% if perms.dcim.change_manufacturer %}
  90. <a href="{% url 'dcim:manufacturer_edit' slug=record.slug %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  91. {% endif %}
  92. """
  93. DEVICEROLE_ACTIONS = """
  94. <a href="{% url 'dcim:devicerole_changelog' slug=record.slug %}" class="btn btn-default btn-xs" title="Change log">
  95. <i class="fa fa-history"></i>
  96. </a>
  97. {% if perms.dcim.change_devicerole %}
  98. <a href="{% url 'dcim:devicerole_edit' slug=record.slug %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  99. {% endif %}
  100. """
  101. DEVICEROLE_DEVICE_COUNT = """
  102. <a href="{% url 'dcim:device_list' %}?role={{ record.slug }}">{{ value }}</a>
  103. """
  104. DEVICEROLE_VM_COUNT = """
  105. <a href="{% url 'virtualization:virtualmachine_list' %}?role={{ record.slug }}">{{ value }}</a>
  106. """
  107. PLATFORM_DEVICE_COUNT = """
  108. <a href="{% url 'dcim:device_list' %}?platform={{ record.slug }}">{{ value }}</a>
  109. """
  110. PLATFORM_VM_COUNT = """
  111. <a href="{% url 'virtualization:virtualmachine_list' %}?platform={{ record.slug }}">{{ value }}</a>
  112. """
  113. PLATFORM_ACTIONS = """
  114. <a href="{% url 'dcim:platform_changelog' slug=record.slug %}" class="btn btn-default btn-xs" title="Change log">
  115. <i class="fa fa-history"></i>
  116. </a>
  117. {% if perms.dcim.change_platform %}
  118. <a href="{% url 'dcim:platform_edit' slug=record.slug %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  119. {% endif %}
  120. """
  121. DEVICE_ROLE = """
  122. {% load helpers %}
  123. <label class="label" style="color: {{ record.device_role.color|fgcolor }}; background-color: #{{ record.device_role.color }}">{{ value }}</label>
  124. """
  125. STATUS_LABEL = """
  126. <span class="label label-{{ record.get_status_class }}">{{ record.get_status_display }}</span>
  127. """
  128. TYPE_LABEL = """
  129. <span class="label label-{{ record.get_type_class }}">{{ record.get_type_display }}</span>
  130. """
  131. DEVICE_PRIMARY_IP = """
  132. {{ record.primary_ip6.address.ip|default:"" }}
  133. {% if record.primary_ip6 and record.primary_ip4 %}<br />{% endif %}
  134. {{ record.primary_ip4.address.ip|default:"" }}
  135. """
  136. DEVICETYPE_INSTANCES_TEMPLATE = """
  137. <a href="{% url 'dcim:device_list' %}?manufacturer_id={{ record.manufacturer_id }}&device_type_id={{ record.pk }}">{{ record.instance_count }}</a>
  138. """
  139. UTILIZATION_GRAPH = """
  140. {% load helpers %}
  141. {% utilization_graph value %}
  142. """
  143. VIRTUALCHASSIS_ACTIONS = """
  144. <a href="{% url 'dcim:virtualchassis_changelog' pk=record.pk %}" class="btn btn-default btn-xs" title="Change log">
  145. <i class="fa fa-history"></i>
  146. </a>
  147. {% if perms.dcim.change_virtualchassis %}
  148. <a href="{% url 'dcim:virtualchassis_edit' pk=record.pk %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  149. {% endif %}
  150. """
  151. CABLE_TERMINATION_PARENT = """
  152. {% if value.device %}
  153. <a href="{{ value.device.get_absolute_url }}">{{ value.device }}</a>
  154. {% elif value.circuit %}
  155. <a href="{{ value.circuit.get_absolute_url }}">{{ value.circuit }}</a>
  156. {% elif value.power_panel %}
  157. <a href="{{ value.power_panel.get_absolute_url }}">{{ value.power_panel }}</a>
  158. {% endif %}
  159. """
  160. CABLE_LENGTH = """
  161. {% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}&mdash;{% endif %}
  162. """
  163. POWERPANEL_POWERFEED_COUNT = """
  164. <a href="{% url 'dcim:powerfeed_list' %}?power_panel_id={{ record.pk }}">{{ value }}</a>
  165. """
  166. def get_component_template_actions(model_name):
  167. return """
  168. {{% if perms.dcim.change_{model_name} %}}
  169. <a href="{{% url 'dcim:{model_name}_edit' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-xs btn-warning">
  170. <i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
  171. </a>
  172. {{% endif %}}
  173. {{% if perms.dcim.delete_{model_name} %}}
  174. <a href="{{% url 'dcim:{model_name}_delete' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-xs btn-danger">
  175. <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
  176. </a>
  177. {{% endif %}}
  178. """.format(model_name=model_name).strip()
  179. #
  180. # Regions
  181. #
  182. class RegionTable(BaseTable):
  183. pk = ToggleColumn()
  184. name = tables.TemplateColumn(template_code=MPTT_LINK, orderable=False)
  185. site_count = tables.Column(verbose_name='Sites')
  186. slug = tables.Column(verbose_name='Slug')
  187. actions = tables.TemplateColumn(
  188. template_code=REGION_ACTIONS,
  189. attrs={'td': {'class': 'text-right noprint'}},
  190. verbose_name=''
  191. )
  192. class Meta(BaseTable.Meta):
  193. model = Region
  194. fields = ('pk', 'name', 'site_count', 'slug', 'actions')
  195. #
  196. # Sites
  197. #
  198. class SiteTable(BaseTable):
  199. pk = ToggleColumn()
  200. name = tables.LinkColumn(order_by=('_name',))
  201. status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
  202. region = tables.TemplateColumn(template_code=SITE_REGION_LINK)
  203. tenant = tables.TemplateColumn(template_code=COL_TENANT)
  204. class Meta(BaseTable.Meta):
  205. model = Site
  206. fields = ('pk', 'name', 'status', 'facility', 'region', 'tenant', 'asn', 'description')
  207. #
  208. # Rack groups
  209. #
  210. class RackGroupTable(BaseTable):
  211. pk = ToggleColumn()
  212. name = tables.TemplateColumn(
  213. template_code=MPTT_LINK,
  214. orderable=False
  215. )
  216. site = tables.LinkColumn(
  217. viewname='dcim:site',
  218. args=[Accessor('site.slug')],
  219. verbose_name='Site'
  220. )
  221. rack_count = tables.Column(
  222. verbose_name='Racks'
  223. )
  224. slug = tables.Column()
  225. actions = tables.TemplateColumn(
  226. template_code=RACKGROUP_ACTIONS,
  227. attrs={'td': {'class': 'text-right noprint'}},
  228. verbose_name=''
  229. )
  230. class Meta(BaseTable.Meta):
  231. model = RackGroup
  232. fields = ('pk', 'name', 'site', 'rack_count', 'slug', 'actions')
  233. #
  234. # Rack roles
  235. #
  236. class RackRoleTable(BaseTable):
  237. pk = ToggleColumn()
  238. rack_count = tables.Column(verbose_name='Racks')
  239. color = tables.TemplateColumn(COLOR_LABEL)
  240. actions = tables.TemplateColumn(
  241. template_code=RACKROLE_ACTIONS,
  242. attrs={'td': {'class': 'text-right noprint'}},
  243. verbose_name=''
  244. )
  245. class Meta(BaseTable.Meta):
  246. model = RackRole
  247. fields = ('pk', 'name', 'rack_count', 'color', 'description', 'slug', 'actions')
  248. #
  249. # Racks
  250. #
  251. class RackTable(BaseTable):
  252. pk = ToggleColumn()
  253. name = tables.LinkColumn(order_by=('_name',))
  254. site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
  255. group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
  256. tenant = tables.TemplateColumn(template_code=COL_TENANT)
  257. status = tables.TemplateColumn(STATUS_LABEL)
  258. role = tables.TemplateColumn(RACK_ROLE)
  259. u_height = tables.TemplateColumn("{{ record.u_height }}U", verbose_name='Height')
  260. class Meta(BaseTable.Meta):
  261. model = Rack
  262. fields = ('pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height')
  263. class RackDetailTable(RackTable):
  264. device_count = tables.TemplateColumn(
  265. template_code=RACK_DEVICE_COUNT,
  266. verbose_name='Devices'
  267. )
  268. get_utilization = tables.TemplateColumn(
  269. template_code=UTILIZATION_GRAPH,
  270. orderable=False,
  271. verbose_name='Space'
  272. )
  273. get_power_utilization = tables.TemplateColumn(
  274. template_code=UTILIZATION_GRAPH,
  275. orderable=False,
  276. verbose_name='Power'
  277. )
  278. class Meta(RackTable.Meta):
  279. fields = (
  280. 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height', 'device_count',
  281. 'get_utilization', 'get_power_utilization',
  282. )
  283. #
  284. # Rack reservations
  285. #
  286. class RackReservationTable(BaseTable):
  287. pk = ToggleColumn()
  288. site = tables.LinkColumn(
  289. viewname='dcim:site',
  290. accessor=Accessor('rack.site'),
  291. args=[Accessor('rack.site.slug')],
  292. )
  293. tenant = tables.TemplateColumn(template_code=COL_TENANT)
  294. rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
  295. unit_list = tables.Column(orderable=False, verbose_name='Units')
  296. actions = tables.TemplateColumn(
  297. template_code=RACKRESERVATION_ACTIONS, attrs={'td': {'class': 'text-right noprint'}}, verbose_name=''
  298. )
  299. class Meta(BaseTable.Meta):
  300. model = RackReservation
  301. fields = ('pk', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'actions')
  302. #
  303. # Manufacturers
  304. #
  305. class ManufacturerTable(BaseTable):
  306. pk = ToggleColumn()
  307. name = tables.LinkColumn()
  308. devicetype_count = tables.Column(
  309. verbose_name='Device Types'
  310. )
  311. inventoryitem_count = tables.Column(
  312. verbose_name='Inventory Items'
  313. )
  314. platform_count = tables.Column(
  315. verbose_name='Platforms'
  316. )
  317. slug = tables.Column()
  318. actions = tables.TemplateColumn(
  319. template_code=MANUFACTURER_ACTIONS,
  320. attrs={'td': {'class': 'text-right noprint'}},
  321. verbose_name=''
  322. )
  323. class Meta(BaseTable.Meta):
  324. model = Manufacturer
  325. fields = ('pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'slug', 'actions')
  326. #
  327. # Device types
  328. #
  329. class DeviceTypeTable(BaseTable):
  330. pk = ToggleColumn()
  331. model = tables.LinkColumn(
  332. viewname='dcim:devicetype',
  333. args=[Accessor('pk')],
  334. verbose_name='Device Type'
  335. )
  336. is_full_depth = BooleanColumn(verbose_name='Full Depth')
  337. instance_count = tables.TemplateColumn(
  338. template_code=DEVICETYPE_INSTANCES_TEMPLATE,
  339. verbose_name='Instances'
  340. )
  341. class Meta(BaseTable.Meta):
  342. model = DeviceType
  343. fields = (
  344. 'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
  345. 'instance_count',
  346. )
  347. #
  348. # Device type components
  349. #
  350. class ConsolePortTemplateTable(BaseTable):
  351. pk = ToggleColumn()
  352. name = tables.Column(order_by=('_name',))
  353. actions = tables.TemplateColumn(
  354. template_code=get_component_template_actions('consoleporttemplate'),
  355. attrs={'td': {'class': 'text-right noprint'}},
  356. verbose_name=''
  357. )
  358. class Meta(BaseTable.Meta):
  359. model = ConsolePortTemplate
  360. fields = ('pk', 'name', 'type', 'actions')
  361. empty_text = "None"
  362. class ConsolePortImportTable(BaseTable):
  363. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  364. class Meta(BaseTable.Meta):
  365. model = ConsolePort
  366. fields = ('device', 'name', 'description')
  367. empty_text = False
  368. class ConsoleServerPortTemplateTable(BaseTable):
  369. pk = ToggleColumn()
  370. name = tables.Column(order_by=('_name',))
  371. actions = tables.TemplateColumn(
  372. template_code=get_component_template_actions('consoleserverporttemplate'),
  373. attrs={'td': {'class': 'text-right noprint'}},
  374. verbose_name=''
  375. )
  376. class Meta(BaseTable.Meta):
  377. model = ConsoleServerPortTemplate
  378. fields = ('pk', 'name', 'type', 'actions')
  379. empty_text = "None"
  380. class ConsoleServerPortImportTable(BaseTable):
  381. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  382. class Meta(BaseTable.Meta):
  383. model = ConsoleServerPort
  384. fields = ('device', 'name', 'description')
  385. empty_text = False
  386. class PowerPortTemplateTable(BaseTable):
  387. pk = ToggleColumn()
  388. name = tables.Column(order_by=('_name',))
  389. actions = tables.TemplateColumn(
  390. template_code=get_component_template_actions('powerporttemplate'),
  391. attrs={'td': {'class': 'text-right noprint'}},
  392. verbose_name=''
  393. )
  394. class Meta(BaseTable.Meta):
  395. model = PowerPortTemplate
  396. fields = ('pk', 'name', 'type', 'maximum_draw', 'allocated_draw', 'actions')
  397. empty_text = "None"
  398. class PowerPortImportTable(BaseTable):
  399. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  400. class Meta(BaseTable.Meta):
  401. model = PowerPort
  402. fields = ('device', 'name', 'description', 'maximum_draw', 'allocated_draw')
  403. empty_text = False
  404. class PowerOutletTemplateTable(BaseTable):
  405. pk = ToggleColumn()
  406. name = tables.Column(order_by=('_name',))
  407. actions = tables.TemplateColumn(
  408. template_code=get_component_template_actions('poweroutlettemplate'),
  409. attrs={'td': {'class': 'text-right noprint'}},
  410. verbose_name=''
  411. )
  412. class Meta(BaseTable.Meta):
  413. model = PowerOutletTemplate
  414. fields = ('pk', 'name', 'type', 'power_port', 'feed_leg', 'actions')
  415. empty_text = "None"
  416. class PowerOutletImportTable(BaseTable):
  417. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  418. class Meta(BaseTable.Meta):
  419. model = PowerOutlet
  420. fields = ('device', 'name', 'description', 'power_port', 'feed_leg')
  421. empty_text = False
  422. class InterfaceTemplateTable(BaseTable):
  423. pk = ToggleColumn()
  424. mgmt_only = tables.TemplateColumn("{% if value %}OOB Management{% endif %}")
  425. actions = tables.TemplateColumn(
  426. template_code=get_component_template_actions('interfacetemplate'),
  427. attrs={'td': {'class': 'text-right noprint'}},
  428. verbose_name=''
  429. )
  430. class Meta(BaseTable.Meta):
  431. model = InterfaceTemplate
  432. fields = ('pk', 'name', 'mgmt_only', 'type', 'actions')
  433. empty_text = "None"
  434. class InterfaceImportTable(BaseTable):
  435. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  436. virtual_machine = tables.LinkColumn('virtualization:virtualmachine', args=[Accessor('virtual_machine.pk')], verbose_name='Virtual Machine')
  437. class Meta(BaseTable.Meta):
  438. model = Interface
  439. fields = ('device', 'virtual_machine', 'name', 'description', 'lag', 'type', 'enabled', 'mac_address', 'mtu', 'mgmt_only', 'mode')
  440. empty_text = False
  441. class FrontPortTemplateTable(BaseTable):
  442. pk = ToggleColumn()
  443. name = tables.Column(order_by=('_name',))
  444. rear_port_position = tables.Column(
  445. verbose_name='Position'
  446. )
  447. actions = tables.TemplateColumn(
  448. template_code=get_component_template_actions('frontporttemplate'),
  449. attrs={'td': {'class': 'text-right noprint'}},
  450. verbose_name=''
  451. )
  452. class Meta(BaseTable.Meta):
  453. model = FrontPortTemplate
  454. fields = ('pk', 'name', 'type', 'rear_port', 'rear_port_position', 'actions')
  455. empty_text = "None"
  456. class FrontPortImportTable(BaseTable):
  457. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  458. class Meta(BaseTable.Meta):
  459. model = FrontPort
  460. fields = ('device', 'name', 'description', 'type', 'rear_port', 'rear_port_position')
  461. empty_text = False
  462. class RearPortTemplateTable(BaseTable):
  463. pk = ToggleColumn()
  464. name = tables.Column(order_by=('_name',))
  465. actions = tables.TemplateColumn(
  466. template_code=get_component_template_actions('rearporttemplate'),
  467. attrs={'td': {'class': 'text-right noprint'}},
  468. verbose_name=''
  469. )
  470. class Meta(BaseTable.Meta):
  471. model = RearPortTemplate
  472. fields = ('pk', 'name', 'type', 'positions', 'actions')
  473. empty_text = "None"
  474. class RearPortImportTable(BaseTable):
  475. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  476. class Meta(BaseTable.Meta):
  477. model = RearPort
  478. fields = ('device', 'name', 'description', 'type', 'position')
  479. empty_text = False
  480. class DeviceBayTemplateTable(BaseTable):
  481. pk = ToggleColumn()
  482. name = tables.Column(order_by=('_name',))
  483. actions = tables.TemplateColumn(
  484. template_code=get_component_template_actions('devicebaytemplate'),
  485. attrs={'td': {'class': 'text-right noprint'}},
  486. verbose_name=''
  487. )
  488. class Meta(BaseTable.Meta):
  489. model = DeviceBayTemplate
  490. fields = ('pk', 'name', 'actions')
  491. empty_text = "None"
  492. #
  493. # Device roles
  494. #
  495. class DeviceRoleTable(BaseTable):
  496. pk = ToggleColumn()
  497. device_count = tables.TemplateColumn(
  498. template_code=DEVICEROLE_DEVICE_COUNT,
  499. accessor=Accessor('devices.count'),
  500. orderable=False,
  501. verbose_name='Devices'
  502. )
  503. vm_count = tables.TemplateColumn(
  504. template_code=DEVICEROLE_VM_COUNT,
  505. accessor=Accessor('virtual_machines.count'),
  506. orderable=False,
  507. verbose_name='VMs'
  508. )
  509. color = tables.TemplateColumn(COLOR_LABEL, verbose_name='Label')
  510. slug = tables.Column(verbose_name='Slug')
  511. actions = tables.TemplateColumn(
  512. template_code=DEVICEROLE_ACTIONS,
  513. attrs={'td': {'class': 'text-right noprint'}},
  514. verbose_name=''
  515. )
  516. class Meta(BaseTable.Meta):
  517. model = DeviceRole
  518. fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions')
  519. #
  520. # Platforms
  521. #
  522. class PlatformTable(BaseTable):
  523. pk = ToggleColumn()
  524. device_count = tables.TemplateColumn(
  525. template_code=PLATFORM_DEVICE_COUNT,
  526. accessor=Accessor('devices.count'),
  527. orderable=False,
  528. verbose_name='Devices'
  529. )
  530. vm_count = tables.TemplateColumn(
  531. template_code=PLATFORM_VM_COUNT,
  532. accessor=Accessor('virtual_machines.count'),
  533. orderable=False,
  534. verbose_name='VMs'
  535. )
  536. actions = tables.TemplateColumn(
  537. template_code=PLATFORM_ACTIONS,
  538. attrs={'td': {'class': 'text-right noprint'}},
  539. verbose_name=''
  540. )
  541. class Meta(BaseTable.Meta):
  542. model = Platform
  543. fields = ('pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'actions')
  544. #
  545. # Devices
  546. #
  547. class DeviceTable(BaseTable):
  548. pk = ToggleColumn()
  549. name = tables.TemplateColumn(
  550. order_by=('_name',),
  551. template_code=DEVICE_LINK
  552. )
  553. status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
  554. tenant = tables.TemplateColumn(template_code=COL_TENANT)
  555. site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
  556. rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
  557. device_role = tables.TemplateColumn(DEVICE_ROLE, verbose_name='Role')
  558. device_type = tables.LinkColumn(
  559. 'dcim:devicetype', args=[Accessor('device_type.pk')], verbose_name='Type',
  560. text=lambda record: record.device_type.display_name
  561. )
  562. class Meta(BaseTable.Meta):
  563. model = Device
  564. fields = ('pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type')
  565. class DeviceDetailTable(DeviceTable):
  566. primary_ip = tables.TemplateColumn(
  567. orderable=False, verbose_name='IP Address', template_code=DEVICE_PRIMARY_IP
  568. )
  569. class Meta(DeviceTable.Meta):
  570. model = Device
  571. fields = ('pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip')
  572. class DeviceImportTable(BaseTable):
  573. name = tables.TemplateColumn(template_code=DEVICE_LINK, verbose_name='Name')
  574. status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
  575. tenant = tables.TemplateColumn(template_code=COL_TENANT)
  576. site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
  577. rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')], verbose_name='Rack')
  578. position = tables.Column(verbose_name='Position')
  579. device_role = tables.Column(verbose_name='Role')
  580. device_type = tables.Column(verbose_name='Type')
  581. class Meta(BaseTable.Meta):
  582. model = Device
  583. fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
  584. empty_text = False
  585. #
  586. # Device components
  587. #
  588. class DeviceComponentDetailTable(BaseTable):
  589. pk = ToggleColumn()
  590. name = tables.Column(order_by=('_name',))
  591. cable = tables.LinkColumn()
  592. class Meta(BaseTable.Meta):
  593. order_by = ('device', 'name')
  594. fields = ('pk', 'device', 'name', 'type', 'description', 'cable')
  595. sequence = ('pk', 'device', 'name', 'type', 'description', 'cable')
  596. class ConsolePortTable(BaseTable):
  597. name = tables.Column(order_by=('_name',))
  598. class Meta(BaseTable.Meta):
  599. model = ConsolePort
  600. fields = ('name', 'type')
  601. class ConsolePortDetailTable(DeviceComponentDetailTable):
  602. device = tables.LinkColumn()
  603. class Meta(DeviceComponentDetailTable.Meta, ConsolePortTable.Meta):
  604. pass
  605. class ConsoleServerPortTable(BaseTable):
  606. name = tables.Column(order_by=('_name',))
  607. class Meta(BaseTable.Meta):
  608. model = ConsoleServerPort
  609. fields = ('name', 'description')
  610. class ConsoleServerPortDetailTable(DeviceComponentDetailTable):
  611. device = tables.LinkColumn()
  612. class Meta(DeviceComponentDetailTable.Meta, ConsoleServerPortTable.Meta):
  613. pass
  614. class PowerPortTable(BaseTable):
  615. name = tables.Column(order_by=('_name',))
  616. class Meta(BaseTable.Meta):
  617. model = PowerPort
  618. fields = ('name', 'type')
  619. class PowerPortDetailTable(DeviceComponentDetailTable):
  620. device = tables.LinkColumn()
  621. class Meta(DeviceComponentDetailTable.Meta, PowerPortTable.Meta):
  622. pass
  623. class PowerOutletTable(BaseTable):
  624. name = tables.Column(order_by=('_name',))
  625. class Meta(BaseTable.Meta):
  626. model = PowerOutlet
  627. fields = ('name', 'type', 'description')
  628. class PowerOutletDetailTable(DeviceComponentDetailTable):
  629. device = tables.LinkColumn()
  630. class Meta(DeviceComponentDetailTable.Meta, PowerOutletTable.Meta):
  631. pass
  632. class InterfaceTable(BaseTable):
  633. class Meta(BaseTable.Meta):
  634. model = Interface
  635. fields = ('name', 'type', 'lag', 'enabled', 'mgmt_only', 'description')
  636. class InterfaceDetailTable(DeviceComponentDetailTable):
  637. parent = tables.LinkColumn(order_by=('device', 'virtual_machine'))
  638. name = tables.LinkColumn()
  639. enabled = BooleanColumn()
  640. class Meta(InterfaceTable.Meta):
  641. order_by = ('parent', 'name')
  642. fields = ('pk', 'parent', 'name', 'enabled', 'type', 'description', 'cable')
  643. sequence = ('pk', 'parent', 'name', 'enabled', 'type', 'description', 'cable')
  644. class FrontPortTable(BaseTable):
  645. name = tables.Column(order_by=('_name',))
  646. class Meta(BaseTable.Meta):
  647. model = FrontPort
  648. fields = ('name', 'type', 'rear_port', 'rear_port_position', 'description')
  649. empty_text = "None"
  650. class FrontPortDetailTable(DeviceComponentDetailTable):
  651. device = tables.LinkColumn()
  652. class Meta(DeviceComponentDetailTable.Meta, FrontPortTable.Meta):
  653. pass
  654. class RearPortTable(BaseTable):
  655. name = tables.Column(order_by=('_name',))
  656. class Meta(BaseTable.Meta):
  657. model = RearPort
  658. fields = ('name', 'type', 'positions', 'description')
  659. empty_text = "None"
  660. class RearPortDetailTable(DeviceComponentDetailTable):
  661. device = tables.LinkColumn()
  662. class Meta(DeviceComponentDetailTable.Meta, RearPortTable.Meta):
  663. pass
  664. class DeviceBayTable(BaseTable):
  665. name = tables.Column(order_by=('_name',))
  666. class Meta(BaseTable.Meta):
  667. model = DeviceBay
  668. fields = ('name',)
  669. class DeviceBayDetailTable(DeviceComponentDetailTable):
  670. device = tables.LinkColumn()
  671. installed_device = tables.LinkColumn()
  672. class Meta(DeviceBayTable.Meta):
  673. fields = ('pk', 'name', 'device', 'installed_device')
  674. sequence = ('pk', 'name', 'device', 'installed_device')
  675. exclude = ('cable',)
  676. class DeviceBayImportTable(BaseTable):
  677. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  678. installed_device = tables.LinkColumn('dcim:device', args=[Accessor('installed_device.pk')], verbose_name='Installed Device')
  679. class Meta(BaseTable.Meta):
  680. model = DeviceBay
  681. fields = ('device', 'name', 'installed_device', 'description')
  682. empty_text = False
  683. #
  684. # Cables
  685. #
  686. class CableTable(BaseTable):
  687. pk = ToggleColumn()
  688. id = tables.LinkColumn(
  689. viewname='dcim:cable',
  690. args=[Accessor('pk')],
  691. verbose_name='ID'
  692. )
  693. termination_a_parent = tables.TemplateColumn(
  694. template_code=CABLE_TERMINATION_PARENT,
  695. accessor=Accessor('termination_a'),
  696. orderable=False,
  697. verbose_name='Termination A'
  698. )
  699. termination_a = tables.LinkColumn(
  700. accessor=Accessor('termination_a'),
  701. orderable=False,
  702. verbose_name=''
  703. )
  704. termination_b_parent = tables.TemplateColumn(
  705. template_code=CABLE_TERMINATION_PARENT,
  706. accessor=Accessor('termination_b'),
  707. orderable=False,
  708. verbose_name='Termination B'
  709. )
  710. termination_b = tables.LinkColumn(
  711. accessor=Accessor('termination_b'),
  712. orderable=False,
  713. verbose_name=''
  714. )
  715. status = tables.TemplateColumn(
  716. template_code=STATUS_LABEL
  717. )
  718. length = tables.TemplateColumn(
  719. template_code=CABLE_LENGTH,
  720. order_by='_abs_length'
  721. )
  722. color = ColorColumn()
  723. class Meta(BaseTable.Meta):
  724. model = Cable
  725. fields = (
  726. 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b',
  727. 'status', 'type', 'color', 'length',
  728. )
  729. #
  730. # Device connections
  731. #
  732. class ConsoleConnectionTable(BaseTable):
  733. console_server = tables.LinkColumn(
  734. viewname='dcim:device',
  735. accessor=Accessor('connected_endpoint.device'),
  736. args=[Accessor('connected_endpoint.device.pk')],
  737. verbose_name='Console Server'
  738. )
  739. connected_endpoint = tables.Column(
  740. verbose_name='Port'
  741. )
  742. device = tables.LinkColumn(
  743. viewname='dcim:device',
  744. args=[Accessor('device.pk')]
  745. )
  746. name = tables.Column(
  747. verbose_name='Console Port'
  748. )
  749. class Meta(BaseTable.Meta):
  750. model = ConsolePort
  751. fields = ('console_server', 'connected_endpoint', 'device', 'name', 'connection_status')
  752. class PowerConnectionTable(BaseTable):
  753. pdu = tables.LinkColumn(
  754. viewname='dcim:device',
  755. accessor=Accessor('connected_endpoint.device'),
  756. args=[Accessor('connected_endpoint.device.pk')],
  757. order_by='_connected_poweroutlet__device',
  758. verbose_name='PDU'
  759. )
  760. outlet = tables.Column(
  761. accessor=Accessor('_connected_poweroutlet'),
  762. verbose_name='Outlet'
  763. )
  764. device = tables.LinkColumn(
  765. viewname='dcim:device',
  766. args=[Accessor('device.pk')]
  767. )
  768. name = tables.Column(
  769. verbose_name='Power Port'
  770. )
  771. class Meta(BaseTable.Meta):
  772. model = PowerPort
  773. fields = ('pdu', 'outlet', 'device', 'name', 'connection_status')
  774. class InterfaceConnectionTable(BaseTable):
  775. device_a = tables.LinkColumn(
  776. viewname='dcim:device',
  777. accessor=Accessor('device'),
  778. args=[Accessor('device.pk')],
  779. verbose_name='Device A'
  780. )
  781. interface_a = tables.LinkColumn(
  782. viewname='dcim:interface',
  783. accessor=Accessor('name'),
  784. args=[Accessor('pk')],
  785. verbose_name='Interface A'
  786. )
  787. description_a = tables.Column(
  788. accessor=Accessor('description'),
  789. verbose_name='Description'
  790. )
  791. device_b = tables.LinkColumn(
  792. viewname='dcim:device',
  793. accessor=Accessor('_connected_interface.device'),
  794. args=[Accessor('_connected_interface.device.pk')],
  795. verbose_name='Device B'
  796. )
  797. interface_b = tables.LinkColumn(
  798. viewname='dcim:interface',
  799. accessor=Accessor('_connected_interface'),
  800. args=[Accessor('_connected_interface.pk')],
  801. verbose_name='Interface B'
  802. )
  803. description_b = tables.Column(
  804. accessor=Accessor('_connected_interface.description'),
  805. verbose_name='Description'
  806. )
  807. class Meta(BaseTable.Meta):
  808. model = Interface
  809. fields = (
  810. 'device_a', 'interface_a', 'description_a', 'device_b', 'interface_b', 'description_b', 'connection_status',
  811. )
  812. #
  813. # InventoryItems
  814. #
  815. class InventoryItemTable(BaseTable):
  816. pk = ToggleColumn()
  817. device = tables.LinkColumn('dcim:device_inventory', args=[Accessor('device.pk')])
  818. manufacturer = tables.Column(accessor=Accessor('manufacturer.name'), verbose_name='Manufacturer')
  819. class Meta(BaseTable.Meta):
  820. model = InventoryItem
  821. fields = ('pk', 'device', 'name', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description')
  822. #
  823. # Virtual chassis
  824. #
  825. class VirtualChassisTable(BaseTable):
  826. pk = ToggleColumn()
  827. master = tables.LinkColumn()
  828. member_count = tables.Column(verbose_name='Members')
  829. actions = tables.TemplateColumn(
  830. template_code=VIRTUALCHASSIS_ACTIONS,
  831. attrs={'td': {'class': 'text-right noprint'}},
  832. verbose_name=''
  833. )
  834. class Meta(BaseTable.Meta):
  835. model = VirtualChassis
  836. fields = ('pk', 'master', 'domain', 'member_count', 'actions')
  837. #
  838. # Power panels
  839. #
  840. class PowerPanelTable(BaseTable):
  841. pk = ToggleColumn()
  842. name = tables.LinkColumn()
  843. site = tables.LinkColumn(
  844. viewname='dcim:site',
  845. args=[Accessor('site.slug')]
  846. )
  847. powerfeed_count = tables.TemplateColumn(
  848. template_code=POWERPANEL_POWERFEED_COUNT,
  849. verbose_name='Feeds'
  850. )
  851. class Meta(BaseTable.Meta):
  852. model = PowerPanel
  853. fields = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count')
  854. #
  855. # Power feeds
  856. #
  857. class PowerFeedTable(BaseTable):
  858. pk = ToggleColumn()
  859. name = tables.LinkColumn()
  860. power_panel = tables.LinkColumn(
  861. viewname='dcim:powerpanel',
  862. args=[Accessor('power_panel.pk')],
  863. )
  864. rack = tables.LinkColumn(
  865. viewname='dcim:rack',
  866. args=[Accessor('rack.pk')]
  867. )
  868. status = tables.TemplateColumn(
  869. template_code=STATUS_LABEL
  870. )
  871. type = tables.TemplateColumn(
  872. template_code=TYPE_LABEL
  873. )
  874. class Meta(BaseTable.Meta):
  875. model = PowerFeed
  876. fields = ('pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase')