tables.py 31 KB

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