tables.py 36 KB

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