tables.py 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  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', 'description', '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', 'description', '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. reservation = tables.LinkColumn(
  289. viewname='dcim:rackreservation',
  290. args=[Accessor('pk')],
  291. accessor='pk'
  292. )
  293. site = tables.LinkColumn(
  294. viewname='dcim:site',
  295. accessor=Accessor('rack.site'),
  296. args=[Accessor('rack.site.slug')],
  297. )
  298. tenant = tables.TemplateColumn(
  299. template_code=COL_TENANT
  300. )
  301. rack = tables.LinkColumn(
  302. viewname='dcim:rack',
  303. args=[Accessor('rack.pk')]
  304. )
  305. unit_list = tables.Column(
  306. orderable=False,
  307. verbose_name='Units'
  308. )
  309. actions = tables.TemplateColumn(
  310. template_code=RACKRESERVATION_ACTIONS,
  311. attrs={'td': {'class': 'text-right noprint'}},
  312. verbose_name=''
  313. )
  314. class Meta(BaseTable.Meta):
  315. model = RackReservation
  316. fields = (
  317. 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'actions',
  318. )
  319. #
  320. # Manufacturers
  321. #
  322. class ManufacturerTable(BaseTable):
  323. pk = ToggleColumn()
  324. name = tables.LinkColumn()
  325. devicetype_count = tables.Column(
  326. verbose_name='Device Types'
  327. )
  328. inventoryitem_count = tables.Column(
  329. verbose_name='Inventory Items'
  330. )
  331. platform_count = tables.Column(
  332. verbose_name='Platforms'
  333. )
  334. slug = tables.Column()
  335. actions = tables.TemplateColumn(
  336. template_code=MANUFACTURER_ACTIONS,
  337. attrs={'td': {'class': 'text-right noprint'}},
  338. verbose_name=''
  339. )
  340. class Meta(BaseTable.Meta):
  341. model = Manufacturer
  342. fields = (
  343. 'pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug', 'actions',
  344. )
  345. #
  346. # Device types
  347. #
  348. class DeviceTypeTable(BaseTable):
  349. pk = ToggleColumn()
  350. model = tables.LinkColumn(
  351. viewname='dcim:devicetype',
  352. args=[Accessor('pk')],
  353. verbose_name='Device Type'
  354. )
  355. is_full_depth = BooleanColumn(verbose_name='Full Depth')
  356. instance_count = tables.TemplateColumn(
  357. template_code=DEVICETYPE_INSTANCES_TEMPLATE,
  358. verbose_name='Instances'
  359. )
  360. class Meta(BaseTable.Meta):
  361. model = DeviceType
  362. fields = (
  363. 'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
  364. 'instance_count',
  365. )
  366. #
  367. # Device type components
  368. #
  369. class ConsolePortTemplateTable(BaseTable):
  370. pk = ToggleColumn()
  371. name = tables.Column(order_by=('_name',))
  372. actions = tables.TemplateColumn(
  373. template_code=get_component_template_actions('consoleporttemplate'),
  374. attrs={'td': {'class': 'text-right noprint'}},
  375. verbose_name=''
  376. )
  377. class Meta(BaseTable.Meta):
  378. model = ConsolePortTemplate
  379. fields = ('pk', 'name', 'type', 'actions')
  380. empty_text = "None"
  381. class ConsolePortImportTable(BaseTable):
  382. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  383. class Meta(BaseTable.Meta):
  384. model = ConsolePort
  385. fields = ('device', 'name', 'description')
  386. empty_text = False
  387. class ConsoleServerPortTemplateTable(BaseTable):
  388. pk = ToggleColumn()
  389. name = tables.Column(order_by=('_name',))
  390. actions = tables.TemplateColumn(
  391. template_code=get_component_template_actions('consoleserverporttemplate'),
  392. attrs={'td': {'class': 'text-right noprint'}},
  393. verbose_name=''
  394. )
  395. class Meta(BaseTable.Meta):
  396. model = ConsoleServerPortTemplate
  397. fields = ('pk', 'name', 'type', 'actions')
  398. empty_text = "None"
  399. class ConsoleServerPortImportTable(BaseTable):
  400. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  401. class Meta(BaseTable.Meta):
  402. model = ConsoleServerPort
  403. fields = ('device', 'name', 'description')
  404. empty_text = False
  405. class PowerPortTemplateTable(BaseTable):
  406. pk = ToggleColumn()
  407. name = tables.Column(order_by=('_name',))
  408. actions = tables.TemplateColumn(
  409. template_code=get_component_template_actions('powerporttemplate'),
  410. attrs={'td': {'class': 'text-right noprint'}},
  411. verbose_name=''
  412. )
  413. class Meta(BaseTable.Meta):
  414. model = PowerPortTemplate
  415. fields = ('pk', 'name', 'type', 'maximum_draw', 'allocated_draw', 'actions')
  416. empty_text = "None"
  417. class PowerPortImportTable(BaseTable):
  418. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  419. class Meta(BaseTable.Meta):
  420. model = PowerPort
  421. fields = ('device', 'name', 'description', 'maximum_draw', 'allocated_draw')
  422. empty_text = False
  423. class PowerOutletTemplateTable(BaseTable):
  424. pk = ToggleColumn()
  425. name = tables.Column(order_by=('_name',))
  426. actions = tables.TemplateColumn(
  427. template_code=get_component_template_actions('poweroutlettemplate'),
  428. attrs={'td': {'class': 'text-right noprint'}},
  429. verbose_name=''
  430. )
  431. class Meta(BaseTable.Meta):
  432. model = PowerOutletTemplate
  433. fields = ('pk', 'name', 'type', 'power_port', 'feed_leg', 'actions')
  434. empty_text = "None"
  435. class PowerOutletImportTable(BaseTable):
  436. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  437. class Meta(BaseTable.Meta):
  438. model = PowerOutlet
  439. fields = ('device', 'name', 'description', 'power_port', 'feed_leg')
  440. empty_text = False
  441. class InterfaceTemplateTable(BaseTable):
  442. pk = ToggleColumn()
  443. mgmt_only = tables.TemplateColumn("{% if value %}OOB Management{% endif %}")
  444. actions = tables.TemplateColumn(
  445. template_code=get_component_template_actions('interfacetemplate'),
  446. attrs={'td': {'class': 'text-right noprint'}},
  447. verbose_name=''
  448. )
  449. class Meta(BaseTable.Meta):
  450. model = InterfaceTemplate
  451. fields = ('pk', 'name', 'mgmt_only', 'type', 'actions')
  452. empty_text = "None"
  453. class InterfaceImportTable(BaseTable):
  454. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  455. virtual_machine = tables.LinkColumn('virtualization:virtualmachine', args=[Accessor('virtual_machine.pk')], verbose_name='Virtual Machine')
  456. class Meta(BaseTable.Meta):
  457. model = Interface
  458. fields = ('device', 'virtual_machine', 'name', 'description', 'lag', 'type', 'enabled', 'mac_address', 'mtu', 'mgmt_only', 'mode')
  459. empty_text = False
  460. class FrontPortTemplateTable(BaseTable):
  461. pk = ToggleColumn()
  462. name = tables.Column(order_by=('_name',))
  463. rear_port_position = tables.Column(
  464. verbose_name='Position'
  465. )
  466. actions = tables.TemplateColumn(
  467. template_code=get_component_template_actions('frontporttemplate'),
  468. attrs={'td': {'class': 'text-right noprint'}},
  469. verbose_name=''
  470. )
  471. class Meta(BaseTable.Meta):
  472. model = FrontPortTemplate
  473. fields = ('pk', 'name', 'type', 'rear_port', 'rear_port_position', 'actions')
  474. empty_text = "None"
  475. class FrontPortImportTable(BaseTable):
  476. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  477. class Meta(BaseTable.Meta):
  478. model = FrontPort
  479. fields = ('device', 'name', 'description', 'type', 'rear_port', 'rear_port_position')
  480. empty_text = False
  481. class RearPortTemplateTable(BaseTable):
  482. pk = ToggleColumn()
  483. name = tables.Column(order_by=('_name',))
  484. actions = tables.TemplateColumn(
  485. template_code=get_component_template_actions('rearporttemplate'),
  486. attrs={'td': {'class': 'text-right noprint'}},
  487. verbose_name=''
  488. )
  489. class Meta(BaseTable.Meta):
  490. model = RearPortTemplate
  491. fields = ('pk', 'name', 'type', 'positions', 'actions')
  492. empty_text = "None"
  493. class RearPortImportTable(BaseTable):
  494. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  495. class Meta(BaseTable.Meta):
  496. model = RearPort
  497. fields = ('device', 'name', 'description', 'type', 'position')
  498. empty_text = False
  499. class DeviceBayTemplateTable(BaseTable):
  500. pk = ToggleColumn()
  501. name = tables.Column(order_by=('_name',))
  502. actions = tables.TemplateColumn(
  503. template_code=get_component_template_actions('devicebaytemplate'),
  504. attrs={'td': {'class': 'text-right noprint'}},
  505. verbose_name=''
  506. )
  507. class Meta(BaseTable.Meta):
  508. model = DeviceBayTemplate
  509. fields = ('pk', 'name', 'actions')
  510. empty_text = "None"
  511. #
  512. # Device roles
  513. #
  514. class DeviceRoleTable(BaseTable):
  515. pk = ToggleColumn()
  516. device_count = tables.TemplateColumn(
  517. template_code=DEVICEROLE_DEVICE_COUNT,
  518. accessor=Accessor('devices.count'),
  519. orderable=False,
  520. verbose_name='Devices'
  521. )
  522. vm_count = tables.TemplateColumn(
  523. template_code=DEVICEROLE_VM_COUNT,
  524. accessor=Accessor('virtual_machines.count'),
  525. orderable=False,
  526. verbose_name='VMs'
  527. )
  528. color = tables.TemplateColumn(COLOR_LABEL, verbose_name='Label')
  529. slug = tables.Column(verbose_name='Slug')
  530. actions = tables.TemplateColumn(
  531. template_code=DEVICEROLE_ACTIONS,
  532. attrs={'td': {'class': 'text-right noprint'}},
  533. verbose_name=''
  534. )
  535. class Meta(BaseTable.Meta):
  536. model = DeviceRole
  537. fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions')
  538. #
  539. # Platforms
  540. #
  541. class PlatformTable(BaseTable):
  542. pk = ToggleColumn()
  543. device_count = tables.TemplateColumn(
  544. template_code=PLATFORM_DEVICE_COUNT,
  545. accessor=Accessor('devices.count'),
  546. orderable=False,
  547. verbose_name='Devices'
  548. )
  549. vm_count = tables.TemplateColumn(
  550. template_code=PLATFORM_VM_COUNT,
  551. accessor=Accessor('virtual_machines.count'),
  552. orderable=False,
  553. verbose_name='VMs'
  554. )
  555. actions = tables.TemplateColumn(
  556. template_code=PLATFORM_ACTIONS,
  557. attrs={'td': {'class': 'text-right noprint'}},
  558. verbose_name=''
  559. )
  560. class Meta(BaseTable.Meta):
  561. model = Platform
  562. fields = (
  563. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'description', 'actions',
  564. )
  565. #
  566. # Devices
  567. #
  568. class DeviceTable(BaseTable):
  569. pk = ToggleColumn()
  570. name = tables.TemplateColumn(
  571. order_by=('_name',),
  572. template_code=DEVICE_LINK
  573. )
  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')])
  577. rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
  578. device_role = tables.TemplateColumn(DEVICE_ROLE, verbose_name='Role')
  579. device_type = tables.LinkColumn(
  580. 'dcim:devicetype', args=[Accessor('device_type.pk')], verbose_name='Type',
  581. text=lambda record: record.device_type.display_name
  582. )
  583. class Meta(BaseTable.Meta):
  584. model = Device
  585. fields = ('pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type')
  586. class DeviceDetailTable(DeviceTable):
  587. primary_ip = tables.TemplateColumn(
  588. orderable=False, verbose_name='IP Address', template_code=DEVICE_PRIMARY_IP
  589. )
  590. class Meta(DeviceTable.Meta):
  591. model = Device
  592. fields = ('pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip')
  593. class DeviceImportTable(BaseTable):
  594. name = tables.TemplateColumn(template_code=DEVICE_LINK, verbose_name='Name')
  595. status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
  596. tenant = tables.TemplateColumn(template_code=COL_TENANT)
  597. site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
  598. rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')], verbose_name='Rack')
  599. position = tables.Column(verbose_name='Position')
  600. device_role = tables.Column(verbose_name='Role')
  601. device_type = tables.Column(verbose_name='Type')
  602. class Meta(BaseTable.Meta):
  603. model = Device
  604. fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
  605. empty_text = False
  606. #
  607. # Device components
  608. #
  609. class DeviceComponentDetailTable(BaseTable):
  610. pk = ToggleColumn()
  611. name = tables.Column(order_by=('_name',))
  612. cable = tables.LinkColumn()
  613. class Meta(BaseTable.Meta):
  614. order_by = ('device', 'name')
  615. fields = ('pk', 'device', 'name', 'type', 'description', 'cable')
  616. sequence = ('pk', 'device', 'name', 'type', 'description', 'cable')
  617. class ConsolePortTable(BaseTable):
  618. name = tables.Column(order_by=('_name',))
  619. class Meta(BaseTable.Meta):
  620. model = ConsolePort
  621. fields = ('name', 'type')
  622. class ConsolePortDetailTable(DeviceComponentDetailTable):
  623. device = tables.LinkColumn()
  624. class Meta(DeviceComponentDetailTable.Meta, ConsolePortTable.Meta):
  625. pass
  626. class ConsoleServerPortTable(BaseTable):
  627. name = tables.Column(order_by=('_name',))
  628. class Meta(BaseTable.Meta):
  629. model = ConsoleServerPort
  630. fields = ('name', 'description')
  631. class ConsoleServerPortDetailTable(DeviceComponentDetailTable):
  632. device = tables.LinkColumn()
  633. class Meta(DeviceComponentDetailTable.Meta, ConsoleServerPortTable.Meta):
  634. pass
  635. class PowerPortTable(BaseTable):
  636. name = tables.Column(order_by=('_name',))
  637. class Meta(BaseTable.Meta):
  638. model = PowerPort
  639. fields = ('name', 'type')
  640. class PowerPortDetailTable(DeviceComponentDetailTable):
  641. device = tables.LinkColumn()
  642. class Meta(DeviceComponentDetailTable.Meta, PowerPortTable.Meta):
  643. pass
  644. class PowerOutletTable(BaseTable):
  645. name = tables.Column(order_by=('_name',))
  646. class Meta(BaseTable.Meta):
  647. model = PowerOutlet
  648. fields = ('name', 'type', 'description')
  649. class PowerOutletDetailTable(DeviceComponentDetailTable):
  650. device = tables.LinkColumn()
  651. class Meta(DeviceComponentDetailTable.Meta, PowerOutletTable.Meta):
  652. pass
  653. class InterfaceTable(BaseTable):
  654. class Meta(BaseTable.Meta):
  655. model = Interface
  656. fields = ('name', 'type', 'lag', 'enabled', 'mgmt_only', 'description')
  657. class InterfaceDetailTable(DeviceComponentDetailTable):
  658. parent = tables.LinkColumn(order_by=('device', 'virtual_machine'))
  659. name = tables.LinkColumn()
  660. enabled = BooleanColumn()
  661. class Meta(InterfaceTable.Meta):
  662. order_by = ('parent', 'name')
  663. fields = ('pk', 'parent', 'name', 'enabled', 'type', 'description', 'cable')
  664. sequence = ('pk', 'parent', 'name', 'enabled', 'type', 'description', 'cable')
  665. class FrontPortTable(BaseTable):
  666. name = tables.Column(order_by=('_name',))
  667. class Meta(BaseTable.Meta):
  668. model = FrontPort
  669. fields = ('name', 'type', 'rear_port', 'rear_port_position', 'description')
  670. empty_text = "None"
  671. class FrontPortDetailTable(DeviceComponentDetailTable):
  672. device = tables.LinkColumn()
  673. class Meta(DeviceComponentDetailTable.Meta, FrontPortTable.Meta):
  674. pass
  675. class RearPortTable(BaseTable):
  676. name = tables.Column(order_by=('_name',))
  677. class Meta(BaseTable.Meta):
  678. model = RearPort
  679. fields = ('name', 'type', 'positions', 'description')
  680. empty_text = "None"
  681. class RearPortDetailTable(DeviceComponentDetailTable):
  682. device = tables.LinkColumn()
  683. class Meta(DeviceComponentDetailTable.Meta, RearPortTable.Meta):
  684. pass
  685. class DeviceBayTable(BaseTable):
  686. name = tables.Column(order_by=('_name',))
  687. class Meta(BaseTable.Meta):
  688. model = DeviceBay
  689. fields = ('name', 'description')
  690. class DeviceBayDetailTable(DeviceComponentDetailTable):
  691. device = tables.LinkColumn()
  692. installed_device = tables.LinkColumn()
  693. class Meta(DeviceBayTable.Meta):
  694. fields = ('pk', 'name', 'device', 'installed_device', 'description')
  695. sequence = ('pk', 'name', 'device', 'installed_device', 'description')
  696. exclude = ('cable',)
  697. class DeviceBayImportTable(BaseTable):
  698. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  699. installed_device = tables.LinkColumn('dcim:device', args=[Accessor('installed_device.pk')], verbose_name='Installed Device')
  700. class Meta(BaseTable.Meta):
  701. model = DeviceBay
  702. fields = ('device', 'name', 'installed_device', 'description')
  703. empty_text = False
  704. #
  705. # Cables
  706. #
  707. class CableTable(BaseTable):
  708. pk = ToggleColumn()
  709. id = tables.LinkColumn(
  710. viewname='dcim:cable',
  711. args=[Accessor('pk')],
  712. verbose_name='ID'
  713. )
  714. termination_a_parent = tables.TemplateColumn(
  715. template_code=CABLE_TERMINATION_PARENT,
  716. accessor=Accessor('termination_a'),
  717. orderable=False,
  718. verbose_name='Termination A'
  719. )
  720. termination_a = tables.LinkColumn(
  721. accessor=Accessor('termination_a'),
  722. orderable=False,
  723. verbose_name=''
  724. )
  725. termination_b_parent = tables.TemplateColumn(
  726. template_code=CABLE_TERMINATION_PARENT,
  727. accessor=Accessor('termination_b'),
  728. orderable=False,
  729. verbose_name='Termination B'
  730. )
  731. termination_b = tables.LinkColumn(
  732. accessor=Accessor('termination_b'),
  733. orderable=False,
  734. verbose_name=''
  735. )
  736. status = tables.TemplateColumn(
  737. template_code=STATUS_LABEL
  738. )
  739. length = tables.TemplateColumn(
  740. template_code=CABLE_LENGTH,
  741. order_by='_abs_length'
  742. )
  743. color = ColorColumn()
  744. class Meta(BaseTable.Meta):
  745. model = Cable
  746. fields = (
  747. 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b',
  748. 'status', 'type', 'color', 'length',
  749. )
  750. #
  751. # Device connections
  752. #
  753. class ConsoleConnectionTable(BaseTable):
  754. console_server = tables.LinkColumn(
  755. viewname='dcim:device',
  756. accessor=Accessor('connected_endpoint.device'),
  757. args=[Accessor('connected_endpoint.device.pk')],
  758. verbose_name='Console Server'
  759. )
  760. connected_endpoint = tables.Column(
  761. verbose_name='Port'
  762. )
  763. device = tables.LinkColumn(
  764. viewname='dcim:device',
  765. args=[Accessor('device.pk')]
  766. )
  767. name = tables.Column(
  768. verbose_name='Console Port'
  769. )
  770. class Meta(BaseTable.Meta):
  771. model = ConsolePort
  772. fields = ('console_server', 'connected_endpoint', 'device', 'name', 'connection_status')
  773. class PowerConnectionTable(BaseTable):
  774. pdu = tables.LinkColumn(
  775. viewname='dcim:device',
  776. accessor=Accessor('connected_endpoint.device'),
  777. args=[Accessor('connected_endpoint.device.pk')],
  778. order_by='_connected_poweroutlet__device',
  779. verbose_name='PDU'
  780. )
  781. outlet = tables.Column(
  782. accessor=Accessor('_connected_poweroutlet'),
  783. verbose_name='Outlet'
  784. )
  785. device = tables.LinkColumn(
  786. viewname='dcim:device',
  787. args=[Accessor('device.pk')]
  788. )
  789. name = tables.Column(
  790. verbose_name='Power Port'
  791. )
  792. class Meta(BaseTable.Meta):
  793. model = PowerPort
  794. fields = ('pdu', 'outlet', 'device', 'name', 'connection_status')
  795. class InterfaceConnectionTable(BaseTable):
  796. device_a = tables.LinkColumn(
  797. viewname='dcim:device',
  798. accessor=Accessor('device'),
  799. args=[Accessor('device.pk')],
  800. verbose_name='Device A'
  801. )
  802. interface_a = tables.LinkColumn(
  803. viewname='dcim:interface',
  804. accessor=Accessor('name'),
  805. args=[Accessor('pk')],
  806. verbose_name='Interface A'
  807. )
  808. description_a = tables.Column(
  809. accessor=Accessor('description'),
  810. verbose_name='Description'
  811. )
  812. device_b = tables.LinkColumn(
  813. viewname='dcim:device',
  814. accessor=Accessor('_connected_interface.device'),
  815. args=[Accessor('_connected_interface.device.pk')],
  816. verbose_name='Device B'
  817. )
  818. interface_b = tables.LinkColumn(
  819. viewname='dcim:interface',
  820. accessor=Accessor('_connected_interface'),
  821. args=[Accessor('_connected_interface.pk')],
  822. verbose_name='Interface B'
  823. )
  824. description_b = tables.Column(
  825. accessor=Accessor('_connected_interface.description'),
  826. verbose_name='Description'
  827. )
  828. class Meta(BaseTable.Meta):
  829. model = Interface
  830. fields = (
  831. 'device_a', 'interface_a', 'description_a', 'device_b', 'interface_b', 'description_b', 'connection_status',
  832. )
  833. #
  834. # InventoryItems
  835. #
  836. class InventoryItemTable(BaseTable):
  837. pk = ToggleColumn()
  838. device = tables.LinkColumn('dcim:device_inventory', args=[Accessor('device.pk')])
  839. manufacturer = tables.Column(accessor=Accessor('manufacturer.name'), verbose_name='Manufacturer')
  840. class Meta(BaseTable.Meta):
  841. model = InventoryItem
  842. fields = ('pk', 'device', 'name', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description')
  843. #
  844. # Virtual chassis
  845. #
  846. class VirtualChassisTable(BaseTable):
  847. pk = ToggleColumn()
  848. master = tables.LinkColumn()
  849. member_count = tables.Column(verbose_name='Members')
  850. actions = tables.TemplateColumn(
  851. template_code=VIRTUALCHASSIS_ACTIONS,
  852. attrs={'td': {'class': 'text-right noprint'}},
  853. verbose_name=''
  854. )
  855. class Meta(BaseTable.Meta):
  856. model = VirtualChassis
  857. fields = ('pk', 'master', 'domain', 'member_count', 'actions')
  858. #
  859. # Power panels
  860. #
  861. class PowerPanelTable(BaseTable):
  862. pk = ToggleColumn()
  863. name = tables.LinkColumn()
  864. site = tables.LinkColumn(
  865. viewname='dcim:site',
  866. args=[Accessor('site.slug')]
  867. )
  868. powerfeed_count = tables.TemplateColumn(
  869. template_code=POWERPANEL_POWERFEED_COUNT,
  870. verbose_name='Feeds'
  871. )
  872. class Meta(BaseTable.Meta):
  873. model = PowerPanel
  874. fields = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count')
  875. #
  876. # Power feeds
  877. #
  878. class PowerFeedTable(BaseTable):
  879. pk = ToggleColumn()
  880. name = tables.LinkColumn()
  881. power_panel = tables.LinkColumn(
  882. viewname='dcim:powerpanel',
  883. args=[Accessor('power_panel.pk')],
  884. )
  885. rack = tables.LinkColumn(
  886. viewname='dcim:rack',
  887. args=[Accessor('rack.pk')]
  888. )
  889. status = tables.TemplateColumn(
  890. template_code=STATUS_LABEL
  891. )
  892. type = tables.TemplateColumn(
  893. template_code=TYPE_LABEL
  894. )
  895. class Meta(BaseTable.Meta):
  896. model = PowerFeed
  897. fields = ('pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase')