tables.py 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  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.all %}
  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.Column(
  221. order_by=('_name',),
  222. linkify=True
  223. )
  224. group = tables.Column(
  225. linkify=True
  226. )
  227. site = tables.Column(
  228. linkify=True
  229. )
  230. tenant = tables.TemplateColumn(
  231. template_code=COL_TENANT
  232. )
  233. status = tables.TemplateColumn(
  234. template_code=STATUS_LABEL
  235. )
  236. role = ColoredLabelColumn()
  237. u_height = tables.TemplateColumn(
  238. template_code="{{ record.u_height }}U",
  239. verbose_name='Height'
  240. )
  241. class Meta(BaseTable.Meta):
  242. model = Rack
  243. fields = (
  244. 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type',
  245. 'width', 'u_height',
  246. )
  247. default_columns = ('pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height')
  248. class RackDetailTable(RackTable):
  249. device_count = tables.TemplateColumn(
  250. template_code=RACK_DEVICE_COUNT,
  251. verbose_name='Devices'
  252. )
  253. get_utilization = tables.TemplateColumn(
  254. template_code=UTILIZATION_GRAPH,
  255. orderable=False,
  256. verbose_name='Space'
  257. )
  258. get_power_utilization = tables.TemplateColumn(
  259. template_code=UTILIZATION_GRAPH,
  260. orderable=False,
  261. verbose_name='Power'
  262. )
  263. tags = TagColumn(
  264. url_name='dcim:rack_list'
  265. )
  266. class Meta(RackTable.Meta):
  267. fields = (
  268. 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type',
  269. 'width', 'u_height', 'device_count', 'get_utilization', 'get_power_utilization', 'tags',
  270. )
  271. default_columns = (
  272. 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height', 'device_count',
  273. 'get_utilization', 'get_power_utilization',
  274. )
  275. #
  276. # Rack reservations
  277. #
  278. class RackReservationTable(BaseTable):
  279. pk = ToggleColumn()
  280. reservation = tables.Column(
  281. accessor='pk',
  282. linkify=True
  283. )
  284. site = tables.Column(
  285. accessor=Accessor('rack__site'),
  286. linkify=True
  287. )
  288. tenant = tables.TemplateColumn(
  289. template_code=COL_TENANT
  290. )
  291. rack = tables.Column(
  292. linkify=True
  293. )
  294. unit_list = tables.Column(
  295. orderable=False,
  296. verbose_name='Units'
  297. )
  298. tags = TagColumn(
  299. url_name='dcim:rackreservation_list'
  300. )
  301. actions = ButtonsColumn(RackReservation)
  302. class Meta(BaseTable.Meta):
  303. model = RackReservation
  304. fields = (
  305. 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'tags',
  306. 'actions',
  307. )
  308. default_columns = (
  309. 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'description', 'actions',
  310. )
  311. #
  312. # Manufacturers
  313. #
  314. class ManufacturerTable(BaseTable):
  315. pk = ToggleColumn()
  316. name = tables.LinkColumn()
  317. devicetype_count = tables.Column(
  318. verbose_name='Device Types'
  319. )
  320. inventoryitem_count = tables.Column(
  321. verbose_name='Inventory Items'
  322. )
  323. platform_count = tables.Column(
  324. verbose_name='Platforms'
  325. )
  326. slug = tables.Column()
  327. actions = ButtonsColumn(Manufacturer, pk_field='slug')
  328. class Meta(BaseTable.Meta):
  329. model = Manufacturer
  330. fields = (
  331. 'pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug', 'actions',
  332. )
  333. #
  334. # Device types
  335. #
  336. class DeviceTypeTable(BaseTable):
  337. pk = ToggleColumn()
  338. model = tables.Column(
  339. linkify=True,
  340. verbose_name='Device Type'
  341. )
  342. is_full_depth = BooleanColumn(
  343. verbose_name='Full Depth'
  344. )
  345. instance_count = tables.TemplateColumn(
  346. template_code=DEVICETYPE_INSTANCES_TEMPLATE,
  347. verbose_name='Instances'
  348. )
  349. tags = TagColumn(
  350. url_name='dcim:devicetype_list'
  351. )
  352. class Meta(BaseTable.Meta):
  353. model = DeviceType
  354. fields = (
  355. 'pk', 'model', 'manufacturer', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
  356. 'instance_count', 'tags',
  357. )
  358. default_columns = (
  359. 'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'instance_count',
  360. )
  361. #
  362. # Device type components
  363. #
  364. class ComponentTemplateTable(BaseTable):
  365. pk = ToggleColumn()
  366. name = tables.Column(
  367. order_by=('_name',)
  368. )
  369. class ConsolePortTemplateTable(ComponentTemplateTable):
  370. actions = ButtonsColumn(
  371. model=ConsolePortTemplate,
  372. buttons=('edit', 'delete'),
  373. return_url_extra='%23tab_consoleports'
  374. )
  375. class Meta(BaseTable.Meta):
  376. model = ConsolePortTemplate
  377. fields = ('pk', 'name', 'label', 'type', 'description', 'actions')
  378. empty_text = "None"
  379. class ConsoleServerPortTemplateTable(ComponentTemplateTable):
  380. actions = ButtonsColumn(
  381. model=ConsoleServerPortTemplate,
  382. buttons=('edit', 'delete'),
  383. return_url_extra='%23tab_consoleserverports'
  384. )
  385. class Meta(BaseTable.Meta):
  386. model = ConsoleServerPortTemplate
  387. fields = ('pk', 'name', 'label', 'type', 'description', 'actions')
  388. empty_text = "None"
  389. class PowerPortTemplateTable(ComponentTemplateTable):
  390. actions = ButtonsColumn(
  391. model=PowerPortTemplate,
  392. buttons=('edit', 'delete'),
  393. return_url_extra='%23tab_powerports'
  394. )
  395. class Meta(BaseTable.Meta):
  396. model = PowerPortTemplate
  397. fields = ('pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'actions')
  398. empty_text = "None"
  399. class PowerOutletTemplateTable(ComponentTemplateTable):
  400. actions = ButtonsColumn(
  401. model=PowerOutletTemplate,
  402. buttons=('edit', 'delete'),
  403. return_url_extra='%23tab_poweroutlets'
  404. )
  405. class Meta(BaseTable.Meta):
  406. model = PowerOutletTemplate
  407. fields = ('pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'actions')
  408. empty_text = "None"
  409. class InterfaceTemplateTable(ComponentTemplateTable):
  410. mgmt_only = BooleanColumn(
  411. verbose_name='Management Only'
  412. )
  413. actions = ButtonsColumn(
  414. model=InterfaceTemplate,
  415. buttons=('edit', 'delete'),
  416. return_url_extra='%23tab_interfaces'
  417. )
  418. class Meta(BaseTable.Meta):
  419. model = InterfaceTemplate
  420. fields = ('pk', 'name', 'label', 'mgmt_only', 'type', 'description', 'actions')
  421. empty_text = "None"
  422. class FrontPortTemplateTable(ComponentTemplateTable):
  423. rear_port_position = tables.Column(
  424. verbose_name='Position'
  425. )
  426. actions = ButtonsColumn(
  427. model=FrontPortTemplate,
  428. buttons=('edit', 'delete'),
  429. return_url_extra='%23tab_frontports'
  430. )
  431. class Meta(BaseTable.Meta):
  432. model = FrontPortTemplate
  433. fields = ('pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'actions')
  434. empty_text = "None"
  435. class RearPortTemplateTable(ComponentTemplateTable):
  436. actions = ButtonsColumn(
  437. model=RearPortTemplate,
  438. buttons=('edit', 'delete'),
  439. return_url_extra='%23tab_rearports'
  440. )
  441. class Meta(BaseTable.Meta):
  442. model = RearPortTemplate
  443. fields = ('pk', 'name', 'label', 'type', 'positions', 'description', 'actions')
  444. empty_text = "None"
  445. class DeviceBayTemplateTable(ComponentTemplateTable):
  446. actions = ButtonsColumn(
  447. model=DeviceBayTemplate,
  448. buttons=('edit', 'delete'),
  449. return_url_extra='%23tab_devicebays'
  450. )
  451. class Meta(BaseTable.Meta):
  452. model = DeviceBayTemplate
  453. fields = ('pk', 'name', 'label', 'description', 'actions')
  454. empty_text = "None"
  455. #
  456. # Device roles
  457. #
  458. class DeviceRoleTable(BaseTable):
  459. pk = ToggleColumn()
  460. device_count = tables.TemplateColumn(
  461. template_code=DEVICEROLE_DEVICE_COUNT,
  462. verbose_name='Devices'
  463. )
  464. vm_count = tables.TemplateColumn(
  465. template_code=DEVICEROLE_VM_COUNT,
  466. verbose_name='VMs'
  467. )
  468. color = tables.TemplateColumn(
  469. template_code=COLOR_LABEL,
  470. verbose_name='Label'
  471. )
  472. vm_role = BooleanColumn()
  473. actions = ButtonsColumn(DeviceRole, pk_field='slug')
  474. class Meta(BaseTable.Meta):
  475. model = DeviceRole
  476. fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions')
  477. default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'actions')
  478. #
  479. # Platforms
  480. #
  481. class PlatformTable(BaseTable):
  482. pk = ToggleColumn()
  483. device_count = tables.TemplateColumn(
  484. template_code=PLATFORM_DEVICE_COUNT,
  485. verbose_name='Devices'
  486. )
  487. vm_count = tables.TemplateColumn(
  488. template_code=PLATFORM_VM_COUNT,
  489. verbose_name='VMs'
  490. )
  491. actions = ButtonsColumn(Platform, pk_field='slug')
  492. class Meta(BaseTable.Meta):
  493. model = Platform
  494. fields = (
  495. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args',
  496. 'description', 'actions',
  497. )
  498. default_columns = (
  499. 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'napalm_driver', 'description', 'actions',
  500. )
  501. #
  502. # Devices
  503. #
  504. class DeviceTable(BaseTable):
  505. pk = ToggleColumn()
  506. name = tables.TemplateColumn(
  507. order_by=('_name',),
  508. template_code=DEVICE_LINK
  509. )
  510. status = tables.TemplateColumn(
  511. template_code=STATUS_LABEL
  512. )
  513. tenant = tables.TemplateColumn(
  514. template_code=COL_TENANT
  515. )
  516. site = tables.Column(
  517. linkify=True
  518. )
  519. rack = tables.Column(
  520. linkify=True
  521. )
  522. device_role = ColoredLabelColumn(
  523. verbose_name='Role'
  524. )
  525. device_type = tables.LinkColumn(
  526. viewname='dcim:devicetype',
  527. args=[Accessor('device_type__pk')],
  528. verbose_name='Type',
  529. text=lambda record: record.device_type.display_name
  530. )
  531. primary_ip = tables.TemplateColumn(
  532. template_code=DEVICE_PRIMARY_IP,
  533. orderable=False,
  534. verbose_name='IP Address'
  535. )
  536. primary_ip4 = tables.Column(
  537. linkify=True,
  538. verbose_name='IPv4 Address'
  539. )
  540. primary_ip6 = tables.Column(
  541. linkify=True,
  542. verbose_name='IPv6 Address'
  543. )
  544. cluster = tables.LinkColumn(
  545. viewname='virtualization:cluster',
  546. args=[Accessor('cluster__pk')]
  547. )
  548. virtual_chassis = tables.LinkColumn(
  549. viewname='dcim:virtualchassis',
  550. args=[Accessor('virtual_chassis__pk')]
  551. )
  552. vc_position = tables.Column(
  553. verbose_name='VC Position'
  554. )
  555. vc_priority = tables.Column(
  556. verbose_name='VC Priority'
  557. )
  558. tags = TagColumn(
  559. url_name='dcim:device_list'
  560. )
  561. class Meta(BaseTable.Meta):
  562. model = Device
  563. fields = (
  564. 'pk', 'name', 'status', 'tenant', 'device_role', 'device_type', 'platform', 'serial', 'asset_tag', 'site',
  565. 'rack', 'position', 'face', 'primary_ip', 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis',
  566. 'vc_position', 'vc_priority', 'tags',
  567. )
  568. default_columns = (
  569. 'pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip',
  570. )
  571. class DeviceImportTable(BaseTable):
  572. name = tables.TemplateColumn(
  573. template_code=DEVICE_LINK
  574. )
  575. status = tables.TemplateColumn(
  576. template_code=STATUS_LABEL
  577. )
  578. tenant = tables.TemplateColumn(
  579. template_code=COL_TENANT
  580. )
  581. site = tables.Column(
  582. linkify=True
  583. )
  584. rack = tables.Column(
  585. linkify=True
  586. )
  587. device_role = tables.Column(
  588. verbose_name='Role'
  589. )
  590. device_type = tables.Column(
  591. verbose_name='Type'
  592. )
  593. class Meta(BaseTable.Meta):
  594. model = Device
  595. fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
  596. empty_text = False
  597. #
  598. # Device components
  599. #
  600. class DeviceComponentTable(BaseTable):
  601. pk = ToggleColumn()
  602. device = tables.Column(
  603. linkify=True
  604. )
  605. name = tables.Column(
  606. linkify=True,
  607. order_by=('_name',)
  608. )
  609. cable = tables.Column(
  610. linkify=True
  611. )
  612. class Meta(BaseTable.Meta):
  613. order_by = ('device', 'name')
  614. class ConsolePortTable(DeviceComponentTable):
  615. tags = TagColumn(
  616. url_name='dcim:consoleport_list'
  617. )
  618. class Meta(DeviceComponentTable.Meta):
  619. model = ConsolePort
  620. fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags')
  621. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  622. class ConsoleServerPortTable(DeviceComponentTable):
  623. tags = TagColumn(
  624. url_name='dcim:consoleserverport_list'
  625. )
  626. class Meta(DeviceComponentTable.Meta):
  627. model = ConsoleServerPort
  628. fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags')
  629. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  630. class PowerPortTable(DeviceComponentTable):
  631. tags = TagColumn(
  632. url_name='dcim:powerport_list'
  633. )
  634. class Meta(DeviceComponentTable.Meta):
  635. model = PowerPort
  636. fields = (
  637. 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable', 'tags',
  638. )
  639. default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
  640. class PowerOutletTable(DeviceComponentTable):
  641. tags = TagColumn(
  642. url_name='dcim:poweroutlet_list'
  643. )
  644. class Meta(DeviceComponentTable.Meta):
  645. model = PowerOutlet
  646. fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'tags')
  647. default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description')
  648. class BaseInterfaceTable(BaseTable):
  649. enabled = BooleanColumn()
  650. ip_addresses = tables.TemplateColumn(
  651. template_code=INTERFACE_IPADDRESSES,
  652. orderable=False,
  653. verbose_name='IP Addresses'
  654. )
  655. untagged_vlan = tables.Column(linkify=True)
  656. tagged_vlans = tables.TemplateColumn(
  657. template_code=INTERFACE_TAGGED_VLANS,
  658. orderable=False,
  659. verbose_name='Tagged VLANs'
  660. )
  661. class InterfaceTable(DeviceComponentTable, BaseInterfaceTable):
  662. tags = TagColumn(
  663. url_name='dcim:interface_list'
  664. )
  665. class Meta(DeviceComponentTable.Meta):
  666. model = Interface
  667. fields = (
  668. 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address',
  669. 'description', 'cable', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans',
  670. )
  671. default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description')
  672. class FrontPortTable(DeviceComponentTable):
  673. rear_port_position = tables.Column(
  674. verbose_name='Position'
  675. )
  676. tags = TagColumn(
  677. url_name='dcim:frontport_list'
  678. )
  679. class Meta(DeviceComponentTable.Meta):
  680. model = FrontPort
  681. fields = (
  682. 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'tags',
  683. )
  684. default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description')
  685. class RearPortTable(DeviceComponentTable):
  686. tags = TagColumn(
  687. url_name='dcim:rearport_list'
  688. )
  689. class Meta(DeviceComponentTable.Meta):
  690. model = RearPort
  691. fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'tags')
  692. default_columns = ('pk', 'device', 'name', 'label', 'type', 'description')
  693. class DeviceBayTable(DeviceComponentTable):
  694. installed_device = tables.Column(
  695. linkify=True
  696. )
  697. tags = TagColumn(
  698. url_name='dcim:devicebay_list'
  699. )
  700. class Meta(DeviceComponentTable.Meta):
  701. model = DeviceBay
  702. fields = ('pk', 'device', 'name', 'label', 'installed_device', 'description', 'tags')
  703. default_columns = ('pk', 'device', 'name', 'label', 'installed_device', 'description')
  704. class InventoryItemTable(DeviceComponentTable):
  705. manufacturer = tables.Column(
  706. linkify=True
  707. )
  708. discovered = BooleanColumn()
  709. tags = TagColumn(
  710. url_name='dcim:inventoryitem_list'
  711. )
  712. cable = None # Override DeviceComponentTable
  713. class Meta(DeviceComponentTable.Meta):
  714. model = InventoryItem
  715. fields = (
  716. 'pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description',
  717. 'discovered', 'tags',
  718. )
  719. default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag')
  720. #
  721. # Cables
  722. #
  723. class CableTable(BaseTable):
  724. pk = ToggleColumn()
  725. id = tables.Column(
  726. linkify=True,
  727. verbose_name='ID'
  728. )
  729. termination_a_parent = tables.TemplateColumn(
  730. template_code=CABLE_TERMINATION_PARENT,
  731. accessor=Accessor('termination_a'),
  732. orderable=False,
  733. verbose_name='Side A'
  734. )
  735. termination_a = tables.LinkColumn(
  736. accessor=Accessor('termination_a'),
  737. orderable=False,
  738. verbose_name='Termination A'
  739. )
  740. termination_b_parent = tables.TemplateColumn(
  741. template_code=CABLE_TERMINATION_PARENT,
  742. accessor=Accessor('termination_b'),
  743. orderable=False,
  744. verbose_name='Side B'
  745. )
  746. termination_b = tables.LinkColumn(
  747. accessor=Accessor('termination_b'),
  748. orderable=False,
  749. verbose_name='Termination B'
  750. )
  751. status = tables.TemplateColumn(
  752. template_code=STATUS_LABEL
  753. )
  754. length = tables.TemplateColumn(
  755. template_code=CABLE_LENGTH,
  756. order_by='_abs_length'
  757. )
  758. color = ColorColumn()
  759. tags = TagColumn(
  760. url_name='dcim:cable_list'
  761. )
  762. class Meta(BaseTable.Meta):
  763. model = Cable
  764. fields = (
  765. 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b',
  766. 'status', 'type', 'color', 'length', 'tags',
  767. )
  768. default_columns = (
  769. 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b',
  770. 'status', 'type',
  771. )
  772. #
  773. # Device connections
  774. #
  775. class ConsoleConnectionTable(BaseTable):
  776. console_server = tables.LinkColumn(
  777. viewname='dcim:device',
  778. accessor=Accessor('connected_endpoint__device'),
  779. args=[Accessor('connected_endpoint__device__pk')],
  780. verbose_name='Console Server'
  781. )
  782. connected_endpoint = tables.Column(
  783. linkify=True,
  784. verbose_name='Port'
  785. )
  786. device = tables.Column(
  787. linkify=True
  788. )
  789. name = tables.Column(
  790. linkify=True,
  791. verbose_name='Console Port'
  792. )
  793. connection_status = tables.TemplateColumn(
  794. template_code=CONNECTION_STATUS,
  795. verbose_name='Status'
  796. )
  797. class Meta(BaseTable.Meta):
  798. model = ConsolePort
  799. fields = ('console_server', 'connected_endpoint', 'device', 'name', 'connection_status')
  800. class PowerConnectionTable(BaseTable):
  801. pdu = tables.LinkColumn(
  802. viewname='dcim:device',
  803. accessor=Accessor('connected_endpoint__device'),
  804. args=[Accessor('connected_endpoint__device__pk')],
  805. order_by='_connected_poweroutlet__device',
  806. verbose_name='PDU'
  807. )
  808. outlet = tables.Column(
  809. accessor=Accessor('_connected_poweroutlet'),
  810. linkify=True,
  811. verbose_name='Outlet'
  812. )
  813. device = tables.Column(
  814. linkify=True
  815. )
  816. name = tables.Column(
  817. linkify=True,
  818. verbose_name='Power Port'
  819. )
  820. connection_status = tables.TemplateColumn(
  821. template_code=CONNECTION_STATUS,
  822. verbose_name='Status'
  823. )
  824. class Meta(BaseTable.Meta):
  825. model = PowerPort
  826. fields = ('pdu', 'outlet', 'device', 'name', 'connection_status')
  827. class InterfaceConnectionTable(BaseTable):
  828. device_a = tables.LinkColumn(
  829. viewname='dcim:device',
  830. accessor=Accessor('device'),
  831. args=[Accessor('device__pk')],
  832. verbose_name='Device A'
  833. )
  834. interface_a = tables.LinkColumn(
  835. viewname='dcim:interface',
  836. accessor=Accessor('name'),
  837. args=[Accessor('pk')],
  838. verbose_name='Interface A'
  839. )
  840. device_b = tables.LinkColumn(
  841. viewname='dcim:device',
  842. accessor=Accessor('_connected_interface__device'),
  843. args=[Accessor('_connected_interface__device__pk')],
  844. verbose_name='Device B'
  845. )
  846. interface_b = tables.LinkColumn(
  847. viewname='dcim:interface',
  848. accessor=Accessor('_connected_interface'),
  849. args=[Accessor('_connected_interface__pk')],
  850. verbose_name='Interface B'
  851. )
  852. connection_status = tables.TemplateColumn(
  853. template_code=CONNECTION_STATUS,
  854. verbose_name='Status'
  855. )
  856. class Meta(BaseTable.Meta):
  857. model = Interface
  858. fields = (
  859. 'device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status',
  860. )
  861. #
  862. # Virtual chassis
  863. #
  864. class VirtualChassisTable(BaseTable):
  865. pk = ToggleColumn()
  866. name = tables.Column(
  867. linkify=True
  868. )
  869. master = tables.Column(
  870. linkify=True
  871. )
  872. member_count = tables.Column(
  873. verbose_name='Members'
  874. )
  875. tags = TagColumn(
  876. url_name='dcim:virtualchassis_list'
  877. )
  878. class Meta(BaseTable.Meta):
  879. model = VirtualChassis
  880. fields = ('pk', 'name', 'domain', 'master', 'member_count', 'tags')
  881. default_columns = ('pk', 'name', 'domain', 'master', 'member_count')
  882. #
  883. # Power panels
  884. #
  885. class PowerPanelTable(BaseTable):
  886. pk = ToggleColumn()
  887. name = tables.LinkColumn()
  888. site = tables.LinkColumn(
  889. viewname='dcim:site',
  890. args=[Accessor('site__slug')]
  891. )
  892. powerfeed_count = tables.TemplateColumn(
  893. template_code=POWERPANEL_POWERFEED_COUNT,
  894. verbose_name='Feeds'
  895. )
  896. tags = TagColumn(
  897. url_name='dcim:powerpanel_list'
  898. )
  899. class Meta(BaseTable.Meta):
  900. model = PowerPanel
  901. fields = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count', 'tags')
  902. default_columns = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count')
  903. #
  904. # Power feeds
  905. #
  906. class PowerFeedTable(BaseTable):
  907. pk = ToggleColumn()
  908. name = tables.LinkColumn()
  909. power_panel = tables.Column(
  910. linkify=True
  911. )
  912. rack = tables.Column(
  913. linkify=True
  914. )
  915. status = tables.TemplateColumn(
  916. template_code=STATUS_LABEL
  917. )
  918. type = tables.TemplateColumn(
  919. template_code=TYPE_LABEL
  920. )
  921. max_utilization = tables.TemplateColumn(
  922. template_code="{{ value }}%"
  923. )
  924. available_power = tables.Column(
  925. verbose_name='Available power (VA)'
  926. )
  927. tags = TagColumn(
  928. url_name='dcim:powerfeed_list'
  929. )
  930. class Meta(BaseTable.Meta):
  931. model = PowerFeed
  932. fields = (
  933. 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
  934. 'max_utilization', 'available_power', 'tags',
  935. )
  936. default_columns = (
  937. 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
  938. )