tables.py 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  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. CABLE_TERMINATION_PARENT = """
  144. {% if value.device %}
  145. <a href="{{ value.device.get_absolute_url }}">{{ value.device }}</a>
  146. {% elif value.circuit %}
  147. <a href="{{ value.circuit.get_absolute_url }}">{{ value.circuit }}</a>
  148. {% elif value.power_panel %}
  149. <a href="{{ value.power_panel.get_absolute_url }}">{{ value.power_panel }}</a>
  150. {% endif %}
  151. """
  152. CABLE_LENGTH = """
  153. {% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}&mdash;{% endif %}
  154. """
  155. POWERPANEL_POWERFEED_COUNT = """
  156. <a href="{% url 'dcim:powerfeed_list' %}?power_panel_id={{ record.pk }}">{{ value }}</a>
  157. """
  158. def get_component_template_actions(model_name):
  159. return """
  160. {{% if perms.dcim.change_{model_name} %}}
  161. <a href="{{% url 'dcim:{model_name}_edit' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-xs btn-warning">
  162. <i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
  163. </a>
  164. {{% endif %}}
  165. {{% if perms.dcim.delete_{model_name} %}}
  166. <a href="{{% url 'dcim:{model_name}_delete' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-xs btn-danger">
  167. <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
  168. </a>
  169. {{% endif %}}
  170. """.format(model_name=model_name).strip()
  171. #
  172. # Regions
  173. #
  174. class RegionTable(BaseTable):
  175. pk = ToggleColumn()
  176. name = tables.TemplateColumn(
  177. template_code=MPTT_LINK,
  178. orderable=False
  179. )
  180. site_count = tables.Column(
  181. verbose_name='Sites'
  182. )
  183. actions = tables.TemplateColumn(
  184. template_code=REGION_ACTIONS,
  185. attrs={'td': {'class': 'text-right noprint'}},
  186. verbose_name=''
  187. )
  188. class Meta(BaseTable.Meta):
  189. model = Region
  190. fields = ('pk', 'name', 'slug', 'site_count', 'description', 'actions')
  191. default_columns = ('pk', 'name', 'site_count', 'description', 'actions')
  192. #
  193. # Sites
  194. #
  195. class SiteTable(BaseTable):
  196. pk = ToggleColumn()
  197. name = tables.LinkColumn(
  198. order_by=('_name',)
  199. )
  200. status = tables.TemplateColumn(
  201. template_code=STATUS_LABEL
  202. )
  203. region = tables.TemplateColumn(
  204. template_code=SITE_REGION_LINK
  205. )
  206. tenant = tables.TemplateColumn(
  207. template_code=COL_TENANT
  208. )
  209. class Meta(BaseTable.Meta):
  210. model = Site
  211. fields = (
  212. 'pk', 'name', 'slug', 'status', 'facility', 'region', 'tenant', 'asn', 'time_zone', 'description',
  213. 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone',
  214. 'contact_email',
  215. )
  216. default_columns = ('pk', 'name', 'status', 'facility', 'region', 'tenant', 'asn', 'description')
  217. #
  218. # Rack groups
  219. #
  220. class RackGroupTable(BaseTable):
  221. pk = ToggleColumn()
  222. name = tables.TemplateColumn(
  223. template_code=MPTT_LINK,
  224. orderable=False
  225. )
  226. site = tables.LinkColumn(
  227. viewname='dcim:site',
  228. args=[Accessor('site.slug')],
  229. verbose_name='Site'
  230. )
  231. rack_count = tables.Column(
  232. verbose_name='Racks'
  233. )
  234. actions = tables.TemplateColumn(
  235. template_code=RACKGROUP_ACTIONS,
  236. attrs={'td': {'class': 'text-right noprint'}},
  237. verbose_name=''
  238. )
  239. class Meta(BaseTable.Meta):
  240. model = RackGroup
  241. fields = ('pk', 'name', 'site', 'rack_count', 'description', 'slug', 'actions')
  242. default_columns = ('pk', 'name', 'site', 'rack_count', 'description', 'actions')
  243. #
  244. # Rack roles
  245. #
  246. class RackRoleTable(BaseTable):
  247. pk = ToggleColumn()
  248. rack_count = tables.Column(verbose_name='Racks')
  249. color = tables.TemplateColumn(COLOR_LABEL)
  250. actions = tables.TemplateColumn(
  251. template_code=RACKROLE_ACTIONS,
  252. attrs={'td': {'class': 'text-right noprint'}},
  253. verbose_name=''
  254. )
  255. class Meta(BaseTable.Meta):
  256. model = RackRole
  257. fields = ('pk', 'name', 'rack_count', 'color', 'description', 'slug', 'actions')
  258. default_columns = ('pk', 'name', 'rack_count', 'color', 'description', 'actions')
  259. #
  260. # Racks
  261. #
  262. class RackTable(BaseTable):
  263. pk = ToggleColumn()
  264. name = tables.LinkColumn(
  265. order_by=('_name',)
  266. )
  267. site = tables.LinkColumn(
  268. viewname='dcim:site',
  269. args=[Accessor('site.slug')]
  270. )
  271. group = tables.Column(
  272. accessor=Accessor('group.name')
  273. )
  274. tenant = tables.TemplateColumn(
  275. template_code=COL_TENANT
  276. )
  277. status = tables.TemplateColumn(
  278. template_code=STATUS_LABEL
  279. )
  280. role = tables.TemplateColumn(
  281. template_code=RACK_ROLE
  282. )
  283. u_height = tables.TemplateColumn(
  284. template_code="{{ record.u_height }}U",
  285. verbose_name='Height'
  286. )
  287. class Meta(BaseTable.Meta):
  288. model = Rack
  289. fields = (
  290. 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type',
  291. 'width', 'u_height',
  292. )
  293. default_columns = ('pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height')
  294. class RackDetailTable(RackTable):
  295. device_count = tables.TemplateColumn(
  296. template_code=RACK_DEVICE_COUNT,
  297. verbose_name='Devices'
  298. )
  299. get_utilization = tables.TemplateColumn(
  300. template_code=UTILIZATION_GRAPH,
  301. orderable=False,
  302. verbose_name='Space'
  303. )
  304. get_power_utilization = tables.TemplateColumn(
  305. template_code=UTILIZATION_GRAPH,
  306. orderable=False,
  307. verbose_name='Power'
  308. )
  309. class Meta(RackTable.Meta):
  310. fields = (
  311. 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type',
  312. 'width', 'u_height', 'device_count', 'get_utilization', 'get_power_utilization',
  313. )
  314. default_columns = (
  315. 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height', 'device_count',
  316. 'get_utilization', 'get_power_utilization',
  317. )
  318. #
  319. # Rack reservations
  320. #
  321. class RackReservationTable(BaseTable):
  322. pk = ToggleColumn()
  323. reservation = tables.LinkColumn(
  324. viewname='dcim:rackreservation',
  325. args=[Accessor('pk')],
  326. accessor='pk'
  327. )
  328. site = tables.LinkColumn(
  329. viewname='dcim:site',
  330. accessor=Accessor('rack.site'),
  331. args=[Accessor('rack.site.slug')],
  332. )
  333. tenant = tables.TemplateColumn(
  334. template_code=COL_TENANT
  335. )
  336. rack = tables.LinkColumn(
  337. viewname='dcim:rack',
  338. args=[Accessor('rack.pk')]
  339. )
  340. unit_list = tables.Column(
  341. orderable=False,
  342. verbose_name='Units'
  343. )
  344. actions = tables.TemplateColumn(
  345. template_code=RACKRESERVATION_ACTIONS,
  346. attrs={'td': {'class': 'text-right noprint'}},
  347. verbose_name=''
  348. )
  349. class Meta(BaseTable.Meta):
  350. model = RackReservation
  351. fields = (
  352. 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'actions',
  353. )
  354. default_columns = (
  355. 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'description', 'actions',
  356. )
  357. #
  358. # Manufacturers
  359. #
  360. class ManufacturerTable(BaseTable):
  361. pk = ToggleColumn()
  362. name = tables.LinkColumn()
  363. devicetype_count = tables.Column(
  364. verbose_name='Device Types'
  365. )
  366. inventoryitem_count = tables.Column(
  367. verbose_name='Inventory Items'
  368. )
  369. platform_count = tables.Column(
  370. verbose_name='Platforms'
  371. )
  372. slug = tables.Column()
  373. actions = tables.TemplateColumn(
  374. template_code=MANUFACTURER_ACTIONS,
  375. attrs={'td': {'class': 'text-right noprint'}},
  376. verbose_name=''
  377. )
  378. class Meta(BaseTable.Meta):
  379. model = Manufacturer
  380. fields = (
  381. 'pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug', 'actions',
  382. )
  383. #
  384. # Device types
  385. #
  386. class DeviceTypeTable(BaseTable):
  387. pk = ToggleColumn()
  388. model = tables.LinkColumn(
  389. viewname='dcim:devicetype',
  390. args=[Accessor('pk')],
  391. verbose_name='Device Type'
  392. )
  393. is_full_depth = BooleanColumn(verbose_name='Full Depth')
  394. instance_count = tables.TemplateColumn(
  395. template_code=DEVICETYPE_INSTANCES_TEMPLATE,
  396. verbose_name='Instances'
  397. )
  398. class Meta(BaseTable.Meta):
  399. model = DeviceType
  400. fields = (
  401. 'pk', 'model', 'manufacturer', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
  402. 'instance_count',
  403. )
  404. default_columns = (
  405. 'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'instance_count',
  406. )
  407. #
  408. # Device type components
  409. #
  410. class ConsolePortTemplateTable(BaseTable):
  411. pk = ToggleColumn()
  412. name = tables.Column(
  413. order_by=('_name',)
  414. )
  415. actions = tables.TemplateColumn(
  416. template_code=get_component_template_actions('consoleporttemplate'),
  417. attrs={'td': {'class': 'text-right noprint'}},
  418. verbose_name=''
  419. )
  420. class Meta(BaseTable.Meta):
  421. model = ConsolePortTemplate
  422. fields = ('pk', 'name', 'type', 'actions')
  423. empty_text = "None"
  424. class ConsolePortImportTable(BaseTable):
  425. device = tables.LinkColumn(
  426. viewname='dcim:device',
  427. args=[Accessor('device.pk')]
  428. )
  429. class Meta(BaseTable.Meta):
  430. model = ConsolePort
  431. fields = ('device', 'name', 'description')
  432. empty_text = False
  433. class ConsoleServerPortTemplateTable(BaseTable):
  434. pk = ToggleColumn()
  435. name = tables.Column(
  436. order_by=('_name',)
  437. )
  438. actions = tables.TemplateColumn(
  439. template_code=get_component_template_actions('consoleserverporttemplate'),
  440. attrs={'td': {'class': 'text-right noprint'}},
  441. verbose_name=''
  442. )
  443. class Meta(BaseTable.Meta):
  444. model = ConsoleServerPortTemplate
  445. fields = ('pk', 'name', 'type', 'actions')
  446. empty_text = "None"
  447. class ConsoleServerPortImportTable(BaseTable):
  448. device = tables.LinkColumn(
  449. viewname='dcim:device',
  450. args=[Accessor('device.pk')]
  451. )
  452. class Meta(BaseTable.Meta):
  453. model = ConsoleServerPort
  454. fields = ('device', 'name', 'description')
  455. empty_text = False
  456. class PowerPortTemplateTable(BaseTable):
  457. pk = ToggleColumn()
  458. name = tables.Column(
  459. order_by=('_name',)
  460. )
  461. actions = tables.TemplateColumn(
  462. template_code=get_component_template_actions('powerporttemplate'),
  463. attrs={'td': {'class': 'text-right noprint'}},
  464. verbose_name=''
  465. )
  466. class Meta(BaseTable.Meta):
  467. model = PowerPortTemplate
  468. fields = ('pk', 'name', 'type', 'maximum_draw', 'allocated_draw', 'actions')
  469. empty_text = "None"
  470. class PowerPortImportTable(BaseTable):
  471. device = tables.LinkColumn(
  472. viewname='dcim:device',
  473. args=[Accessor('device.pk')]
  474. )
  475. class Meta(BaseTable.Meta):
  476. model = PowerPort
  477. fields = ('device', 'name', 'description', 'maximum_draw', 'allocated_draw')
  478. empty_text = False
  479. class PowerOutletTemplateTable(BaseTable):
  480. pk = ToggleColumn()
  481. name = tables.Column(
  482. order_by=('_name',)
  483. )
  484. actions = tables.TemplateColumn(
  485. template_code=get_component_template_actions('poweroutlettemplate'),
  486. attrs={'td': {'class': 'text-right noprint'}},
  487. verbose_name=''
  488. )
  489. class Meta(BaseTable.Meta):
  490. model = PowerOutletTemplate
  491. fields = ('pk', 'name', 'type', 'power_port', 'feed_leg', 'actions')
  492. empty_text = "None"
  493. class PowerOutletImportTable(BaseTable):
  494. device = tables.LinkColumn(
  495. viewname='dcim:device',
  496. args=[Accessor('device.pk')]
  497. )
  498. class Meta(BaseTable.Meta):
  499. model = PowerOutlet
  500. fields = ('device', 'name', 'description', 'power_port', 'feed_leg')
  501. empty_text = False
  502. class InterfaceTemplateTable(BaseTable):
  503. pk = ToggleColumn()
  504. mgmt_only = tables.TemplateColumn(
  505. template_code="{% if value %}OOB Management{% endif %}"
  506. )
  507. actions = tables.TemplateColumn(
  508. template_code=get_component_template_actions('interfacetemplate'),
  509. attrs={'td': {'class': 'text-right noprint'}},
  510. verbose_name=''
  511. )
  512. class Meta(BaseTable.Meta):
  513. model = InterfaceTemplate
  514. fields = ('pk', 'name', 'mgmt_only', 'type', 'actions')
  515. empty_text = "None"
  516. class InterfaceImportTable(BaseTable):
  517. device = tables.LinkColumn(
  518. viewname='dcim:device',
  519. args=[Accessor('device.pk')]
  520. )
  521. virtual_machine = tables.LinkColumn(
  522. viewname='virtualization:virtualmachine',
  523. args=[Accessor('virtual_machine.pk')],
  524. verbose_name='Virtual Machine'
  525. )
  526. class Meta(BaseTable.Meta):
  527. model = Interface
  528. fields = (
  529. 'device', 'virtual_machine', 'name', 'description', 'lag', 'type', 'enabled', 'mac_address', 'mtu',
  530. 'mgmt_only', 'mode',
  531. )
  532. empty_text = False
  533. class FrontPortTemplateTable(BaseTable):
  534. pk = ToggleColumn()
  535. name = tables.Column(
  536. order_by=('_name',)
  537. )
  538. rear_port_position = tables.Column(
  539. verbose_name='Position'
  540. )
  541. actions = tables.TemplateColumn(
  542. template_code=get_component_template_actions('frontporttemplate'),
  543. attrs={'td': {'class': 'text-right noprint'}},
  544. verbose_name=''
  545. )
  546. class Meta(BaseTable.Meta):
  547. model = FrontPortTemplate
  548. fields = ('pk', 'name', 'type', 'rear_port', 'rear_port_position', 'actions')
  549. empty_text = "None"
  550. class FrontPortImportTable(BaseTable):
  551. device = tables.LinkColumn(
  552. viewname='dcim:device',
  553. args=[Accessor('device.pk')]
  554. )
  555. class Meta(BaseTable.Meta):
  556. model = FrontPort
  557. fields = ('device', 'name', 'description', 'type', 'rear_port', 'rear_port_position')
  558. empty_text = False
  559. class RearPortTemplateTable(BaseTable):
  560. pk = ToggleColumn()
  561. name = tables.Column(
  562. order_by=('_name',)
  563. )
  564. actions = tables.TemplateColumn(
  565. template_code=get_component_template_actions('rearporttemplate'),
  566. attrs={'td': {'class': 'text-right noprint'}},
  567. verbose_name=''
  568. )
  569. class Meta(BaseTable.Meta):
  570. model = RearPortTemplate
  571. fields = ('pk', 'name', 'type', 'positions', 'actions')
  572. empty_text = "None"
  573. class RearPortImportTable(BaseTable):
  574. device = tables.LinkColumn(
  575. viewname='dcim:device',
  576. args=[Accessor('device.pk')]
  577. )
  578. class Meta(BaseTable.Meta):
  579. model = RearPort
  580. fields = ('device', 'name', 'description', 'type', 'position')
  581. empty_text = False
  582. class DeviceBayTemplateTable(BaseTable):
  583. pk = ToggleColumn()
  584. name = tables.Column(
  585. order_by=('_name',)
  586. )
  587. actions = tables.TemplateColumn(
  588. template_code=get_component_template_actions('devicebaytemplate'),
  589. attrs={'td': {'class': 'text-right noprint'}},
  590. verbose_name=''
  591. )
  592. class Meta(BaseTable.Meta):
  593. model = DeviceBayTemplate
  594. fields = ('pk', 'name', 'actions')
  595. empty_text = "None"
  596. #
  597. # Device roles
  598. #
  599. class DeviceRoleTable(BaseTable):
  600. pk = ToggleColumn()
  601. device_count = tables.TemplateColumn(
  602. template_code=DEVICEROLE_DEVICE_COUNT,
  603. accessor=Accessor('devices.count'),
  604. orderable=False,
  605. verbose_name='Devices'
  606. )
  607. vm_count = tables.TemplateColumn(
  608. template_code=DEVICEROLE_VM_COUNT,
  609. accessor=Accessor('virtual_machines.count'),
  610. orderable=False,
  611. verbose_name='VMs'
  612. )
  613. color = tables.TemplateColumn(
  614. template_code=COLOR_LABEL,
  615. verbose_name='Label'
  616. )
  617. actions = tables.TemplateColumn(
  618. template_code=DEVICEROLE_ACTIONS,
  619. attrs={'td': {'class': 'text-right noprint'}},
  620. verbose_name=''
  621. )
  622. class Meta(BaseTable.Meta):
  623. model = DeviceRole
  624. fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions')
  625. default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'actions')
  626. #
  627. # Platforms
  628. #
  629. class PlatformTable(BaseTable):
  630. pk = ToggleColumn()
  631. device_count = tables.TemplateColumn(
  632. template_code=PLATFORM_DEVICE_COUNT,
  633. accessor=Accessor('devices.count'),
  634. orderable=False,
  635. verbose_name='Devices'
  636. )
  637. vm_count = tables.TemplateColumn(
  638. template_code=PLATFORM_VM_COUNT,
  639. accessor=Accessor('virtual_machines.count'),
  640. orderable=False,
  641. verbose_name='VMs'
  642. )
  643. actions = tables.TemplateColumn(
  644. template_code=PLATFORM_ACTIONS,
  645. attrs={'td': {'class': 'text-right noprint'}},
  646. verbose_name=''
  647. )
  648. class Meta(BaseTable.Meta):
  649. model = Platform
  650. fields = (
  651. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args',
  652. 'description', 'actions',
  653. )
  654. default_columns = (
  655. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'napalm_driver', 'description', 'actions',
  656. )
  657. #
  658. # Devices
  659. #
  660. class DeviceTable(BaseTable):
  661. pk = ToggleColumn()
  662. name = tables.TemplateColumn(
  663. order_by=('_name',),
  664. template_code=DEVICE_LINK
  665. )
  666. status = tables.TemplateColumn(
  667. template_code=STATUS_LABEL
  668. )
  669. tenant = tables.TemplateColumn(
  670. template_code=COL_TENANT
  671. )
  672. site = tables.LinkColumn(
  673. viewname='dcim:site',
  674. args=[Accessor('site.slug')]
  675. )
  676. rack = tables.LinkColumn(
  677. viewname='dcim:rack',
  678. args=[Accessor('rack.pk')]
  679. )
  680. device_role = tables.TemplateColumn(
  681. template_code=DEVICE_ROLE,
  682. verbose_name='Role'
  683. )
  684. device_type = tables.LinkColumn(
  685. viewname='dcim:devicetype',
  686. args=[Accessor('device_type.pk')],
  687. verbose_name='Type',
  688. text=lambda record: record.device_type.display_name
  689. )
  690. primary_ip = tables.TemplateColumn(
  691. template_code=DEVICE_PRIMARY_IP,
  692. orderable=False,
  693. verbose_name='IP Address'
  694. )
  695. primary_ip4 = tables.LinkColumn(
  696. viewname='ipam:ipaddress',
  697. args=[Accessor('primary_ip4.pk')],
  698. verbose_name='IPv4 Address'
  699. )
  700. primary_ip6 = tables.LinkColumn(
  701. viewname='ipam:ipaddress',
  702. args=[Accessor('primary_ip6.pk')],
  703. verbose_name='IPv6 Address'
  704. )
  705. cluster = tables.LinkColumn(
  706. viewname='virtualization:cluster',
  707. args=[Accessor('cluster.pk')]
  708. )
  709. virtual_chassis = tables.LinkColumn(
  710. viewname='dcim:virtualchassis',
  711. args=[Accessor('virtual_chassis.pk')]
  712. )
  713. vc_position = tables.Column(
  714. verbose_name='VC Position'
  715. )
  716. vc_priority = tables.Column(
  717. verbose_name='VC Priority'
  718. )
  719. class Meta(BaseTable.Meta):
  720. model = Device
  721. fields = (
  722. 'pk', 'name', 'status', 'tenant', 'device_role', 'device_type', 'platform', 'serial', 'asset_tag', 'site',
  723. 'rack', 'position', 'face', 'primary_ip', 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis',
  724. 'vc_position', 'vc_priority',
  725. )
  726. default_columns = (
  727. 'pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip',
  728. )
  729. class DeviceImportTable(BaseTable):
  730. name = tables.TemplateColumn(
  731. template_code=DEVICE_LINK
  732. )
  733. status = tables.TemplateColumn(
  734. template_code=STATUS_LABEL
  735. )
  736. tenant = tables.TemplateColumn(
  737. template_code=COL_TENANT
  738. )
  739. site = tables.LinkColumn(
  740. viewname='dcim:site',
  741. args=[Accessor('site.slug')]
  742. )
  743. rack = tables.LinkColumn(
  744. viewname='dcim:rack',
  745. args=[Accessor('rack.pk')]
  746. )
  747. device_role = tables.Column(
  748. verbose_name='Role'
  749. )
  750. device_type = tables.Column(
  751. verbose_name='Type'
  752. )
  753. class Meta(BaseTable.Meta):
  754. model = Device
  755. fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
  756. empty_text = False
  757. #
  758. # Device components
  759. #
  760. class DeviceComponentDetailTable(BaseTable):
  761. pk = ToggleColumn()
  762. name = tables.Column(order_by=('_name',))
  763. cable = tables.LinkColumn()
  764. class Meta(BaseTable.Meta):
  765. order_by = ('device', 'name')
  766. fields = ('pk', 'device', 'name', 'type', 'description', 'cable')
  767. sequence = ('pk', 'device', 'name', 'type', 'description', 'cable')
  768. class ConsolePortTable(BaseTable):
  769. name = tables.Column(order_by=('_name',))
  770. class Meta(BaseTable.Meta):
  771. model = ConsolePort
  772. fields = ('name', 'type')
  773. class ConsolePortDetailTable(DeviceComponentDetailTable):
  774. device = tables.LinkColumn()
  775. class Meta(DeviceComponentDetailTable.Meta, ConsolePortTable.Meta):
  776. pass
  777. class ConsoleServerPortTable(BaseTable):
  778. name = tables.Column(order_by=('_name',))
  779. class Meta(BaseTable.Meta):
  780. model = ConsoleServerPort
  781. fields = ('name', 'description')
  782. class ConsoleServerPortDetailTable(DeviceComponentDetailTable):
  783. device = tables.LinkColumn()
  784. class Meta(DeviceComponentDetailTable.Meta, ConsoleServerPortTable.Meta):
  785. pass
  786. class PowerPortTable(BaseTable):
  787. name = tables.Column(order_by=('_name',))
  788. class Meta(BaseTable.Meta):
  789. model = PowerPort
  790. fields = ('name', 'type')
  791. class PowerPortDetailTable(DeviceComponentDetailTable):
  792. device = tables.LinkColumn()
  793. class Meta(DeviceComponentDetailTable.Meta, PowerPortTable.Meta):
  794. pass
  795. class PowerOutletTable(BaseTable):
  796. name = tables.Column(order_by=('_name',))
  797. class Meta(BaseTable.Meta):
  798. model = PowerOutlet
  799. fields = ('name', 'type', 'description')
  800. class PowerOutletDetailTable(DeviceComponentDetailTable):
  801. device = tables.LinkColumn()
  802. class Meta(DeviceComponentDetailTable.Meta, PowerOutletTable.Meta):
  803. pass
  804. class InterfaceTable(BaseTable):
  805. class Meta(BaseTable.Meta):
  806. model = Interface
  807. fields = ('name', 'type', 'lag', 'enabled', 'mgmt_only', 'description')
  808. class InterfaceDetailTable(DeviceComponentDetailTable):
  809. parent = tables.LinkColumn(order_by=('device', 'virtual_machine'))
  810. name = tables.LinkColumn()
  811. enabled = BooleanColumn()
  812. class Meta(InterfaceTable.Meta):
  813. order_by = ('parent', 'name')
  814. fields = ('pk', 'parent', 'name', 'enabled', 'type', 'description', 'cable')
  815. sequence = ('pk', 'parent', 'name', 'enabled', 'type', 'description', 'cable')
  816. class FrontPortTable(BaseTable):
  817. name = tables.Column(order_by=('_name',))
  818. class Meta(BaseTable.Meta):
  819. model = FrontPort
  820. fields = ('name', 'type', 'rear_port', 'rear_port_position', 'description')
  821. empty_text = "None"
  822. class FrontPortDetailTable(DeviceComponentDetailTable):
  823. device = tables.LinkColumn()
  824. class Meta(DeviceComponentDetailTable.Meta, FrontPortTable.Meta):
  825. pass
  826. class RearPortTable(BaseTable):
  827. name = tables.Column(order_by=('_name',))
  828. class Meta(BaseTable.Meta):
  829. model = RearPort
  830. fields = ('name', 'type', 'positions', 'description')
  831. empty_text = "None"
  832. class RearPortDetailTable(DeviceComponentDetailTable):
  833. device = tables.LinkColumn()
  834. class Meta(DeviceComponentDetailTable.Meta, RearPortTable.Meta):
  835. pass
  836. class DeviceBayTable(BaseTable):
  837. name = tables.Column(order_by=('_name',))
  838. class Meta(BaseTable.Meta):
  839. model = DeviceBay
  840. fields = ('name', 'description')
  841. class DeviceBayDetailTable(DeviceComponentDetailTable):
  842. device = tables.LinkColumn()
  843. installed_device = tables.LinkColumn()
  844. class Meta(DeviceBayTable.Meta):
  845. fields = ('pk', 'name', 'device', 'installed_device', 'description')
  846. sequence = ('pk', 'name', 'device', 'installed_device', 'description')
  847. exclude = ('cable',)
  848. class DeviceBayImportTable(BaseTable):
  849. device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
  850. installed_device = tables.LinkColumn('dcim:device', args=[Accessor('installed_device.pk')], verbose_name='Installed Device')
  851. class Meta(BaseTable.Meta):
  852. model = DeviceBay
  853. fields = ('device', 'name', 'installed_device', 'description')
  854. empty_text = False
  855. #
  856. # Cables
  857. #
  858. class CableTable(BaseTable):
  859. pk = ToggleColumn()
  860. id = tables.LinkColumn(
  861. viewname='dcim:cable',
  862. args=[Accessor('pk')],
  863. verbose_name='ID'
  864. )
  865. termination_a_parent = tables.TemplateColumn(
  866. template_code=CABLE_TERMINATION_PARENT,
  867. accessor=Accessor('termination_a'),
  868. orderable=False,
  869. verbose_name='Side A'
  870. )
  871. termination_a = tables.LinkColumn(
  872. accessor=Accessor('termination_a'),
  873. orderable=False,
  874. verbose_name='Termination A'
  875. )
  876. termination_b_parent = tables.TemplateColumn(
  877. template_code=CABLE_TERMINATION_PARENT,
  878. accessor=Accessor('termination_b'),
  879. orderable=False,
  880. verbose_name='Side B'
  881. )
  882. termination_b = tables.LinkColumn(
  883. accessor=Accessor('termination_b'),
  884. orderable=False,
  885. verbose_name='Termination B'
  886. )
  887. status = tables.TemplateColumn(
  888. template_code=STATUS_LABEL
  889. )
  890. length = tables.TemplateColumn(
  891. template_code=CABLE_LENGTH,
  892. order_by='_abs_length'
  893. )
  894. color = ColorColumn()
  895. class Meta(BaseTable.Meta):
  896. model = Cable
  897. fields = (
  898. 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b',
  899. 'status', 'type', 'color', 'length',
  900. )
  901. default_columns = (
  902. 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b',
  903. 'status', 'type',
  904. )
  905. #
  906. # Device connections
  907. #
  908. class ConsoleConnectionTable(BaseTable):
  909. console_server = tables.LinkColumn(
  910. viewname='dcim:device',
  911. accessor=Accessor('connected_endpoint.device'),
  912. args=[Accessor('connected_endpoint.device.pk')],
  913. verbose_name='Console Server'
  914. )
  915. connected_endpoint = tables.Column(
  916. verbose_name='Port'
  917. )
  918. device = tables.LinkColumn(
  919. viewname='dcim:device',
  920. args=[Accessor('device.pk')]
  921. )
  922. name = tables.Column(
  923. verbose_name='Console Port'
  924. )
  925. class Meta(BaseTable.Meta):
  926. model = ConsolePort
  927. fields = ('console_server', 'connected_endpoint', 'device', 'name', 'connection_status')
  928. class PowerConnectionTable(BaseTable):
  929. pdu = tables.LinkColumn(
  930. viewname='dcim:device',
  931. accessor=Accessor('connected_endpoint.device'),
  932. args=[Accessor('connected_endpoint.device.pk')],
  933. order_by='_connected_poweroutlet__device',
  934. verbose_name='PDU'
  935. )
  936. outlet = tables.Column(
  937. accessor=Accessor('_connected_poweroutlet'),
  938. verbose_name='Outlet'
  939. )
  940. device = tables.LinkColumn(
  941. viewname='dcim:device',
  942. args=[Accessor('device.pk')]
  943. )
  944. name = tables.Column(
  945. verbose_name='Power Port'
  946. )
  947. class Meta(BaseTable.Meta):
  948. model = PowerPort
  949. fields = ('pdu', 'outlet', 'device', 'name', 'connection_status')
  950. class InterfaceConnectionTable(BaseTable):
  951. device_a = tables.LinkColumn(
  952. viewname='dcim:device',
  953. accessor=Accessor('device'),
  954. args=[Accessor('device.pk')],
  955. verbose_name='Device A'
  956. )
  957. interface_a = tables.LinkColumn(
  958. viewname='dcim:interface',
  959. accessor=Accessor('name'),
  960. args=[Accessor('pk')],
  961. verbose_name='Interface A'
  962. )
  963. description_a = tables.Column(
  964. accessor=Accessor('description'),
  965. verbose_name='Description'
  966. )
  967. device_b = tables.LinkColumn(
  968. viewname='dcim:device',
  969. accessor=Accessor('_connected_interface.device'),
  970. args=[Accessor('_connected_interface.device.pk')],
  971. verbose_name='Device B'
  972. )
  973. interface_b = tables.LinkColumn(
  974. viewname='dcim:interface',
  975. accessor=Accessor('_connected_interface'),
  976. args=[Accessor('_connected_interface.pk')],
  977. verbose_name='Interface B'
  978. )
  979. description_b = tables.Column(
  980. accessor=Accessor('_connected_interface.description'),
  981. verbose_name='Description'
  982. )
  983. class Meta(BaseTable.Meta):
  984. model = Interface
  985. fields = (
  986. 'device_a', 'interface_a', 'description_a', 'device_b', 'interface_b', 'description_b', 'connection_status',
  987. )
  988. #
  989. # InventoryItems
  990. #
  991. class InventoryItemTable(BaseTable):
  992. pk = ToggleColumn()
  993. device = tables.LinkColumn(
  994. viewname='dcim:device_inventory',
  995. args=[Accessor('device.pk')]
  996. )
  997. manufacturer = tables.Column(
  998. accessor=Accessor('manufacturer.name')
  999. )
  1000. discovered = BooleanColumn()
  1001. class Meta(BaseTable.Meta):
  1002. model = InventoryItem
  1003. fields = (
  1004. 'pk', 'device', 'name', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered'
  1005. )
  1006. default_columns = ('pk', 'device', 'name', 'manufacturer', 'part_id', 'serial', 'asset_tag')
  1007. #
  1008. # Virtual chassis
  1009. #
  1010. class VirtualChassisTable(BaseTable):
  1011. pk = ToggleColumn()
  1012. name = tables.Column(
  1013. accessor=Accessor('master__name'),
  1014. linkify=True
  1015. )
  1016. member_count = tables.Column(
  1017. verbose_name='Members'
  1018. )
  1019. class Meta(BaseTable.Meta):
  1020. model = VirtualChassis
  1021. fields = ('pk', 'name', 'domain', 'member_count')
  1022. default_columns = ('pk', 'name', 'domain', 'member_count')
  1023. #
  1024. # Power panels
  1025. #
  1026. class PowerPanelTable(BaseTable):
  1027. pk = ToggleColumn()
  1028. name = tables.LinkColumn()
  1029. site = tables.LinkColumn(
  1030. viewname='dcim:site',
  1031. args=[Accessor('site.slug')]
  1032. )
  1033. powerfeed_count = tables.TemplateColumn(
  1034. template_code=POWERPANEL_POWERFEED_COUNT,
  1035. verbose_name='Feeds'
  1036. )
  1037. class Meta(BaseTable.Meta):
  1038. model = PowerPanel
  1039. fields = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count')
  1040. default_columns = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count')
  1041. #
  1042. # Power feeds
  1043. #
  1044. class PowerFeedTable(BaseTable):
  1045. pk = ToggleColumn()
  1046. name = tables.LinkColumn()
  1047. power_panel = tables.LinkColumn(
  1048. viewname='dcim:powerpanel',
  1049. args=[Accessor('power_panel.pk')],
  1050. )
  1051. rack = tables.LinkColumn(
  1052. viewname='dcim:rack',
  1053. args=[Accessor('rack.pk')]
  1054. )
  1055. status = tables.TemplateColumn(
  1056. template_code=STATUS_LABEL
  1057. )
  1058. type = tables.TemplateColumn(
  1059. template_code=TYPE_LABEL
  1060. )
  1061. max_utilization = tables.TemplateColumn(
  1062. template_code="{{ value }}%"
  1063. )
  1064. available_power = tables.Column(
  1065. verbose_name='Available power (VA)'
  1066. )
  1067. class Meta(BaseTable.Meta):
  1068. model = PowerFeed
  1069. fields = (
  1070. 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
  1071. 'max_utilization', 'available_power',
  1072. )
  1073. default_columns = (
  1074. 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
  1075. )