tables.py 33 KB

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