tables.py 30 KB

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