filters.py 31 KB

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