filters.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. import django_filters
  2. from netaddr.core import AddrFormatError
  3. from django.db.models import Q
  4. from extras.filters import CustomFieldFilterSet
  5. from tenancy.models import Tenant
  6. from utilities.filters import NullableModelMultipleChoiceFilter, NumericInFilter
  7. from .models import (
  8. ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
  9. DeviceBayTemplate, DeviceRole, DeviceType, IFACE_FF_LAG, Interface, InterfaceTemplate, Manufacturer, InventoryItem,
  10. Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, RackReservation,
  11. RackRole, Region, Site, VIRTUAL_IFACE_TYPES,
  12. )
  13. class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
  14. id__in = NumericInFilter(name='id', lookup_expr='in')
  15. q = django_filters.CharFilter(
  16. method='search',
  17. label='Search',
  18. )
  19. region_id = NullableModelMultipleChoiceFilter(
  20. name='region',
  21. queryset=Region.objects.all(),
  22. label='Region (ID)',
  23. )
  24. region = NullableModelMultipleChoiceFilter(
  25. name='region',
  26. queryset=Region.objects.all(),
  27. to_field_name='slug',
  28. label='Region (slug)',
  29. )
  30. tenant_id = NullableModelMultipleChoiceFilter(
  31. name='tenant',
  32. queryset=Tenant.objects.all(),
  33. label='Tenant (ID)',
  34. )
  35. tenant = NullableModelMultipleChoiceFilter(
  36. name='tenant',
  37. queryset=Tenant.objects.all(),
  38. to_field_name='slug',
  39. label='Tenant (slug)',
  40. )
  41. class Meta:
  42. model = Site
  43. fields = ['q', 'name', 'facility', 'asn']
  44. def search(self, queryset, name, value):
  45. if not value.strip():
  46. return queryset
  47. qs_filter = (
  48. Q(name__icontains=value) |
  49. Q(facility__icontains=value) |
  50. Q(physical_address__icontains=value) |
  51. Q(shipping_address__icontains=value) |
  52. Q(comments__icontains=value)
  53. )
  54. try:
  55. qs_filter |= Q(asn=int(value.strip()))
  56. except ValueError:
  57. pass
  58. return queryset.filter(qs_filter)
  59. class RackGroupFilter(django_filters.FilterSet):
  60. site_id = django_filters.ModelMultipleChoiceFilter(
  61. name='site',
  62. queryset=Site.objects.all(),
  63. label='Site (ID)',
  64. )
  65. site = django_filters.ModelMultipleChoiceFilter(
  66. name='site__slug',
  67. queryset=Site.objects.all(),
  68. to_field_name='slug',
  69. label='Site (slug)',
  70. )
  71. class Meta:
  72. model = RackGroup
  73. fields = ['name']
  74. class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
  75. id__in = NumericInFilter(name='id', lookup_expr='in')
  76. q = django_filters.CharFilter(
  77. method='search',
  78. label='Search',
  79. )
  80. site_id = django_filters.ModelMultipleChoiceFilter(
  81. name='site',
  82. queryset=Site.objects.all(),
  83. label='Site (ID)',
  84. )
  85. site = django_filters.ModelMultipleChoiceFilter(
  86. name='site__slug',
  87. queryset=Site.objects.all(),
  88. to_field_name='slug',
  89. label='Site (slug)',
  90. )
  91. group_id = NullableModelMultipleChoiceFilter(
  92. name='group',
  93. queryset=RackGroup.objects.all(),
  94. label='Group (ID)',
  95. )
  96. group = NullableModelMultipleChoiceFilter(
  97. name='group',
  98. queryset=RackGroup.objects.all(),
  99. to_field_name='slug',
  100. label='Group',
  101. )
  102. tenant_id = NullableModelMultipleChoiceFilter(
  103. name='tenant',
  104. queryset=Tenant.objects.all(),
  105. label='Tenant (ID)',
  106. )
  107. tenant = NullableModelMultipleChoiceFilter(
  108. name='tenant',
  109. queryset=Tenant.objects.all(),
  110. to_field_name='slug',
  111. label='Tenant (slug)',
  112. )
  113. role_id = NullableModelMultipleChoiceFilter(
  114. name='role',
  115. queryset=RackRole.objects.all(),
  116. label='Role (ID)',
  117. )
  118. role = NullableModelMultipleChoiceFilter(
  119. name='role',
  120. queryset=RackRole.objects.all(),
  121. to_field_name='slug',
  122. label='Role (slug)',
  123. )
  124. class Meta:
  125. model = Rack
  126. fields = ['u_height']
  127. def search(self, queryset, name, value):
  128. if not value.strip():
  129. return queryset
  130. return queryset.filter(
  131. Q(name__icontains=value) |
  132. Q(facility_id__icontains=value) |
  133. Q(comments__icontains=value)
  134. )
  135. class RackReservationFilter(django_filters.FilterSet):
  136. rack_id = django_filters.ModelMultipleChoiceFilter(
  137. name='rack',
  138. queryset=Rack.objects.all(),
  139. label='Rack (ID)',
  140. )
  141. class Meta:
  142. model = RackReservation
  143. fields = ['rack', 'user']
  144. class DeviceTypeFilter(CustomFieldFilterSet, django_filters.FilterSet):
  145. id__in = NumericInFilter(name='id', lookup_expr='in')
  146. q = django_filters.CharFilter(
  147. method='search',
  148. label='Search',
  149. )
  150. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  151. name='manufacturer',
  152. queryset=Manufacturer.objects.all(),
  153. label='Manufacturer (ID)',
  154. )
  155. manufacturer = django_filters.ModelMultipleChoiceFilter(
  156. name='manufacturer__slug',
  157. queryset=Manufacturer.objects.all(),
  158. to_field_name='slug',
  159. label='Manufacturer (slug)',
  160. )
  161. class Meta:
  162. model = DeviceType
  163. fields = [
  164. 'model', 'part_number', 'u_height', 'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role',
  165. ]
  166. def search(self, queryset, name, value):
  167. if not value.strip():
  168. return queryset
  169. return queryset.filter(
  170. Q(manufacturer__name__icontains=value) |
  171. Q(model__icontains=value) |
  172. Q(part_number__icontains=value) |
  173. Q(comments__icontains=value)
  174. )
  175. class DeviceTypeComponentFilterSet(django_filters.FilterSet):
  176. devicetype_id = django_filters.ModelMultipleChoiceFilter(
  177. name='device_type',
  178. queryset=DeviceType.objects.all(),
  179. label='Device type (ID)',
  180. )
  181. devicetype = django_filters.ModelMultipleChoiceFilter(
  182. name='device_type',
  183. queryset=DeviceType.objects.all(),
  184. to_field_name='name',
  185. label='Device type (name)',
  186. )
  187. class ConsolePortTemplateFilter(DeviceTypeComponentFilterSet):
  188. class Meta:
  189. model = ConsolePortTemplate
  190. fields = ['name']
  191. class ConsoleServerPortTemplateFilter(DeviceTypeComponentFilterSet):
  192. class Meta:
  193. model = ConsoleServerPortTemplate
  194. fields = ['name']
  195. class PowerPortTemplateFilter(DeviceTypeComponentFilterSet):
  196. class Meta:
  197. model = PowerPortTemplate
  198. fields = ['name']
  199. class PowerOutletTemplateFilter(DeviceTypeComponentFilterSet):
  200. class Meta:
  201. model = PowerOutletTemplate
  202. fields = ['name']
  203. class InterfaceTemplateFilter(DeviceTypeComponentFilterSet):
  204. class Meta:
  205. model = InterfaceTemplate
  206. fields = ['name', 'form_factor']
  207. class DeviceBayTemplateFilter(DeviceTypeComponentFilterSet):
  208. class Meta:
  209. model = DeviceBayTemplate
  210. fields = ['name']
  211. class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet):
  212. id__in = NumericInFilter(name='id', lookup_expr='in')
  213. q = django_filters.CharFilter(
  214. method='search',
  215. label='Search',
  216. )
  217. mac_address = django_filters.CharFilter(
  218. method='_mac_address',
  219. label='MAC address',
  220. )
  221. site_id = django_filters.ModelMultipleChoiceFilter(
  222. name='site',
  223. queryset=Site.objects.all(),
  224. label='Site (ID)',
  225. )
  226. site = django_filters.ModelMultipleChoiceFilter(
  227. name='site__slug',
  228. queryset=Site.objects.all(),
  229. to_field_name='slug',
  230. label='Site name (slug)',
  231. )
  232. rack_group_id = django_filters.ModelMultipleChoiceFilter(
  233. name='rack__group',
  234. queryset=RackGroup.objects.all(),
  235. label='Rack group (ID)',
  236. )
  237. rack_id = NullableModelMultipleChoiceFilter(
  238. name='rack',
  239. queryset=Rack.objects.all(),
  240. label='Rack (ID)',
  241. )
  242. role_id = django_filters.ModelMultipleChoiceFilter(
  243. name='device_role',
  244. queryset=DeviceRole.objects.all(),
  245. label='Role (ID)',
  246. )
  247. role = django_filters.ModelMultipleChoiceFilter(
  248. name='device_role__slug',
  249. queryset=DeviceRole.objects.all(),
  250. to_field_name='slug',
  251. label='Role (slug)',
  252. )
  253. tenant_id = NullableModelMultipleChoiceFilter(
  254. name='tenant',
  255. queryset=Tenant.objects.all(),
  256. label='Tenant (ID)',
  257. )
  258. tenant = NullableModelMultipleChoiceFilter(
  259. name='tenant',
  260. queryset=Tenant.objects.all(),
  261. to_field_name='slug',
  262. label='Tenant (slug)',
  263. )
  264. device_type_id = django_filters.ModelMultipleChoiceFilter(
  265. name='device_type',
  266. queryset=DeviceType.objects.all(),
  267. label='Device type (ID)',
  268. )
  269. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  270. name='device_type__manufacturer',
  271. queryset=Manufacturer.objects.all(),
  272. label='Manufacturer (ID)',
  273. )
  274. manufacturer = django_filters.ModelMultipleChoiceFilter(
  275. name='device_type__manufacturer__slug',
  276. queryset=Manufacturer.objects.all(),
  277. to_field_name='slug',
  278. label='Manufacturer (slug)',
  279. )
  280. model = django_filters.ModelMultipleChoiceFilter(
  281. name='device_type__slug',
  282. queryset=DeviceType.objects.all(),
  283. to_field_name='slug',
  284. label='Device model (slug)',
  285. )
  286. platform_id = NullableModelMultipleChoiceFilter(
  287. name='platform',
  288. queryset=Platform.objects.all(),
  289. label='Platform (ID)',
  290. )
  291. platform = NullableModelMultipleChoiceFilter(
  292. name='platform',
  293. queryset=Platform.objects.all(),
  294. to_field_name='slug',
  295. label='Platform (slug)',
  296. )
  297. status = django_filters.BooleanFilter(
  298. name='status',
  299. label='Status',
  300. )
  301. is_console_server = django_filters.BooleanFilter(
  302. name='device_type__is_console_server',
  303. label='Is a console server',
  304. )
  305. is_pdu = django_filters.BooleanFilter(
  306. name='device_type__is_pdu',
  307. label='Is a PDU',
  308. )
  309. is_network_device = django_filters.BooleanFilter(
  310. name='device_type__is_network_device',
  311. label='Is a network device',
  312. )
  313. has_primary_ip = django_filters.BooleanFilter(
  314. method='_has_primary_ip',
  315. label='Has a primary IP',
  316. )
  317. class Meta:
  318. model = Device
  319. fields = ['name', 'serial', 'asset_tag']
  320. def search(self, queryset, name, value):
  321. if not value.strip():
  322. return queryset
  323. return queryset.filter(
  324. Q(name__icontains=value) |
  325. Q(serial__icontains=value.strip()) |
  326. Q(inventory_items__serial__icontains=value.strip()) |
  327. Q(asset_tag=value.strip()) |
  328. Q(comments__icontains=value)
  329. ).distinct()
  330. def _mac_address(self, queryset, name, value):
  331. value = value.strip()
  332. if not value:
  333. return queryset
  334. try:
  335. return queryset.filter(interfaces__mac_address=value).distinct()
  336. except AddrFormatError:
  337. return queryset.none()
  338. def _has_primary_ip(self, queryset, name, value):
  339. if value:
  340. return queryset.filter(
  341. Q(primary_ip4__isnull=False) |
  342. Q(primary_ip6__isnull=False)
  343. )
  344. else:
  345. return queryset.exclude(
  346. Q(primary_ip4__isnull=False) |
  347. Q(primary_ip6__isnull=False)
  348. )
  349. class DeviceComponentFilterSet(django_filters.FilterSet):
  350. device_id = django_filters.ModelMultipleChoiceFilter(
  351. name='device',
  352. queryset=Device.objects.all(),
  353. label='Device (ID)',
  354. )
  355. device = django_filters.ModelMultipleChoiceFilter(
  356. name='device__name',
  357. queryset=Device.objects.all(),
  358. to_field_name='name',
  359. label='Device (name)',
  360. )
  361. class ConsolePortFilter(DeviceComponentFilterSet):
  362. class Meta:
  363. model = ConsolePort
  364. fields = ['name']
  365. class ConsoleServerPortFilter(DeviceComponentFilterSet):
  366. class Meta:
  367. model = ConsoleServerPort
  368. fields = ['name']
  369. class PowerPortFilter(DeviceComponentFilterSet):
  370. class Meta:
  371. model = PowerPort
  372. fields = ['name']
  373. class PowerOutletFilter(DeviceComponentFilterSet):
  374. class Meta:
  375. model = PowerOutlet
  376. fields = ['name']
  377. class InterfaceFilter(DeviceComponentFilterSet):
  378. type = django_filters.CharFilter(
  379. method='filter_type',
  380. label='Interface type',
  381. )
  382. mac_address = django_filters.CharFilter(
  383. method='_mac_address',
  384. label='MAC address',
  385. )
  386. class Meta:
  387. model = Interface
  388. fields = ['name', 'form_factor']
  389. def filter_type(self, queryset, name, value):
  390. value = value.strip().lower()
  391. if value == 'physical':
  392. return queryset.exclude(form_factor__in=VIRTUAL_IFACE_TYPES)
  393. elif value == 'virtual':
  394. return queryset.filter(form_factor__in=VIRTUAL_IFACE_TYPES)
  395. elif value == 'lag':
  396. return queryset.filter(form_factor=IFACE_FF_LAG)
  397. return queryset
  398. def _mac_address(self, queryset, name, value):
  399. value = value.strip()
  400. if not value:
  401. return queryset
  402. try:
  403. return queryset.filter(mac_address=value)
  404. except AddrFormatError:
  405. return queryset.none()
  406. class DeviceBayFilter(DeviceComponentFilterSet):
  407. class Meta:
  408. model = DeviceBay
  409. fields = ['name']
  410. class InventoryItemFilter(DeviceComponentFilterSet):
  411. class Meta:
  412. model = InventoryItem
  413. fields = ['name']
  414. class ConsoleConnectionFilter(django_filters.FilterSet):
  415. site = django_filters.CharFilter(
  416. method='filter_site',
  417. label='Site (slug)',
  418. )
  419. device = django_filters.CharFilter(
  420. method='filter_device',
  421. label='Device',
  422. )
  423. class Meta:
  424. model = ConsolePort
  425. fields = ['name', 'connection_status']
  426. def filter_site(self, queryset, name, value):
  427. if not value.strip():
  428. return queryset
  429. return queryset.filter(cs_port__device__site__slug=value)
  430. def filter_device(self, queryset, name, value):
  431. if not value.strip():
  432. return queryset
  433. return queryset.filter(
  434. Q(device__name__icontains=value) |
  435. Q(cs_port__device__name__icontains=value)
  436. )
  437. class PowerConnectionFilter(django_filters.FilterSet):
  438. site = django_filters.CharFilter(
  439. method='filter_site',
  440. label='Site (slug)',
  441. )
  442. device = django_filters.CharFilter(
  443. method='filter_device',
  444. label='Device',
  445. )
  446. class Meta:
  447. model = PowerPort
  448. fields = ['name', 'connection_status']
  449. def filter_site(self, queryset, name, value):
  450. if not value.strip():
  451. return queryset
  452. return queryset.filter(power_outlet__device__site__slug=value)
  453. def filter_device(self, queryset, name, value):
  454. if not value.strip():
  455. return queryset
  456. return queryset.filter(
  457. Q(device__name__icontains=value) |
  458. Q(power_outlet__device__name__icontains=value)
  459. )
  460. class InterfaceConnectionFilter(django_filters.FilterSet):
  461. site = django_filters.CharFilter(
  462. method='filter_site',
  463. label='Site (slug)',
  464. )
  465. device = django_filters.CharFilter(
  466. method='filter_device',
  467. label='Device',
  468. )
  469. def filter_site(self, queryset, name, value):
  470. if not value.strip():
  471. return queryset
  472. return queryset.filter(
  473. Q(interface_a__device__site__slug=value) |
  474. Q(interface_b__device__site__slug=value)
  475. )
  476. def filter_device(self, queryset, name, value):
  477. if not value.strip():
  478. return queryset
  479. return queryset.filter(
  480. Q(interface_a__device__name__icontains=value) |
  481. Q(interface_b__device__name__icontains=value)
  482. )