tables.py 29 KB

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