filters.py 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130
  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 extras.filters import CustomFieldFilterSet, LocalConfigContextFilter
  6. from tenancy.filtersets import TenancyFilterSet
  7. from tenancy.models import Tenant
  8. from utilities.constants import COLOR_CHOICES
  9. from utilities.filters import (
  10. MultiValueMACAddressFilter, MultiValueNumberFilter, NameSlugSearchFilterSet, NumericInFilter, TagFilter,
  11. TreeNodeMultipleChoiceFilter,
  12. )
  13. from virtualization.models import Cluster
  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):
  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=SITE_STATUS_CHOICES,
  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):
  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=RACK_STATUS_CHOICES,
  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):
  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']
  311. class ConsoleServerPortTemplateFilter(DeviceTypeComponentFilterSet):
  312. class Meta:
  313. model = ConsoleServerPortTemplate
  314. fields = ['id', 'name']
  315. class PowerPortTemplateFilter(DeviceTypeComponentFilterSet):
  316. class Meta:
  317. model = PowerPortTemplate
  318. fields = ['id', 'name', 'maximum_draw', 'allocated_draw']
  319. class PowerOutletTemplateFilter(DeviceTypeComponentFilterSet):
  320. class Meta:
  321. model = PowerOutletTemplate
  322. fields = ['id', 'name', '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):
  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=DEVICE_STATUS_CHOICES,
  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. device_id = django_filters.ModelMultipleChoiceFilter(
  544. queryset=Device.objects.all(),
  545. label='Device (ID)',
  546. )
  547. device = django_filters.ModelChoiceFilter(
  548. queryset=Device.objects.all(),
  549. to_field_name='name',
  550. label='Device (name)',
  551. )
  552. tag = TagFilter()
  553. def search(self, queryset, name, value):
  554. if not value.strip():
  555. return queryset
  556. return queryset.filter(
  557. Q(name__icontains=value) |
  558. Q(description__icontains=value)
  559. )
  560. class ConsolePortFilter(DeviceComponentFilterSet):
  561. cabled = django_filters.BooleanFilter(
  562. field_name='cable',
  563. lookup_expr='isnull',
  564. exclude=True
  565. )
  566. class Meta:
  567. model = ConsolePort
  568. fields = ['id', 'name', 'description', 'connection_status']
  569. class ConsoleServerPortFilter(DeviceComponentFilterSet):
  570. cabled = django_filters.BooleanFilter(
  571. field_name='cable',
  572. lookup_expr='isnull',
  573. exclude=True
  574. )
  575. class Meta:
  576. model = ConsoleServerPort
  577. fields = ['id', 'name', 'description', 'connection_status']
  578. class PowerPortFilter(DeviceComponentFilterSet):
  579. cabled = django_filters.BooleanFilter(
  580. field_name='cable',
  581. lookup_expr='isnull',
  582. exclude=True
  583. )
  584. class Meta:
  585. model = PowerPort
  586. fields = ['id', 'name', 'maximum_draw', 'allocated_draw', 'description', 'connection_status']
  587. class PowerOutletFilter(DeviceComponentFilterSet):
  588. cabled = django_filters.BooleanFilter(
  589. field_name='cable',
  590. lookup_expr='isnull',
  591. exclude=True
  592. )
  593. class Meta:
  594. model = PowerOutlet
  595. fields = ['id', 'name', 'feed_leg', 'description', 'connection_status']
  596. class InterfaceFilter(django_filters.FilterSet):
  597. """
  598. Not using DeviceComponentFilterSet for Interfaces because we need to check for VirtualChassis membership.
  599. """
  600. q = django_filters.CharFilter(
  601. method='search',
  602. label='Search',
  603. )
  604. device = django_filters.CharFilter(
  605. method='filter_device',
  606. field_name='name',
  607. label='Device',
  608. )
  609. device_id = MultiValueNumberFilter(
  610. method='filter_device_id',
  611. field_name='pk',
  612. label='Device (ID)',
  613. )
  614. cabled = django_filters.BooleanFilter(
  615. field_name='cable',
  616. lookup_expr='isnull',
  617. exclude=True
  618. )
  619. kind = django_filters.CharFilter(
  620. method='filter_kind',
  621. label='Kind of interface',
  622. )
  623. lag_id = django_filters.ModelMultipleChoiceFilter(
  624. field_name='lag',
  625. queryset=Interface.objects.all(),
  626. label='LAG interface (ID)',
  627. )
  628. mac_address = MultiValueMACAddressFilter()
  629. tag = TagFilter()
  630. vlan_id = django_filters.CharFilter(
  631. method='filter_vlan_id',
  632. label='Assigned VLAN'
  633. )
  634. vlan = django_filters.CharFilter(
  635. method='filter_vlan',
  636. label='Assigned VID'
  637. )
  638. type = django_filters.MultipleChoiceFilter(
  639. choices=IFACE_TYPE_CHOICES,
  640. null_value=None
  641. )
  642. class Meta:
  643. model = Interface
  644. fields = ['id', 'name', 'connection_status', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'description']
  645. def search(self, queryset, name, value):
  646. if not value.strip():
  647. return queryset
  648. return queryset.filter(
  649. Q(name__icontains=value) |
  650. Q(description__icontains=value)
  651. ).distinct()
  652. def filter_device(self, queryset, name, value):
  653. try:
  654. device = Device.objects.get(**{name: value})
  655. vc_interface_ids = device.vc_interfaces.values_list('id', flat=True)
  656. return queryset.filter(pk__in=vc_interface_ids)
  657. except Device.DoesNotExist:
  658. return queryset.none()
  659. def filter_device_id(self, queryset, name, id_list):
  660. # Include interfaces belonging to peer virtual chassis members
  661. vc_interface_ids = []
  662. try:
  663. devices = Device.objects.filter(pk__in=id_list)
  664. for device in devices:
  665. vc_interface_ids += device.vc_interfaces.values_list('id', flat=True)
  666. return queryset.filter(pk__in=vc_interface_ids)
  667. except Device.DoesNotExist:
  668. return queryset.none()
  669. def filter_vlan_id(self, queryset, name, value):
  670. value = value.strip()
  671. if not value:
  672. return queryset
  673. return queryset.filter(
  674. Q(untagged_vlan_id=value) |
  675. Q(tagged_vlans=value)
  676. )
  677. def filter_vlan(self, queryset, name, value):
  678. value = value.strip()
  679. if not value:
  680. return queryset
  681. return queryset.filter(
  682. Q(untagged_vlan_id__vid=value) |
  683. Q(tagged_vlans__vid=value)
  684. )
  685. def filter_kind(self, queryset, name, value):
  686. value = value.strip().lower()
  687. return {
  688. 'physical': queryset.exclude(type__in=NONCONNECTABLE_IFACE_TYPES),
  689. 'virtual': queryset.filter(type__in=VIRTUAL_IFACE_TYPES),
  690. 'wireless': queryset.filter(type__in=WIRELESS_IFACE_TYPES),
  691. }.get(value, queryset.none())
  692. class FrontPortFilter(DeviceComponentFilterSet):
  693. cabled = django_filters.BooleanFilter(
  694. field_name='cable',
  695. lookup_expr='isnull',
  696. exclude=True
  697. )
  698. class Meta:
  699. model = FrontPort
  700. fields = ['id', 'name', 'type', 'description']
  701. class RearPortFilter(DeviceComponentFilterSet):
  702. cabled = django_filters.BooleanFilter(
  703. field_name='cable',
  704. lookup_expr='isnull',
  705. exclude=True
  706. )
  707. class Meta:
  708. model = RearPort
  709. fields = ['id', 'name', 'type', 'positions', 'description']
  710. class DeviceBayFilter(DeviceComponentFilterSet):
  711. class Meta:
  712. model = DeviceBay
  713. fields = ['id', 'name', 'description']
  714. class InventoryItemFilter(DeviceComponentFilterSet):
  715. q = django_filters.CharFilter(
  716. method='search',
  717. label='Search',
  718. )
  719. device_id = django_filters.ModelChoiceFilter(
  720. queryset=Device.objects.all(),
  721. label='Device (ID)',
  722. )
  723. device = django_filters.ModelChoiceFilter(
  724. queryset=Device.objects.all(),
  725. to_field_name='name',
  726. label='Device (name)',
  727. )
  728. parent_id = django_filters.ModelMultipleChoiceFilter(
  729. queryset=InventoryItem.objects.all(),
  730. label='Parent inventory item (ID)',
  731. )
  732. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  733. queryset=Manufacturer.objects.all(),
  734. label='Manufacturer (ID)',
  735. )
  736. manufacturer = django_filters.ModelMultipleChoiceFilter(
  737. field_name='manufacturer__slug',
  738. queryset=Manufacturer.objects.all(),
  739. to_field_name='slug',
  740. label='Manufacturer (slug)',
  741. )
  742. serial = django_filters.CharFilter(
  743. lookup_expr='iexact'
  744. )
  745. class Meta:
  746. model = InventoryItem
  747. fields = ['id', 'name', 'part_id', 'asset_tag', 'discovered']
  748. def search(self, queryset, name, value):
  749. if not value.strip():
  750. return queryset
  751. qs_filter = (
  752. Q(name__icontains=value) |
  753. Q(part_id__icontains=value) |
  754. Q(serial__iexact=value) |
  755. Q(asset_tag__iexact=value) |
  756. Q(description__icontains=value)
  757. )
  758. return queryset.filter(qs_filter)
  759. class VirtualChassisFilter(django_filters.FilterSet):
  760. q = django_filters.CharFilter(
  761. method='search',
  762. label='Search',
  763. )
  764. site_id = django_filters.ModelMultipleChoiceFilter(
  765. field_name='master__site',
  766. queryset=Site.objects.all(),
  767. label='Site (ID)',
  768. )
  769. site = django_filters.ModelMultipleChoiceFilter(
  770. field_name='master__site__slug',
  771. queryset=Site.objects.all(),
  772. to_field_name='slug',
  773. label='Site name (slug)',
  774. )
  775. tenant_id = django_filters.ModelMultipleChoiceFilter(
  776. field_name='master__tenant',
  777. queryset=Tenant.objects.all(),
  778. label='Tenant (ID)',
  779. )
  780. tenant = django_filters.ModelMultipleChoiceFilter(
  781. field_name='master__tenant__slug',
  782. queryset=Tenant.objects.all(),
  783. to_field_name='slug',
  784. label='Tenant (slug)',
  785. )
  786. tag = TagFilter()
  787. class Meta:
  788. model = VirtualChassis
  789. fields = ['id', 'domain']
  790. def search(self, queryset, name, value):
  791. if not value.strip():
  792. return queryset
  793. qs_filter = (
  794. Q(master__name__icontains=value) |
  795. Q(domain__icontains=value)
  796. )
  797. return queryset.filter(qs_filter)
  798. class CableFilter(django_filters.FilterSet):
  799. q = django_filters.CharFilter(
  800. method='search',
  801. label='Search',
  802. )
  803. type = django_filters.MultipleChoiceFilter(
  804. choices=CABLE_TYPE_CHOICES
  805. )
  806. status = django_filters.MultipleChoiceFilter(
  807. choices=CONNECTION_STATUS_CHOICES
  808. )
  809. color = django_filters.MultipleChoiceFilter(
  810. choices=COLOR_CHOICES
  811. )
  812. device = django_filters.CharFilter(
  813. method='filter_connected_device',
  814. field_name='name'
  815. )
  816. device_id = django_filters.CharFilter(
  817. method='filter_connected_device',
  818. field_name='pk'
  819. )
  820. class Meta:
  821. model = Cable
  822. fields = ['id', 'label', 'length', 'length_unit']
  823. def search(self, queryset, name, value):
  824. if not value.strip():
  825. return queryset
  826. return queryset.filter(label__icontains=value)
  827. def filter_connected_device(self, queryset, name, value):
  828. if not value.strip():
  829. return queryset
  830. try:
  831. device = Device.objects.get(**{name: value})
  832. except ObjectDoesNotExist:
  833. return queryset.none()
  834. cable_pks = device.get_cables(pk_list=True)
  835. return queryset.filter(pk__in=cable_pks)
  836. class ConsoleConnectionFilter(django_filters.FilterSet):
  837. site = django_filters.CharFilter(
  838. method='filter_site',
  839. label='Site (slug)',
  840. )
  841. device = django_filters.CharFilter(
  842. method='filter_device',
  843. label='Device',
  844. )
  845. class Meta:
  846. model = ConsolePort
  847. fields = ['name', 'connection_status']
  848. def filter_site(self, queryset, name, value):
  849. if not value.strip():
  850. return queryset
  851. return queryset.filter(connected_endpoint__device__site__slug=value)
  852. def filter_device(self, queryset, name, value):
  853. if not value.strip():
  854. return queryset
  855. return queryset.filter(
  856. Q(device__name__icontains=value) |
  857. Q(connected_endpoint__device__name__icontains=value)
  858. )
  859. class PowerConnectionFilter(django_filters.FilterSet):
  860. site = django_filters.CharFilter(
  861. method='filter_site',
  862. label='Site (slug)',
  863. )
  864. device = django_filters.CharFilter(
  865. method='filter_device',
  866. label='Device',
  867. )
  868. class Meta:
  869. model = PowerPort
  870. fields = ['name', 'connection_status']
  871. def filter_site(self, queryset, name, value):
  872. if not value.strip():
  873. return queryset
  874. return queryset.filter(_connected_poweroutlet__device__site__slug=value)
  875. def filter_device(self, queryset, name, value):
  876. if not value.strip():
  877. return queryset
  878. return queryset.filter(
  879. Q(device__name__icontains=value) |
  880. Q(_connected_poweroutlet__device__name__icontains=value)
  881. )
  882. class InterfaceConnectionFilter(django_filters.FilterSet):
  883. site = django_filters.CharFilter(
  884. method='filter_site',
  885. label='Site (slug)',
  886. )
  887. device = django_filters.CharFilter(
  888. method='filter_device',
  889. label='Device',
  890. )
  891. class Meta:
  892. model = Interface
  893. fields = ['connection_status']
  894. def filter_site(self, queryset, name, value):
  895. if not value.strip():
  896. return queryset
  897. return queryset.filter(
  898. Q(device__site__slug=value) |
  899. Q(_connected_interface__device__site__slug=value)
  900. )
  901. def filter_device(self, queryset, name, value):
  902. if not value.strip():
  903. return queryset
  904. return queryset.filter(
  905. Q(device__name__icontains=value) |
  906. Q(_connected_interface__device__name__icontains=value)
  907. )
  908. class PowerPanelFilter(django_filters.FilterSet):
  909. id__in = NumericInFilter(
  910. field_name='id',
  911. lookup_expr='in'
  912. )
  913. q = django_filters.CharFilter(
  914. method='search',
  915. label='Search',
  916. )
  917. site_id = django_filters.ModelMultipleChoiceFilter(
  918. queryset=Site.objects.all(),
  919. label='Site (ID)',
  920. )
  921. site = django_filters.ModelMultipleChoiceFilter(
  922. field_name='site__slug',
  923. queryset=Site.objects.all(),
  924. to_field_name='slug',
  925. label='Site name (slug)',
  926. )
  927. rack_group_id = django_filters.ModelMultipleChoiceFilter(
  928. field_name='rack_group',
  929. queryset=RackGroup.objects.all(),
  930. label='Rack group (ID)',
  931. )
  932. class Meta:
  933. model = PowerPanel
  934. fields = ['name']
  935. def search(self, queryset, name, value):
  936. if not value.strip():
  937. return queryset
  938. qs_filter = (
  939. Q(name__icontains=value)
  940. )
  941. return queryset.filter(qs_filter)
  942. class PowerFeedFilter(CustomFieldFilterSet):
  943. id__in = NumericInFilter(
  944. field_name='id',
  945. lookup_expr='in'
  946. )
  947. q = django_filters.CharFilter(
  948. method='search',
  949. label='Search',
  950. )
  951. site_id = django_filters.ModelMultipleChoiceFilter(
  952. field_name='power_panel__site',
  953. queryset=Site.objects.all(),
  954. label='Site (ID)',
  955. )
  956. site = django_filters.ModelMultipleChoiceFilter(
  957. field_name='power_panel__site__slug',
  958. queryset=Site.objects.all(),
  959. to_field_name='slug',
  960. label='Site name (slug)',
  961. )
  962. power_panel_id = django_filters.ModelMultipleChoiceFilter(
  963. queryset=PowerPanel.objects.all(),
  964. label='Power panel (ID)',
  965. )
  966. rack_id = django_filters.ModelMultipleChoiceFilter(
  967. field_name='rack',
  968. queryset=Rack.objects.all(),
  969. label='Rack (ID)',
  970. )
  971. tag = TagFilter()
  972. class Meta:
  973. model = PowerFeed
  974. fields = ['name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization']
  975. def search(self, queryset, name, value):
  976. if not value.strip():
  977. return queryset
  978. qs_filter = (
  979. Q(name__icontains=value) |
  980. Q(comments__icontains=value)
  981. )
  982. return queryset.filter(qs_filter)