filters.py 34 KB

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