2
0

filters.py 35 KB

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