tables.py 33 KB

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