filters.py 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. import django_filters
  2. from django.contrib.auth.models import User
  3. from django.db.models import Q
  4. from extras.filters import CustomFieldFilterSet, LocalConfigContextFilter
  5. from tenancy.filtersets import TenancyFilterSet
  6. from tenancy.models import Tenant
  7. from utilities.constants import COLOR_CHOICES
  8. from utilities.filters import (
  9. MultiValueMACAddressFilter, MultiValueNumberFilter, NameSlugSearchFilterSet, NumericInFilter, TagFilter,
  10. TreeNodeMultipleChoiceFilter,
  11. )
  12. from virtualization.models import Cluster
  13. from .constants import *
  14. from .models import (
  15. Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
  16. DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate,
  17. InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort,
  18. PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
  19. VirtualChassis,
  20. )
  21. class RegionFilter(NameSlugSearchFilterSet):
  22. parent_id = django_filters.ModelMultipleChoiceFilter(
  23. queryset=Region.objects.all(),
  24. label='Parent region (ID)',
  25. )
  26. parent = django_filters.ModelMultipleChoiceFilter(
  27. field_name='parent__slug',
  28. queryset=Region.objects.all(),
  29. to_field_name='slug',
  30. label='Parent region (slug)',
  31. )
  32. class Meta:
  33. model = Region
  34. fields = ['id', 'name', 'slug']
  35. class SiteFilter(TenancyFilterSet, CustomFieldFilterSet):
  36. id__in = NumericInFilter(
  37. field_name='id',
  38. lookup_expr='in'
  39. )
  40. q = django_filters.CharFilter(
  41. method='search',
  42. label='Search',
  43. )
  44. status = django_filters.MultipleChoiceFilter(
  45. choices=SITE_STATUS_CHOICES,
  46. null_value=None
  47. )
  48. region_id = TreeNodeMultipleChoiceFilter(
  49. queryset=Region.objects.all(),
  50. field_name='region__in',
  51. label='Region (ID)',
  52. )
  53. region = TreeNodeMultipleChoiceFilter(
  54. queryset=Region.objects.all(),
  55. field_name='region__in',
  56. to_field_name='slug',
  57. label='Region (slug)',
  58. )
  59. tag = TagFilter()
  60. class Meta:
  61. model = Site
  62. fields = [
  63. 'id', 'name', 'slug', 'facility', 'asn', 'latitude', 'longitude', 'contact_name', 'contact_phone',
  64. 'contact_email',
  65. ]
  66. def search(self, queryset, name, value):
  67. if not value.strip():
  68. return queryset
  69. qs_filter = (
  70. Q(name__icontains=value) |
  71. Q(facility__icontains=value) |
  72. Q(description__icontains=value) |
  73. Q(physical_address__icontains=value) |
  74. Q(shipping_address__icontains=value) |
  75. Q(contact_name__icontains=value) |
  76. Q(contact_phone__icontains=value) |
  77. Q(contact_email__icontains=value) |
  78. Q(comments__icontains=value)
  79. )
  80. try:
  81. qs_filter |= Q(asn=int(value.strip()))
  82. except ValueError:
  83. pass
  84. return queryset.filter(qs_filter)
  85. class RackGroupFilter(NameSlugSearchFilterSet):
  86. site_id = django_filters.ModelMultipleChoiceFilter(
  87. queryset=Site.objects.all(),
  88. label='Site (ID)',
  89. )
  90. site = django_filters.ModelMultipleChoiceFilter(
  91. field_name='site__slug',
  92. queryset=Site.objects.all(),
  93. to_field_name='slug',
  94. label='Site (slug)',
  95. )
  96. class Meta:
  97. model = RackGroup
  98. fields = ['id', 'name', 'slug']
  99. class RackRoleFilter(NameSlugSearchFilterSet):
  100. class Meta:
  101. model = RackRole
  102. fields = ['id', 'name', 'slug', 'color']
  103. class RackFilter(TenancyFilterSet, CustomFieldFilterSet):
  104. id__in = NumericInFilter(
  105. field_name='id',
  106. lookup_expr='in'
  107. )
  108. q = django_filters.CharFilter(
  109. method='search',
  110. label='Search',
  111. )
  112. site_id = django_filters.ModelMultipleChoiceFilter(
  113. queryset=Site.objects.all(),
  114. label='Site (ID)',
  115. )
  116. site = django_filters.ModelMultipleChoiceFilter(
  117. field_name='site__slug',
  118. queryset=Site.objects.all(),
  119. to_field_name='slug',
  120. label='Site (slug)',
  121. )
  122. group_id = django_filters.ModelMultipleChoiceFilter(
  123. queryset=RackGroup.objects.all(),
  124. label='Group (ID)',
  125. )
  126. group = django_filters.ModelMultipleChoiceFilter(
  127. field_name='group__slug',
  128. queryset=RackGroup.objects.all(),
  129. to_field_name='slug',
  130. label='Group',
  131. )
  132. status = django_filters.MultipleChoiceFilter(
  133. choices=RACK_STATUS_CHOICES,
  134. null_value=None
  135. )
  136. role_id = django_filters.ModelMultipleChoiceFilter(
  137. queryset=RackRole.objects.all(),
  138. label='Role (ID)',
  139. )
  140. role = django_filters.ModelMultipleChoiceFilter(
  141. field_name='role__slug',
  142. queryset=RackRole.objects.all(),
  143. to_field_name='slug',
  144. label='Role (slug)',
  145. )
  146. serial = django_filters.CharFilter(
  147. lookup_expr='iexact'
  148. )
  149. tag = TagFilter()
  150. class Meta:
  151. model = Rack
  152. fields = [
  153. 'id', 'name', 'facility_id', 'asset_tag', 'type', 'width', 'u_height', 'desc_units',
  154. 'outer_width', 'outer_depth', 'outer_unit',
  155. ]
  156. def search(self, queryset, name, value):
  157. if not value.strip():
  158. return queryset
  159. return queryset.filter(
  160. Q(name__icontains=value) |
  161. Q(facility_id__icontains=value) |
  162. Q(serial__icontains=value.strip()) |
  163. Q(asset_tag__icontains=value.strip()) |
  164. Q(comments__icontains=value)
  165. )
  166. class RackReservationFilter(TenancyFilterSet):
  167. id__in = NumericInFilter(
  168. field_name='id',
  169. lookup_expr='in'
  170. )
  171. q = django_filters.CharFilter(
  172. method='search',
  173. label='Search',
  174. )
  175. rack_id = django_filters.ModelMultipleChoiceFilter(
  176. queryset=Rack.objects.all(),
  177. label='Rack (ID)',
  178. )
  179. site_id = django_filters.ModelMultipleChoiceFilter(
  180. field_name='rack__site',
  181. queryset=Site.objects.all(),
  182. label='Site (ID)',
  183. )
  184. site = django_filters.ModelMultipleChoiceFilter(
  185. field_name='rack__site__slug',
  186. queryset=Site.objects.all(),
  187. to_field_name='slug',
  188. label='Site (slug)',
  189. )
  190. group_id = django_filters.ModelMultipleChoiceFilter(
  191. field_name='rack__group',
  192. queryset=RackGroup.objects.all(),
  193. label='Group (ID)',
  194. )
  195. group = django_filters.ModelMultipleChoiceFilter(
  196. field_name='rack__group__slug',
  197. queryset=RackGroup.objects.all(),
  198. to_field_name='slug',
  199. label='Group',
  200. )
  201. user_id = django_filters.ModelMultipleChoiceFilter(
  202. queryset=User.objects.all(),
  203. label='User (ID)',
  204. )
  205. user = django_filters.ModelMultipleChoiceFilter(
  206. field_name='user',
  207. queryset=User.objects.all(),
  208. to_field_name='username',
  209. label='User (name)',
  210. )
  211. class Meta:
  212. model = RackReservation
  213. fields = ['created']
  214. def search(self, queryset, name, value):
  215. if not value.strip():
  216. return queryset
  217. return queryset.filter(
  218. Q(rack__name__icontains=value) |
  219. Q(rack__facility_id__icontains=value) |
  220. Q(user__username__icontains=value) |
  221. Q(description__icontains=value)
  222. )
  223. class ManufacturerFilter(NameSlugSearchFilterSet):
  224. class Meta:
  225. model = Manufacturer
  226. fields = ['id', 'name', 'slug']
  227. class DeviceTypeFilter(CustomFieldFilterSet):
  228. id__in = NumericInFilter(
  229. field_name='id',
  230. lookup_expr='in'
  231. )
  232. q = django_filters.CharFilter(
  233. method='search',
  234. label='Search',
  235. )
  236. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  237. queryset=Manufacturer.objects.all(),
  238. label='Manufacturer (ID)',
  239. )
  240. manufacturer = django_filters.ModelMultipleChoiceFilter(
  241. field_name='manufacturer__slug',
  242. queryset=Manufacturer.objects.all(),
  243. to_field_name='slug',
  244. label='Manufacturer (slug)',
  245. )
  246. console_ports = django_filters.BooleanFilter(
  247. method='_console_ports',
  248. label='Has console ports',
  249. )
  250. console_server_ports = django_filters.BooleanFilter(
  251. method='_console_server_ports',
  252. label='Has console server ports',
  253. )
  254. power_ports = django_filters.BooleanFilter(
  255. method='_power_ports',
  256. label='Has power ports',
  257. )
  258. power_outlets = django_filters.BooleanFilter(
  259. method='_power_outlets',
  260. label='Has power outlets',
  261. )
  262. interfaces = django_filters.BooleanFilter(
  263. method='_interfaces',
  264. label='Has interfaces',
  265. )
  266. pass_through_ports = django_filters.BooleanFilter(
  267. method='_pass_through_ports',
  268. label='Has pass-through ports',
  269. )
  270. tag = TagFilter()
  271. class Meta:
  272. model = DeviceType
  273. fields = [
  274. 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
  275. ]
  276. def search(self, queryset, name, value):
  277. if not value.strip():
  278. return queryset
  279. return queryset.filter(
  280. Q(manufacturer__name__icontains=value) |
  281. Q(model__icontains=value) |
  282. Q(part_number__icontains=value) |
  283. Q(comments__icontains=value)
  284. )
  285. def _console_ports(self, queryset, name, value):
  286. return queryset.exclude(consoleport_templates__isnull=value)
  287. def _console_server_ports(self, queryset, name, value):
  288. return queryset.exclude(consoleserverport_templates__isnull=value)
  289. def _power_ports(self, queryset, name, value):
  290. return queryset.exclude(powerport_templates__isnull=value)
  291. def _power_outlets(self, queryset, name, value):
  292. return queryset.exclude(poweroutlet_templates__isnull=value)
  293. def _interfaces(self, queryset, name, value):
  294. return queryset.exclude(interface_templates__isnull=value)
  295. def _pass_through_ports(self, queryset, name, value):
  296. return queryset.exclude(
  297. frontport_templates__isnull=value,
  298. rearport_templates__isnull=value
  299. )
  300. class DeviceTypeComponentFilterSet(NameSlugSearchFilterSet):
  301. devicetype_id = django_filters.ModelMultipleChoiceFilter(
  302. queryset=DeviceType.objects.all(),
  303. field_name='device_type_id',
  304. label='Device type (ID)',
  305. )
  306. class ConsolePortTemplateFilter(DeviceTypeComponentFilterSet):
  307. class Meta:
  308. model = ConsolePortTemplate
  309. fields = ['id', 'name']
  310. class ConsoleServerPortTemplateFilter(DeviceTypeComponentFilterSet):
  311. class Meta:
  312. model = ConsoleServerPortTemplate
  313. fields = ['id', 'name']
  314. class PowerPortTemplateFilter(DeviceTypeComponentFilterSet):
  315. class Meta:
  316. model = PowerPortTemplate
  317. fields = ['id', 'name', 'maximum_draw', 'allocated_draw']
  318. class PowerOutletTemplateFilter(DeviceTypeComponentFilterSet):
  319. class Meta:
  320. model = PowerOutletTemplate
  321. fields = ['id', 'name', 'feed_leg']
  322. class InterfaceTemplateFilter(DeviceTypeComponentFilterSet):
  323. class Meta:
  324. model = InterfaceTemplate
  325. fields = ['id', 'name', 'type', 'mgmt_only']
  326. class FrontPortTemplateFilter(DeviceTypeComponentFilterSet):
  327. class Meta:
  328. model = FrontPortTemplate
  329. fields = ['id', 'name', 'type']
  330. class RearPortTemplateFilter(DeviceTypeComponentFilterSet):
  331. class Meta:
  332. model = RearPortTemplate
  333. fields = ['id', 'name', 'type', 'positions']
  334. class DeviceBayTemplateFilter(DeviceTypeComponentFilterSet):
  335. class Meta:
  336. model = DeviceBayTemplate
  337. fields = ['id', 'name']
  338. class DeviceRoleFilter(NameSlugSearchFilterSet):
  339. class Meta:
  340. model = DeviceRole
  341. fields = ['id', 'name', 'slug', 'color', 'vm_role']
  342. class PlatformFilter(NameSlugSearchFilterSet):
  343. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  344. field_name='manufacturer',
  345. queryset=Manufacturer.objects.all(),
  346. label='Manufacturer (ID)',
  347. )
  348. manufacturer = django_filters.ModelMultipleChoiceFilter(
  349. field_name='manufacturer__slug',
  350. queryset=Manufacturer.objects.all(),
  351. to_field_name='slug',
  352. label='Manufacturer (slug)',
  353. )
  354. class Meta:
  355. model = Platform
  356. fields = ['id', 'name', 'slug', 'napalm_driver']
  357. class DeviceFilter(LocalConfigContextFilter, TenancyFilterSet, CustomFieldFilterSet):
  358. id__in = NumericInFilter(
  359. field_name='id',
  360. lookup_expr='in'
  361. )
  362. q = django_filters.CharFilter(
  363. method='search',
  364. label='Search',
  365. )
  366. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  367. field_name='device_type__manufacturer',
  368. queryset=Manufacturer.objects.all(),
  369. label='Manufacturer (ID)',
  370. )
  371. manufacturer = django_filters.ModelMultipleChoiceFilter(
  372. field_name='device_type__manufacturer__slug',
  373. queryset=Manufacturer.objects.all(),
  374. to_field_name='slug',
  375. label='Manufacturer (slug)',
  376. )
  377. device_type_id = django_filters.ModelMultipleChoiceFilter(
  378. queryset=DeviceType.objects.all(),
  379. label='Device type (ID)',
  380. )
  381. role_id = django_filters.ModelMultipleChoiceFilter(
  382. field_name='device_role_id',
  383. queryset=DeviceRole.objects.all(),
  384. label='Role (ID)',
  385. )
  386. role = django_filters.ModelMultipleChoiceFilter(
  387. field_name='device_role__slug',
  388. queryset=DeviceRole.objects.all(),
  389. to_field_name='slug',
  390. label='Role (slug)',
  391. )
  392. platform_id = django_filters.ModelMultipleChoiceFilter(
  393. queryset=Platform.objects.all(),
  394. label='Platform (ID)',
  395. )
  396. platform = django_filters.ModelMultipleChoiceFilter(
  397. field_name='platform__slug',
  398. queryset=Platform.objects.all(),
  399. to_field_name='slug',
  400. label='Platform (slug)',
  401. )
  402. region_id = TreeNodeMultipleChoiceFilter(
  403. queryset=Region.objects.all(),
  404. field_name='site__region__in',
  405. label='Region (ID)',
  406. )
  407. region = TreeNodeMultipleChoiceFilter(
  408. queryset=Region.objects.all(),
  409. field_name='site__region__in',
  410. to_field_name='slug',
  411. label='Region (slug)',
  412. )
  413. site_id = django_filters.ModelMultipleChoiceFilter(
  414. queryset=Site.objects.all(),
  415. label='Site (ID)',
  416. )
  417. site = django_filters.ModelMultipleChoiceFilter(
  418. field_name='site__slug',
  419. queryset=Site.objects.all(),
  420. to_field_name='slug',
  421. label='Site name (slug)',
  422. )
  423. rack_group_id = django_filters.ModelMultipleChoiceFilter(
  424. field_name='rack__group',
  425. queryset=RackGroup.objects.all(),
  426. label='Rack group (ID)',
  427. )
  428. rack_id = django_filters.ModelMultipleChoiceFilter(
  429. field_name='rack',
  430. queryset=Rack.objects.all(),
  431. label='Rack (ID)',
  432. )
  433. cluster_id = django_filters.ModelMultipleChoiceFilter(
  434. queryset=Cluster.objects.all(),
  435. label='VM cluster (ID)',
  436. )
  437. model = django_filters.ModelMultipleChoiceFilter(
  438. field_name='device_type__slug',
  439. queryset=DeviceType.objects.all(),
  440. to_field_name='slug',
  441. label='Device model (slug)',
  442. )
  443. status = django_filters.MultipleChoiceFilter(
  444. choices=DEVICE_STATUS_CHOICES,
  445. null_value=None
  446. )
  447. is_full_depth = django_filters.BooleanFilter(
  448. field_name='device_type__is_full_depth',
  449. label='Is full depth',
  450. )
  451. mac_address = MultiValueMACAddressFilter(
  452. field_name='interfaces__mac_address',
  453. label='MAC address',
  454. )
  455. serial = django_filters.CharFilter(
  456. lookup_expr='iexact'
  457. )
  458. has_primary_ip = django_filters.BooleanFilter(
  459. method='_has_primary_ip',
  460. label='Has a primary IP',
  461. )
  462. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  463. field_name='virtual_chassis',
  464. queryset=VirtualChassis.objects.all(),
  465. label='Virtual chassis (ID)',
  466. )
  467. virtual_chassis_member = django_filters.BooleanFilter(
  468. method='_virtual_chassis_member',
  469. label='Is a virtual chassis member'
  470. )
  471. console_ports = django_filters.BooleanFilter(
  472. method='_console_ports',
  473. label='Has console ports',
  474. )
  475. console_server_ports = django_filters.BooleanFilter(
  476. method='_console_server_ports',
  477. label='Has console server ports',
  478. )
  479. power_ports = django_filters.BooleanFilter(
  480. method='_power_ports',
  481. label='Has power ports',
  482. )
  483. power_outlets = django_filters.BooleanFilter(
  484. method='_power_outlets',
  485. label='Has power outlets',
  486. )
  487. interfaces = django_filters.BooleanFilter(
  488. method='_interfaces',
  489. label='Has interfaces',
  490. )
  491. pass_through_ports = django_filters.BooleanFilter(
  492. method='_pass_through_ports',
  493. label='Has pass-through ports',
  494. )
  495. tag = TagFilter()
  496. class Meta:
  497. model = Device
  498. fields = ['id', 'name', 'asset_tag', 'face', 'position', 'vc_position', 'vc_priority']
  499. def search(self, queryset, name, value):
  500. if not value.strip():
  501. return queryset
  502. return queryset.filter(
  503. Q(name__icontains=value) |
  504. Q(serial__icontains=value.strip()) |
  505. Q(inventory_items__serial__icontains=value.strip()) |
  506. Q(asset_tag__icontains=value.strip()) |
  507. Q(comments__icontains=value)
  508. ).distinct()
  509. def _has_primary_ip(self, queryset, name, value):
  510. if value:
  511. return queryset.filter(
  512. Q(primary_ip4__isnull=False) |
  513. Q(primary_ip6__isnull=False)
  514. )
  515. else:
  516. return queryset.exclude(
  517. Q(primary_ip4__isnull=False) |
  518. Q(primary_ip6__isnull=False)
  519. )
  520. def _virtual_chassis_member(self, queryset, name, value):
  521. return queryset.exclude(virtual_chassis__isnull=value)
  522. def _console_ports(self, queryset, name, value):
  523. return queryset.exclude(consoleports__isnull=value)
  524. def _console_server_ports(self, queryset, name, value):
  525. return queryset.exclude(consoleserverports__isnull=value)
  526. def _power_ports(self, queryset, name, value):
  527. return queryset.exclude(powerports__isnull=value)
  528. def _power_outlets(self, queryset, name, value):
  529. return queryset.exclude(poweroutlets__isnull=value)
  530. def _interfaces(self, queryset, name, value):
  531. return queryset.exclude(interfaces__isnull=value)
  532. def _pass_through_ports(self, queryset, name, value):
  533. return queryset.exclude(
  534. frontports__isnull=value,
  535. rearports__isnull=value
  536. )
  537. class DeviceComponentFilterSet(django_filters.FilterSet):
  538. q = django_filters.CharFilter(
  539. method='search',
  540. label='Search',
  541. )
  542. device_id = django_filters.ModelMultipleChoiceFilter(
  543. queryset=Device.objects.all(),
  544. label='Device (ID)',
  545. )
  546. device = django_filters.ModelChoiceFilter(
  547. queryset=Device.objects.all(),
  548. to_field_name='name',
  549. label='Device (name)',
  550. )
  551. tag = TagFilter()
  552. def search(self, queryset, name, value):
  553. if not value.strip():
  554. return queryset
  555. return queryset.filter(
  556. Q(name__icontains=value) |
  557. Q(description__icontains=value)
  558. )
  559. class ConsolePortFilter(DeviceComponentFilterSet):
  560. cabled = django_filters.BooleanFilter(
  561. field_name='cable',
  562. lookup_expr='isnull',
  563. exclude=True
  564. )
  565. class Meta:
  566. model = ConsolePort
  567. fields = ['id', 'name', 'description', 'connection_status']
  568. class ConsoleServerPortFilter(DeviceComponentFilterSet):
  569. cabled = django_filters.BooleanFilter(
  570. field_name='cable',
  571. lookup_expr='isnull',
  572. exclude=True
  573. )
  574. class Meta:
  575. model = ConsoleServerPort
  576. fields = ['id', 'name', 'description', 'connection_status']
  577. class PowerPortFilter(DeviceComponentFilterSet):
  578. cabled = django_filters.BooleanFilter(
  579. field_name='cable',
  580. lookup_expr='isnull',
  581. exclude=True
  582. )
  583. class Meta:
  584. model = PowerPort
  585. fields = ['id', 'name', 'maximum_draw', 'allocated_draw', 'description', 'connection_status']
  586. class PowerOutletFilter(DeviceComponentFilterSet):
  587. cabled = django_filters.BooleanFilter(
  588. field_name='cable',
  589. lookup_expr='isnull',
  590. exclude=True
  591. )
  592. class Meta:
  593. model = PowerOutlet
  594. fields = ['id', 'name', 'feed_leg', 'description', 'connection_status']
  595. class InterfaceFilter(django_filters.FilterSet):
  596. """
  597. Not using DeviceComponentFilterSet for Interfaces because we need to check for VirtualChassis membership.
  598. """
  599. q = django_filters.CharFilter(
  600. method='search',
  601. label='Search',
  602. )
  603. device = django_filters.CharFilter(
  604. method='filter_device',
  605. field_name='name',
  606. label='Device',
  607. )
  608. device_id = MultiValueNumberFilter(
  609. method='filter_device_id',
  610. field_name='pk',
  611. label='Device (ID)',
  612. )
  613. cabled = django_filters.BooleanFilter(
  614. field_name='cable',
  615. lookup_expr='isnull',
  616. exclude=True
  617. )
  618. kind = django_filters.CharFilter(
  619. method='filter_kind',
  620. label='Kind of interface',
  621. )
  622. lag_id = django_filters.ModelMultipleChoiceFilter(
  623. field_name='lag',
  624. queryset=Interface.objects.all(),
  625. label='LAG interface (ID)',
  626. )
  627. mac_address = MultiValueMACAddressFilter()
  628. tag = TagFilter()
  629. vlan_id = django_filters.CharFilter(
  630. method='filter_vlan_id',
  631. label='Assigned VLAN'
  632. )
  633. vlan = django_filters.CharFilter(
  634. method='filter_vlan',
  635. label='Assigned VID'
  636. )
  637. type = django_filters.MultipleChoiceFilter(
  638. choices=IFACE_TYPE_CHOICES,
  639. null_value=None
  640. )
  641. class Meta:
  642. model = Interface
  643. fields = ['id', 'name', 'connection_status', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'description']
  644. def search(self, queryset, name, value):
  645. if not value.strip():
  646. return queryset
  647. return queryset.filter(
  648. Q(name__icontains=value) |
  649. Q(description__icontains=value)
  650. ).distinct()
  651. def filter_device(self, queryset, name, value):
  652. try:
  653. device = Device.objects.get(**{name: value})
  654. vc_interface_ids = device.vc_interfaces.values_list('id', flat=True)
  655. return queryset.filter(pk__in=vc_interface_ids)
  656. except Device.DoesNotExist:
  657. return queryset.none()
  658. def filter_device_id(self, queryset, name, id_list):
  659. # Include interfaces belonging to peer virtual chassis members
  660. vc_interface_ids = []
  661. try:
  662. devices = Device.objects.filter(pk__in=id_list)
  663. for device in devices:
  664. vc_interface_ids += device.vc_interfaces.values_list('id', flat=True)
  665. return queryset.filter(pk__in=vc_interface_ids)
  666. except Device.DoesNotExist:
  667. return queryset.none()
  668. def filter_vlan_id(self, queryset, name, value):
  669. value = value.strip()
  670. if not value:
  671. return queryset
  672. return queryset.filter(
  673. Q(untagged_vlan_id=value) |
  674. Q(tagged_vlans=value)
  675. )
  676. def filter_vlan(self, queryset, name, value):
  677. value = value.strip()
  678. if not value:
  679. return queryset
  680. return queryset.filter(
  681. Q(untagged_vlan_id__vid=value) |
  682. Q(tagged_vlans__vid=value)
  683. )
  684. def filter_kind(self, queryset, name, value):
  685. value = value.strip().lower()
  686. return {
  687. 'physical': queryset.exclude(type__in=NONCONNECTABLE_IFACE_TYPES),
  688. 'virtual': queryset.filter(type__in=VIRTUAL_IFACE_TYPES),
  689. 'wireless': queryset.filter(type__in=WIRELESS_IFACE_TYPES),
  690. }.get(value, queryset.none())
  691. class FrontPortFilter(DeviceComponentFilterSet):
  692. cabled = django_filters.BooleanFilter(
  693. field_name='cable',
  694. lookup_expr='isnull',
  695. exclude=True
  696. )
  697. class Meta:
  698. model = FrontPort
  699. fields = ['id', 'name', 'type', 'description']
  700. class RearPortFilter(DeviceComponentFilterSet):
  701. cabled = django_filters.BooleanFilter(
  702. field_name='cable',
  703. lookup_expr='isnull',
  704. exclude=True
  705. )
  706. class Meta:
  707. model = RearPort
  708. fields = ['id', 'name', 'type', 'positions', 'description']
  709. class DeviceBayFilter(DeviceComponentFilterSet):
  710. class Meta:
  711. model = DeviceBay
  712. fields = ['id', 'name', 'description']
  713. class InventoryItemFilter(DeviceComponentFilterSet):
  714. q = django_filters.CharFilter(
  715. method='search',
  716. label='Search',
  717. )
  718. device_id = django_filters.ModelChoiceFilter(
  719. queryset=Device.objects.all(),
  720. label='Device (ID)',
  721. )
  722. device = django_filters.ModelChoiceFilter(
  723. queryset=Device.objects.all(),
  724. to_field_name='name',
  725. label='Device (name)',
  726. )
  727. parent_id = django_filters.ModelMultipleChoiceFilter(
  728. queryset=InventoryItem.objects.all(),
  729. label='Parent inventory item (ID)',
  730. )
  731. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  732. queryset=Manufacturer.objects.all(),
  733. label='Manufacturer (ID)',
  734. )
  735. manufacturer = django_filters.ModelMultipleChoiceFilter(
  736. field_name='manufacturer__slug',
  737. queryset=Manufacturer.objects.all(),
  738. to_field_name='slug',
  739. label='Manufacturer (slug)',
  740. )
  741. serial = django_filters.CharFilter(
  742. lookup_expr='iexact'
  743. )
  744. class Meta:
  745. model = InventoryItem
  746. fields = ['id', 'name', 'part_id', 'asset_tag', 'discovered']
  747. def search(self, queryset, name, value):
  748. if not value.strip():
  749. return queryset
  750. qs_filter = (
  751. Q(name__icontains=value) |
  752. Q(part_id__icontains=value) |
  753. Q(serial__iexact=value) |
  754. Q(asset_tag__iexact=value) |
  755. Q(description__icontains=value)
  756. )
  757. return queryset.filter(qs_filter)
  758. class VirtualChassisFilter(django_filters.FilterSet):
  759. q = django_filters.CharFilter(
  760. method='search',
  761. label='Search',
  762. )
  763. site_id = django_filters.ModelMultipleChoiceFilter(
  764. field_name='master__site',
  765. queryset=Site.objects.all(),
  766. label='Site (ID)',
  767. )
  768. site = django_filters.ModelMultipleChoiceFilter(
  769. field_name='master__site__slug',
  770. queryset=Site.objects.all(),
  771. to_field_name='slug',
  772. label='Site name (slug)',
  773. )
  774. tenant_id = django_filters.ModelMultipleChoiceFilter(
  775. field_name='master__tenant',
  776. queryset=Tenant.objects.all(),
  777. label='Tenant (ID)',
  778. )
  779. tenant = django_filters.ModelMultipleChoiceFilter(
  780. field_name='master__tenant__slug',
  781. queryset=Tenant.objects.all(),
  782. to_field_name='slug',
  783. label='Tenant (slug)',
  784. )
  785. tag = TagFilter()
  786. class Meta:
  787. model = VirtualChassis
  788. fields = ['id', 'domain']
  789. def search(self, queryset, name, value):
  790. if not value.strip():
  791. return queryset
  792. qs_filter = (
  793. Q(master__name__icontains=value) |
  794. Q(domain__icontains=value)
  795. )
  796. return queryset.filter(qs_filter)
  797. class CableFilter(django_filters.FilterSet):
  798. q = django_filters.CharFilter(
  799. method='search',
  800. label='Search',
  801. )
  802. type = django_filters.MultipleChoiceFilter(
  803. choices=CABLE_TYPE_CHOICES
  804. )
  805. status = django_filters.MultipleChoiceFilter(
  806. choices=CONNECTION_STATUS_CHOICES
  807. )
  808. color = django_filters.MultipleChoiceFilter(
  809. choices=COLOR_CHOICES
  810. )
  811. device_id = MultiValueNumberFilter(
  812. method='filter_device'
  813. )
  814. device = MultiValueNumberFilter(
  815. method='filter_device',
  816. field_name='device__name'
  817. )
  818. rack_id = MultiValueNumberFilter(
  819. method='filter_device',
  820. field_name='device__rack_id'
  821. )
  822. rack = MultiValueNumberFilter(
  823. method='filter_device',
  824. field_name='device__rack__name'
  825. )
  826. site_id = MultiValueNumberFilter(
  827. method='filter_device',
  828. field_name='device__site_id'
  829. )
  830. site = MultiValueNumberFilter(
  831. method='filter_device',
  832. field_name='device__site__slug'
  833. )
  834. class Meta:
  835. model = Cable
  836. fields = ['id', 'label', 'length', 'length_unit']
  837. def search(self, queryset, name, value):
  838. if not value.strip():
  839. return queryset
  840. return queryset.filter(label__icontains=value)
  841. def filter_device(self, queryset, name, value):
  842. queryset = queryset.filter(
  843. Q(**{'_termination_a_{}__in'.format(name): value}) |
  844. Q(**{'_termination_b_{}__in'.format(name): value})
  845. )
  846. return queryset
  847. class ConsoleConnectionFilter(django_filters.FilterSet):
  848. site = django_filters.CharFilter(
  849. method='filter_site',
  850. label='Site (slug)',
  851. )
  852. device = django_filters.CharFilter(
  853. method='filter_device',
  854. label='Device',
  855. )
  856. class Meta:
  857. model = ConsolePort
  858. fields = ['name', 'connection_status']
  859. def filter_site(self, queryset, name, value):
  860. if not value.strip():
  861. return queryset
  862. return queryset.filter(connected_endpoint__device__site__slug=value)
  863. def filter_device(self, queryset, name, value):
  864. if not value.strip():
  865. return queryset
  866. return queryset.filter(
  867. Q(device__name__icontains=value) |
  868. Q(connected_endpoint__device__name__icontains=value)
  869. )
  870. class PowerConnectionFilter(django_filters.FilterSet):
  871. site = django_filters.CharFilter(
  872. method='filter_site',
  873. label='Site (slug)',
  874. )
  875. device = django_filters.CharFilter(
  876. method='filter_device',
  877. label='Device',
  878. )
  879. class Meta:
  880. model = PowerPort
  881. fields = ['name', 'connection_status']
  882. def filter_site(self, queryset, name, value):
  883. if not value.strip():
  884. return queryset
  885. return queryset.filter(_connected_poweroutlet__device__site__slug=value)
  886. def filter_device(self, queryset, name, value):
  887. if not value.strip():
  888. return queryset
  889. return queryset.filter(
  890. Q(device__name__icontains=value) |
  891. Q(_connected_poweroutlet__device__name__icontains=value)
  892. )
  893. class InterfaceConnectionFilter(django_filters.FilterSet):
  894. site = django_filters.CharFilter(
  895. method='filter_site',
  896. label='Site (slug)',
  897. )
  898. device = django_filters.CharFilter(
  899. method='filter_device',
  900. label='Device',
  901. )
  902. class Meta:
  903. model = Interface
  904. fields = ['connection_status']
  905. def filter_site(self, queryset, name, value):
  906. if not value.strip():
  907. return queryset
  908. return queryset.filter(
  909. Q(device__site__slug=value) |
  910. Q(_connected_interface__device__site__slug=value)
  911. )
  912. def filter_device(self, queryset, name, value):
  913. if not value.strip():
  914. return queryset
  915. return queryset.filter(
  916. Q(device__name__icontains=value) |
  917. Q(_connected_interface__device__name__icontains=value)
  918. )
  919. class PowerPanelFilter(django_filters.FilterSet):
  920. id__in = NumericInFilter(
  921. field_name='id',
  922. lookup_expr='in'
  923. )
  924. q = django_filters.CharFilter(
  925. method='search',
  926. label='Search',
  927. )
  928. site_id = django_filters.ModelMultipleChoiceFilter(
  929. queryset=Site.objects.all(),
  930. label='Site (ID)',
  931. )
  932. site = django_filters.ModelMultipleChoiceFilter(
  933. field_name='site__slug',
  934. queryset=Site.objects.all(),
  935. to_field_name='slug',
  936. label='Site name (slug)',
  937. )
  938. rack_group_id = django_filters.ModelMultipleChoiceFilter(
  939. field_name='rack_group',
  940. queryset=RackGroup.objects.all(),
  941. label='Rack group (ID)',
  942. )
  943. class Meta:
  944. model = PowerPanel
  945. fields = ['name']
  946. def search(self, queryset, name, value):
  947. if not value.strip():
  948. return queryset
  949. qs_filter = (
  950. Q(name__icontains=value)
  951. )
  952. return queryset.filter(qs_filter)
  953. class PowerFeedFilter(CustomFieldFilterSet):
  954. id__in = NumericInFilter(
  955. field_name='id',
  956. lookup_expr='in'
  957. )
  958. q = django_filters.CharFilter(
  959. method='search',
  960. label='Search',
  961. )
  962. site_id = django_filters.ModelMultipleChoiceFilter(
  963. field_name='power_panel__site',
  964. queryset=Site.objects.all(),
  965. label='Site (ID)',
  966. )
  967. site = django_filters.ModelMultipleChoiceFilter(
  968. field_name='power_panel__site__slug',
  969. queryset=Site.objects.all(),
  970. to_field_name='slug',
  971. label='Site name (slug)',
  972. )
  973. power_panel_id = django_filters.ModelMultipleChoiceFilter(
  974. queryset=PowerPanel.objects.all(),
  975. label='Power panel (ID)',
  976. )
  977. rack_id = django_filters.ModelMultipleChoiceFilter(
  978. field_name='rack',
  979. queryset=Rack.objects.all(),
  980. label='Rack (ID)',
  981. )
  982. tag = TagFilter()
  983. class Meta:
  984. model = PowerFeed
  985. fields = ['name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization']
  986. def search(self, queryset, name, value):
  987. if not value.strip():
  988. return queryset
  989. qs_filter = (
  990. Q(name__icontains=value) |
  991. Q(comments__icontains=value)
  992. )
  993. return queryset.filter(qs_filter)