filters.py 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333
  1. import django_filters
  2. from django.contrib.auth.models import User
  3. from extras.filters import CustomFieldFilterSet, LocalConfigContextFilterSet, CreatedUpdatedFilterSet
  4. from tenancy.filters import TenancyFilterSet
  5. from tenancy.models import Tenant
  6. from utilities.choices import ColorChoices
  7. from utilities.filters import (
  8. BaseFilterSet, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter,
  9. NameSlugSearchFilterSet, TagFilter, TreeNodeMultipleChoiceFilter,
  10. )
  11. from virtualization.models import Cluster
  12. from .choices import *
  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. __all__ = (
  22. 'CableFilterSet',
  23. 'ConsoleConnectionFilterSet',
  24. 'ConsolePortFilterSet',
  25. 'ConsolePortTemplateFilterSet',
  26. 'ConsoleServerPortFilterSet',
  27. 'ConsoleServerPortTemplateFilterSet',
  28. 'DeviceBayFilterSet',
  29. 'DeviceBayTemplateFilterSet',
  30. 'DeviceFilterSet',
  31. 'DeviceRoleFilterSet',
  32. 'DeviceTypeFilterSet',
  33. 'FrontPortFilterSet',
  34. 'FrontPortTemplateFilterSet',
  35. 'InterfaceConnectionFilterSet',
  36. 'InterfaceFilterSet',
  37. 'InterfaceTemplateFilterSet',
  38. 'InventoryItemFilterSet',
  39. 'ManufacturerFilterSet',
  40. 'PlatformFilterSet',
  41. 'PowerConnectionFilterSet',
  42. 'PowerFeedFilterSet',
  43. 'PowerOutletFilterSet',
  44. 'PowerOutletTemplateFilterSet',
  45. 'PowerPanelFilterSet',
  46. 'PowerPortFilterSet',
  47. 'PowerPortTemplateFilterSet',
  48. 'RackFilterSet',
  49. 'RackGroupFilterSet',
  50. 'RackReservationFilterSet',
  51. 'RackRoleFilterSet',
  52. 'RearPortFilterSet',
  53. 'RearPortTemplateFilterSet',
  54. 'RegionFilterSet',
  55. 'SiteFilterSet',
  56. 'VirtualChassisFilterSet',
  57. )
  58. class RegionFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  59. parent_id = django_filters.ModelMultipleChoiceFilter(
  60. queryset=Region.objects.all(),
  61. label='Parent region (ID)',
  62. )
  63. parent = django_filters.ModelMultipleChoiceFilter(
  64. field_name='parent__slug',
  65. queryset=Region.objects.all(),
  66. to_field_name='slug',
  67. label='Parent region (slug)',
  68. )
  69. class Meta:
  70. model = Region
  71. fields = ['id', 'name', 'slug', 'description']
  72. class SiteFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
  73. q = django_filters.CharFilter(
  74. method='search',
  75. label='Search',
  76. )
  77. status = django_filters.MultipleChoiceFilter(
  78. choices=SiteStatusChoices,
  79. null_value=None
  80. )
  81. region_id = TreeNodeMultipleChoiceFilter(
  82. queryset=Region.objects.all(),
  83. field_name='region',
  84. lookup_expr='in',
  85. label='Region (ID)',
  86. )
  87. region = TreeNodeMultipleChoiceFilter(
  88. queryset=Region.objects.all(),
  89. field_name='region',
  90. lookup_expr='in',
  91. to_field_name='slug',
  92. label='Region (slug)',
  93. )
  94. tag = TagFilter()
  95. class Meta:
  96. model = Site
  97. fields = [
  98. 'id', 'name', 'slug', 'facility', 'asn', 'latitude', 'longitude', 'contact_name', 'contact_phone',
  99. 'contact_email',
  100. ]
  101. def search(self, queryset, name, value):
  102. if not value.strip():
  103. return queryset
  104. qs_filter = (
  105. Q(name__icontains=value) |
  106. Q(facility__icontains=value) |
  107. Q(description__icontains=value) |
  108. Q(physical_address__icontains=value) |
  109. Q(shipping_address__icontains=value) |
  110. Q(contact_name__icontains=value) |
  111. Q(contact_phone__icontains=value) |
  112. Q(contact_email__icontains=value) |
  113. Q(comments__icontains=value)
  114. )
  115. try:
  116. qs_filter |= Q(asn=int(value.strip()))
  117. except ValueError:
  118. pass
  119. return queryset.filter(qs_filter)
  120. class RackGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  121. region_id = TreeNodeMultipleChoiceFilter(
  122. queryset=Region.objects.all(),
  123. field_name='site__region',
  124. lookup_expr='in',
  125. label='Region (ID)',
  126. )
  127. region = TreeNodeMultipleChoiceFilter(
  128. queryset=Region.objects.all(),
  129. field_name='site__region',
  130. lookup_expr='in',
  131. to_field_name='slug',
  132. label='Region (slug)',
  133. )
  134. site_id = django_filters.ModelMultipleChoiceFilter(
  135. queryset=Site.objects.all(),
  136. label='Site (ID)',
  137. )
  138. site = django_filters.ModelMultipleChoiceFilter(
  139. field_name='site__slug',
  140. queryset=Site.objects.all(),
  141. to_field_name='slug',
  142. label='Site (slug)',
  143. )
  144. parent_id = django_filters.ModelMultipleChoiceFilter(
  145. queryset=RackGroup.objects.all(),
  146. label='Rack group (ID)',
  147. )
  148. parent = django_filters.ModelMultipleChoiceFilter(
  149. field_name='parent__slug',
  150. queryset=RackGroup.objects.all(),
  151. to_field_name='slug',
  152. label='Rack group (slug)',
  153. )
  154. class Meta:
  155. model = RackGroup
  156. fields = ['id', 'name', 'slug', 'description']
  157. class RackRoleFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  158. class Meta:
  159. model = RackRole
  160. fields = ['id', 'name', 'slug', 'color']
  161. class RackFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
  162. q = django_filters.CharFilter(
  163. method='search',
  164. label='Search',
  165. )
  166. region_id = TreeNodeMultipleChoiceFilter(
  167. queryset=Region.objects.all(),
  168. field_name='site__region',
  169. lookup_expr='in',
  170. label='Region (ID)',
  171. )
  172. region = TreeNodeMultipleChoiceFilter(
  173. queryset=Region.objects.all(),
  174. field_name='site__region',
  175. lookup_expr='in',
  176. to_field_name='slug',
  177. label='Region (slug)',
  178. )
  179. site_id = django_filters.ModelMultipleChoiceFilter(
  180. queryset=Site.objects.all(),
  181. label='Site (ID)',
  182. )
  183. site = django_filters.ModelMultipleChoiceFilter(
  184. field_name='site__slug',
  185. queryset=Site.objects.all(),
  186. to_field_name='slug',
  187. label='Site (slug)',
  188. )
  189. group_id = TreeNodeMultipleChoiceFilter(
  190. queryset=RackGroup.objects.all(),
  191. field_name='group',
  192. lookup_expr='in',
  193. label='Rack group (ID)',
  194. )
  195. group = TreeNodeMultipleChoiceFilter(
  196. queryset=RackGroup.objects.all(),
  197. field_name='group',
  198. lookup_expr='in',
  199. to_field_name='slug',
  200. label='Rack group (slug)',
  201. )
  202. status = django_filters.MultipleChoiceFilter(
  203. choices=RackStatusChoices,
  204. null_value=None
  205. )
  206. role_id = django_filters.ModelMultipleChoiceFilter(
  207. queryset=RackRole.objects.all(),
  208. label='Role (ID)',
  209. )
  210. role = django_filters.ModelMultipleChoiceFilter(
  211. field_name='role__slug',
  212. queryset=RackRole.objects.all(),
  213. to_field_name='slug',
  214. label='Role (slug)',
  215. )
  216. serial = django_filters.CharFilter(
  217. lookup_expr='iexact'
  218. )
  219. tag = TagFilter()
  220. class Meta:
  221. model = Rack
  222. fields = [
  223. 'id', 'name', 'facility_id', 'asset_tag', 'type', 'width', 'u_height', 'desc_units',
  224. 'outer_width', 'outer_depth', 'outer_unit',
  225. ]
  226. def search(self, queryset, name, value):
  227. if not value.strip():
  228. return queryset
  229. return queryset.filter(
  230. Q(name__icontains=value) |
  231. Q(facility_id__icontains=value) |
  232. Q(serial__icontains=value.strip()) |
  233. Q(asset_tag__icontains=value.strip()) |
  234. Q(comments__icontains=value)
  235. )
  236. class RackReservationFilterSet(BaseFilterSet, TenancyFilterSet):
  237. q = django_filters.CharFilter(
  238. method='search',
  239. label='Search',
  240. )
  241. rack_id = django_filters.ModelMultipleChoiceFilter(
  242. queryset=Rack.objects.all(),
  243. label='Rack (ID)',
  244. )
  245. site_id = django_filters.ModelMultipleChoiceFilter(
  246. field_name='rack__site',
  247. queryset=Site.objects.all(),
  248. label='Site (ID)',
  249. )
  250. site = django_filters.ModelMultipleChoiceFilter(
  251. field_name='rack__site__slug',
  252. queryset=Site.objects.all(),
  253. to_field_name='slug',
  254. label='Site (slug)',
  255. )
  256. group_id = TreeNodeMultipleChoiceFilter(
  257. queryset=RackGroup.objects.all(),
  258. field_name='rack__group',
  259. lookup_expr='in',
  260. label='Rack group (ID)',
  261. )
  262. group = TreeNodeMultipleChoiceFilter(
  263. queryset=RackGroup.objects.all(),
  264. field_name='rack__group',
  265. lookup_expr='in',
  266. to_field_name='slug',
  267. label='Rack group (slug)',
  268. )
  269. user_id = django_filters.ModelMultipleChoiceFilter(
  270. queryset=User.objects.all(),
  271. label='User (ID)',
  272. )
  273. user = django_filters.ModelMultipleChoiceFilter(
  274. field_name='user',
  275. queryset=User.objects.all(),
  276. to_field_name='username',
  277. label='User (name)',
  278. )
  279. class Meta:
  280. model = RackReservation
  281. fields = ['id', 'created']
  282. def search(self, queryset, name, value):
  283. if not value.strip():
  284. return queryset
  285. return queryset.filter(
  286. Q(rack__name__icontains=value) |
  287. Q(rack__facility_id__icontains=value) |
  288. Q(user__username__icontains=value) |
  289. Q(description__icontains=value)
  290. )
  291. class ManufacturerFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  292. class Meta:
  293. model = Manufacturer
  294. fields = ['id', 'name', 'slug', 'description']
  295. class DeviceTypeFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
  296. q = django_filters.CharFilter(
  297. method='search',
  298. label='Search',
  299. )
  300. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  301. queryset=Manufacturer.objects.all(),
  302. label='Manufacturer (ID)',
  303. )
  304. manufacturer = django_filters.ModelMultipleChoiceFilter(
  305. field_name='manufacturer__slug',
  306. queryset=Manufacturer.objects.all(),
  307. to_field_name='slug',
  308. label='Manufacturer (slug)',
  309. )
  310. console_ports = django_filters.BooleanFilter(
  311. method='_console_ports',
  312. label='Has console ports',
  313. )
  314. console_server_ports = django_filters.BooleanFilter(
  315. method='_console_server_ports',
  316. label='Has console server ports',
  317. )
  318. power_ports = django_filters.BooleanFilter(
  319. method='_power_ports',
  320. label='Has power ports',
  321. )
  322. power_outlets = django_filters.BooleanFilter(
  323. method='_power_outlets',
  324. label='Has power outlets',
  325. )
  326. interfaces = django_filters.BooleanFilter(
  327. method='_interfaces',
  328. label='Has interfaces',
  329. )
  330. pass_through_ports = django_filters.BooleanFilter(
  331. method='_pass_through_ports',
  332. label='Has pass-through ports',
  333. )
  334. device_bays = django_filters.BooleanFilter(
  335. method='_device_bays',
  336. label='Has device bays',
  337. )
  338. tag = TagFilter()
  339. class Meta:
  340. model = DeviceType
  341. fields = [
  342. 'id', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
  343. ]
  344. def search(self, queryset, name, value):
  345. if not value.strip():
  346. return queryset
  347. return queryset.filter(
  348. Q(manufacturer__name__icontains=value) |
  349. Q(model__icontains=value) |
  350. Q(part_number__icontains=value) |
  351. Q(comments__icontains=value)
  352. )
  353. def _console_ports(self, queryset, name, value):
  354. return queryset.exclude(consoleport_templates__isnull=value)
  355. def _console_server_ports(self, queryset, name, value):
  356. return queryset.exclude(consoleserverport_templates__isnull=value)
  357. def _power_ports(self, queryset, name, value):
  358. return queryset.exclude(powerport_templates__isnull=value)
  359. def _power_outlets(self, queryset, name, value):
  360. return queryset.exclude(poweroutlet_templates__isnull=value)
  361. def _interfaces(self, queryset, name, value):
  362. return queryset.exclude(interface_templates__isnull=value)
  363. def _pass_through_ports(self, queryset, name, value):
  364. return queryset.exclude(
  365. frontport_templates__isnull=value,
  366. rearport_templates__isnull=value
  367. )
  368. def _device_bays(self, queryset, name, value):
  369. return queryset.exclude(device_bay_templates__isnull=value)
  370. class DeviceTypeComponentFilterSet(NameSlugSearchFilterSet):
  371. devicetype_id = django_filters.ModelMultipleChoiceFilter(
  372. queryset=DeviceType.objects.all(),
  373. field_name='device_type_id',
  374. label='Device type (ID)',
  375. )
  376. class ConsolePortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  377. class Meta:
  378. model = ConsolePortTemplate
  379. fields = ['id', 'name', 'type']
  380. class ConsoleServerPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  381. class Meta:
  382. model = ConsoleServerPortTemplate
  383. fields = ['id', 'name', 'type']
  384. class PowerPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  385. class Meta:
  386. model = PowerPortTemplate
  387. fields = ['id', 'name', 'type', 'maximum_draw', 'allocated_draw']
  388. class PowerOutletTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  389. class Meta:
  390. model = PowerOutletTemplate
  391. fields = ['id', 'name', 'type', 'feed_leg']
  392. class InterfaceTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  393. class Meta:
  394. model = InterfaceTemplate
  395. fields = ['id', 'name', 'type', 'mgmt_only']
  396. class FrontPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  397. class Meta:
  398. model = FrontPortTemplate
  399. fields = ['id', 'name', 'type']
  400. class RearPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  401. class Meta:
  402. model = RearPortTemplate
  403. fields = ['id', 'name', 'type', 'positions']
  404. class DeviceBayTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  405. class Meta:
  406. model = DeviceBayTemplate
  407. fields = ['id', 'name']
  408. class DeviceRoleFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  409. class Meta:
  410. model = DeviceRole
  411. fields = ['id', 'name', 'slug', 'color', 'vm_role']
  412. class PlatformFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  413. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  414. field_name='manufacturer',
  415. queryset=Manufacturer.objects.all(),
  416. label='Manufacturer (ID)',
  417. )
  418. manufacturer = django_filters.ModelMultipleChoiceFilter(
  419. field_name='manufacturer__slug',
  420. queryset=Manufacturer.objects.all(),
  421. to_field_name='slug',
  422. label='Manufacturer (slug)',
  423. )
  424. class Meta:
  425. model = Platform
  426. fields = ['id', 'name', 'slug', 'napalm_driver', 'description']
  427. class DeviceFilterSet(
  428. BaseFilterSet,
  429. TenancyFilterSet,
  430. LocalConfigContextFilterSet,
  431. CustomFieldFilterSet,
  432. CreatedUpdatedFilterSet
  433. ):
  434. q = django_filters.CharFilter(
  435. method='search',
  436. label='Search',
  437. )
  438. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  439. field_name='device_type__manufacturer',
  440. queryset=Manufacturer.objects.all(),
  441. label='Manufacturer (ID)',
  442. )
  443. manufacturer = django_filters.ModelMultipleChoiceFilter(
  444. field_name='device_type__manufacturer__slug',
  445. queryset=Manufacturer.objects.all(),
  446. to_field_name='slug',
  447. label='Manufacturer (slug)',
  448. )
  449. device_type_id = django_filters.ModelMultipleChoiceFilter(
  450. queryset=DeviceType.objects.all(),
  451. label='Device type (ID)',
  452. )
  453. role_id = django_filters.ModelMultipleChoiceFilter(
  454. field_name='device_role_id',
  455. queryset=DeviceRole.objects.all(),
  456. label='Role (ID)',
  457. )
  458. role = django_filters.ModelMultipleChoiceFilter(
  459. field_name='device_role__slug',
  460. queryset=DeviceRole.objects.all(),
  461. to_field_name='slug',
  462. label='Role (slug)',
  463. )
  464. platform_id = django_filters.ModelMultipleChoiceFilter(
  465. queryset=Platform.objects.all(),
  466. label='Platform (ID)',
  467. )
  468. platform = django_filters.ModelMultipleChoiceFilter(
  469. field_name='platform__slug',
  470. queryset=Platform.objects.all(),
  471. to_field_name='slug',
  472. label='Platform (slug)',
  473. )
  474. region_id = TreeNodeMultipleChoiceFilter(
  475. queryset=Region.objects.all(),
  476. field_name='site__region',
  477. lookup_expr='in',
  478. label='Region (ID)',
  479. )
  480. region = TreeNodeMultipleChoiceFilter(
  481. queryset=Region.objects.all(),
  482. field_name='site__region',
  483. lookup_expr='in',
  484. to_field_name='slug',
  485. label='Region (slug)',
  486. )
  487. site_id = django_filters.ModelMultipleChoiceFilter(
  488. queryset=Site.objects.all(),
  489. label='Site (ID)',
  490. )
  491. site = django_filters.ModelMultipleChoiceFilter(
  492. field_name='site__slug',
  493. queryset=Site.objects.all(),
  494. to_field_name='slug',
  495. label='Site name (slug)',
  496. )
  497. rack_group_id = TreeNodeMultipleChoiceFilter(
  498. queryset=RackGroup.objects.all(),
  499. field_name='rack__group',
  500. lookup_expr='in',
  501. label='Rack group (ID)',
  502. )
  503. rack_id = django_filters.ModelMultipleChoiceFilter(
  504. field_name='rack',
  505. queryset=Rack.objects.all(),
  506. label='Rack (ID)',
  507. )
  508. cluster_id = django_filters.ModelMultipleChoiceFilter(
  509. queryset=Cluster.objects.all(),
  510. label='VM cluster (ID)',
  511. )
  512. model = django_filters.ModelMultipleChoiceFilter(
  513. field_name='device_type__slug',
  514. queryset=DeviceType.objects.all(),
  515. to_field_name='slug',
  516. label='Device model (slug)',
  517. )
  518. status = django_filters.MultipleChoiceFilter(
  519. choices=DeviceStatusChoices,
  520. null_value=None
  521. )
  522. is_full_depth = django_filters.BooleanFilter(
  523. field_name='device_type__is_full_depth',
  524. label='Is full depth',
  525. )
  526. mac_address = MultiValueMACAddressFilter(
  527. field_name='interfaces__mac_address',
  528. label='MAC address',
  529. )
  530. serial = django_filters.CharFilter(
  531. lookup_expr='iexact'
  532. )
  533. has_primary_ip = django_filters.BooleanFilter(
  534. method='_has_primary_ip',
  535. label='Has a primary IP',
  536. )
  537. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  538. field_name='virtual_chassis',
  539. queryset=VirtualChassis.objects.all(),
  540. label='Virtual chassis (ID)',
  541. )
  542. virtual_chassis_member = django_filters.BooleanFilter(
  543. method='_virtual_chassis_member',
  544. label='Is a virtual chassis member'
  545. )
  546. console_ports = django_filters.BooleanFilter(
  547. method='_console_ports',
  548. label='Has console ports',
  549. )
  550. console_server_ports = django_filters.BooleanFilter(
  551. method='_console_server_ports',
  552. label='Has console server ports',
  553. )
  554. power_ports = django_filters.BooleanFilter(
  555. method='_power_ports',
  556. label='Has power ports',
  557. )
  558. power_outlets = django_filters.BooleanFilter(
  559. method='_power_outlets',
  560. label='Has power outlets',
  561. )
  562. interfaces = django_filters.BooleanFilter(
  563. method='_interfaces',
  564. label='Has interfaces',
  565. )
  566. pass_through_ports = django_filters.BooleanFilter(
  567. method='_pass_through_ports',
  568. label='Has pass-through ports',
  569. )
  570. device_bays = django_filters.BooleanFilter(
  571. method='_device_bays',
  572. label='Has device bays',
  573. )
  574. tag = TagFilter()
  575. class Meta:
  576. model = Device
  577. fields = ['id', 'name', 'asset_tag', 'face', 'position', 'vc_position', 'vc_priority']
  578. def search(self, queryset, name, value):
  579. if not value.strip():
  580. return queryset
  581. return queryset.filter(
  582. Q(name__icontains=value) |
  583. Q(serial__icontains=value.strip()) |
  584. Q(inventory_items__serial__icontains=value.strip()) |
  585. Q(asset_tag__icontains=value.strip()) |
  586. Q(comments__icontains=value)
  587. ).distinct()
  588. def _has_primary_ip(self, queryset, name, value):
  589. if value:
  590. return queryset.filter(
  591. Q(primary_ip4__isnull=False) |
  592. Q(primary_ip6__isnull=False)
  593. )
  594. else:
  595. return queryset.exclude(
  596. Q(primary_ip4__isnull=False) |
  597. Q(primary_ip6__isnull=False)
  598. )
  599. def _virtual_chassis_member(self, queryset, name, value):
  600. return queryset.exclude(virtual_chassis__isnull=value)
  601. def _console_ports(self, queryset, name, value):
  602. return queryset.exclude(consoleports__isnull=value)
  603. def _console_server_ports(self, queryset, name, value):
  604. return queryset.exclude(consoleserverports__isnull=value)
  605. def _power_ports(self, queryset, name, value):
  606. return queryset.exclude(powerports__isnull=value)
  607. def _power_outlets(self, queryset, name, value):
  608. return queryset.exclude(poweroutlets__isnull=value)
  609. def _interfaces(self, queryset, name, value):
  610. return queryset.exclude(interfaces__isnull=value)
  611. def _pass_through_ports(self, queryset, name, value):
  612. return queryset.exclude(
  613. frontports__isnull=value,
  614. rearports__isnull=value
  615. )
  616. def _device_bays(self, queryset, name, value):
  617. return queryset.exclude(device_bays__isnull=value)
  618. class DeviceComponentFilterSet(django_filters.FilterSet):
  619. q = django_filters.CharFilter(
  620. method='search',
  621. label='Search',
  622. )
  623. region_id = TreeNodeMultipleChoiceFilter(
  624. queryset=Region.objects.all(),
  625. field_name='device__site__region',
  626. lookup_expr='in',
  627. label='Region (ID)',
  628. )
  629. region = TreeNodeMultipleChoiceFilter(
  630. queryset=Region.objects.all(),
  631. field_name='device__site__region',
  632. lookup_expr='in',
  633. to_field_name='slug',
  634. label='Region (slug)',
  635. )
  636. site_id = django_filters.ModelMultipleChoiceFilter(
  637. field_name='device__site',
  638. queryset=Site.objects.all(),
  639. label='Site (ID)',
  640. )
  641. site = django_filters.ModelMultipleChoiceFilter(
  642. field_name='device__site__slug',
  643. queryset=Site.objects.all(),
  644. to_field_name='slug',
  645. label='Site name (slug)',
  646. )
  647. device_id = django_filters.ModelMultipleChoiceFilter(
  648. queryset=Device.objects.all(),
  649. label='Device (ID)',
  650. )
  651. device = django_filters.ModelMultipleChoiceFilter(
  652. field_name='device__name',
  653. queryset=Device.objects.all(),
  654. to_field_name='name',
  655. label='Device (name)',
  656. )
  657. tag = TagFilter()
  658. def search(self, queryset, name, value):
  659. if not value.strip():
  660. return queryset
  661. return queryset.filter(
  662. Q(name__icontains=value) |
  663. Q(description__icontains=value)
  664. )
  665. class ConsolePortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  666. type = django_filters.MultipleChoiceFilter(
  667. choices=ConsolePortTypeChoices,
  668. null_value=None
  669. )
  670. cabled = django_filters.BooleanFilter(
  671. field_name='cable',
  672. lookup_expr='isnull',
  673. exclude=True
  674. )
  675. class Meta:
  676. model = ConsolePort
  677. fields = ['id', 'name', 'description', 'connection_status']
  678. class ConsoleServerPortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  679. type = django_filters.MultipleChoiceFilter(
  680. choices=ConsolePortTypeChoices,
  681. null_value=None
  682. )
  683. cabled = django_filters.BooleanFilter(
  684. field_name='cable',
  685. lookup_expr='isnull',
  686. exclude=True
  687. )
  688. class Meta:
  689. model = ConsoleServerPort
  690. fields = ['id', 'name', 'description', 'connection_status']
  691. class PowerPortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  692. type = django_filters.MultipleChoiceFilter(
  693. choices=PowerPortTypeChoices,
  694. null_value=None
  695. )
  696. cabled = django_filters.BooleanFilter(
  697. field_name='cable',
  698. lookup_expr='isnull',
  699. exclude=True
  700. )
  701. class Meta:
  702. model = PowerPort
  703. fields = ['id', 'name', 'maximum_draw', 'allocated_draw', 'description', 'connection_status']
  704. class PowerOutletFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  705. type = django_filters.MultipleChoiceFilter(
  706. choices=PowerOutletTypeChoices,
  707. null_value=None
  708. )
  709. cabled = django_filters.BooleanFilter(
  710. field_name='cable',
  711. lookup_expr='isnull',
  712. exclude=True
  713. )
  714. class Meta:
  715. model = PowerOutlet
  716. fields = ['id', 'name', 'feed_leg', 'description', 'connection_status']
  717. class InterfaceFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  718. q = django_filters.CharFilter(
  719. method='search',
  720. label='Search',
  721. )
  722. # Override device and device_id filters from DeviceComponentFilterSet to match against any peer virtual chassis
  723. # members
  724. device = MultiValueCharFilter(
  725. method='filter_device',
  726. field_name='name',
  727. label='Device',
  728. )
  729. device_id = MultiValueNumberFilter(
  730. method='filter_device_id',
  731. field_name='pk',
  732. label='Device (ID)',
  733. )
  734. cabled = django_filters.BooleanFilter(
  735. field_name='cable',
  736. lookup_expr='isnull',
  737. exclude=True
  738. )
  739. kind = django_filters.CharFilter(
  740. method='filter_kind',
  741. label='Kind of interface',
  742. )
  743. lag_id = django_filters.ModelMultipleChoiceFilter(
  744. field_name='lag',
  745. queryset=Interface.objects.all(),
  746. label='LAG interface (ID)',
  747. )
  748. mac_address = MultiValueMACAddressFilter()
  749. tag = TagFilter()
  750. vlan_id = django_filters.CharFilter(
  751. method='filter_vlan_id',
  752. label='Assigned VLAN'
  753. )
  754. vlan = django_filters.CharFilter(
  755. method='filter_vlan',
  756. label='Assigned VID'
  757. )
  758. type = django_filters.MultipleChoiceFilter(
  759. choices=InterfaceTypeChoices,
  760. null_value=None
  761. )
  762. class Meta:
  763. model = Interface
  764. fields = ['id', 'name', 'connection_status', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'description']
  765. def filter_device(self, queryset, name, value):
  766. try:
  767. devices = Device.objects.filter(**{'{}__in'.format(name): value})
  768. vc_interface_ids = []
  769. for device in devices:
  770. vc_interface_ids.extend(device.vc_interfaces.values_list('id', flat=True))
  771. return queryset.filter(pk__in=vc_interface_ids)
  772. except Device.DoesNotExist:
  773. return queryset.none()
  774. def filter_device_id(self, queryset, name, id_list):
  775. # Include interfaces belonging to peer virtual chassis members
  776. vc_interface_ids = []
  777. try:
  778. devices = Device.objects.filter(pk__in=id_list)
  779. for device in devices:
  780. vc_interface_ids += device.vc_interfaces.values_list('id', flat=True)
  781. return queryset.filter(pk__in=vc_interface_ids)
  782. except Device.DoesNotExist:
  783. return queryset.none()
  784. def filter_vlan_id(self, queryset, name, value):
  785. value = value.strip()
  786. if not value:
  787. return queryset
  788. return queryset.filter(
  789. Q(untagged_vlan_id=value) |
  790. Q(tagged_vlans=value)
  791. )
  792. def filter_vlan(self, queryset, name, value):
  793. value = value.strip()
  794. if not value:
  795. return queryset
  796. return queryset.filter(
  797. Q(untagged_vlan_id__vid=value) |
  798. Q(tagged_vlans__vid=value)
  799. )
  800. def filter_kind(self, queryset, name, value):
  801. value = value.strip().lower()
  802. return {
  803. 'physical': queryset.exclude(type__in=NONCONNECTABLE_IFACE_TYPES),
  804. 'virtual': queryset.filter(type__in=VIRTUAL_IFACE_TYPES),
  805. 'wireless': queryset.filter(type__in=WIRELESS_IFACE_TYPES),
  806. }.get(value, queryset.none())
  807. class FrontPortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  808. cabled = django_filters.BooleanFilter(
  809. field_name='cable',
  810. lookup_expr='isnull',
  811. exclude=True
  812. )
  813. class Meta:
  814. model = FrontPort
  815. fields = ['id', 'name', 'type', 'description']
  816. class RearPortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  817. cabled = django_filters.BooleanFilter(
  818. field_name='cable',
  819. lookup_expr='isnull',
  820. exclude=True
  821. )
  822. class Meta:
  823. model = RearPort
  824. fields = ['id', 'name', 'type', 'positions', 'description']
  825. class DeviceBayFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  826. class Meta:
  827. model = DeviceBay
  828. fields = ['id', 'name', 'description']
  829. class InventoryItemFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  830. q = django_filters.CharFilter(
  831. method='search',
  832. label='Search',
  833. )
  834. region_id = TreeNodeMultipleChoiceFilter(
  835. queryset=Region.objects.all(),
  836. field_name='device__site__region',
  837. lookup_expr='in',
  838. label='Region (ID)',
  839. )
  840. region = TreeNodeMultipleChoiceFilter(
  841. queryset=Region.objects.all(),
  842. field_name='device__site__region',
  843. lookup_expr='in',
  844. to_field_name='slug',
  845. label='Region (slug)',
  846. )
  847. site_id = django_filters.ModelMultipleChoiceFilter(
  848. field_name='device__site',
  849. queryset=Site.objects.all(),
  850. label='Site (ID)',
  851. )
  852. site = django_filters.ModelMultipleChoiceFilter(
  853. field_name='device__site__slug',
  854. queryset=Site.objects.all(),
  855. to_field_name='slug',
  856. label='Site name (slug)',
  857. )
  858. device_id = django_filters.ModelChoiceFilter(
  859. queryset=Device.objects.all(),
  860. label='Device (ID)',
  861. )
  862. device = django_filters.ModelChoiceFilter(
  863. queryset=Device.objects.all(),
  864. to_field_name='name',
  865. label='Device (name)',
  866. )
  867. parent_id = django_filters.ModelMultipleChoiceFilter(
  868. queryset=InventoryItem.objects.all(),
  869. label='Parent inventory item (ID)',
  870. )
  871. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  872. queryset=Manufacturer.objects.all(),
  873. label='Manufacturer (ID)',
  874. )
  875. manufacturer = django_filters.ModelMultipleChoiceFilter(
  876. field_name='manufacturer__slug',
  877. queryset=Manufacturer.objects.all(),
  878. to_field_name='slug',
  879. label='Manufacturer (slug)',
  880. )
  881. serial = django_filters.CharFilter(
  882. lookup_expr='iexact'
  883. )
  884. class Meta:
  885. model = InventoryItem
  886. fields = ['id', 'name', 'part_id', 'asset_tag', 'discovered']
  887. def search(self, queryset, name, value):
  888. if not value.strip():
  889. return queryset
  890. qs_filter = (
  891. Q(name__icontains=value) |
  892. Q(part_id__icontains=value) |
  893. Q(serial__icontains=value) |
  894. Q(asset_tag__icontains=value) |
  895. Q(description__icontains=value)
  896. )
  897. return queryset.filter(qs_filter)
  898. class VirtualChassisFilterSet(BaseFilterSet):
  899. q = django_filters.CharFilter(
  900. method='search',
  901. label='Search',
  902. )
  903. region_id = TreeNodeMultipleChoiceFilter(
  904. queryset=Region.objects.all(),
  905. field_name='master__site__region',
  906. lookup_expr='in',
  907. label='Region (ID)',
  908. )
  909. region = TreeNodeMultipleChoiceFilter(
  910. queryset=Region.objects.all(),
  911. field_name='master__site__region',
  912. lookup_expr='in',
  913. to_field_name='slug',
  914. label='Region (slug)',
  915. )
  916. site_id = django_filters.ModelMultipleChoiceFilter(
  917. field_name='master__site',
  918. queryset=Site.objects.all(),
  919. label='Site (ID)',
  920. )
  921. site = django_filters.ModelMultipleChoiceFilter(
  922. field_name='master__site__slug',
  923. queryset=Site.objects.all(),
  924. to_field_name='slug',
  925. label='Site name (slug)',
  926. )
  927. tenant_id = django_filters.ModelMultipleChoiceFilter(
  928. field_name='master__tenant',
  929. queryset=Tenant.objects.all(),
  930. label='Tenant (ID)',
  931. )
  932. tenant = django_filters.ModelMultipleChoiceFilter(
  933. field_name='master__tenant__slug',
  934. queryset=Tenant.objects.all(),
  935. to_field_name='slug',
  936. label='Tenant (slug)',
  937. )
  938. tag = TagFilter()
  939. class Meta:
  940. model = VirtualChassis
  941. fields = ['id', 'domain']
  942. def search(self, queryset, name, value):
  943. if not value.strip():
  944. return queryset
  945. qs_filter = (
  946. Q(master__name__icontains=value) |
  947. Q(domain__icontains=value)
  948. )
  949. return queryset.filter(qs_filter)
  950. class CableFilterSet(BaseFilterSet):
  951. q = django_filters.CharFilter(
  952. method='search',
  953. label='Search',
  954. )
  955. type = django_filters.MultipleChoiceFilter(
  956. choices=CableTypeChoices
  957. )
  958. status = django_filters.MultipleChoiceFilter(
  959. choices=CableStatusChoices
  960. )
  961. color = django_filters.MultipleChoiceFilter(
  962. choices=ColorChoices
  963. )
  964. device_id = MultiValueNumberFilter(
  965. method='filter_device'
  966. )
  967. device = MultiValueCharFilter(
  968. method='filter_device',
  969. field_name='device__name'
  970. )
  971. rack_id = MultiValueNumberFilter(
  972. method='filter_device',
  973. field_name='device__rack_id'
  974. )
  975. rack = MultiValueNumberFilter(
  976. method='filter_device',
  977. field_name='device__rack__name'
  978. )
  979. site_id = MultiValueNumberFilter(
  980. method='filter_device',
  981. field_name='device__site_id'
  982. )
  983. site = MultiValueNumberFilter(
  984. method='filter_device',
  985. field_name='device__site__slug'
  986. )
  987. tenant_id = MultiValueNumberFilter(
  988. method='filter_device',
  989. field_name='device__tenant_id'
  990. )
  991. tenant = MultiValueNumberFilter(
  992. method='filter_device',
  993. field_name='device__tenant__slug'
  994. )
  995. class Meta:
  996. model = Cable
  997. fields = ['id', 'label', 'length', 'length_unit']
  998. def search(self, queryset, name, value):
  999. if not value.strip():
  1000. return queryset
  1001. return queryset.filter(label__icontains=value)
  1002. def filter_device(self, queryset, name, value):
  1003. queryset = queryset.filter(
  1004. Q(**{'_termination_a_{}__in'.format(name): value}) |
  1005. Q(**{'_termination_b_{}__in'.format(name): value})
  1006. )
  1007. return queryset
  1008. class ConsoleConnectionFilterSet(BaseFilterSet):
  1009. site = django_filters.CharFilter(
  1010. method='filter_site',
  1011. label='Site (slug)',
  1012. )
  1013. device_id = MultiValueNumberFilter(
  1014. method='filter_device'
  1015. )
  1016. device = MultiValueCharFilter(
  1017. method='filter_device',
  1018. field_name='device__name'
  1019. )
  1020. class Meta:
  1021. model = ConsolePort
  1022. fields = ['name', 'connection_status']
  1023. def filter_site(self, queryset, name, value):
  1024. if not value.strip():
  1025. return queryset
  1026. return queryset.filter(connected_endpoint__device__site__slug=value)
  1027. def filter_device(self, queryset, name, value):
  1028. if not value:
  1029. return queryset
  1030. return queryset.filter(
  1031. Q(**{'{}__in'.format(name): value}) |
  1032. Q(**{'connected_endpoint__{}__in'.format(name): value})
  1033. )
  1034. class PowerConnectionFilterSet(BaseFilterSet):
  1035. site = django_filters.CharFilter(
  1036. method='filter_site',
  1037. label='Site (slug)',
  1038. )
  1039. device_id = MultiValueNumberFilter(
  1040. method='filter_device'
  1041. )
  1042. device = MultiValueCharFilter(
  1043. method='filter_device',
  1044. field_name='device__name'
  1045. )
  1046. class Meta:
  1047. model = PowerPort
  1048. fields = ['name', 'connection_status']
  1049. def filter_site(self, queryset, name, value):
  1050. if not value.strip():
  1051. return queryset
  1052. return queryset.filter(_connected_poweroutlet__device__site__slug=value)
  1053. def filter_device(self, queryset, name, value):
  1054. if not value:
  1055. return queryset
  1056. return queryset.filter(
  1057. Q(**{'{}__in'.format(name): value}) |
  1058. Q(**{'_connected_poweroutlet__{}__in'.format(name): value})
  1059. )
  1060. class InterfaceConnectionFilterSet(BaseFilterSet):
  1061. site = django_filters.CharFilter(
  1062. method='filter_site',
  1063. label='Site (slug)',
  1064. )
  1065. device_id = MultiValueNumberFilter(
  1066. method='filter_device'
  1067. )
  1068. device = MultiValueCharFilter(
  1069. method='filter_device',
  1070. field_name='device__name'
  1071. )
  1072. class Meta:
  1073. model = Interface
  1074. fields = ['connection_status']
  1075. def filter_site(self, queryset, name, value):
  1076. if not value.strip():
  1077. return queryset
  1078. return queryset.filter(
  1079. Q(device__site__slug=value) |
  1080. Q(_connected_interface__device__site__slug=value)
  1081. )
  1082. def filter_device(self, queryset, name, value):
  1083. if not value:
  1084. return queryset
  1085. return queryset.filter(
  1086. Q(**{'{}__in'.format(name): value}) |
  1087. Q(**{'_connected_interface__{}__in'.format(name): value})
  1088. )
  1089. class PowerPanelFilterSet(BaseFilterSet):
  1090. q = django_filters.CharFilter(
  1091. method='search',
  1092. label='Search',
  1093. )
  1094. region_id = TreeNodeMultipleChoiceFilter(
  1095. queryset=Region.objects.all(),
  1096. field_name='site__region',
  1097. lookup_expr='in',
  1098. label='Region (ID)',
  1099. )
  1100. region = TreeNodeMultipleChoiceFilter(
  1101. queryset=Region.objects.all(),
  1102. field_name='site__region',
  1103. lookup_expr='in',
  1104. to_field_name='slug',
  1105. label='Region (slug)',
  1106. )
  1107. site_id = django_filters.ModelMultipleChoiceFilter(
  1108. queryset=Site.objects.all(),
  1109. label='Site (ID)',
  1110. )
  1111. site = django_filters.ModelMultipleChoiceFilter(
  1112. field_name='site__slug',
  1113. queryset=Site.objects.all(),
  1114. to_field_name='slug',
  1115. label='Site name (slug)',
  1116. )
  1117. rack_group_id = TreeNodeMultipleChoiceFilter(
  1118. queryset=RackGroup.objects.all(),
  1119. field_name='rack_group',
  1120. lookup_expr='in',
  1121. label='Rack group (ID)',
  1122. )
  1123. class Meta:
  1124. model = PowerPanel
  1125. fields = ['id', 'name']
  1126. def search(self, queryset, name, value):
  1127. if not value.strip():
  1128. return queryset
  1129. qs_filter = (
  1130. Q(name__icontains=value)
  1131. )
  1132. return queryset.filter(qs_filter)
  1133. class PowerFeedFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
  1134. q = django_filters.CharFilter(
  1135. method='search',
  1136. label='Search',
  1137. )
  1138. region_id = TreeNodeMultipleChoiceFilter(
  1139. queryset=Region.objects.all(),
  1140. field_name='power_panel__site__region',
  1141. lookup_expr='in',
  1142. label='Region (ID)',
  1143. )
  1144. region = TreeNodeMultipleChoiceFilter(
  1145. queryset=Region.objects.all(),
  1146. field_name='power_panel__site__region',
  1147. lookup_expr='in',
  1148. to_field_name='slug',
  1149. label='Region (slug)',
  1150. )
  1151. site_id = django_filters.ModelMultipleChoiceFilter(
  1152. field_name='power_panel__site',
  1153. queryset=Site.objects.all(),
  1154. label='Site (ID)',
  1155. )
  1156. site = django_filters.ModelMultipleChoiceFilter(
  1157. field_name='power_panel__site__slug',
  1158. queryset=Site.objects.all(),
  1159. to_field_name='slug',
  1160. label='Site name (slug)',
  1161. )
  1162. power_panel_id = django_filters.ModelMultipleChoiceFilter(
  1163. queryset=PowerPanel.objects.all(),
  1164. label='Power panel (ID)',
  1165. )
  1166. rack_id = django_filters.ModelMultipleChoiceFilter(
  1167. field_name='rack',
  1168. queryset=Rack.objects.all(),
  1169. label='Rack (ID)',
  1170. )
  1171. tag = TagFilter()
  1172. class Meta:
  1173. model = PowerFeed
  1174. fields = ['id', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization']
  1175. def search(self, queryset, name, value):
  1176. if not value.strip():
  1177. return queryset
  1178. qs_filter = (
  1179. Q(name__icontains=value) |
  1180. Q(comments__icontains=value)
  1181. )
  1182. return queryset.filter(qs_filter)