filters.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. import django_filters
  2. from django.contrib.auth.models import User
  3. from django.db.models import Q
  4. from netaddr import EUI
  5. from netaddr.core import AddrFormatError
  6. from extras.filters import CustomFieldFilterSet
  7. from tenancy.models import Tenant
  8. from utilities.filters import NullableCharFieldFilter, NumericInFilter
  9. from virtualization.models import Cluster
  10. from .constants import (
  11. DEVICE_STATUS_CHOICES, IFACE_FF_LAG, NONCONNECTABLE_IFACE_TYPES, SITE_STATUS_CHOICES, VIRTUAL_IFACE_TYPES,
  12. WIRELESS_IFACE_TYPES,
  13. )
  14. from .models import (
  15. ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
  16. DeviceBayTemplate, DeviceRole, DeviceType, FrontPanelPort, FrontPanelPortTemplate, Interface, InterfaceConnection,
  17. InterfaceTemplate, InventoryItem, Manufacturer, Platform, PowerOutlet, PowerOutletTemplate, PowerPort,
  18. PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPanelPort, RearPanelPortTemplate, Region, Site,
  19. VirtualChassis,
  20. )
  21. class RegionFilter(django_filters.FilterSet):
  22. q = django_filters.CharFilter(
  23. method='search',
  24. label='Search',
  25. )
  26. parent_id = django_filters.ModelMultipleChoiceFilter(
  27. queryset=Region.objects.all(),
  28. label='Parent region (ID)',
  29. )
  30. parent = django_filters.ModelMultipleChoiceFilter(
  31. name='parent__slug',
  32. queryset=Region.objects.all(),
  33. to_field_name='slug',
  34. label='Parent region (slug)',
  35. )
  36. class Meta:
  37. model = Region
  38. fields = ['name', 'slug']
  39. def search(self, queryset, name, value):
  40. if not value.strip():
  41. return queryset
  42. qs_filter = (
  43. Q(name__icontains=value) |
  44. Q(slug__icontains=value)
  45. )
  46. return queryset.filter(qs_filter)
  47. class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
  48. id__in = NumericInFilter(name='id', lookup_expr='in')
  49. q = django_filters.CharFilter(
  50. method='search',
  51. label='Search',
  52. )
  53. status = django_filters.MultipleChoiceFilter(
  54. choices=SITE_STATUS_CHOICES,
  55. null_value=None
  56. )
  57. region_id = django_filters.ModelMultipleChoiceFilter(
  58. queryset=Region.objects.all(),
  59. label='Region (ID)',
  60. )
  61. region = django_filters.ModelMultipleChoiceFilter(
  62. name='region__slug',
  63. queryset=Region.objects.all(),
  64. to_field_name='slug',
  65. label='Region (slug)',
  66. )
  67. tenant_id = django_filters.ModelMultipleChoiceFilter(
  68. queryset=Tenant.objects.all(),
  69. label='Tenant (ID)',
  70. )
  71. tenant = django_filters.ModelMultipleChoiceFilter(
  72. name='tenant__slug',
  73. queryset=Tenant.objects.all(),
  74. to_field_name='slug',
  75. label='Tenant (slug)',
  76. )
  77. tag = django_filters.CharFilter(
  78. name='tags__slug',
  79. )
  80. class Meta:
  81. model = Site
  82. fields = ['q', 'name', 'slug', 'facility', 'asn', 'contact_name', 'contact_phone', 'contact_email']
  83. def search(self, queryset, name, value):
  84. if not value.strip():
  85. return queryset
  86. qs_filter = (
  87. Q(name__icontains=value) |
  88. Q(facility__icontains=value) |
  89. Q(description__icontains=value) |
  90. Q(physical_address__icontains=value) |
  91. Q(shipping_address__icontains=value) |
  92. Q(contact_name__icontains=value) |
  93. Q(contact_phone__icontains=value) |
  94. Q(contact_email__icontains=value) |
  95. Q(comments__icontains=value)
  96. )
  97. try:
  98. qs_filter |= Q(asn=int(value.strip()))
  99. except ValueError:
  100. pass
  101. return queryset.filter(qs_filter)
  102. class RackGroupFilter(django_filters.FilterSet):
  103. q = django_filters.CharFilter(
  104. method='search',
  105. label='Search',
  106. )
  107. site_id = django_filters.ModelMultipleChoiceFilter(
  108. queryset=Site.objects.all(),
  109. label='Site (ID)',
  110. )
  111. site = django_filters.ModelMultipleChoiceFilter(
  112. name='site__slug',
  113. queryset=Site.objects.all(),
  114. to_field_name='slug',
  115. label='Site (slug)',
  116. )
  117. class Meta:
  118. model = RackGroup
  119. fields = ['site_id', 'name', 'slug']
  120. def search(self, queryset, name, value):
  121. if not value.strip():
  122. return queryset
  123. qs_filter = (
  124. Q(name__icontains=value) |
  125. Q(slug__icontains=value)
  126. )
  127. return queryset.filter(qs_filter)
  128. class RackRoleFilter(django_filters.FilterSet):
  129. class Meta:
  130. model = RackRole
  131. fields = ['name', 'slug', 'color']
  132. class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
  133. id__in = NumericInFilter(name='id', lookup_expr='in')
  134. q = django_filters.CharFilter(
  135. method='search',
  136. label='Search',
  137. )
  138. facility_id = NullableCharFieldFilter()
  139. site_id = django_filters.ModelMultipleChoiceFilter(
  140. queryset=Site.objects.all(),
  141. label='Site (ID)',
  142. )
  143. site = django_filters.ModelMultipleChoiceFilter(
  144. name='site__slug',
  145. queryset=Site.objects.all(),
  146. to_field_name='slug',
  147. label='Site (slug)',
  148. )
  149. group_id = django_filters.ModelMultipleChoiceFilter(
  150. queryset=RackGroup.objects.all(),
  151. label='Group (ID)',
  152. )
  153. group = django_filters.ModelMultipleChoiceFilter(
  154. name='group__slug',
  155. queryset=RackGroup.objects.all(),
  156. to_field_name='slug',
  157. label='Group',
  158. )
  159. tenant_id = django_filters.ModelMultipleChoiceFilter(
  160. queryset=Tenant.objects.all(),
  161. label='Tenant (ID)',
  162. )
  163. tenant = django_filters.ModelMultipleChoiceFilter(
  164. name='tenant__slug',
  165. queryset=Tenant.objects.all(),
  166. to_field_name='slug',
  167. label='Tenant (slug)',
  168. )
  169. role_id = django_filters.ModelMultipleChoiceFilter(
  170. queryset=RackRole.objects.all(),
  171. label='Role (ID)',
  172. )
  173. role = django_filters.ModelMultipleChoiceFilter(
  174. name='role__slug',
  175. queryset=RackRole.objects.all(),
  176. to_field_name='slug',
  177. label='Role (slug)',
  178. )
  179. tag = django_filters.CharFilter(
  180. name='tags__slug',
  181. )
  182. class Meta:
  183. model = Rack
  184. fields = ['name', 'serial', 'type', 'width', 'u_height', 'desc_units']
  185. def search(self, queryset, name, value):
  186. if not value.strip():
  187. return queryset
  188. return queryset.filter(
  189. Q(name__icontains=value) |
  190. Q(facility_id__icontains=value) |
  191. Q(serial__icontains=value.strip()) |
  192. Q(comments__icontains=value)
  193. )
  194. class RackReservationFilter(django_filters.FilterSet):
  195. id__in = NumericInFilter(name='id', lookup_expr='in')
  196. q = django_filters.CharFilter(
  197. method='search',
  198. label='Search',
  199. )
  200. rack_id = django_filters.ModelMultipleChoiceFilter(
  201. queryset=Rack.objects.all(),
  202. label='Rack (ID)',
  203. )
  204. site_id = django_filters.ModelMultipleChoiceFilter(
  205. name='rack__site',
  206. queryset=Site.objects.all(),
  207. label='Site (ID)',
  208. )
  209. site = django_filters.ModelMultipleChoiceFilter(
  210. name='rack__site__slug',
  211. queryset=Site.objects.all(),
  212. to_field_name='slug',
  213. label='Site (slug)',
  214. )
  215. group_id = django_filters.ModelMultipleChoiceFilter(
  216. name='rack__group',
  217. queryset=RackGroup.objects.all(),
  218. label='Group (ID)',
  219. )
  220. group = django_filters.ModelMultipleChoiceFilter(
  221. name='rack__group__slug',
  222. queryset=RackGroup.objects.all(),
  223. to_field_name='slug',
  224. label='Group',
  225. )
  226. tenant_id = django_filters.ModelMultipleChoiceFilter(
  227. queryset=Tenant.objects.all(),
  228. label='Tenant (ID)',
  229. )
  230. tenant = django_filters.ModelMultipleChoiceFilter(
  231. name='tenant__slug',
  232. queryset=Tenant.objects.all(),
  233. to_field_name='slug',
  234. label='Tenant (slug)',
  235. )
  236. user_id = django_filters.ModelMultipleChoiceFilter(
  237. queryset=User.objects.all(),
  238. label='User (ID)',
  239. )
  240. user = django_filters.ModelMultipleChoiceFilter(
  241. name='user',
  242. queryset=User.objects.all(),
  243. to_field_name='username',
  244. label='User (name)',
  245. )
  246. class Meta:
  247. model = RackReservation
  248. fields = ['created']
  249. def search(self, queryset, name, value):
  250. if not value.strip():
  251. return queryset
  252. return queryset.filter(
  253. Q(rack__name__icontains=value) |
  254. Q(rack__facility_id__icontains=value) |
  255. Q(user__username__icontains=value) |
  256. Q(description__icontains=value)
  257. )
  258. class ManufacturerFilter(django_filters.FilterSet):
  259. class Meta:
  260. model = Manufacturer
  261. fields = ['name', 'slug']
  262. class DeviceTypeFilter(CustomFieldFilterSet, django_filters.FilterSet):
  263. id__in = NumericInFilter(name='id', lookup_expr='in')
  264. q = django_filters.CharFilter(
  265. method='search',
  266. label='Search',
  267. )
  268. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  269. queryset=Manufacturer.objects.all(),
  270. label='Manufacturer (ID)',
  271. )
  272. manufacturer = django_filters.ModelMultipleChoiceFilter(
  273. name='manufacturer__slug',
  274. queryset=Manufacturer.objects.all(),
  275. to_field_name='slug',
  276. label='Manufacturer (slug)',
  277. )
  278. tag = django_filters.CharFilter(
  279. name='tags__slug',
  280. )
  281. class Meta:
  282. model = DeviceType
  283. fields = [
  284. 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'is_console_server', 'is_pdu',
  285. 'is_network_device', 'subdevice_role',
  286. ]
  287. def search(self, queryset, name, value):
  288. if not value.strip():
  289. return queryset
  290. return queryset.filter(
  291. Q(manufacturer__name__icontains=value) |
  292. Q(model__icontains=value) |
  293. Q(part_number__icontains=value) |
  294. Q(comments__icontains=value)
  295. )
  296. class DeviceTypeComponentFilterSet(django_filters.FilterSet):
  297. devicetype_id = django_filters.ModelMultipleChoiceFilter(
  298. queryset=DeviceType.objects.all(),
  299. name='device_type_id',
  300. label='Device type (ID)',
  301. )
  302. class ConsolePortTemplateFilter(DeviceTypeComponentFilterSet):
  303. class Meta:
  304. model = ConsolePortTemplate
  305. fields = ['name']
  306. class ConsoleServerPortTemplateFilter(DeviceTypeComponentFilterSet):
  307. class Meta:
  308. model = ConsoleServerPortTemplate
  309. fields = ['name']
  310. class PowerPortTemplateFilter(DeviceTypeComponentFilterSet):
  311. class Meta:
  312. model = PowerPortTemplate
  313. fields = ['name']
  314. class PowerOutletTemplateFilter(DeviceTypeComponentFilterSet):
  315. class Meta:
  316. model = PowerOutletTemplate
  317. fields = ['name']
  318. class InterfaceTemplateFilter(DeviceTypeComponentFilterSet):
  319. class Meta:
  320. model = InterfaceTemplate
  321. fields = ['name', 'form_factor', 'mgmt_only']
  322. class FrontPanelPortTemplateFilter(DeviceTypeComponentFilterSet):
  323. class Meta:
  324. model = FrontPanelPortTemplate
  325. fields = ['name', 'type']
  326. class RearPanelPortTemplateFilter(DeviceTypeComponentFilterSet):
  327. class Meta:
  328. model = RearPanelPortTemplate
  329. fields = ['name', 'type']
  330. class DeviceBayTemplateFilter(DeviceTypeComponentFilterSet):
  331. class Meta:
  332. model = DeviceBayTemplate
  333. fields = ['name']
  334. class DeviceRoleFilter(django_filters.FilterSet):
  335. class Meta:
  336. model = DeviceRole
  337. fields = ['name', 'slug', 'color', 'vm_role']
  338. class PlatformFilter(django_filters.FilterSet):
  339. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  340. name='manufacturer',
  341. queryset=Manufacturer.objects.all(),
  342. label='Manufacturer (ID)',
  343. )
  344. manufacturer = django_filters.ModelMultipleChoiceFilter(
  345. name='manufacturer__slug',
  346. queryset=Manufacturer.objects.all(),
  347. to_field_name='slug',
  348. label='Manufacturer (slug)',
  349. )
  350. class Meta:
  351. model = Platform
  352. fields = ['name', 'slug']
  353. class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet):
  354. id__in = NumericInFilter(name='id', lookup_expr='in')
  355. q = django_filters.CharFilter(
  356. method='search',
  357. label='Search',
  358. )
  359. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  360. name='device_type__manufacturer',
  361. queryset=Manufacturer.objects.all(),
  362. label='Manufacturer (ID)',
  363. )
  364. manufacturer = django_filters.ModelMultipleChoiceFilter(
  365. name='device_type__manufacturer__slug',
  366. queryset=Manufacturer.objects.all(),
  367. to_field_name='slug',
  368. label='Manufacturer (slug)',
  369. )
  370. device_type_id = django_filters.ModelMultipleChoiceFilter(
  371. queryset=DeviceType.objects.all(),
  372. label='Device type (ID)',
  373. )
  374. role_id = django_filters.ModelMultipleChoiceFilter(
  375. name='device_role_id',
  376. queryset=DeviceRole.objects.all(),
  377. label='Role (ID)',
  378. )
  379. role = django_filters.ModelMultipleChoiceFilter(
  380. name='device_role__slug',
  381. queryset=DeviceRole.objects.all(),
  382. to_field_name='slug',
  383. label='Role (slug)',
  384. )
  385. tenant_id = django_filters.ModelMultipleChoiceFilter(
  386. queryset=Tenant.objects.all(),
  387. label='Tenant (ID)',
  388. )
  389. tenant = django_filters.ModelMultipleChoiceFilter(
  390. name='tenant__slug',
  391. queryset=Tenant.objects.all(),
  392. to_field_name='slug',
  393. label='Tenant (slug)',
  394. )
  395. platform_id = django_filters.ModelMultipleChoiceFilter(
  396. queryset=Platform.objects.all(),
  397. label='Platform (ID)',
  398. )
  399. platform = django_filters.ModelMultipleChoiceFilter(
  400. name='platform__slug',
  401. queryset=Platform.objects.all(),
  402. to_field_name='slug',
  403. label='Platform (slug)',
  404. )
  405. name = NullableCharFieldFilter()
  406. asset_tag = NullableCharFieldFilter()
  407. site_id = django_filters.ModelMultipleChoiceFilter(
  408. queryset=Site.objects.all(),
  409. label='Site (ID)',
  410. )
  411. site = django_filters.ModelMultipleChoiceFilter(
  412. name='site__slug',
  413. queryset=Site.objects.all(),
  414. to_field_name='slug',
  415. label='Site name (slug)',
  416. )
  417. rack_group_id = django_filters.ModelMultipleChoiceFilter(
  418. name='rack__group',
  419. queryset=RackGroup.objects.all(),
  420. label='Rack group (ID)',
  421. )
  422. rack_id = django_filters.ModelMultipleChoiceFilter(
  423. name='rack',
  424. queryset=Rack.objects.all(),
  425. label='Rack (ID)',
  426. )
  427. cluster_id = django_filters.ModelMultipleChoiceFilter(
  428. queryset=Cluster.objects.all(),
  429. label='VM cluster (ID)',
  430. )
  431. model = django_filters.ModelMultipleChoiceFilter(
  432. name='device_type__slug',
  433. queryset=DeviceType.objects.all(),
  434. to_field_name='slug',
  435. label='Device model (slug)',
  436. )
  437. status = django_filters.MultipleChoiceFilter(
  438. choices=DEVICE_STATUS_CHOICES,
  439. null_value=None
  440. )
  441. is_full_depth = django_filters.BooleanFilter(
  442. name='device_type__is_full_depth',
  443. label='Is full depth',
  444. )
  445. is_console_server = django_filters.BooleanFilter(
  446. name='device_type__is_console_server',
  447. label='Is a console server',
  448. )
  449. is_pdu = django_filters.BooleanFilter(
  450. name='device_type__is_pdu',
  451. label='Is a PDU',
  452. )
  453. is_network_device = django_filters.BooleanFilter(
  454. name='device_type__is_network_device',
  455. label='Is a network device',
  456. )
  457. mac_address = django_filters.CharFilter(
  458. method='_mac_address',
  459. label='MAC address',
  460. )
  461. has_primary_ip = django_filters.BooleanFilter(
  462. method='_has_primary_ip',
  463. label='Has a primary IP',
  464. )
  465. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  466. name='virtual_chassis',
  467. queryset=VirtualChassis.objects.all(),
  468. label='Virtual chassis (ID)',
  469. )
  470. tag = django_filters.CharFilter(
  471. name='tags__slug',
  472. )
  473. class Meta:
  474. model = Device
  475. fields = ['serial', 'position']
  476. def search(self, queryset, name, value):
  477. if not value.strip():
  478. return queryset
  479. return queryset.filter(
  480. Q(name__icontains=value) |
  481. Q(serial__icontains=value.strip()) |
  482. Q(inventory_items__serial__icontains=value.strip()) |
  483. Q(asset_tag__icontains=value.strip()) |
  484. Q(comments__icontains=value)
  485. ).distinct()
  486. def _mac_address(self, queryset, name, value):
  487. value = value.strip()
  488. if not value:
  489. return queryset
  490. try:
  491. mac = EUI(value.strip())
  492. return queryset.filter(interfaces__mac_address=mac).distinct()
  493. except AddrFormatError:
  494. return queryset.none()
  495. def _has_primary_ip(self, queryset, name, value):
  496. if value:
  497. return queryset.filter(
  498. Q(primary_ip4__isnull=False) |
  499. Q(primary_ip6__isnull=False)
  500. )
  501. else:
  502. return queryset.exclude(
  503. Q(primary_ip4__isnull=False) |
  504. Q(primary_ip6__isnull=False)
  505. )
  506. class DeviceComponentFilterSet(django_filters.FilterSet):
  507. device_id = django_filters.ModelChoiceFilter(
  508. queryset=Device.objects.all(),
  509. label='Device (ID)',
  510. )
  511. device = django_filters.ModelChoiceFilter(
  512. queryset=Device.objects.all(),
  513. to_field_name='name',
  514. label='Device (name)',
  515. )
  516. tag = django_filters.CharFilter(
  517. name='tags__slug',
  518. )
  519. class ConsolePortFilter(DeviceComponentFilterSet):
  520. class Meta:
  521. model = ConsolePort
  522. fields = ['name']
  523. class ConsoleServerPortFilter(DeviceComponentFilterSet):
  524. class Meta:
  525. model = ConsoleServerPort
  526. fields = ['name']
  527. class PowerPortFilter(DeviceComponentFilterSet):
  528. class Meta:
  529. model = PowerPort
  530. fields = ['name']
  531. class PowerOutletFilter(DeviceComponentFilterSet):
  532. class Meta:
  533. model = PowerOutlet
  534. fields = ['name']
  535. class InterfaceFilter(django_filters.FilterSet):
  536. """
  537. Not using DeviceComponentFilterSet for Interfaces because we need to glean the ordering logic from the parent
  538. Device's DeviceType.
  539. """
  540. device = django_filters.CharFilter(
  541. method='filter_device',
  542. name='name',
  543. label='Device',
  544. )
  545. device_id = django_filters.NumberFilter(
  546. method='filter_device',
  547. name='pk',
  548. label='Device (ID)',
  549. )
  550. type = django_filters.CharFilter(
  551. method='filter_type',
  552. label='Interface type',
  553. )
  554. lag_id = django_filters.ModelMultipleChoiceFilter(
  555. name='lag',
  556. queryset=Interface.objects.all(),
  557. label='LAG interface (ID)',
  558. )
  559. mac_address = django_filters.CharFilter(
  560. method='_mac_address',
  561. label='MAC address',
  562. )
  563. tag = django_filters.CharFilter(
  564. name='tags__slug',
  565. )
  566. class Meta:
  567. model = Interface
  568. fields = ['name', 'form_factor', 'enabled', 'mtu', 'mgmt_only']
  569. def filter_device(self, queryset, name, value):
  570. try:
  571. device = Device.objects.select_related('device_type').get(**{name: value})
  572. vc_interface_ids = [i['id'] for i in device.vc_interfaces.values('id')]
  573. ordering = device.device_type.interface_ordering
  574. return queryset.filter(pk__in=vc_interface_ids).order_naturally(ordering)
  575. except Device.DoesNotExist:
  576. return queryset.none()
  577. def filter_type(self, queryset, name, value):
  578. value = value.strip().lower()
  579. return {
  580. 'physical': queryset.exclude(form_factor__in=NONCONNECTABLE_IFACE_TYPES),
  581. 'virtual': queryset.filter(form_factor__in=VIRTUAL_IFACE_TYPES),
  582. 'wireless': queryset.filter(form_factor__in=WIRELESS_IFACE_TYPES),
  583. 'lag': queryset.filter(form_factor=IFACE_FF_LAG),
  584. }.get(value, queryset.none())
  585. def _mac_address(self, queryset, name, value):
  586. value = value.strip()
  587. if not value:
  588. return queryset
  589. try:
  590. mac = EUI(value.strip())
  591. return queryset.filter(mac_address=mac)
  592. except AddrFormatError:
  593. return queryset.none()
  594. class FrontPanelPortFilter(DeviceComponentFilterSet):
  595. class Meta:
  596. model = FrontPanelPort
  597. fields = ['name', 'type']
  598. class RearPanelPortFilter(DeviceComponentFilterSet):
  599. class Meta:
  600. model = RearPanelPort
  601. fields = ['name', 'type']
  602. class DeviceBayFilter(DeviceComponentFilterSet):
  603. class Meta:
  604. model = DeviceBay
  605. fields = ['name']
  606. class InventoryItemFilter(DeviceComponentFilterSet):
  607. q = django_filters.CharFilter(
  608. method='search',
  609. label='Search',
  610. )
  611. parent_id = django_filters.ModelMultipleChoiceFilter(
  612. queryset=InventoryItem.objects.all(),
  613. label='Parent inventory item (ID)',
  614. )
  615. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  616. queryset=Manufacturer.objects.all(),
  617. label='Manufacturer (ID)',
  618. )
  619. manufacturer = django_filters.ModelMultipleChoiceFilter(
  620. name='manufacturer__slug',
  621. queryset=Manufacturer.objects.all(),
  622. to_field_name='slug',
  623. label='Manufacturer (slug)',
  624. )
  625. asset_tag = NullableCharFieldFilter()
  626. class Meta:
  627. model = InventoryItem
  628. fields = ['name', 'part_id', 'serial', 'asset_tag', 'discovered']
  629. def search(self, queryset, name, value):
  630. if not value.strip():
  631. return queryset
  632. qs_filter = (
  633. Q(name__icontains=value) |
  634. Q(part_id__icontains=value) |
  635. Q(serial__iexact=value) |
  636. Q(asset_tag__iexact=value) |
  637. Q(description__icontains=value)
  638. )
  639. return queryset.filter(qs_filter)
  640. class VirtualChassisFilter(django_filters.FilterSet):
  641. q = django_filters.CharFilter(
  642. method='search',
  643. label='Search',
  644. )
  645. site_id = django_filters.ModelMultipleChoiceFilter(
  646. name='master__site',
  647. queryset=Site.objects.all(),
  648. label='Site (ID)',
  649. )
  650. site = django_filters.ModelMultipleChoiceFilter(
  651. name='master__site__slug',
  652. queryset=Site.objects.all(),
  653. to_field_name='slug',
  654. label='Site name (slug)',
  655. )
  656. tenant_id = django_filters.ModelMultipleChoiceFilter(
  657. name='master__tenant',
  658. queryset=Tenant.objects.all(),
  659. label='Tenant (ID)',
  660. )
  661. tenant = django_filters.ModelMultipleChoiceFilter(
  662. name='master__tenant__slug',
  663. queryset=Tenant.objects.all(),
  664. to_field_name='slug',
  665. label='Tenant (slug)',
  666. )
  667. tag = django_filters.CharFilter(
  668. name='tags__slug',
  669. )
  670. class Meta:
  671. model = VirtualChassis
  672. fields = ['domain']
  673. def search(self, queryset, name, value):
  674. if not value.strip():
  675. return queryset
  676. qs_filter = (
  677. Q(master__name__icontains=value) |
  678. Q(domain__icontains=value)
  679. )
  680. return queryset.filter(qs_filter)
  681. class ConsoleConnectionFilter(django_filters.FilterSet):
  682. site = django_filters.CharFilter(
  683. method='filter_site',
  684. label='Site (slug)',
  685. )
  686. device = django_filters.CharFilter(
  687. method='filter_device',
  688. label='Device',
  689. )
  690. class Meta:
  691. model = ConsolePort
  692. fields = ['name', 'connection_status']
  693. def filter_site(self, queryset, name, value):
  694. if not value.strip():
  695. return queryset
  696. return queryset.filter(connected_endpoint__device__site__slug=value)
  697. def filter_device(self, queryset, name, value):
  698. if not value.strip():
  699. return queryset
  700. return queryset.filter(
  701. Q(device__name__icontains=value) |
  702. Q(connected_endpoint__device__name__icontains=value)
  703. )
  704. class PowerConnectionFilter(django_filters.FilterSet):
  705. site = django_filters.CharFilter(
  706. method='filter_site',
  707. label='Site (slug)',
  708. )
  709. device = django_filters.CharFilter(
  710. method='filter_device',
  711. label='Device',
  712. )
  713. class Meta:
  714. model = PowerPort
  715. fields = ['name', 'connection_status']
  716. def filter_site(self, queryset, name, value):
  717. if not value.strip():
  718. return queryset
  719. return queryset.filter(power_outlet__device__site__slug=value)
  720. def filter_device(self, queryset, name, value):
  721. if not value.strip():
  722. return queryset
  723. return queryset.filter(
  724. Q(device__name__icontains=value) |
  725. Q(power_outlet__device__name__icontains=value)
  726. )
  727. class InterfaceConnectionFilter(django_filters.FilterSet):
  728. site = django_filters.CharFilter(
  729. method='filter_site',
  730. label='Site (slug)',
  731. )
  732. device = django_filters.CharFilter(
  733. method='filter_device',
  734. label='Device',
  735. )
  736. class Meta:
  737. model = InterfaceConnection
  738. fields = ['connection_status']
  739. def filter_site(self, queryset, name, value):
  740. if not value.strip():
  741. return queryset
  742. return queryset.filter(
  743. Q(interface_a__device__site__slug=value) |
  744. Q(interface_b__device__site__slug=value)
  745. )
  746. def filter_device(self, queryset, name, value):
  747. if not value.strip():
  748. return queryset
  749. return queryset.filter(
  750. Q(interface_a__device__name__icontains=value) |
  751. Q(interface_b__device__name__icontains=value)
  752. )